Merge "Fix the ISurfaceComposer onTransact switch."
diff --git a/Android.mk b/Android.mk
index 07b76d8..ad7027c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -311,18 +311,9 @@
 # as "final" in the official SDK APIs.
 fwbase_dirs_to_document += core/config/sdk
 
+# include definition of libcore_to_document
 # These are relative to libcore
-# Intentionally not included from libcore:
-#     icu openssl suncompat support
-libcore_to_document := \
-	dalvik/src/main/java/dalvik \
-	json/src/main/java \
-	junit/src/main/java \
-	luni/src/main/java/java \
-	luni/src/main/java/javax \
-	luni/src/main/java/org/xml/sax \
-	luni/src/main/java/org/w3c \
-	xml/src/main/java/org/xmlpull/v1 \
+include $(LOCAL_PATH)/../../libcore/Docs.mk
 
 non_base_dirs := \
 	../../external/apache-http/src/org/apache/http
diff --git a/NOTICE b/NOTICE
index 8d6f583..9324631 100644
--- a/NOTICE
+++ b/NOTICE
@@ -72,6 +72,15 @@
 OF ANY KIND, either express or implied; not even the implied warranty
 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for Additional Codecs code.                           ==
+   =========================================================================
+
+Additional Codecs
+These files are Copyright 2003-2010 VisualOn, but released under
+the Apache2 License.
 
                                Apache License
                            Version 2.0, January 2004
diff --git a/api/11.xml b/api/11.xml
index 5fd9c8c..34a7a5c 100644
--- a/api/11.xml
+++ b/api/11.xml
@@ -1615,6 +1615,45 @@
 >
 </field>
 </class>
+<class name="R.animator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="R.animator"
+ type="android.R.animator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="fade_in"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17498112"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fade_out"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17498113"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="R.array"
  extends="java.lang.Object"
  abstract="false"
@@ -1747,6 +1786,193 @@
  visibility="public"
 >
 </field>
+<field name="actionBarSize"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843501"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionBarStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843470"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionBarTabBarStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843510"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionBarTabStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843509"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionBarTabTextStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843511"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionButtonStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843480"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionDropDownStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843479"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionLayout"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843517"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionModeBackground"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843483"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionModeCloseButtonStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843513"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionModeCloseDrawable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843484"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionModeCopyDrawable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843540"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionModeCutDrawable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843539"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionModePasteDrawable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843541"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionOverflowButtonStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843512"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="actionViewClass"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843518"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="activatedBackgroundIndicator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843519"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="activityCloseEnterAnimation"
  type="int"
  transient="false"
@@ -1813,6 +2039,17 @@
  visibility="public"
 >
 </field>
+<field name="alertDialogIcon"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843607"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="alertDialogStyle"
  type="int"
  transient="false"
@@ -1824,6 +2061,28 @@
  visibility="public"
 >
 </field>
+<field name="alertDialogTheme"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843531"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="allContactsName"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843468"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="allowBackup"
  type="int"
  transient="false"
@@ -1846,6 +2105,17 @@
  visibility="public"
 >
 </field>
+<field name="allowParallelSyncs"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843572"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="allowSingleTap"
  type="int"
  transient="false"
@@ -1868,6 +2138,17 @@
  visibility="public"
 >
 </field>
+<field name="alpha"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843553"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="alphabeticShortcut"
  type="int"
  transient="false"
@@ -1912,6 +2193,28 @@
  visibility="public"
 >
 </field>
+<field name="animateFirstView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843477"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="animateLayoutChanges"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843508"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="animateOnClick"
  type="int"
  transient="false"
@@ -1967,6 +2270,17 @@
  visibility="public"
 >
 </field>
+<field name="animationResolution"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843548"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="antialias"
  type="int"
  transient="false"
@@ -2022,6 +2336,17 @@
  visibility="public"
 >
 </field>
+<field name="autoAdvanceViewId"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843537"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="autoCompleteTextViewStyle"
  type="int"
  transient="false"
@@ -2121,6 +2446,17 @@
  visibility="public"
 >
 </field>
+<field name="baseline"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843550"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="baselineAlignBottom"
  type="int"
  transient="false"
@@ -2154,6 +2490,17 @@
  visibility="public"
 >
 </field>
+<field name="borderlessButtonStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843565"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="bottom"
  type="int"
  transient="false"
@@ -2231,6 +2578,28 @@
  visibility="public"
 >
 </field>
+<field name="breadCrumbShortTitle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843526"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="breadCrumbTitle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843525"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="bufferType"
  type="int"
  transient="false"
@@ -2253,6 +2622,28 @@
  visibility="public"
 >
 </field>
+<field name="buttonBarButtonStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843569"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="buttonBarStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843568"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="buttonStyle"
  type="int"
  transient="false"
@@ -2308,6 +2699,17 @@
  visibility="public"
 >
 </field>
+<field name="calendarViewShown"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843598"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="candidatesTextStyleSpans"
  type="int"
  transient="false"
@@ -2803,6 +3205,28 @@
  visibility="public"
 >
 </field>
+<field name="customNavigationLayout"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843474"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="customTokens"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843581"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="cycles"
  type="int"
  transient="false"
@@ -2847,6 +3271,17 @@
  visibility="public"
 >
 </field>
+<field name="dateTextAppearance"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843595"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="debuggable"
  type="int"
  transient="false"
@@ -2946,6 +3381,17 @@
  visibility="public"
 >
 </field>
+<field name="detailsElementBackground"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843600"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="dial"
  type="int"
  transient="false"
@@ -3001,6 +3447,17 @@
  visibility="public"
 >
 </field>
+<field name="dialogTheme"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843530"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="dialogTitle"
  type="int"
  transient="false"
@@ -3067,6 +3524,17 @@
  visibility="public"
 >
 </field>
+<field name="displayOptions"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843472"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="dither"
  type="int"
  transient="false"
@@ -3100,6 +3568,39 @@
  visibility="public"
 >
 </field>
+<field name="dividerHorizontal"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843566"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="dividerPadding"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843564"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="dividerVertical"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843532"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="drawSelectorOnTop"
  type="int"
  transient="false"
@@ -3265,6 +3766,17 @@
  visibility="public"
 >
 </field>
+<field name="dropDownSpinnerStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843478"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="dropDownVerticalOffset"
  type="int"
  transient="false"
@@ -3309,6 +3821,28 @@
  visibility="public"
 >
 </field>
+<field name="editTextBackground"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843604"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="editTextColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843603"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="editTextPreferenceStyle"
  type="int"
  transient="false"
@@ -3408,6 +3942,17 @@
  visibility="public"
 >
 </field>
+<field name="enterFadeDuration"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843534"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="entries"
  type="int"
  transient="false"
@@ -3452,6 +3997,17 @@
  visibility="public"
 >
 </field>
+<field name="exitFadeDuration"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843535"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="expandableListPreferredChildIndicatorLeft"
  type="int"
  transient="false"
@@ -3639,6 +4195,17 @@
  visibility="public"
 >
 </field>
+<field name="fastScrollAlwaysVisible"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843575"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="fastScrollEnabled"
  type="int"
  transient="false"
@@ -3650,6 +4217,61 @@
  visibility="public"
 >
 </field>
+<field name="fastScrollOverlayPosition"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843580"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fastScrollPreviewBackgroundLeft"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843577"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fastScrollPreviewBackgroundRight"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843578"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fastScrollThumbDrawable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843576"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fastScrollTrackDrawable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843579"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="fillAfter"
  type="int"
  transient="false"
@@ -3738,6 +4360,17 @@
  visibility="public"
 >
 </field>
+<field name="firstDayOfWeek"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843583"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="fitsSystemWindows"
  type="int"
  transient="false"
@@ -3782,6 +4415,17 @@
  visibility="public"
 >
 </field>
+<field name="focusedMonthDateColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843589"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="footerDividersEnabled"
  type="int"
  transient="false"
@@ -3826,6 +4470,105 @@
  visibility="public"
 >
 </field>
+<field name="fragment"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843491"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fragmentCloseEnterAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843495"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fragmentCloseExitAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843496"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fragmentNextEnterAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843497"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fragmentNextExitAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843498"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fragmentOpenEnterAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843493"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fragmentOpenExitAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843494"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fragmentPrevEnterAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843499"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fragmentPrevExitAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843500"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="freezesText"
  type="int"
  transient="false"
@@ -4145,6 +4888,17 @@
  visibility="public"
 >
 </field>
+<field name="hardwareAccelerated"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843475"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="hasCode"
  type="int"
  transient="false"
@@ -4200,6 +4954,28 @@
  visibility="public"
 >
 </field>
+<field name="homeAsUpIndicator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843533"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="homeLayout"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843551"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="horizontalDivider"
  type="int"
  transient="false"
@@ -4222,6 +4998,17 @@
  visibility="public"
 >
 </field>
+<field name="horizontalScrollViewStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843605"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="horizontalSpacing"
  type="int"
  transient="false"
@@ -4266,6 +5053,17 @@
  visibility="public"
 >
 </field>
+<field name="iconifiedByDefault"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843516"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="id"
  type="int"
  transient="false"
@@ -4376,6 +5174,50 @@
  visibility="public"
 >
 </field>
+<field name="imeSubtypeExtraValue"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843504"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="imeSubtypeLocale"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843502"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="imeSubtypeMode"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843503"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="immersive"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843456"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="inAnimation"
  type="int"
  transient="false"
@@ -4464,6 +5306,17 @@
  visibility="public"
 >
 </field>
+<field name="indeterminateProgressStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843546"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="indicatorLeft"
  type="int"
  transient="false"
@@ -4629,6 +5482,17 @@
  visibility="public"
 >
 </field>
+<field name="isAlwaysSyncable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843573"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="isDefault"
  type="int"
  transient="false"
@@ -4717,6 +5581,17 @@
  visibility="public"
 >
 </field>
+<field name="itemPadding"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843567"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="itemTextAppearance"
  type="int"
  transient="false"
@@ -4959,6 +5834,17 @@
  visibility="public"
 >
 </field>
+<field name="layerType"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843606"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="layout"
  type="int"
  transient="false"
@@ -5377,6 +6263,17 @@
  visibility="public"
 >
 </field>
+<field name="listChoiceBackgroundIndicator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843506"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="listChoiceIndicatorMultiple"
  type="int"
  transient="false"
@@ -5410,6 +6307,28 @@
  visibility="public"
 >
 </field>
+<field name="listDividerAlertDialog"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843527"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="listPopupWindowStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843521"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="listPreferredItemHeight"
  type="int"
  transient="false"
@@ -5465,6 +6384,17 @@
  visibility="public"
 >
 </field>
+<field name="logo"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843454"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="longClickable"
  type="int"
  transient="false"
@@ -5476,6 +6406,17 @@
  visibility="public"
 >
 </field>
+<field name="loopViews"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843529"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="manageSpaceActivity"
  type="int"
  transient="false"
@@ -5520,6 +6461,17 @@
  visibility="public"
 >
 </field>
+<field name="maxDate"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843586"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="maxEms"
  type="int"
  transient="false"
@@ -5630,6 +6582,17 @@
  visibility="public"
 >
 </field>
+<field name="measureWithLargestChild"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843476"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="menuCategory"
  type="int"
  transient="false"
@@ -5652,6 +6615,17 @@
  visibility="public"
 >
 </field>
+<field name="minDate"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843585"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="minEms"
  type="int"
  transient="false"
@@ -5762,6 +6736,17 @@
  visibility="public"
 >
 </field>
+<field name="navigationMode"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843471"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="negativeButtonText"
  type="int"
  transient="false"
@@ -5784,6 +6769,17 @@
  visibility="public"
 >
 </field>
+<field name="nextFocusForward"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843582"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="nextFocusLeft"
  type="int"
  transient="false"
@@ -5905,6 +6901,17 @@
  visibility="public"
 >
 </field>
+<field name="opacity"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843552"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="order"
  type="int"
  transient="false"
@@ -5927,6 +6934,17 @@
  visibility="public"
 >
 </field>
+<field name="ordering"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843490"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="orderingFromXml"
  type="int"
  transient="false"
@@ -6279,6 +7297,17 @@
  visibility="public"
 >
 </field>
+<field name="popupMenuStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843522"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="popupWindowStyle"
  type="int"
  transient="false"
@@ -6367,6 +7396,17 @@
  visibility="public"
 >
 </field>
+<field name="previewImage"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843482"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="priority"
  type="int"
  transient="false"
@@ -6411,6 +7451,17 @@
  visibility="public"
 >
 </field>
+<field name="progressBarPadding"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843547"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="progressBarStyle"
  type="int"
  transient="false"
@@ -6521,6 +7572,17 @@
  visibility="public"
 >
 </field>
+<field name="propertyName"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843489"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="protectionLevel"
  type="int"
  transient="false"
@@ -6554,6 +7616,17 @@
  visibility="public"
 >
 </field>
+<field name="queryHint"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843610"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="quickContactBadgeStyleSmallWindowLarge"
  type="int"
  transient="false"
@@ -6862,6 +7935,39 @@
  visibility="public"
 >
 </field>
+<field name="rotation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843560"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="rotationX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843561"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="rotationY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843562"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="rowDelay"
  type="int"
  transient="false"
@@ -6950,6 +8056,28 @@
  visibility="public"
 >
 </field>
+<field name="scaleX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843558"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="scaleY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843559"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="scheme"
  type="int"
  transient="false"
@@ -7291,6 +8419,17 @@
  visibility="public"
 >
 </field>
+<field name="segmentedButtonStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843570"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="selectAllOnFocus"
  type="int"
  transient="false"
@@ -7313,6 +8452,39 @@
  visibility="public"
 >
 </field>
+<field name="selectableItemBackground"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843536"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="selectedDateVerticalBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843593"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="selectedWeekBackgroundColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843588"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="settingsActivity"
  type="int"
  transient="false"
@@ -7423,6 +8595,17 @@
  visibility="public"
 >
 </field>
+<field name="showAsAction"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843481"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="showDefault"
  type="int"
  transient="false"
@@ -7434,6 +8617,17 @@
  visibility="public"
 >
 </field>
+<field name="showDividers"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843563"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="showSilent"
  type="int"
  transient="false"
@@ -7445,6 +8639,28 @@
  visibility="public"
 >
 </field>
+<field name="showWeekNumber"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843584"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="shownWeekCount"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843587"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="shrinkColumns"
  type="int"
  transient="false"
@@ -7500,6 +8716,17 @@
  visibility="public"
 >
 </field>
+<field name="solidColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843596"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="soundEffectsEnabled"
  type="int"
  transient="false"
@@ -7544,6 +8771,17 @@
  visibility="public"
 >
 </field>
+<field name="spinnerMode"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843507"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="spinnerStyle"
  type="int"
  transient="false"
@@ -7555,6 +8793,28 @@
  visibility="public"
 >
 </field>
+<field name="spinnersShown"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843597"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="splitMotionEvents"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843505"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="src"
  type="int"
  transient="false"
@@ -7643,6 +8903,28 @@
  visibility="public"
 >
 </field>
+<field name="state_accelerated"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843549"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="state_activated"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843520"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="state_active"
  type="int"
  transient="false"
@@ -7764,6 +9046,17 @@
  visibility="public"
 >
 </field>
+<field name="state_multiline"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843599"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="state_pressed"
  type="int"
  transient="false"
@@ -7808,6 +9101,17 @@
  visibility="public"
 >
 </field>
+<field name="staticWallpaperPreview"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843571"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="stepSize"
  type="int"
  transient="false"
@@ -7852,6 +9156,28 @@
  visibility="public"
 >
 </field>
+<field name="subtitle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843473"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="subtitleTextStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843515"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="suggestActionMsg"
  type="int"
  transient="false"
@@ -8226,6 +9552,17 @@
  visibility="public"
 >
 </field>
+<field name="textAppearanceLargePopupMenu"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843523"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="textAppearanceMedium"
  type="int"
  transient="false"
@@ -8292,6 +9629,17 @@
  visibility="public"
 >
 </field>
+<field name="textAppearanceSmallPopupMenu"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843524"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="textCheckMark"
  type="int"
  transient="false"
@@ -8325,6 +9673,17 @@
  visibility="public"
 >
 </field>
+<field name="textColorAlertDialogListItem"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843528"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="textColorHighlight"
  type="int"
  transient="false"
@@ -8336,6 +9695,17 @@
  visibility="public"
 >
 </field>
+<field name="textColorHighlightInverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843601"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="textColorHint"
  type="int"
  transient="false"
@@ -8369,6 +9739,17 @@
  visibility="public"
 >
 </field>
+<field name="textColorLinkInverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843602"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="textColorPrimary"
  type="int"
  transient="false"
@@ -8501,6 +9882,28 @@
  visibility="public"
 >
 </field>
+<field name="textEditNoPasteWindowLayout"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843543"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="textEditPasteWindowLayout"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843542"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="textFilterEnabled"
  type="int"
  transient="false"
@@ -8512,6 +9915,17 @@
  visibility="public"
 >
 </field>
+<field name="textIsSelectable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843544"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="textOff"
  type="int"
  transient="false"
@@ -8732,6 +10146,17 @@
  visibility="public"
 >
 </field>
+<field name="titleTextStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843514"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="toAlpha"
  type="int"
  transient="false"
@@ -8875,6 +10300,50 @@
  visibility="public"
 >
 </field>
+<field name="transformPivotX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843554"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="transformPivotY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843555"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="translationX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843556"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="translationY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843557"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="type"
  type="int"
  transient="false"
@@ -8908,6 +10377,17 @@
  visibility="public"
 >
 </field>
+<field name="unfocusedMonthDateColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843590"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="unselectedAlpha"
  type="int"
  transient="false"
@@ -8930,6 +10410,17 @@
  visibility="public"
 >
 </field>
+<field name="useIntrinsicSizeAsMinimum"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843538"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="useLevel"
  type="int"
  transient="false"
@@ -8963,6 +10454,39 @@
  visibility="public"
 >
 </field>
+<field name="valueFrom"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843486"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="valueTo"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843487"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="valueType"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843488"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="variablePadding"
  type="int"
  transient="false"
@@ -9029,6 +10553,17 @@
  visibility="public"
 >
 </field>
+<field name="verticalScrollbarPosition"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843574"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="verticalSpacing"
  type="int"
  transient="false"
@@ -9238,6 +10773,39 @@
  visibility="public"
 >
 </field>
+<field name="weekDayTextAppearance"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843594"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="weekNumberColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843591"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="weekSeparatorLineColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843592"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="weightSum"
  type="int"
  transient="false"
@@ -9271,6 +10839,39 @@
  visibility="public"
 >
 </field>
+<field name="windowActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843469"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="windowActionBarOverlay"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843492"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="windowActionModeOverlay"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843485"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="windowAnimationStyle"
  type="int"
  transient="false"
@@ -9315,6 +10916,17 @@
  visibility="public"
 >
 </field>
+<field name="windowEnableSplitTouch"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843545"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="windowEnterAnimation"
  type="int"
  transient="false"
@@ -9392,6 +11004,28 @@
  visibility="public"
 >
 </field>
+<field name="windowMinWidthMajor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843608"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="windowMinWidthMinor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843609"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="windowNoDisplay"
  type="int"
  transient="false"
@@ -9806,6 +11440,28 @@
  visibility="public"
 >
 </field>
+<field name="dialog_min_width_major"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104899"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="dialog_min_width_minor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104900"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="thumbnail_height"
  type="int"
  transient="false"
@@ -11738,6 +13394,23 @@
 >
 </field>
 </class>
+<class name="R.fraction"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="R.fraction"
+ type="android.R.fraction"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+</class>
 <class name="R.id"
  extends="java.lang.Object"
  abstract="false"
@@ -11941,6 +13614,17 @@
  visibility="public"
 >
 </field>
+<field name="home"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908332"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="icon"
  type="int"
  transient="false"
@@ -12095,6 +13779,17 @@
  visibility="public"
 >
 </field>
+<field name="selectTextMode"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908333"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="selectedIcon"
  type="int"
  transient="false"
@@ -12227,6 +13922,17 @@
  visibility="public"
 >
 </field>
+<field name="up"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908334"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="widget_frame"
  type="int"
  transient="false"
@@ -12289,6 +13995,166 @@
 >
 </field>
 </class>
+<class name="R.interpolator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="R.interpolator"
+ type="android.R.interpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="accelerate_cubic"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563650"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="accelerate_decelerate"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563654"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="accelerate_quad"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563648"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="accelerate_quint"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563652"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="anticipate"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563655"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="anticipate_overshoot"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563657"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="bounce"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563658"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="cycle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563660"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="decelerate_cubic"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563651"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="decelerate_quad"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563649"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="decelerate_quint"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563653"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="linear"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563659"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="overshoot"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563656"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="R.layout"
  extends="java.lang.Object"
  abstract="false"
@@ -12338,6 +14204,17 @@
  visibility="public"
 >
 </field>
+<field name="list_content"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367060"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="preference_category"
  type="int"
  transient="false"
@@ -12448,6 +14325,28 @@
  visibility="public"
 >
 </field>
+<field name="simple_list_item_activated_1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367062"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="simple_list_item_activated_2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367063"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="simple_list_item_checked"
  type="int"
  transient="false"
@@ -12481,6 +14380,17 @@
  visibility="public"
 >
 </field>
+<field name="simple_selectable_list_item"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367061"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="simple_spinner_dropdown_item"
  type="int"
  transient="false"
@@ -12526,6 +14436,51 @@
 >
 </field>
 </class>
+<class name="R.menu"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="R.menu"
+ type="android.R.menu"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+</class>
+<class name="R.mipmap"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="R.mipmap"
+ type="android.R.mipmap"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="sym_def_app_icon"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17629184"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="R.plurals"
  extends="java.lang.Object"
  abstract="false"
@@ -12785,6 +14740,17 @@
  visibility="public"
 >
 </field>
+<field name="selectTextMode"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17039382"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="unknownName"
  type="int"
  transient="false"
@@ -12901,6 +14867,72 @@
  visibility="public"
 >
 </field>
+<field name="Holo_ButtonBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974054"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Holo_ButtonBar_AlertDialog"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974056"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Holo_Light_ButtonBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974055"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Holo_Light_ButtonBar_AlertDialog"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974057"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Holo_Light_SegmentedButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974059"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Holo_SegmentedButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974058"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MediaButton"
  type="int"
  transient="false"
@@ -13209,6 +15241,28 @@
  visibility="public"
 >
 </field>
+<field name="TextAppearance_Widget_PopupMenu_Large"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973953"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TextAppearance_Widget_PopupMenu_Small"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973954"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TextAppearance_Widget_TabWidget"
  type="int"
  transient="false"
@@ -13319,6 +15373,237 @@
  visibility="public"
 >
 </field>
+<field name="Theme_Holo"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973931"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Dialog"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973936"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_DialogWhenLarge"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973944"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_DialogWhenLarge_NoActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973945"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Dialog_MinWidth"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973937"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Dialog_NoActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973938"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Dialog_NoActionBar_MinWidth"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973939"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_InputMethod"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973952"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973935"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light_Dialog"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973940"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light_DialogWhenLarge"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973946"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light_DialogWhenLarge_NoActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973947"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light_Dialog_MinWidth"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973941"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light_Dialog_NoActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973942"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light_Dialog_NoActionBar_MinWidth"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973943"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light_Panel"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973949"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_NoActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973933"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_NoActionBar_Fullscreen"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973934"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Panel"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973948"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Wallpaper"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973950"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Wallpaper_NoTitleBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973951"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Theme_InputMethod"
  type="int"
  transient="false"
@@ -13341,6 +15626,17 @@
  visibility="public"
 >
 </field>
+<field name="Theme_Light_Holo"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973932"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Theme_Light_NoTitleBar"
  type="int"
  transient="false"
@@ -13418,6 +15714,17 @@
  visibility="public"
 >
 </field>
+<field name="Theme_NoTitleBar_OverlayActionModes"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973930"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Theme_Panel"
  type="int"
  transient="false"
@@ -13506,6 +15813,17 @@
  visibility="public"
 >
 </field>
+<field name="Theme_WithActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973929"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget"
  type="int"
  transient="false"
@@ -13528,6 +15846,50 @@
  visibility="public"
 >
 </field>
+<field name="Widget_ActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973955"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_ActionButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973957"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_ActionButton_CloseMode"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973961"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_ActionButton_Overflow"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973960"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_AutoCompleteTextView"
  type="int"
  transient="false"
@@ -13583,6 +15945,17 @@
  visibility="public"
 >
 </field>
+<field name="Widget_CalendarView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974069"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_CompoundButton"
  type="int"
  transient="false"
@@ -13660,6 +16033,17 @@
  visibility="public"
 >
 </field>
+<field name="Widget_EditText_NumberPickerInputText"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974061"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_ExpandableListView"
  type="int"
  transient="false"
@@ -13671,6 +16055,17 @@
  visibility="public"
 >
 </field>
+<field name="Widget_FragmentBreadCrumbs"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973962"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_Gallery"
  type="int"
  transient="false"
@@ -13693,6 +16088,1095 @@
  visibility="public"
 >
 </field>
+<field name="Widget_Holo"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973963"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974005"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ActionButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974000"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ActionButton_CloseMode"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974004"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ActionButton_Overflow"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974001"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ActionButton_TextButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974002"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ActionMode"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974003"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_AutoCompleteTextView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973969"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Button"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973964"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Button_Borderless"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974051"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Button_Inset"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973966"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Button_Small"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973965"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Button_Toggle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973967"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_CalendarView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974070"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_CompoundButton_CheckBox"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973970"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_CompoundButton_RadioButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973987"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_CompoundButton_Star"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973991"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_DropDownItem"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973995"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_DropDownItem_Spinner"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973996"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_EditText"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973972"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_EditText_NumberPickerInputText"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974064"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ExpandableListView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973973"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_GridView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973974"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_HorizontalScrollView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973989"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ImageButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973975"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ImageButton_NumberPickerDownButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974065"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ImageButton_NumberPickerUpButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974063"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974006"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974050"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ActionButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974046"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ActionButton_CloseMode"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974049"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ActionButton_Overflow"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974047"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ActionMode"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974048"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_AutoCompleteTextView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974012"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_Button"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974007"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_Button_Inset"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974009"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_Button_Small"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974008"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_Button_Toggle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974010"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_CalendarView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974071"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_CompoundButton_CheckBox"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974013"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_CompoundButton_RadioButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974033"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_CompoundButton_Star"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974037"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_DropDownItem"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974041"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_DropDownItem_Spinner"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974042"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_EditText"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974015"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_EditText_NumberPickerInputText"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974067"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ExpandableListView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974016"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_GridView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974017"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_HorizontalScrollView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974035"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ImageButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974018"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ImageButton_NumberPickerDownButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974068"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ImageButton_NumberPickerUpButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974066"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ListPopupWindow"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974044"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ListView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974019"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ListView_DropDown"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974014"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_PopupMenu"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974045"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_PopupWindow"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974020"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ProgressBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974021"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ProgressBar_Horizontal"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974022"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ProgressBar_Inverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974026"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ProgressBar_Large"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974025"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ProgressBar_Large_Inverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974028"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ProgressBar_Small"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974023"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ProgressBar_Small_Inverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974027"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ProgressBar_Small_Title"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974024"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_RatingBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974030"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_RatingBar_Indicator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974031"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_RatingBar_Small"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974032"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ScrollView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974034"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_SeekBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974029"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_Spinner"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974036"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_Tab"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974053"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_TabWidget"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974038"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_TextView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974011"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_TextView_SpinnerItem"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974043"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_WebTextView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974039"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_WebView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974040"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ListPopupWindow"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973998"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ListView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973976"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ListView_DropDown"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973971"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_PopupMenu"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973999"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_PopupWindow"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973977"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ProgressBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973978"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ProgressBar_Horizontal"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973979"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ProgressBar_Large"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973982"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ProgressBar_Small"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973980"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ProgressBar_Small_Title"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973981"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_RatingBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973984"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_RatingBar_Indicator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973985"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_RatingBar_Small"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973986"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ScrollView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973988"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_SeekBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973983"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Spinner"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973990"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Tab"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974052"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_TabWidget"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973992"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_TextView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973968"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_TextView_SpinnerItem"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973997"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_WebTextView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973993"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_WebView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973994"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_ImageButton"
  type="int"
  transient="false"
@@ -13704,6 +17188,28 @@
  visibility="public"
 >
 </field>
+<field name="Widget_ImageButton_NumberPickerDownButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974062"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_ImageButton_NumberPickerUpButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974060"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_ImageWell"
  type="int"
  transient="false"
@@ -13726,6 +17232,17 @@
  visibility="public"
 >
 </field>
+<field name="Widget_ListPopupWindow"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973958"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_ListView"
  type="int"
  transient="false"
@@ -13770,6 +17287,17 @@
  visibility="public"
 >
 </field>
+<field name="Widget_PopupMenu"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973959"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_PopupWindow"
  type="int"
  transient="false"
@@ -13902,6 +17430,17 @@
  visibility="public"
 >
 </field>
+<field name="Widget_Spinner_DropDown"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973956"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_TabWidget"
  type="int"
  transient="false"
@@ -15315,6 +18854,28 @@
  visibility="public"
 >
 </field>
+<field name="KEY_CALLER_PID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;callerPid&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEY_CALLER_UID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;callerUid&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEY_ERROR_CODE"
  type="java.lang.String"
  transient="false"
@@ -15562,6 +19123,28 @@
 </parameter>
 <parameter name="prefId" type="int">
 </parameter>
+<parameter name="customTokens" type="boolean">
+</parameter>
+</constructor>
+<constructor name="AuthenticatorDescription"
+ type="android.accounts.AuthenticatorDescription"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.String">
+</parameter>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+<parameter name="labelId" type="int">
+</parameter>
+<parameter name="iconId" type="int">
+</parameter>
+<parameter name="smallIconId" type="int">
+</parameter>
+<parameter name="prefId" type="int">
+</parameter>
 </constructor>
 <method name="describeContents"
  return="int"
@@ -15622,6 +19205,16 @@
  visibility="public"
 >
 </field>
+<field name="customTokens"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="iconId"
  type="int"
  transient="false"
@@ -15842,8 +19435,3283 @@
 </constructor>
 </class>
 </package>
+<package name="android.animation"
+>
+<class name="Animator"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.Cloneable">
+</implements>
+<constructor name="Animator"
+ type="android.animation.Animator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.animation.Animator.AnimatorListener">
+</parameter>
+</method>
+<method name="cancel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="clone"
+ return="android.animation.Animator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="end"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDuration"
+ return="long"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getListeners"
+ return="java.util.ArrayList&lt;android.animation.Animator.AnimatorListener&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStartDelay"
+ return="long"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isRunning"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="removeAllListeners"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="removeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.animation.Animator.AnimatorListener">
+</parameter>
+</method>
+<method name="setDuration"
+ return="android.animation.Animator"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="duration" type="long">
+</parameter>
+</method>
+<method name="setInterpolator"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="android.animation.TimeInterpolator">
+</parameter>
+</method>
+<method name="setStartDelay"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="startDelay" type="long">
+</parameter>
+</method>
+<method name="setTarget"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="java.lang.Object">
+</parameter>
+</method>
+<method name="setupEndValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setupStartValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="start"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="Animator.AnimatorListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onAnimationCancel"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.animation.Animator">
+</parameter>
+</method>
+<method name="onAnimationEnd"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.animation.Animator">
+</parameter>
+</method>
+<method name="onAnimationRepeat"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.animation.Animator">
+</parameter>
+</method>
+<method name="onAnimationStart"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.animation.Animator">
+</parameter>
+</method>
+</interface>
+<class name="AnimatorInflater"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="AnimatorInflater"
+ type="android.animation.AnimatorInflater"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="loadAnimator"
+ return="android.animation.Animator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="id" type="int">
+</parameter>
+<exception name="Resources.NotFoundException" type="android.content.res.Resources.NotFoundException">
+</exception>
+</method>
+</class>
+<class name="AnimatorListenerAdapter"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.animation.Animator.AnimatorListener">
+</implements>
+<constructor name="AnimatorListenerAdapter"
+ type="android.animation.AnimatorListenerAdapter"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="onAnimationCancel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.animation.Animator">
+</parameter>
+</method>
+<method name="onAnimationEnd"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.animation.Animator">
+</parameter>
+</method>
+<method name="onAnimationRepeat"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.animation.Animator">
+</parameter>
+</method>
+<method name="onAnimationStart"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.animation.Animator">
+</parameter>
+</method>
+</class>
+<class name="AnimatorSet"
+ extends="android.animation.Animator"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="AnimatorSet"
+ type="android.animation.AnimatorSet"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getChildAnimations"
+ return="java.util.ArrayList&lt;android.animation.Animator&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDuration"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStartDelay"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isRunning"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="play"
+ return="android.animation.AnimatorSet.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="anim" type="android.animation.Animator">
+</parameter>
+</method>
+<method name="playSequentially"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="items" type="android.animation.Animator...">
+</parameter>
+</method>
+<method name="playSequentially"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="items" type="java.util.List&lt;android.animation.Animator&gt;">
+</parameter>
+</method>
+<method name="playTogether"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="items" type="android.animation.Animator...">
+</parameter>
+</method>
+<method name="playTogether"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="items" type="java.util.Collection&lt;android.animation.Animator&gt;">
+</parameter>
+</method>
+<method name="setDuration"
+ return="android.animation.AnimatorSet"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="duration" type="long">
+</parameter>
+</method>
+<method name="setInterpolator"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interpolator" type="android.animation.TimeInterpolator">
+</parameter>
+</method>
+<method name="setStartDelay"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="startDelay" type="long">
+</parameter>
+</method>
+</class>
+<class name="AnimatorSet.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="after"
+ return="android.animation.AnimatorSet.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="anim" type="android.animation.Animator">
+</parameter>
+</method>
+<method name="after"
+ return="android.animation.AnimatorSet.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="delay" type="long">
+</parameter>
+</method>
+<method name="before"
+ return="android.animation.AnimatorSet.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="anim" type="android.animation.Animator">
+</parameter>
+</method>
+<method name="with"
+ return="android.animation.AnimatorSet.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="anim" type="android.animation.Animator">
+</parameter>
+</method>
+</class>
+<class name="ArgbEvaluator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.animation.TypeEvaluator">
+</implements>
+<constructor name="ArgbEvaluator"
+ type="android.animation.ArgbEvaluator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="evaluate"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+<parameter name="startValue" type="java.lang.Object">
+</parameter>
+<parameter name="endValue" type="java.lang.Object">
+</parameter>
+</method>
+</class>
+<class name="DoubleEvaluator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.animation.TypeEvaluator">
+</implements>
+<constructor name="DoubleEvaluator"
+ type="android.animation.DoubleEvaluator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="evaluate"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+<parameter name="startValue" type="java.lang.Object">
+</parameter>
+<parameter name="endValue" type="java.lang.Object">
+</parameter>
+</method>
+</class>
+<class name="FloatEvaluator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.animation.TypeEvaluator">
+</implements>
+<constructor name="FloatEvaluator"
+ type="android.animation.FloatEvaluator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="evaluate"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+<parameter name="startValue" type="java.lang.Object">
+</parameter>
+<parameter name="endValue" type="java.lang.Object">
+</parameter>
+</method>
+</class>
+<class name="IntEvaluator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.animation.TypeEvaluator">
+</implements>
+<constructor name="IntEvaluator"
+ type="android.animation.IntEvaluator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="evaluate"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+<parameter name="startValue" type="java.lang.Object">
+</parameter>
+<parameter name="endValue" type="java.lang.Object">
+</parameter>
+</method>
+</class>
+<class name="Keyframe"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.Cloneable">
+</implements>
+<constructor name="Keyframe"
+ type="android.animation.Keyframe"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="clone"
+ return="android.animation.Keyframe"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFraction"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInterpolator"
+ return="android.animation.TimeInterpolator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="java.lang.Class"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getValue"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasValue"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="ofFloat"
+ return="android.animation.Keyframe"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+<parameter name="value" type="float">
+</parameter>
+</method>
+<method name="ofFloat"
+ return="android.animation.Keyframe"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+</method>
+<method name="ofInt"
+ return="android.animation.Keyframe"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+<parameter name="value" type="int">
+</parameter>
+</method>
+<method name="ofInt"
+ return="android.animation.Keyframe"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+</method>
+<method name="ofObject"
+ return="android.animation.Keyframe"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+<method name="ofObject"
+ return="android.animation.Keyframe"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+</method>
+<method name="setFraction"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+</method>
+<method name="setInterpolator"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interpolator" type="android.animation.TimeInterpolator">
+</parameter>
+</method>
+<method name="setValue"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+</class>
+<class name="LayoutTransition"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="LayoutTransition"
+ type="android.animation.LayoutTransition"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addChild"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.ViewGroup">
+</parameter>
+<parameter name="child" type="android.view.View">
+</parameter>
+</method>
+<method name="addTransitionListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.animation.LayoutTransition.TransitionListener">
+</parameter>
+</method>
+<method name="getAnimator"
+ return="android.animation.Animator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transitionType" type="int">
+</parameter>
+</method>
+<method name="getDuration"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transitionType" type="int">
+</parameter>
+</method>
+<method name="getInterpolator"
+ return="android.animation.TimeInterpolator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transitionType" type="int">
+</parameter>
+</method>
+<method name="getStagger"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transitionType" type="int">
+</parameter>
+</method>
+<method name="getStartDelay"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transitionType" type="int">
+</parameter>
+</method>
+<method name="getTransitionListeners"
+ return="java.util.List&lt;android.animation.LayoutTransition.TransitionListener&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hideChild"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.ViewGroup">
+</parameter>
+<parameter name="child" type="android.view.View">
+</parameter>
+</method>
+<method name="isChangingLayout"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isRunning"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="removeChild"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.ViewGroup">
+</parameter>
+<parameter name="child" type="android.view.View">
+</parameter>
+</method>
+<method name="removeTransitionListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.animation.LayoutTransition.TransitionListener">
+</parameter>
+</method>
+<method name="setAnimator"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transitionType" type="int">
+</parameter>
+<parameter name="animator" type="android.animation.Animator">
+</parameter>
+</method>
+<method name="setDuration"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="duration" type="long">
+</parameter>
+</method>
+<method name="setDuration"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transitionType" type="int">
+</parameter>
+<parameter name="duration" type="long">
+</parameter>
+</method>
+<method name="setInterpolator"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transitionType" type="int">
+</parameter>
+<parameter name="interpolator" type="android.animation.TimeInterpolator">
+</parameter>
+</method>
+<method name="setStagger"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transitionType" type="int">
+</parameter>
+<parameter name="duration" type="long">
+</parameter>
+</method>
+<method name="setStartDelay"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transitionType" type="int">
+</parameter>
+<parameter name="delay" type="long">
+</parameter>
+</method>
+<method name="showChild"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.ViewGroup">
+</parameter>
+<parameter name="child" type="android.view.View">
+</parameter>
+</method>
+<field name="APPEARING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANGE_APPEARING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHANGE_DISAPPEARING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISAPPEARING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="LayoutTransition.TransitionListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="endTransition"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transition" type="android.animation.LayoutTransition">
+</parameter>
+<parameter name="container" type="android.view.ViewGroup">
+</parameter>
+<parameter name="view" type="android.view.View">
+</parameter>
+<parameter name="transitionType" type="int">
+</parameter>
+</method>
+<method name="startTransition"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transition" type="android.animation.LayoutTransition">
+</parameter>
+<parameter name="container" type="android.view.ViewGroup">
+</parameter>
+<parameter name="view" type="android.view.View">
+</parameter>
+<parameter name="transitionType" type="int">
+</parameter>
+</method>
+</interface>
+<class name="ObjectAnimator"
+ extends="android.animation.ValueAnimator"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ObjectAnimator"
+ type="android.animation.ObjectAnimator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getPropertyName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTarget"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="ofFloat"
+ return="android.animation.ObjectAnimator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="java.lang.Object">
+</parameter>
+<parameter name="propertyName" type="java.lang.String">
+</parameter>
+<parameter name="values" type="float...">
+</parameter>
+</method>
+<method name="ofInt"
+ return="android.animation.ObjectAnimator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="java.lang.Object">
+</parameter>
+<parameter name="propertyName" type="java.lang.String">
+</parameter>
+<parameter name="values" type="int...">
+</parameter>
+</method>
+<method name="ofObject"
+ return="android.animation.ObjectAnimator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="java.lang.Object">
+</parameter>
+<parameter name="propertyName" type="java.lang.String">
+</parameter>
+<parameter name="evaluator" type="android.animation.TypeEvaluator">
+</parameter>
+<parameter name="values" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="ofPropertyValuesHolder"
+ return="android.animation.ObjectAnimator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="java.lang.Object">
+</parameter>
+<parameter name="values" type="android.animation.PropertyValuesHolder...">
+</parameter>
+</method>
+<method name="setPropertyName"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="propertyName" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="PropertyValuesHolder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.Cloneable">
+</implements>
+<method name="clone"
+ return="android.animation.PropertyValuesHolder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPropertyName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="ofFloat"
+ return="android.animation.PropertyValuesHolder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="propertyName" type="java.lang.String">
+</parameter>
+<parameter name="values" type="float...">
+</parameter>
+</method>
+<method name="ofInt"
+ return="android.animation.PropertyValuesHolder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="propertyName" type="java.lang.String">
+</parameter>
+<parameter name="values" type="int...">
+</parameter>
+</method>
+<method name="ofKeyframe"
+ return="android.animation.PropertyValuesHolder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="propertyName" type="java.lang.String">
+</parameter>
+<parameter name="values" type="android.animation.Keyframe...">
+</parameter>
+</method>
+<method name="ofObject"
+ return="android.animation.PropertyValuesHolder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="propertyName" type="java.lang.String">
+</parameter>
+<parameter name="evaluator" type="android.animation.TypeEvaluator">
+</parameter>
+<parameter name="values" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="setEvaluator"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="evaluator" type="android.animation.TypeEvaluator">
+</parameter>
+</method>
+<method name="setFloatValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="float...">
+</parameter>
+</method>
+<method name="setIntValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="int...">
+</parameter>
+</method>
+<method name="setKeyframes"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="android.animation.Keyframe...">
+</parameter>
+</method>
+<method name="setObjectValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="setPropertyName"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="propertyName" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<interface name="TimeInterpolator"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getInterpolation"
+ return="float"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="input" type="float">
+</parameter>
+</method>
+</interface>
+<interface name="TypeEvaluator"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="evaluate"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+<parameter name="startValue" type="java.lang.Object">
+</parameter>
+<parameter name="endValue" type="java.lang.Object">
+</parameter>
+</method>
+</interface>
+<class name="ValueAnimator"
+ extends="android.animation.Animator"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ValueAnimator"
+ type="android.animation.ValueAnimator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addUpdateListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.animation.ValueAnimator.AnimatorUpdateListener">
+</parameter>
+</method>
+<method name="getAnimatedValue"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAnimatedValue"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="propertyName" type="java.lang.String">
+</parameter>
+</method>
+<method name="getCurrentPlayTime"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDuration"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFrameDelay"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInterpolator"
+ return="android.animation.TimeInterpolator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRepeatCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRepeatMode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStartDelay"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getValues"
+ return="android.animation.PropertyValuesHolder[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isRunning"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="ofFloat"
+ return="android.animation.ValueAnimator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="float...">
+</parameter>
+</method>
+<method name="ofInt"
+ return="android.animation.ValueAnimator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="int...">
+</parameter>
+</method>
+<method name="ofObject"
+ return="android.animation.ValueAnimator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="evaluator" type="android.animation.TypeEvaluator">
+</parameter>
+<parameter name="values" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="ofPropertyValuesHolder"
+ return="android.animation.ValueAnimator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="android.animation.PropertyValuesHolder...">
+</parameter>
+</method>
+<method name="removeAllUpdateListeners"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="removeUpdateListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.animation.ValueAnimator.AnimatorUpdateListener">
+</parameter>
+</method>
+<method name="reverse"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setCurrentPlayTime"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="playTime" type="long">
+</parameter>
+</method>
+<method name="setDuration"
+ return="android.animation.ValueAnimator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="duration" type="long">
+</parameter>
+</method>
+<method name="setEvaluator"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="android.animation.TypeEvaluator">
+</parameter>
+</method>
+<method name="setFloatValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="float...">
+</parameter>
+</method>
+<method name="setFrameDelay"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="frameDelay" type="long">
+</parameter>
+</method>
+<method name="setIntValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="int...">
+</parameter>
+</method>
+<method name="setInterpolator"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="android.animation.TimeInterpolator">
+</parameter>
+</method>
+<method name="setObjectValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="setRepeatCount"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+<method name="setRepeatMode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+<method name="setStartDelay"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="startDelay" type="long">
+</parameter>
+</method>
+<method name="setValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="android.animation.PropertyValuesHolder...">
+</parameter>
+</method>
+<field name="INFINITE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RESTART"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="REVERSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="ValueAnimator.AnimatorUpdateListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onAnimationUpdate"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.animation.ValueAnimator">
+</parameter>
+</method>
+</interface>
+</package>
 <package name="android.app"
 >
+<class name="ActionBar"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ActionBar"
+ type="android.app.ActionBar"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addOnMenuVisibilityListener"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.app.ActionBar.OnMenuVisibilityListener">
+</parameter>
+</method>
+<method name="addTab"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tab" type="android.app.ActionBar.Tab">
+</parameter>
+</method>
+<method name="addTab"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tab" type="android.app.ActionBar.Tab">
+</parameter>
+<parameter name="setSelected" type="boolean">
+</parameter>
+</method>
+<method name="addTab"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tab" type="android.app.ActionBar.Tab">
+</parameter>
+<parameter name="position" type="int">
+</parameter>
+</method>
+<method name="addTab"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tab" type="android.app.ActionBar.Tab">
+</parameter>
+<parameter name="position" type="int">
+</parameter>
+<parameter name="setSelected" type="boolean">
+</parameter>
+</method>
+<method name="getCustomNavigationView"
+ return="android.view.View"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCustomView"
+ return="android.view.View"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDisplayOptions"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHeight"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNavigationItemCount"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNavigationMode"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSelectedNavigationIndex"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSelectedNavigationItem"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSelectedTab"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSubtitle"
+ return="java.lang.CharSequence"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTabAt"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+</method>
+<method name="getTabCount"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTitle"
+ return="java.lang.CharSequence"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hide"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isShowing"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="newTab"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="removeAllTabs"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="removeOnMenuVisibilityListener"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.app.ActionBar.OnMenuVisibilityListener">
+</parameter>
+</method>
+<method name="removeTab"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tab" type="android.app.ActionBar.Tab">
+</parameter>
+</method>
+<method name="removeTabAt"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+<method name="selectTab"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tab" type="android.app.ActionBar.Tab">
+</parameter>
+</method>
+<method name="setBackgroundDrawable"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="android.graphics.drawable.Drawable">
+</parameter>
+</method>
+<method name="setCustomNavigationMode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
+<method name="setCustomView"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
+<method name="setCustomView"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+<parameter name="layoutParams" type="android.app.ActionBar.LayoutParams">
+</parameter>
+</method>
+<method name="setCustomView"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
+<method name="setDisplayHomeAsUpEnabled"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="showHomeAsUp" type="boolean">
+</parameter>
+</method>
+<method name="setDisplayOptions"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="options" type="int">
+</parameter>
+</method>
+<method name="setDisplayOptions"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="options" type="int">
+</parameter>
+<parameter name="mask" type="int">
+</parameter>
+</method>
+<method name="setDisplayShowCustomEnabled"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="showCustom" type="boolean">
+</parameter>
+</method>
+<method name="setDisplayShowHomeEnabled"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="showHome" type="boolean">
+</parameter>
+</method>
+<method name="setDisplayShowTitleEnabled"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="showTitle" type="boolean">
+</parameter>
+</method>
+<method name="setDisplayUseLogoEnabled"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="useLogo" type="boolean">
+</parameter>
+</method>
+<method name="setDropdownNavigationMode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.widget.SpinnerAdapter">
+</parameter>
+<parameter name="callback" type="android.app.ActionBar.OnNavigationListener">
+</parameter>
+</method>
+<method name="setDropdownNavigationMode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.widget.SpinnerAdapter">
+</parameter>
+<parameter name="callback" type="android.app.ActionBar.OnNavigationListener">
+</parameter>
+<parameter name="defaultSelectedPosition" type="int">
+</parameter>
+</method>
+<method name="setListNavigationCallbacks"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.widget.SpinnerAdapter">
+</parameter>
+<parameter name="callback" type="android.app.ActionBar.OnNavigationListener">
+</parameter>
+</method>
+<method name="setNavigationMode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<method name="setSelectedNavigationItem"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+<method name="setStandardNavigationMode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="setSubtitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="subtitle" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setSubtitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
+<method name="setTabNavigationMode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="setTitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setTitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
+<method name="show"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="DISPLAY_HIDE_HOME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4096"
+ static="true"
+ final="true"
+ deprecated="deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISPLAY_HOME_AS_UP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISPLAY_SHOW_CUSTOM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISPLAY_SHOW_HOME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISPLAY_SHOW_TITLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISPLAY_USE_LOGO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NAVIGATION_MODE_DROPDOWN_LIST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="deprecated"
+ visibility="public"
+>
+</field>
+<field name="NAVIGATION_MODE_LIST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NAVIGATION_MODE_STANDARD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NAVIGATION_MODE_TABS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="ActionBar.LayoutParams"
+ extends="android.view.ViewGroup.MarginLayoutParams"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ActionBar.LayoutParams"
+ type="android.app.ActionBar.LayoutParams"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="c" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="ActionBar.LayoutParams"
+ type="android.app.ActionBar.LayoutParams"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+</constructor>
+<constructor name="ActionBar.LayoutParams"
+ type="android.app.ActionBar.LayoutParams"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="gravity" type="int">
+</parameter>
+</constructor>
+<constructor name="ActionBar.LayoutParams"
+ type="android.app.ActionBar.LayoutParams"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gravity" type="int">
+</parameter>
+</constructor>
+<constructor name="ActionBar.LayoutParams"
+ type="android.app.ActionBar.LayoutParams"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="android.app.ActionBar.LayoutParams">
+</parameter>
+</constructor>
+<constructor name="ActionBar.LayoutParams"
+ type="android.app.ActionBar.LayoutParams"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="android.view.ViewGroup.LayoutParams">
+</parameter>
+</constructor>
+<field name="gravity"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="ActionBar.OnMenuVisibilityListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onMenuVisibilityChanged"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="isVisible" type="boolean">
+</parameter>
+</method>
+</interface>
+<interface name="ActionBar.OnNavigationListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onNavigationItemSelected"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="itemPosition" type="int">
+</parameter>
+<parameter name="itemId" type="long">
+</parameter>
+</method>
+</interface>
+<class name="ActionBar.Tab"
+ extends="java.lang.Object"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ActionBar.Tab"
+ type="android.app.ActionBar.Tab"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getCustomView"
+ return="android.view.View"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getIcon"
+ return="android.graphics.drawable.Drawable"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPosition"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTag"
+ return="java.lang.Object"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getText"
+ return="java.lang.CharSequence"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="select"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setCustomView"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
+<method name="setCustomView"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="layoutResId" type="int">
+</parameter>
+</method>
+<method name="setIcon"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="icon" type="android.graphics.drawable.Drawable">
+</parameter>
+</method>
+<method name="setIcon"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
+<method name="setTabListener"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.app.ActionBar.TabListener">
+</parameter>
+</method>
+<method name="setTag"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="obj" type="java.lang.Object">
+</parameter>
+</method>
+<method name="setText"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setText"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
+<field name="INVALID_POSITION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="ActionBar.TabListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onTabReselected"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tab" type="android.app.ActionBar.Tab">
+</parameter>
+<parameter name="ft" type="android.app.FragmentTransaction">
+</parameter>
+</method>
+<method name="onTabSelected"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tab" type="android.app.ActionBar.Tab">
+</parameter>
+<parameter name="ft" type="android.app.FragmentTransaction">
+</parameter>
+</method>
+<method name="onTabUnselected"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tab" type="android.app.ActionBar.Tab">
+</parameter>
+<parameter name="ft" type="android.app.FragmentTransaction">
+</parameter>
+</method>
+</interface>
 <class name="Activity"
  extends="android.view.ContextThemeWrapper"
  abstract="false"
@@ -15856,7 +22724,7 @@
 </implements>
 <implements name="android.view.KeyEvent.Callback">
 </implements>
-<implements name="android.view.LayoutInflater.Factory">
+<implements name="android.view.LayoutInflater.Factory2">
 </implements>
 <implements name="android.view.View.OnCreateContextMenuListener">
 </implements>
@@ -15950,6 +22818,19 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="dispatchKeyShortcutEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="dispatchPopulateAccessibilityEvent"
  return="boolean"
  abstract="false"
@@ -15989,6 +22870,25 @@
 <parameter name="ev" type="android.view.MotionEvent">
 </parameter>
 </method>
+<method name="dump"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
 <method name="findViewById"
  return="android.view.View"
  abstract="false"
@@ -16054,6 +22954,17 @@
 <parameter name="child" type="android.app.Activity">
 </parameter>
 </method>
+<method name="getActionBar"
+ return="android.app.ActionBar"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getApplication"
  return="android.app.Application"
  abstract="false"
@@ -16120,6 +23031,17 @@
  visibility="public"
 >
 </method>
+<method name="getFragmentManager"
+ return="android.app.FragmentManager"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getIntent"
  return="android.content.Intent"
  abstract="false"
@@ -16153,6 +23075,17 @@
  visibility="public"
 >
 </method>
+<method name="getLoaderManager"
+ return="android.app.LoaderManager"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getLocalClassName"
  return="java.lang.String"
  abstract="false"
@@ -16287,6 +23220,28 @@
  visibility="public"
 >
 </method>
+<method name="invalidateOptionsMenu"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isChangingConfigurations"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isChild"
  return="boolean"
  abstract="false"
@@ -16327,7 +23282,7 @@
  synchronized="false"
  static="false"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="uri" type="android.net.Uri">
@@ -16354,6 +23309,32 @@
 <parameter name="nonRoot" type="boolean">
 </parameter>
 </method>
+<method name="onActionModeFinished"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
+<method name="onActionModeStarted"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
 <method name="onActivityResult"
  return="void"
  abstract="false"
@@ -16371,6 +23352,19 @@
 <parameter name="data" type="android.content.Intent">
 </parameter>
 </method>
+<method name="onAttachFragment"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+</method>
 <method name="onAttachedToWindow"
  return="void"
  abstract="false"
@@ -16600,6 +23594,25 @@
 <parameter name="attrs" type="android.util.AttributeSet">
 </parameter>
 </method>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.View">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</method>
 <method name="onDestroy"
  return="void"
  abstract="false"
@@ -16669,6 +23682,21 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="onKeyShortcut"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="onKeyUp"
  return="boolean"
  abstract="false"
@@ -17057,6 +24085,19 @@
 <parameter name="hasFocus" type="boolean">
 </parameter>
 </method>
+<method name="onWindowStartingActionMode"
+ return="android.view.ActionMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
 <method name="openContextMenu"
  return="void"
  abstract="false"
@@ -17096,6 +24137,17 @@
 <parameter name="exitAnim" type="int">
 </parameter>
 </method>
+<method name="recreate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="registerForContextMenu"
  return="void"
  abstract="false"
@@ -17474,6 +24526,19 @@
 <parameter name="args" type="android.os.Bundle">
 </parameter>
 </method>
+<method name="startActionMode"
+ return="android.view.ActionMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
 <method name="startActivityForResult"
  return="void"
  abstract="false"
@@ -17506,6 +24571,23 @@
 <parameter name="requestCode" type="int">
 </parameter>
 </method>
+<method name="startActivityFromFragment"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+<parameter name="requestCode" type="int">
+</parameter>
+</method>
 <method name="startActivityIfNeeded"
  return="boolean"
  abstract="false"
@@ -17580,7 +24662,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="c" type="android.database.Cursor">
@@ -17625,7 +24707,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="c" type="android.database.Cursor">
@@ -17840,6 +24922,17 @@
  visibility="public"
 >
 </method>
+<method name="getLargeMemoryClass"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getMemoryClass"
  return="int"
  abstract="false"
@@ -17961,6 +25054,17 @@
 <exception name="SecurityException" type="java.lang.SecurityException">
 </exception>
 </method>
+<method name="isRunningInTestHarness"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isUserAMonkey"
  return="boolean"
  abstract="false"
@@ -17985,6 +25089,21 @@
 <parameter name="packageName" type="java.lang.String">
 </parameter>
 </method>
+<method name="moveTaskToFront"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="taskId" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
 <method name="restartPackage"
  return="void"
  abstract="false"
@@ -17998,6 +25117,28 @@
 <parameter name="packageName" type="java.lang.String">
 </parameter>
 </method>
+<field name="MOVE_TASK_WITH_HOME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RECENT_IGNORE_UNAVAILABLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="RECENT_WITH_EXCLUDED"
  type="int"
  transient="false"
@@ -18009,6 +25150,17 @@
  visibility="public"
 >
 </field>
+<field name="TASKS_GET_THUMBNAILS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4096"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="ActivityManager.MemoryInfo"
  extends="java.lang.Object"
@@ -18377,6 +25529,16 @@
  visibility="public"
 >
 </field>
+<field name="description"
+ type="java.lang.CharSequence"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="id"
  type="int"
  transient="false"
@@ -18397,6 +25559,16 @@
  visibility="public"
 >
 </field>
+<field name="thumbnail"
+ type="android.graphics.Bitmap"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="ActivityManager.RunningAppProcessInfo"
  extends="java.lang.Object"
@@ -19495,6 +26667,19 @@
 <parameter name="icon" type="android.graphics.drawable.Drawable">
 </parameter>
 </method>
+<method name="setIconAttribute"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="attrId" type="int">
+</parameter>
+</method>
 <method name="setInverseBackgroundForced"
  return="void"
  abstract="false"
@@ -19574,6 +26759,18 @@
 <parameter name="context" type="android.content.Context">
 </parameter>
 </constructor>
+<constructor name="AlertDialog.Builder"
+ type="android.app.AlertDialog.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="theme" type="int">
+</parameter>
+</constructor>
 <method name="create"
  return="android.app.AlertDialog"
  abstract="false"
@@ -19585,6 +26782,17 @@
  visibility="public"
 >
 </method>
+<method name="getContext"
+ return="android.content.Context"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="setAdapter"
  return="android.app.AlertDialog.Builder"
  abstract="false"
@@ -19669,6 +26877,19 @@
 <parameter name="icon" type="android.graphics.drawable.Drawable">
 </parameter>
 </method>
+<method name="setIconAttribute"
+ return="android.app.AlertDialog.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="attrId" type="int">
+</parameter>
+</method>
 <method name="setInverseBackgroundForced"
  return="android.app.AlertDialog.Builder"
  abstract="false"
@@ -20173,6 +27394,17 @@
 <parameter name="dayOfMonth" type="int">
 </parameter>
 </constructor>
+<method name="getDatePicker"
+ return="android.widget.DatePicker"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="onClick"
  return="void"
  abstract="false"
@@ -20365,6 +27597,19 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="dispatchKeyShortcutEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="dispatchPopulateAccessibilityEvent"
  return="boolean"
  abstract="false"
@@ -20417,6 +27662,17 @@
 <parameter name="id" type="int">
 </parameter>
 </method>
+<method name="getActionBar"
+ return="android.app.ActionBar"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getContext"
  return="android.content.Context"
  abstract="false"
@@ -20494,6 +27750,17 @@
  visibility="public"
 >
 </method>
+<method name="invalidateOptionsMenu"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isShowing"
  return="boolean"
  abstract="false"
@@ -20505,6 +27772,32 @@
  visibility="public"
 >
 </method>
+<method name="onActionModeFinished"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
+<method name="onActionModeStarted"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
 <method name="onAttachedToWindow"
  return="void"
  abstract="false"
@@ -20693,6 +27986,21 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="onKeyShortcut"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="onKeyUp"
  return="boolean"
  abstract="false"
@@ -20918,6 +28226,19 @@
 <parameter name="hasFocus" type="boolean">
 </parameter>
 </method>
+<method name="onWindowStartingActionMode"
+ return="android.view.ActionMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
 <method name="openContextMenu"
  return="void"
  abstract="false"
@@ -21263,6 +28584,236 @@
 </parameter>
 </method>
 </class>
+<class name="DialogFragment"
+ extends="android.app.Fragment"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.content.DialogInterface.OnCancelListener">
+</implements>
+<implements name="android.content.DialogInterface.OnDismissListener">
+</implements>
+<constructor name="DialogFragment"
+ type="android.app.DialogFragment"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="dismiss"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCancelable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDialog"
+ return="android.app.Dialog"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getShowsDialog"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTheme"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onCancel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dialog" type="android.content.DialogInterface">
+</parameter>
+</method>
+<method name="onCreateDialog"
+ return="android.app.Dialog"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="savedInstanceState" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="onDismiss"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dialog" type="android.content.DialogInterface">
+</parameter>
+</method>
+<method name="setCancelable"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cancelable" type="boolean">
+</parameter>
+</method>
+<method name="setShowsDialog"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="showsDialog" type="boolean">
+</parameter>
+</method>
+<method name="setStyle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="style" type="int">
+</parameter>
+<parameter name="theme" type="int">
+</parameter>
+</method>
+<method name="show"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="manager" type="android.app.FragmentManager">
+</parameter>
+<parameter name="tag" type="java.lang.String">
+</parameter>
+</method>
+<method name="show"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transaction" type="android.app.FragmentTransaction">
+</parameter>
+<parameter name="tag" type="java.lang.String">
+</parameter>
+</method>
+<field name="STYLE_NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STYLE_NO_FRAME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STYLE_NO_INPUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STYLE_NO_TITLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="DownloadManager"
  extends="java.lang.Object"
  abstract="false"
@@ -21284,6 +28835,32 @@
 <parameter name="request" type="android.app.DownloadManager.Request">
 </parameter>
 </method>
+<method name="getMimeTypeForDownloadedFile"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="long">
+</parameter>
+</method>
+<method name="getUriForDownloadedFile"
+ return="android.net.Uri"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="long">
+</parameter>
+</method>
 <method name="openDownloadedFile"
  return="android.os.ParcelFileDescriptor"
  abstract="false"
@@ -21402,6 +28979,17 @@
  visibility="public"
 >
 </field>
+<field name="COLUMN_LOCAL_FILENAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;local_filename&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="COLUMN_LOCAL_URI"
  type="java.lang.String"
  transient="false"
@@ -21600,6 +29188,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;extra_click_download_ids&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="PAUSED_QUEUED_FOR_WIFI"
  type="int"
  transient="false"
@@ -21776,6 +29375,17 @@
 <parameter name="value" type="java.lang.String">
 </parameter>
 </method>
+<method name="allowScanningByMediaScanner"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="setAllowedNetworkTypes"
  return="android.app.DownloadManager.Request"
  abstract="false"
@@ -21873,7 +29483,7 @@
 <parameter name="mimeType" type="java.lang.String">
 </parameter>
 </method>
-<method name="setShowRunningNotification"
+<method name="setNotificationVisibility"
  return="android.app.DownloadManager.Request"
  abstract="false"
  native="false"
@@ -21883,6 +29493,19 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="visibility" type="int">
+</parameter>
+</method>
+<method name="setShowRunningNotification"
+ return="android.app.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
 <parameter name="show" type="boolean">
 </parameter>
 </method>
@@ -21934,6 +29557,39 @@
  visibility="public"
 >
 </field>
+<field name="VISIBILITY_HIDDEN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="VISIBILITY_VISIBLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="VISIBILITY_VISIBLE_NOTIFY_COMPLETED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="ExpandableListActivity"
  extends="android.app.Activity"
@@ -22094,6 +29750,1628 @@
 </parameter>
 </method>
 </class>
+<class name="Fragment"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.content.ComponentCallbacks">
+</implements>
+<implements name="android.view.View.OnCreateContextMenuListener">
+</implements>
+<constructor name="Fragment"
+ type="android.app.Fragment"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="dump"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="equals"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
+<method name="getActivity"
+ return="android.app.Activity"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getArguments"
+ return="android.os.Bundle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFragmentManager"
+ return="android.app.FragmentManager"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLoaderManager"
+ return="android.app.LoaderManager"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getResources"
+ return="android.content.res.Resources"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRetainInstance"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
+<method name="getString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+<parameter name="formatArgs" type="java.lang.Object...">
+</parameter>
+</method>
+<method name="getTag"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTargetFragment"
+ return="android.app.Fragment"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTargetRequestCode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getText"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
+<method name="getView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hashCode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="instantiate"
+ return="android.app.Fragment"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="fname" type="java.lang.String">
+</parameter>
+</method>
+<method name="instantiate"
+ return="android.app.Fragment"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="fname" type="java.lang.String">
+</parameter>
+<parameter name="args" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="isAdded"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isHidden"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isInLayout"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isResumed"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isVisible"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onActivityCreated"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="savedInstanceState" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="onActivityResult"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="requestCode" type="int">
+</parameter>
+<parameter name="resultCode" type="int">
+</parameter>
+<parameter name="data" type="android.content.Intent">
+</parameter>
+</method>
+<method name="onAttach"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="activity" type="android.app.Activity">
+</parameter>
+</method>
+<method name="onConfigurationChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="newConfig" type="android.content.res.Configuration">
+</parameter>
+</method>
+<method name="onContextItemSelected"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="item" type="android.view.MenuItem">
+</parameter>
+</method>
+<method name="onCreate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="savedInstanceState" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="onCreateAnimator"
+ return="android.animation.Animator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transit" type="int">
+</parameter>
+<parameter name="enter" type="boolean">
+</parameter>
+<parameter name="nextAnim" type="int">
+</parameter>
+</method>
+<method name="onCreateContextMenu"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="menu" type="android.view.ContextMenu">
+</parameter>
+<parameter name="v" type="android.view.View">
+</parameter>
+<parameter name="menuInfo" type="android.view.ContextMenu.ContextMenuInfo">
+</parameter>
+</method>
+<method name="onCreateOptionsMenu"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="menu" type="android.view.Menu">
+</parameter>
+<parameter name="inflater" type="android.view.MenuInflater">
+</parameter>
+</method>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="inflater" type="android.view.LayoutInflater">
+</parameter>
+<parameter name="container" type="android.view.ViewGroup">
+</parameter>
+<parameter name="savedInstanceState" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="onDestroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onDestroyOptionsMenu"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onDestroyView"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onDetach"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onHiddenChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="hidden" type="boolean">
+</parameter>
+</method>
+<method name="onInflate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="savedInstanceState" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="onLowMemory"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onOptionsItemSelected"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="item" type="android.view.MenuItem">
+</parameter>
+</method>
+<method name="onOptionsMenuClosed"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="menu" type="android.view.Menu">
+</parameter>
+</method>
+<method name="onPause"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onPrepareOptionsMenu"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="menu" type="android.view.Menu">
+</parameter>
+</method>
+<method name="onResume"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onSaveInstanceState"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="outState" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="onStart"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onStop"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="registerForContextMenu"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
+<method name="setArguments"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="args" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="setHasOptionsMenu"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="hasMenu" type="boolean">
+</parameter>
+</method>
+<method name="setRetainInstance"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="retain" type="boolean">
+</parameter>
+</method>
+<method name="setTargetFragment"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+<parameter name="requestCode" type="int">
+</parameter>
+</method>
+<method name="startActivity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="startActivityForResult"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+<parameter name="requestCode" type="int">
+</parameter>
+</method>
+<method name="unregisterForContextMenu"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
+</class>
+<class name="Fragment.InstantiationException"
+ extends="android.util.AndroidRuntimeException"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Fragment.InstantiationException"
+ type="android.app.Fragment.InstantiationException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="msg" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Exception">
+</parameter>
+</constructor>
+</class>
+<class name="FragmentBreadCrumbs"
+ extends="android.view.ViewGroup"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.app.FragmentManager.OnBackStackChangedListener">
+</implements>
+<constructor name="FragmentBreadCrumbs"
+ type="android.app.FragmentBreadCrumbs"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="FragmentBreadCrumbs"
+ type="android.app.FragmentBreadCrumbs"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="FragmentBreadCrumbs"
+ type="android.app.FragmentBreadCrumbs"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
+<method name="onBackStackChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onLayout"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="changed" type="boolean">
+</parameter>
+<parameter name="l" type="int">
+</parameter>
+<parameter name="t" type="int">
+</parameter>
+<parameter name="r" type="int">
+</parameter>
+<parameter name="b" type="int">
+</parameter>
+</method>
+<method name="setActivity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="a" type="android.app.Activity">
+</parameter>
+</method>
+<method name="setMaxVisible"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visibleCrumbs" type="int">
+</parameter>
+</method>
+<method name="setParentTitle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+<parameter name="shortTitle" type="java.lang.CharSequence">
+</parameter>
+<parameter name="listener" type="android.view.View.OnClickListener">
+</parameter>
+</method>
+<method name="setTitle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+<parameter name="shortTitle" type="java.lang.CharSequence">
+</parameter>
+</method>
+</class>
+<class name="FragmentManager"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="FragmentManager"
+ type="android.app.FragmentManager"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addOnBackStackChangedListener"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.app.FragmentManager.OnBackStackChangedListener">
+</parameter>
+</method>
+<method name="countBackStackEntries"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="dump"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="enableDebugLogging"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
+<method name="executePendingTransactions"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="findFragmentById"
+ return="android.app.Fragment"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+</method>
+<method name="findFragmentByTag"
+ return="android.app.Fragment"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="java.lang.String">
+</parameter>
+</method>
+<method name="getBackStackEntry"
+ return="android.app.FragmentManager.BackStackEntry"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+</method>
+<method name="getFragment"
+ return="android.app.Fragment"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bundle" type="android.os.Bundle">
+</parameter>
+<parameter name="key" type="java.lang.String">
+</parameter>
+</method>
+<method name="openTransaction"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="popBackStack"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="popBackStack"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="popBackStack"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="popBackStackImmediate"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="popBackStackImmediate"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="popBackStackImmediate"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="putFragment"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bundle" type="android.os.Bundle">
+</parameter>
+<parameter name="key" type="java.lang.String">
+</parameter>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+</method>
+<method name="removeOnBackStackChangedListener"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.app.FragmentManager.OnBackStackChangedListener">
+</parameter>
+</method>
+<field name="POP_BACK_STACK_INCLUSIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="FragmentManager.BackStackEntry"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getBreadCrumbShortTitle"
+ return="java.lang.CharSequence"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBreadCrumbTitle"
+ return="java.lang.CharSequence"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getId"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="FragmentManager.OnBackStackChangedListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onBackStackChanged"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<class name="FragmentTransaction"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="FragmentTransaction"
+ type="android.app.FragmentTransaction"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="add"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+<parameter name="tag" type="java.lang.String">
+</parameter>
+</method>
+<method name="add"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="containerViewId" type="int">
+</parameter>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+</method>
+<method name="add"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="containerViewId" type="int">
+</parameter>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+<parameter name="tag" type="java.lang.String">
+</parameter>
+</method>
+<method name="addToBackStack"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="commit"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="commitAllowingStateLoss"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="disallowAddToBackStack"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hide"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+</method>
+<method name="isAddToBackStackAllowed"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isEmpty"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="remove"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+</method>
+<method name="replace"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="containerViewId" type="int">
+</parameter>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+</method>
+<method name="replace"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="containerViewId" type="int">
+</parameter>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+<parameter name="tag" type="java.lang.String">
+</parameter>
+</method>
+<method name="setBreadCrumbShortTitle"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="int">
+</parameter>
+</method>
+<method name="setBreadCrumbShortTitle"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setBreadCrumbTitle"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="int">
+</parameter>
+</method>
+<method name="setBreadCrumbTitle"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setCustomAnimations"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enter" type="int">
+</parameter>
+<parameter name="exit" type="int">
+</parameter>
+</method>
+<method name="setTransition"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transit" type="int">
+</parameter>
+</method>
+<method name="setTransitionStyle"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="styleRes" type="int">
+</parameter>
+</method>
+<method name="show"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+</method>
+<field name="TRANSIT_ENTER_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4096"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TRANSIT_EXIT_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8192"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TRANSIT_FRAGMENT_CLOSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8194"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TRANSIT_FRAGMENT_NEXT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4099"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TRANSIT_FRAGMENT_OPEN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4097"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TRANSIT_FRAGMENT_PREV"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8196"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TRANSIT_NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TRANSIT_UNSET"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="Instrumentation"
  extends="java.lang.Object"
  abstract="false"
@@ -23543,6 +32821,324 @@
 </parameter>
 </method>
 </class>
+<class name="ListFragment"
+ extends="android.app.Fragment"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ListFragment"
+ type="android.app.ListFragment"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getListAdapter"
+ return="android.widget.ListAdapter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getListView"
+ return="android.widget.ListView"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSelectedItemId"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSelectedItemPosition"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onListItemClick"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="l" type="android.widget.ListView">
+</parameter>
+<parameter name="v" type="android.view.View">
+</parameter>
+<parameter name="position" type="int">
+</parameter>
+<parameter name="id" type="long">
+</parameter>
+</method>
+<method name="setEmptyText"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setListAdapter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.widget.ListAdapter">
+</parameter>
+</method>
+<method name="setListShown"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="shown" type="boolean">
+</parameter>
+</method>
+<method name="setListShownNoAnimation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="shown" type="boolean">
+</parameter>
+</method>
+<method name="setSelection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+</class>
+<class name="LoaderManager"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="LoaderManager"
+ type="android.app.LoaderManager"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="destroyLoader"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+</method>
+<method name="dump"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="enableDebugLogging"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
+<method name="getLoader"
+ return="android.content.Loader&lt;D&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+</method>
+<method name="initLoader"
+ return="android.content.Loader&lt;D&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="args" type="android.os.Bundle">
+</parameter>
+<parameter name="callback" type="android.app.LoaderManager.LoaderCallbacks&lt;D&gt;">
+</parameter>
+</method>
+<method name="restartLoader"
+ return="android.content.Loader&lt;D&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="args" type="android.os.Bundle">
+</parameter>
+<parameter name="callback" type="android.app.LoaderManager.LoaderCallbacks&lt;D&gt;">
+</parameter>
+</method>
+<method name="stopLoader"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+</method>
+</class>
+<interface name="LoaderManager.LoaderCallbacks"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onCreateLoader"
+ return="android.content.Loader&lt;D&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="args" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="onLoadFinished"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="loader" type="android.content.Loader&lt;D&gt;">
+</parameter>
+<parameter name="data" type="D">
+</parameter>
+</method>
+<method name="onLoaderReset"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="loader" type="android.content.Loader&lt;D&gt;">
+</parameter>
+</method>
+</interface>
 <class name="LocalActivityManager"
  extends="java.lang.Object"
  abstract="false"
@@ -23874,7 +33470,7 @@
  type="android.app.Notification"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="icon" type="int">
@@ -23923,7 +33519,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="context" type="android.content.Context">
@@ -24026,6 +33622,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_HIGH_PRIORITY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="128"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_INSISTENT"
  type="int"
  transient="false"
@@ -24182,6 +33789,16 @@
  visibility="public"
 >
 </field>
+<field name="largeIcon"
+ type="android.graphics.Bitmap"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ledARGB"
  type="int"
  transient="false"
@@ -24242,6 +33859,16 @@
  visibility="public"
 >
 </field>
+<field name="tickerView"
+ type="android.widget.RemoteViews"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="vibrate"
  type="long[]"
  transient="false"
@@ -24264,6 +33891,334 @@
 >
 </field>
 </class>
+<class name="Notification.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Notification.Builder"
+ type="android.app.Notification.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<method name="getNotification"
+ return="android.app.Notification"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setAutoCancel"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="autoCancel" type="boolean">
+</parameter>
+</method>
+<method name="setContent"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="views" type="android.widget.RemoteViews">
+</parameter>
+</method>
+<method name="setContentInfo"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="info" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setContentIntent"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.app.PendingIntent">
+</parameter>
+</method>
+<method name="setContentText"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setContentTitle"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setDefaults"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="defaults" type="int">
+</parameter>
+</method>
+<method name="setDeleteIntent"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.app.PendingIntent">
+</parameter>
+</method>
+<method name="setFullScreenIntent"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.app.PendingIntent">
+</parameter>
+<parameter name="highPriority" type="boolean">
+</parameter>
+</method>
+<method name="setLargeIcon"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="icon" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="setLights"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="argb" type="int">
+</parameter>
+<parameter name="onMs" type="int">
+</parameter>
+<parameter name="offMs" type="int">
+</parameter>
+</method>
+<method name="setNumber"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="number" type="int">
+</parameter>
+</method>
+<method name="setOngoing"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ongoing" type="boolean">
+</parameter>
+</method>
+<method name="setOnlyAlertOnce"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="onlyAlertOnce" type="boolean">
+</parameter>
+</method>
+<method name="setSmallIcon"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="icon" type="int">
+</parameter>
+</method>
+<method name="setSmallIcon"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="icon" type="int">
+</parameter>
+<parameter name="level" type="int">
+</parameter>
+</method>
+<method name="setSound"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sound" type="android.net.Uri">
+</parameter>
+</method>
+<method name="setSound"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sound" type="android.net.Uri">
+</parameter>
+<parameter name="streamType" type="int">
+</parameter>
+</method>
+<method name="setTicker"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tickerText" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setTicker"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tickerText" type="java.lang.CharSequence">
+</parameter>
+<parameter name="views" type="android.widget.RemoteViews">
+</parameter>
+</method>
+<method name="setVibrate"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pattern" type="long[]">
+</parameter>
+</method>
+<method name="setWhen"
+ return="android.app.Notification.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="when" type="long">
+</parameter>
+</method>
+</class>
 <class name="NotificationManager"
  extends="java.lang.Object"
  abstract="false"
@@ -24376,6 +34331,25 @@
  visibility="public"
 >
 </method>
+<method name="getActivities"
+ return="android.app.PendingIntent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="requestCode" type="int">
+</parameter>
+<parameter name="intents" type="android.content.Intent[]">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
 <method name="getActivity"
  return="android.app.PendingIntent"
  abstract="false"
@@ -24884,6 +34858,32 @@
 <parameter name="d" type="android.graphics.drawable.Drawable">
 </parameter>
 </method>
+<method name="setProgressNumberFormat"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="format" type="java.lang.String">
+</parameter>
+</method>
+<method name="setProgressPercentFormat"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="format" type="java.text.NumberFormat">
+</parameter>
+</method>
 <method name="setProgressStyle"
  return="void"
  abstract="false"
@@ -25216,6 +35216,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_QUERY_REFINEMENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="INTENT_ACTION_GLOBAL_SEARCH"
  type="java.lang.String"
  transient="false"
@@ -25315,6 +35326,17 @@
  visibility="public"
 >
 </field>
+<field name="SUGGEST_COLUMN_FLAGS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;suggest_flags&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SUGGEST_COLUMN_FORMAT"
  type="java.lang.String"
  transient="false"
@@ -26996,6 +37018,17 @@
  visibility="public"
 >
 </field>
+<field name="COMMAND_SECONDARY_TAP"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.wallpaper.secondaryTap&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="COMMAND_TAP"
  type="java.lang.String"
  transient="false"
@@ -27007,6 +37040,17 @@
  visibility="public"
 >
 </field>
+<field name="WALLPAPER_PREVIEW_META_DATA"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.wallpaper.preview&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 </package>
 <package name="android.app.admin"
@@ -27210,6 +37254,28 @@
  visibility="public"
 >
 </field>
+<field name="USES_ENCRYPTED_STORAGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="USES_POLICY_EXPIRE_PASSWORD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="USES_POLICY_FORCE_LOCK"
  type="int"
  transient="false"
@@ -27243,6 +37309,17 @@
  visibility="public"
 >
 </field>
+<field name="USES_POLICY_SETS_GLOBAL_PROXY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="USES_POLICY_WATCH_LOGIN"
  type="int"
  transient="false"
@@ -27368,6 +37445,21 @@
 <parameter name="intent" type="android.content.Intent">
 </parameter>
 </method>
+<method name="onPasswordExpiring"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
 <method name="onPasswordFailed"
  return="void"
  abstract="false"
@@ -27457,6 +37549,17 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_PASSWORD_EXPIRING"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.app.action.ACTION_PASSWORD_EXPIRING&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_PASSWORD_FAILED"
  type="java.lang.String"
  transient="false"
@@ -27532,6 +37635,17 @@
  visibility="public"
 >
 </method>
+<method name="getGlobalProxyAdmin"
+ return="android.content.ComponentName"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getMaximumFailedPasswordsForWipe"
  return="int"
  abstract="false"
@@ -27558,6 +37672,45 @@
 <parameter name="admin" type="android.content.ComponentName">
 </parameter>
 </method>
+<method name="getPasswordExpiration"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getPasswordExpirationTimeout"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getPasswordHistoryLength"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
 <method name="getPasswordMaximumLength"
  return="int"
  abstract="false"
@@ -27584,6 +37737,84 @@
 <parameter name="admin" type="android.content.ComponentName">
 </parameter>
 </method>
+<method name="getPasswordMinimumLetters"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getPasswordMinimumLowerCase"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getPasswordMinimumNonLetter"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getPasswordMinimumNumeric"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getPasswordMinimumSymbols"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getPasswordMinimumUpperCase"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
 <method name="getPasswordQuality"
  return="int"
  abstract="false"
@@ -27597,6 +37828,34 @@
 <parameter name="admin" type="android.content.ComponentName">
 </parameter>
 </method>
+<method name="getStorageEncryption"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="hasGrantedPolicy"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="usesPolicy" type="int">
+</parameter>
+</method>
 <method name="isActivePasswordSufficient"
  return="boolean"
  abstract="false"
@@ -27660,6 +37919,23 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
+<method name="setGlobalProxy"
+ return="android.content.ComponentName"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="proxySpec" type="java.net.Proxy">
+</parameter>
+<parameter name="exclusionList" type="java.util.List&lt;java.lang.String&gt;">
+</parameter>
+</method>
 <method name="setMaximumFailedPasswordsForWipe"
  return="void"
  abstract="false"
@@ -27690,6 +37966,36 @@
 <parameter name="timeMs" type="long">
 </parameter>
 </method>
+<method name="setPasswordExpirationTimeout"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="timeout" type="long">
+</parameter>
+</method>
+<method name="setPasswordHistoryLength"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+</method>
 <method name="setPasswordMinimumLength"
  return="void"
  abstract="false"
@@ -27705,6 +38011,96 @@
 <parameter name="length" type="int">
 </parameter>
 </method>
+<method name="setPasswordMinimumLetters"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+</method>
+<method name="setPasswordMinimumLowerCase"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+</method>
+<method name="setPasswordMinimumNonLetter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+</method>
+<method name="setPasswordMinimumNumeric"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+</method>
+<method name="setPasswordMinimumSymbols"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+</method>
+<method name="setPasswordMinimumUpperCase"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+</method>
 <method name="setPasswordQuality"
  return="void"
  abstract="false"
@@ -27720,6 +38116,21 @@
 <parameter name="quality" type="int">
 </parameter>
 </method>
+<method name="setStorageEncryption"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="encrypt" type="boolean">
+</parameter>
+</method>
 <method name="wipeData"
  return="void"
  abstract="false"
@@ -27755,6 +38166,72 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_START_ENCRYPTION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.app.action.START_ENCRYPTION&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_ACTIVATING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_ACTIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_INACTIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_REQUESTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_UNSUPPORTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_ADD_EXPLANATION"
  type="java.lang.String"
  transient="false"
@@ -27799,6 +38276,17 @@
  visibility="public"
 >
 </field>
+<field name="PASSWORD_QUALITY_COMPLEX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="393216"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="PASSWORD_QUALITY_NUMERIC"
  type="int"
  transient="false"
@@ -28793,6 +39281,66 @@
 <parameter name="context" type="android.content.Context">
 </parameter>
 </method>
+<method name="notifyAppWidgetViewDataChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="appWidgetIds" type="int[]">
+</parameter>
+<parameter name="viewId" type="int">
+</parameter>
+</method>
+<method name="notifyAppWidgetViewDataChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="appWidgetId" type="int">
+</parameter>
+<parameter name="viewId" type="int">
+</parameter>
+</method>
+<method name="partiallyUpdateAppWidget"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="appWidgetIds" type="int[]">
+</parameter>
+<parameter name="views" type="android.widget.RemoteViews">
+</parameter>
+</method>
+<method name="partiallyUpdateAppWidget"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="appWidgetId" type="int">
+</parameter>
+<parameter name="views" type="android.widget.RemoteViews">
+</parameter>
+</method>
 <method name="updateAppWidget"
  return="void"
  abstract="false"
@@ -29125,6 +39673,16 @@
  visibility="public"
 >
 </field>
+<field name="autoAdvanceViewId"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="configure"
  type="android.content.ComponentName"
  transient="false"
@@ -29209,6 +39767,111 @@
 </package>
 <package name="android.bluetooth"
 >
+<class name="BluetoothA2dp"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.bluetooth.BluetoothProfile">
+</implements>
+<method name="getConnectedDevices"
+ return="java.util.List&lt;android.bluetooth.BluetoothDevice&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getConnectionState"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="device" type="android.bluetooth.BluetoothDevice">
+</parameter>
+</method>
+<method name="getDevicesMatchingConnectionStates"
+ return="java.util.List&lt;android.bluetooth.BluetoothDevice&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="states" type="int[]">
+</parameter>
+</method>
+<method name="isA2dpPlaying"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="device" type="android.bluetooth.BluetoothDevice">
+</parameter>
+</method>
+<field name="ACTION_CONNECTION_STATE_CHANGED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_PLAYING_STATE_CHANGED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_NOT_PLAYING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="11"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_PLAYING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="BluetoothAdapter"
  extends="java.lang.Object"
  abstract="false"
@@ -29241,6 +39904,21 @@
 <parameter name="address" type="java.lang.String">
 </parameter>
 </method>
+<method name="closeProfileProxy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="profile" type="int">
+</parameter>
+<parameter name="proxy" type="android.bluetooth.BluetoothProfile">
+</parameter>
+</method>
 <method name="disable"
  return="boolean"
  abstract="false"
@@ -29307,6 +39985,23 @@
  visibility="public"
 >
 </method>
+<method name="getProfileProxy"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="listener" type="android.bluetooth.BluetoothProfile.ServiceListener">
+</parameter>
+<parameter name="profile" type="int">
+</parameter>
+</method>
 <method name="getRemoteDevice"
  return="android.bluetooth.BluetoothDevice"
  abstract="false"
@@ -29364,6 +40059,23 @@
  visibility="public"
 >
 </method>
+<method name="listenUsingInsecureRfcommWithServiceRecord"
+ return="android.bluetooth.BluetoothServerSocket"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="uuid" type="java.util.UUID">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
 <method name="listenUsingRfcommWithServiceRecord"
  return="android.bluetooth.BluetoothServerSocket"
  abstract="false"
@@ -29405,6 +40117,17 @@
  visibility="public"
 >
 </method>
+<field name="ACTION_CONNECTION_STATE_CHANGED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_DISCOVERY_FINISHED"
  type="java.lang.String"
  transient="false"
@@ -29493,6 +40216,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_CONNECTION_STATE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.adapter.extra.CONNECTION_STATE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_DISCOVERABLE_DURATION"
  type="java.lang.String"
  transient="false"
@@ -29515,6 +40249,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_PREVIOUS_CONNECTION_STATE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_PREVIOUS_SCAN_MODE"
  type="java.lang.String"
  transient="false"
@@ -29592,6 +40337,50 @@
  visibility="public"
 >
 </field>
+<field name="STATE_CONNECTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_CONNECTING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_DISCONNECTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_DISCONNECTING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="STATE_OFF"
  type="int"
  transient="false"
@@ -29637,6 +40426,1082 @@
 >
 </field>
 </class>
+<class name="BluetoothAssignedNumbers"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="ACCEL_SEMICONDUCTOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="74"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ALCATEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="APPLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="76"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="APT_LICENSING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="79"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ATHEROS_COMMUNICATIONS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="69"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ATMEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="19"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AVAGO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="78"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AVM_BERLIN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="31"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="BANDSPEED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="BELKIN_INTERNATIONAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="92"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="BLUEGIGA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="71"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="BLUETOOTH_SIG"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="63"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="BROADCOM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="15"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CAMBRIDGE_SILICON_RADIO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CATC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="52"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COMMIL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="51"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONEXANT_SYSTEMS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="28"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTINENTAL_AUTOMOTIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="75"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONWISE_TECHNOLOGY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="66"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="C_TECHNOLOGIES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="38"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DIGIANSWER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="12"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ECLIPSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="53"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EM_MICROELECTRONIC_MARIN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="90"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERICSSON_TECHNOLOGY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FREE2MOVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="83"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GCT_SEMICONDUCTOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="45"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GENNUM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="59"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="HARMAN_INTERNATIONAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="87"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="HITACHI"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="41"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IBM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INFINEON_TECHNOLOGIES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INTEGRATED_SILICON_SOLUTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="65"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INTEGRATED_SYSTEM_SOLUTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="57"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INTEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INVENTEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="30"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IPEXTREME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="61"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="J_AND_M"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="82"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KC_TECHNOLOGY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="22"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LUCENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MACRONIX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="44"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MANSELLA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MARVELL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="72"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MATSUSHITA_ELECTRIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="58"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MEDIATEK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="70"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MEWTEL_TECHNOLOGY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="47"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MICROSOFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MITEL_SEMICONDUCTOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MITSUBISHI_ELECTRIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="20"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MOBILIAN_CORPORATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="55"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MOTOROLA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NEC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NEWLOGIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="23"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NOKIA_MOBILE_PHONES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NORDIC_SEMICONDUCTOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="89"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NORWOOD_SYSTEMS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="46"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OPEN_INTERFACE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="39"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARROT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="67"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARTHUS_TECHNOLOGIES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="14"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHILIPS_SEMICONDUCTORS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="37"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PLANTRONICS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="85"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="QUALCOMM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="29"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RALINK_TECHNOLOGY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="91"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="REALTEK_SEMICONDUCTOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="93"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RED_M"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="50"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RENESAS_TECHNOLOGY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="54"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RESEARCH_IN_MOTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="60"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RF_MICRO_DEVICES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="40"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RIVIERAWAVES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="96"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ROHDE_AND_SCHWARZ"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="25"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RTX_TELECOM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="21"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SEIKO_EPSON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="64"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SIGNIA_TECHNOLOGIES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="27"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SILICON_WAVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="11"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SIRF_TECHNOLOGY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="80"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SOCKET_MOBILE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="68"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SONY_ERICSSON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="86"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STACCATO_COMMUNICATIONS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="77"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STONESTREET_ONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="94"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ST_MICROELECTRONICS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="48"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYMBOL_TECHNOLOGIES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="42"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNOPSYS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="49"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYSTEMS_AND_CHIPS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="62"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TENOVIS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="43"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TERAX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="56"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TEXAS_INSTRUMENTS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="13"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="THREECOM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="THREE_DIJOY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="84"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="THREE_DSP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="73"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TOSHIBA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TRANSILICA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="24"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTPCOM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="26"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TZERO_TECHNOLOGIES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="81"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="VIZIO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="88"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="WAVEPLUS_TECHNOLOGY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="WICENTRIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="95"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="WIDCOMM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ZEEVO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="18"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="BluetoothClass"
  extends="java.lang.Object"
  abstract="false"
@@ -30550,6 +42415,21 @@
 >
 <implements name="android.os.Parcelable">
 </implements>
+<method name="createInsecureRfcommSocketToServiceRecord"
+ return="android.bluetooth.BluetoothSocket"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uuid" type="java.util.UUID">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
 <method name="createRfcommSocketToServiceRecord"
  return="android.bluetooth.BluetoothSocket"
  abstract="false"
@@ -30833,6 +42713,427 @@
 >
 </field>
 </class>
+<class name="BluetoothHeadset"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.bluetooth.BluetoothProfile">
+</implements>
+<method name="getConnectedDevices"
+ return="java.util.List&lt;android.bluetooth.BluetoothDevice&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getConnectionState"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="device" type="android.bluetooth.BluetoothDevice">
+</parameter>
+</method>
+<method name="getDevicesMatchingConnectionStates"
+ return="java.util.List&lt;android.bluetooth.BluetoothDevice&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="states" type="int[]">
+</parameter>
+</method>
+<method name="isAudioConnected"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="device" type="android.bluetooth.BluetoothDevice">
+</parameter>
+</method>
+<method name="startVoiceRecognition"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="device" type="android.bluetooth.BluetoothDevice">
+</parameter>
+</method>
+<method name="stopVoiceRecognition"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="device" type="android.bluetooth.BluetoothDevice">
+</parameter>
+</method>
+<field name="ACTION_AUDIO_STATE_CHANGED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_CONNECTION_STATE_CHANGED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_VENDOR_SPECIFIC_HEADSET_EVENT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AT_CMD_TYPE_ACTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AT_CMD_TYPE_BASIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AT_CMD_TYPE_READ"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AT_CMD_TYPE_SET"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AT_CMD_TYPE_TEST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_ARGS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_AUDIO_CONNECTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="12"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_AUDIO_CONNECTING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="11"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_AUDIO_DISCONNECTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.headset.intent.category.companyid&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="BluetoothProfile"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getConnectedDevices"
+ return="java.util.List&lt;android.bluetooth.BluetoothDevice&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getConnectionState"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="device" type="android.bluetooth.BluetoothDevice">
+</parameter>
+</method>
+<method name="getDevicesMatchingConnectionStates"
+ return="java.util.List&lt;android.bluetooth.BluetoothDevice&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="states" type="int[]">
+</parameter>
+</method>
+<field name="A2DP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_PREVIOUS_STATE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.profile.extra.PREVIOUS_STATE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_STATE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.bluetooth.profile.extra.STATE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="HEADSET"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_CONNECTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_CONNECTING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_DISCONNECTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_DISCONNECTING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
+<interface name="BluetoothProfile.ServiceListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onServiceConnected"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="profile" type="int">
+</parameter>
+<parameter name="proxy" type="android.bluetooth.BluetoothProfile">
+</parameter>
+</method>
+<method name="onServiceDisconnected"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="profile" type="int">
+</parameter>
+</method>
+</interface>
 <class name="BluetoothServerSocket"
  extends="java.lang.Object"
  abstract="false"
@@ -30982,6 +43283,20 @@
 <parameter name="autoInitialize" type="boolean">
 </parameter>
 </constructor>
+<constructor name="AbstractThreadedSyncAdapter"
+ type="android.content.AbstractThreadedSyncAdapter"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="autoInitialize" type="boolean">
+</parameter>
+<parameter name="allowParallelSyncs" type="boolean">
+</parameter>
+</constructor>
 <method name="getContext"
  return="android.content.Context"
  abstract="false"
@@ -31036,6 +43351,19 @@
  visibility="public"
 >
 </method>
+<method name="onSyncCanceled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="thread" type="java.lang.Thread">
+</parameter>
+</method>
 <field name="LOG_SYNC_DETAILS"
  type="int"
  transient="false"
@@ -31404,6 +43732,95 @@
 </parameter>
 </constructor>
 </class>
+<class name="AsyncTaskLoader"
+ extends="android.content.Loader"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="AsyncTaskLoader"
+ type="android.content.AsyncTaskLoader"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<method name="cancelLoad"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="loadInBackground"
+ return="D"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onCancelled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="D">
+</parameter>
+</method>
+<method name="onLoadInBackground"
+ return="D"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="setUpdateThrottle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="delayMS" type="long">
+</parameter>
+</method>
+<method name="waitForLoader"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
 <class name="BroadcastReceiver"
  extends="java.lang.Object"
  abstract="true"
@@ -31499,6 +43916,17 @@
 <parameter name="makeMap" type="boolean">
 </parameter>
 </method>
+<method name="goAsync"
+ return="android.content.BroadcastReceiver.PendingResult"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isInitialStickyBroadcast"
  return="boolean"
  abstract="false"
@@ -31634,6 +44062,768 @@
 </parameter>
 </method>
 </class>
+<class name="BroadcastReceiver.PendingResult"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="abortBroadcast"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="clearAbortBroadcast"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="finish"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAbortBroadcast"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getResultCode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getResultData"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getResultExtras"
+ return="android.os.Bundle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="makeMap" type="boolean">
+</parameter>
+</method>
+<method name="setResult"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="code" type="int">
+</parameter>
+<parameter name="data" type="java.lang.String">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="setResultCode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="code" type="int">
+</parameter>
+</method>
+<method name="setResultData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="java.lang.String">
+</parameter>
+</method>
+<method name="setResultExtras"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+</method>
+</class>
+<class name="ClipData"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<constructor name="ClipData"
+ type="android.content.ClipData"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="label" type="java.lang.CharSequence">
+</parameter>
+<parameter name="mimeTypes" type="java.lang.String[]">
+</parameter>
+<parameter name="icon" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="item" type="android.content.ClipData.Item">
+</parameter>
+</constructor>
+<constructor name="ClipData"
+ type="android.content.ClipData"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="description" type="android.content.ClipDescription">
+</parameter>
+<parameter name="icon" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="item" type="android.content.ClipData.Item">
+</parameter>
+</constructor>
+<method name="addItem"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="item" type="android.content.ClipData.Item">
+</parameter>
+</method>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDescription"
+ return="android.content.ClipDescription"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getIcon"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getItem"
+ return="android.content.ClipData.Item"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+</method>
+<method name="getItemCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="newIntent"
+ return="android.content.ClipData"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="label" type="java.lang.CharSequence">
+</parameter>
+<parameter name="icon" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="newPlainText"
+ return="android.content.ClipData"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="label" type="java.lang.CharSequence">
+</parameter>
+<parameter name="icon" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="text" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="newRawUri"
+ return="android.content.ClipData"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="label" type="java.lang.CharSequence">
+</parameter>
+<parameter name="icon" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="newUri"
+ return="android.content.ClipData"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resolver" type="android.content.ContentResolver">
+</parameter>
+<parameter name="label" type="java.lang.CharSequence">
+</parameter>
+<parameter name="icon" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="ClipData.Item"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ClipData.Item"
+ type="android.content.ClipData.Item"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.CharSequence">
+</parameter>
+</constructor>
+<constructor name="ClipData.Item"
+ type="android.content.ClipData.Item"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</constructor>
+<constructor name="ClipData.Item"
+ type="android.content.ClipData.Item"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</constructor>
+<constructor name="ClipData.Item"
+ type="android.content.ClipData.Item"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.CharSequence">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</constructor>
+<method name="coerceToText"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</method>
+<method name="getIntent"
+ return="android.content.Intent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getText"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUri"
+ return="android.net.Uri"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ClipDescription"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<constructor name="ClipDescription"
+ type="android.content.ClipDescription"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="label" type="java.lang.CharSequence">
+</parameter>
+<parameter name="mimeTypes" type="java.lang.String[]">
+</parameter>
+</constructor>
+<constructor name="ClipDescription"
+ type="android.content.ClipDescription"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="android.content.ClipDescription">
+</parameter>
+</constructor>
+<method name="compareMimeTypes"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="concreteType" type="java.lang.String">
+</parameter>
+<parameter name="desiredType" type="java.lang.String">
+</parameter>
+</method>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="filterMimeTypes"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</method>
+<method name="getLabel"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMimeType"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+</method>
+<method name="getMimeTypeCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasMimeType"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MIMETYPE_TEXT_INTENT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;text/vnd.android.intent&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MIMETYPE_TEXT_PLAIN"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;text/plain&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MIMETYPE_TEXT_URILIST"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;text/uri-list&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="ClipboardManager"
+ extends="android.text.ClipboardManager"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="addPrimaryClipChangedListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="what" type="android.content.ClipboardManager.OnPrimaryClipChangedListener">
+</parameter>
+</method>
+<method name="getPrimaryClip"
+ return="android.content.ClipData"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPrimaryClipDescription"
+ return="android.content.ClipDescription"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getText"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasPrimaryClip"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasText"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="removePrimaryClipChangedListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="what" type="android.content.ClipboardManager.OnPrimaryClipChangedListener">
+</parameter>
+</method>
+<method name="setPrimaryClip"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="clip" type="android.content.ClipData">
+</parameter>
+</method>
+<method name="setText"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.CharSequence">
+</parameter>
+</method>
+</class>
+<interface name="ClipboardManager.OnPrimaryClipChangedListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onPrimaryClipChanged"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
 <interface name="ComponentCallbacks"
  abstract="true"
  static="false"
@@ -31957,6 +45147,23 @@
 <parameter name="values" type="android.content.ContentValues[]">
 </parameter>
 </method>
+<method name="call"
+ return="android.os.Bundle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="method" type="java.lang.String">
+</parameter>
+<parameter name="arg" type="java.lang.String">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+</method>
 <method name="delete"
  return="int"
  abstract="true"
@@ -32007,6 +45214,21 @@
  visibility="public"
 >
 </method>
+<method name="getStreamTypes"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="mimeTypeFilter" type="java.lang.String">
+</parameter>
+</method>
 <method name="getType"
  return="java.lang.String"
  abstract="true"
@@ -32143,6 +45365,48 @@
 <exception name="FileNotFoundException" type="java.io.FileNotFoundException">
 </exception>
 </method>
+<method name="openPipeHelper"
+ return="android.os.ParcelFileDescriptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+<parameter name="opts" type="android.os.Bundle">
+</parameter>
+<parameter name="args" type="T">
+</parameter>
+<parameter name="func" type="android.content.ContentProvider.PipeDataWriter&lt;T&gt;">
+</parameter>
+<exception name="FileNotFoundException" type="java.io.FileNotFoundException">
+</exception>
+</method>
+<method name="openTypedAssetFile"
+ return="android.content.res.AssetFileDescriptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="mimeTypeFilter" type="java.lang.String">
+</parameter>
+<parameter name="opts" type="android.os.Bundle">
+</parameter>
+<exception name="FileNotFoundException" type="java.io.FileNotFoundException">
+</exception>
+</method>
 <method name="query"
  return="android.database.Cursor"
  abstract="true"
@@ -32203,6 +45467,17 @@
 <parameter name="permission" type="java.lang.String">
 </parameter>
 </method>
+<method name="shutdown"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="update"
  return="int"
  abstract="true"
@@ -32223,6 +45498,35 @@
 </parameter>
 </method>
 </class>
+<interface name="ContentProvider.PipeDataWriter"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="writeDataToPipe"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="output" type="android.os.ParcelFileDescriptor">
+</parameter>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+<parameter name="opts" type="android.os.Bundle">
+</parameter>
+<parameter name="args" type="T">
+</parameter>
+</method>
+</interface>
 <class name="ContentProviderClient"
  extends="java.lang.Object"
  abstract="false"
@@ -32295,6 +45599,23 @@
  visibility="public"
 >
 </method>
+<method name="getStreamTypes"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="url" type="android.net.Uri">
+</parameter>
+<parameter name="mimeTypeFilter" type="java.lang.String">
+</parameter>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</method>
 <method name="getType"
  return="java.lang.String"
  abstract="false"
@@ -32365,6 +45686,27 @@
 <exception name="RemoteException" type="android.os.RemoteException">
 </exception>
 </method>
+<method name="openTypedAssetFileDescriptor"
+ return="android.content.res.AssetFileDescriptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+<parameter name="opts" type="android.os.Bundle">
+</parameter>
+<exception name="FileNotFoundException" type="java.io.FileNotFoundException">
+</exception>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</method>
 <method name="query"
  return="android.database.Cursor"
  abstract="false"
@@ -33038,6 +46380,25 @@
 <parameter name="values" type="android.content.ContentValues[]">
 </parameter>
 </method>
+<method name="call"
+ return="android.os.Bundle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="method" type="java.lang.String">
+</parameter>
+<parameter name="arg" type="java.lang.String">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+</method>
 <method name="cancelSync"
  return="void"
  abstract="false"
@@ -33090,6 +46451,17 @@
  synchronized="false"
  static="true"
  final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentSyncs"
+ return="java.util.List&lt;android.content.SyncInfo&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -33135,6 +46507,21 @@
 <parameter name="authority" type="java.lang.String">
 </parameter>
 </method>
+<method name="getStreamTypes"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="url" type="android.net.Uri">
+</parameter>
+<parameter name="mimeTypeFilter" type="java.lang.String">
+</parameter>
+</method>
 <method name="getSyncAdapterTypes"
  return="android.content.SyncAdapterType[]"
  abstract="false"
@@ -33332,6 +46719,25 @@
 <exception name="FileNotFoundException" type="java.io.FileNotFoundException">
 </exception>
 </method>
+<method name="openTypedAssetFileDescriptor"
+ return="android.content.res.AssetFileDescriptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+<parameter name="opts" type="android.os.Bundle">
+</parameter>
+<exception name="FileNotFoundException" type="java.io.FileNotFoundException">
+</exception>
+</method>
 <method name="query"
  return="android.database.Cursor"
  abstract="false"
@@ -33997,6 +47403,17 @@
 <parameter name="key" type="java.lang.String">
 </parameter>
 </method>
+<method name="keySet"
+ return="java.util.Set&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="put"
  return="void"
  abstract="false"
@@ -35047,6 +48464,25 @@
 <parameter name="factory" type="android.database.sqlite.SQLiteDatabase.CursorFactory">
 </parameter>
 </method>
+<method name="openOrCreateDatabase"
+ return="android.database.sqlite.SQLiteDatabase"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="mode" type="int">
+</parameter>
+<parameter name="factory" type="android.database.sqlite.SQLiteDatabase.CursorFactory">
+</parameter>
+<parameter name="errorHandler" type="android.database.DatabaseErrorHandler">
+</parameter>
+</method>
 <method name="peekWallpaper"
  return="android.graphics.drawable.Drawable"
  abstract="true"
@@ -35267,6 +48703,19 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="startActivities"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intents" type="android.content.Intent[]">
+</parameter>
+</method>
 <method name="startActivity"
  return="void"
  abstract="true"
@@ -35603,6 +49052,17 @@
  visibility="public"
 >
 </field>
+<field name="MODE_MULTI_PROCESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MODE_PRIVATE"
  type="int"
  transient="false"
@@ -35636,6 +49096,17 @@
  visibility="public"
 >
 </field>
+<field name="NFC_SERVICE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;nfc&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="NOTIFICATION_SERVICE"
  type="java.lang.String"
  transient="false"
@@ -36485,6 +49956,25 @@
 <parameter name="factory" type="android.database.sqlite.SQLiteDatabase.CursorFactory">
 </parameter>
 </method>
+<method name="openOrCreateDatabase"
+ return="android.database.sqlite.SQLiteDatabase"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="mode" type="int">
+</parameter>
+<parameter name="factory" type="android.database.sqlite.SQLiteDatabase.CursorFactory">
+</parameter>
+<parameter name="errorHandler" type="android.database.DatabaseErrorHandler">
+</parameter>
+</method>
 <method name="peekWallpaper"
  return="android.graphics.drawable.Drawable"
  abstract="false"
@@ -36705,6 +50195,19 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="startActivities"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intents" type="android.content.Intent[]">
+</parameter>
+</method>
 <method name="startActivity"
  return="void"
  abstract="false"
@@ -36811,6 +50314,192 @@
 </parameter>
 </method>
 </class>
+<class name="CursorLoader"
+ extends="android.content.AsyncTaskLoader"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="CursorLoader"
+ type="android.content.CursorLoader"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="projection" type="java.lang.String[]">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+<parameter name="sortOrder" type="java.lang.String">
+</parameter>
+</constructor>
+<method name="deliverResult"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cursor" type="android.database.Cursor">
+</parameter>
+</method>
+<method name="getProjection"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSelection"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSelectionArgs"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSortOrder"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUri"
+ return="android.net.Uri"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="loadInBackground"
+ return="android.database.Cursor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onCancelled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cursor" type="android.database.Cursor">
+</parameter>
+</method>
+<method name="setProjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="projection" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="setSelection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+</method>
+<method name="setSelectionArgs"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="setSortOrder"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sortOrder" type="java.lang.String">
+</parameter>
+</method>
+<method name="setUri"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+</class>
 <interface name="DialogInterface"
  abstract="true"
  static="false"
@@ -37933,6 +51622,32 @@
  visibility="public"
 >
 </method>
+<method name="makeMainActivity"
+ return="android.content.Intent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mainActivity" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="makeRestartActivityTask"
+ return="android.content.Intent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mainActivity" type="android.content.ComponentName">
+</parameter>
+</method>
 <method name="parseIntent"
  return="android.content.Intent"
  abstract="false"
@@ -39390,6 +53105,17 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_PASTE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.PASTE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_PICK"
  type="java.lang.String"
  transient="false"
@@ -39731,6 +53457,17 @@
  visibility="public"
 >
 </field>
+<field name="CATEGORY_APP_MARKET"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.category.APP_MARKET&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="CATEGORY_BROWSABLE"
  type="java.lang.String"
  transient="false"
@@ -39819,6 +53556,17 @@
  visibility="public"
 >
 </field>
+<field name="CATEGORY_HE_DESK_DOCK"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.category.HE_DESK_DOCK&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="CATEGORY_HOME"
  type="java.lang.String"
  transient="false"
@@ -39852,6 +53600,17 @@
  visibility="public"
 >
 </field>
+<field name="CATEGORY_LE_DESK_DOCK"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.category.LE_DESK_DOCK&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="CATEGORY_MONKEY"
  type="java.lang.String"
  transient="false"
@@ -40071,6 +53830,28 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_DOCK_STATE_HE_DESK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_DOCK_STATE_LE_DESK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_DOCK_STATE_UNDOCKED"
  type="int"
  transient="false"
@@ -40357,6 +54138,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_ACTIVITY_CLEAR_TASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32768"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_ACTIVITY_CLEAR_TOP"
  type="int"
  transient="false"
@@ -40511,6 +54303,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_ACTIVITY_TASK_ON_HOME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16384"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_DEBUG_LOG_RESOLUTION"
  type="int"
  transient="false"
@@ -41788,6 +55591,292 @@
 </parameter>
 </constructor>
 </class>
+<class name="Loader"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Loader"
+ type="android.content.Loader"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<method name="dataToString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="D">
+</parameter>
+</method>
+<method name="deliverResult"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="D">
+</parameter>
+</method>
+<method name="dump"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="forceLoad"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getContext"
+ return="android.content.Context"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isReset"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isStarted"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onContentChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onForceLoad"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="onReset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="onStartLoading"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="onStopLoading"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="registerListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="listener" type="android.content.Loader.OnLoadCompleteListener&lt;D&gt;">
+</parameter>
+</method>
+<method name="reset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="startLoading"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="stopLoading"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="takeContentChanged"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="unregisterListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.content.Loader.OnLoadCompleteListener&lt;D&gt;">
+</parameter>
+</method>
+</class>
+<class name="Loader.ForceLoadContentObserver"
+ extends="android.database.ContentObserver"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Loader.ForceLoadContentObserver"
+ type="android.content.Loader.ForceLoadContentObserver"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+</class>
+<interface name="Loader.OnLoadCompleteListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onLoadComplete"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="loader" type="android.content.Loader&lt;D&gt;">
+</parameter>
+<parameter name="data" type="D">
+</parameter>
+</method>
+</interface>
 <class name="MutableContextWrapper"
  extends="android.content.ContextWrapper"
  abstract="false"
@@ -42327,6 +56416,21 @@
 <parameter name="defValue" type="java.lang.String">
 </parameter>
 </method>
+<method name="getStringSet"
+ return="java.util.Set&lt;java.lang.String&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.String">
+</parameter>
+<parameter name="defValues" type="java.util.Set&lt;java.lang.String&gt;">
+</parameter>
+</method>
 <method name="registerOnSharedPreferenceChangeListener"
  return="void"
  abstract="true"
@@ -42469,6 +56573,21 @@
 <parameter name="value" type="java.lang.String">
 </parameter>
 </method>
+<method name="putStringSet"
+ return="android.content.SharedPreferences.Editor"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.String">
+</parameter>
+<parameter name="values" type="java.util.Set&lt;java.lang.String&gt;">
+</parameter>
+</method>
 <method name="remove"
  return="android.content.SharedPreferences.Editor"
  abstract="true"
@@ -42542,6 +56661,17 @@
 <parameter name="source" type="android.os.Parcel">
 </parameter>
 </constructor>
+<method name="allowParallelSyncs"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="describeContents"
  return="int"
  abstract="false"
@@ -42553,6 +56683,17 @@
  visibility="public"
 >
 </method>
+<method name="isAlwaysSyncable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isUserVisible"
  return="boolean"
  abstract="false"
@@ -42687,6 +56828,34 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.os.Parcelable">
+</implements>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parcel" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
 <field name="account"
  type="android.accounts.Account"
  transient="false"
@@ -43186,6 +57355,145 @@
 >
 </field>
 </class>
+<class name="XmlDocumentProvider"
+ extends="android.content.ContentProvider"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="XmlDocumentProvider"
+ type="android.content.XmlDocumentProvider"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="delete"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="getResourceXmlPullParser"
+ return="org.xmlpull.v1.XmlPullParser"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="resourceUri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="getType"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="getUriXmlPullParser"
+ return="org.xmlpull.v1.XmlPullParser"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="url" type="java.lang.String">
+</parameter>
+</method>
+<method name="insert"
+ return="android.net.Uri"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="values" type="android.content.ContentValues">
+</parameter>
+</method>
+<method name="onCreate"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="query"
+ return="android.database.Cursor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="projection" type="java.lang.String[]">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+<parameter name="sortOrder" type="java.lang.String">
+</parameter>
+</method>
+<method name="update"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="values" type="android.content.ContentValues">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+</method>
+</class>
 </package>
 <package name="android.content.pm"
 >
@@ -43451,6 +57759,28 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_HARDWARE_ACCELERATED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1024"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FLAG_IMMERSIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="512"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_MULTIPROCESS"
  type="int"
  transient="false"
@@ -43993,6 +58323,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_SUPPORTS_XLARGE_SCREENS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="524288"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_SYSTEM"
  type="int"
  transient="false"
@@ -44292,6 +58633,17 @@
  visibility="public"
 >
 </method>
+<method name="isEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <field name="applicationInfo"
  type="android.content.pm.ApplicationInfo"
  transient="false"
@@ -46375,6 +60727,21 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
+<method name="setInstallerPackageName"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetPackage" type="java.lang.String">
+</parameter>
+<parameter name="installerPackageName" type="java.lang.String">
+</parameter>
+</method>
 <field name="COMPONENT_ENABLED_STATE_DEFAULT"
  type="int"
  transient="false"
@@ -48817,6 +63184,19 @@
 <parameter name="that" type="android.content.res.Configuration">
 </parameter>
 </method>
+<method name="isLayoutSizeAtLeast"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="int">
+</parameter>
+</method>
 <method name="needNewResources"
  return="boolean"
  abstract="false"
@@ -51139,6 +65519,17 @@
 <parameter name="column" type="int">
 </parameter>
 </method>
+<method name="getNotificationUri"
+ return="android.net.Uri"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getPosition"
  return="int"
  abstract="false"
@@ -51176,6 +65567,19 @@
 <parameter name="column" type="int">
 </parameter>
 </method>
+<method name="getType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="column" type="int">
+</parameter>
+</method>
 <method name="getUpdatedField"
  return="java.lang.Object"
  abstract="false"
@@ -51183,7 +65587,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="protected"
 >
 <parameter name="columnIndex" type="int">
@@ -51251,7 +65655,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="protected"
 >
 <parameter name="columnIndex" type="int">
@@ -51537,7 +65941,7 @@
  volatile="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="protected"
 >
 </field>
@@ -51673,7 +66077,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="columnIndex" type="int">
@@ -51686,7 +66090,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="columnIndex" type="int">
@@ -51699,7 +66103,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="columnIndex" type="int">
@@ -51725,7 +66129,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="columnIndex" type="int">
@@ -52199,6 +66603,19 @@
 <parameter name="columnIndex" type="int">
 </parameter>
 </method>
+<method name="getType"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="columnIndex" type="int">
+</parameter>
+</method>
 <method name="getWantsAllOnMoveCalls"
  return="boolean"
  abstract="true"
@@ -52381,7 +66798,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -52439,6 +66856,61 @@
 <parameter name="observer" type="android.database.DataSetObserver">
 </parameter>
 </method>
+<field name="FIELD_TYPE_BLOB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FIELD_TYPE_FLOAT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FIELD_TYPE_INTEGER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FIELD_TYPE_NULL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FIELD_TYPE_STRING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </interface>
 <class name="CursorIndexOutOfBoundsException"
  extends="java.lang.IndexOutOfBoundsException"
@@ -52796,6 +67268,21 @@
 <parameter name="col" type="int">
 </parameter>
 </method>
+<method name="getType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="row" type="int">
+</parameter>
+<parameter name="col" type="int">
+</parameter>
+</method>
 <method name="isBlob"
  return="boolean"
  abstract="false"
@@ -52803,7 +67290,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="row" type="int">
@@ -52818,7 +67305,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="row" type="int">
@@ -52833,7 +67320,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="row" type="int">
@@ -52848,7 +67335,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="row" type="int">
@@ -52863,7 +67350,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="row" type="int">
@@ -53274,6 +67761,19 @@
 <parameter name="columnIndex" type="int">
 </parameter>
 </method>
+<method name="getType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="columnIndex" type="int">
+</parameter>
+</method>
 <method name="getWantsAllOnMoveCalls"
  return="boolean"
  abstract="false"
@@ -53285,6 +67785,17 @@
  visibility="public"
 >
 </method>
+<method name="getWrappedCursor"
+ return="android.database.Cursor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isAfterLast"
  return="boolean"
  abstract="false"
@@ -53593,6 +68104,27 @@
 >
 </method>
 </class>
+<interface name="DatabaseErrorHandler"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onCorruption"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dbObj" type="android.database.sqlite.SQLiteDatabase">
+</parameter>
+</method>
+</interface>
 <class name="DatabaseUtils"
  extends="java.lang.Object"
  abstract="false"
@@ -53624,6 +68156,21 @@
 <parameter name="sqlString" type="java.lang.String">
 </parameter>
 </method>
+<method name="appendSelectionArgs"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="originalValues" type="java.lang.String[]">
+</parameter>
+<parameter name="newValues" type="java.lang.String[]">
+</parameter>
+</method>
 <method name="appendValueToSql"
  return="void"
  abstract="false"
@@ -53656,6 +68203,53 @@
 <parameter name="value" type="java.lang.Object">
 </parameter>
 </method>
+<method name="blobFileDescriptorForQuery"
+ return="android.os.ParcelFileDescriptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="db" type="android.database.sqlite.SQLiteDatabase">
+</parameter>
+<parameter name="query" type="java.lang.String">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="blobFileDescriptorForQuery"
+ return="android.os.ParcelFileDescriptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prog" type="android.database.sqlite.SQLiteStatement">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="concatenateWhere"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="a" type="java.lang.String">
+</parameter>
+<parameter name="b" type="java.lang.String">
+</parameter>
+</method>
 <method name="createDbFromSqlStatements"
  return="void"
  abstract="false"
@@ -54093,6 +68687,19 @@
 <parameter name="name" type="java.lang.String">
 </parameter>
 </method>
+<method name="getSqlStatementType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sql" type="java.lang.String">
+</parameter>
+</method>
 <method name="longForQuery"
  return="long"
  abstract="false"
@@ -54140,6 +68747,42 @@
 <parameter name="table" type="java.lang.String">
 </parameter>
 </method>
+<method name="queryNumEntries"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="db" type="android.database.sqlite.SQLiteDatabase">
+</parameter>
+<parameter name="table" type="java.lang.String">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+</method>
+<method name="queryNumEntries"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="db" type="android.database.sqlite.SQLiteDatabase">
+</parameter>
+<parameter name="table" type="java.lang.String">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+</method>
 <method name="readExceptionFromParcel"
  return="void"
  abstract="false"
@@ -54243,6 +68886,116 @@
 <parameter name="e" type="java.lang.Exception">
 </parameter>
 </method>
+<field name="STATEMENT_ABORT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATEMENT_ATTACH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATEMENT_BEGIN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATEMENT_COMMIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATEMENT_DDL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATEMENT_OTHER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="99"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATEMENT_PRAGMA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATEMENT_SELECT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATEMENT_UNPREPARED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATEMENT_UPDATE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="DatabaseUtils.InsertHelper"
  extends="java.lang.Object"
@@ -54477,6 +69230,38 @@
 >
 </field>
 </class>
+<class name="DefaultDatabaseErrorHandler"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.database.DatabaseErrorHandler">
+</implements>
+<constructor name="DefaultDatabaseErrorHandler"
+ type="android.database.DefaultDatabaseErrorHandler"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="onCorruption"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dbObj" type="android.database.sqlite.SQLiteDatabase">
+</parameter>
+</method>
+</class>
 <class name="MatrixCursor"
  extends="android.database.AbstractCursor"
  abstract="false"
@@ -54960,6 +69745,114 @@
 </parameter>
 </constructor>
 </class>
+<class name="SQLiteAccessPermException"
+ extends="android.database.sqlite.SQLiteException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SQLiteAccessPermException"
+ type="android.database.sqlite.SQLiteAccessPermException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SQLiteAccessPermException"
+ type="android.database.sqlite.SQLiteAccessPermException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="error" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="SQLiteBindOrColumnIndexOutOfRangeException"
+ extends="android.database.sqlite.SQLiteException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SQLiteBindOrColumnIndexOutOfRangeException"
+ type="android.database.sqlite.SQLiteBindOrColumnIndexOutOfRangeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SQLiteBindOrColumnIndexOutOfRangeException"
+ type="android.database.sqlite.SQLiteBindOrColumnIndexOutOfRangeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="error" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="SQLiteBlobTooBigException"
+ extends="android.database.sqlite.SQLiteException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SQLiteBlobTooBigException"
+ type="android.database.sqlite.SQLiteBlobTooBigException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SQLiteBlobTooBigException"
+ type="android.database.sqlite.SQLiteBlobTooBigException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="error" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="SQLiteCantOpenDatabaseException"
+ extends="android.database.sqlite.SQLiteException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SQLiteCantOpenDatabaseException"
+ type="android.database.sqlite.SQLiteCantOpenDatabaseException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SQLiteCantOpenDatabaseException"
+ type="android.database.sqlite.SQLiteCantOpenDatabaseException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="error" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
 <class name="SQLiteClosable"
  extends="java.lang.Object"
  abstract="true"
@@ -55071,7 +69964,7 @@
  type="android.database.sqlite.SQLiteCursor"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="db" type="android.database.sqlite.SQLiteDatabase">
@@ -55083,6 +69976,20 @@
 <parameter name="query" type="android.database.sqlite.SQLiteQuery">
 </parameter>
 </constructor>
+<constructor name="SQLiteCursor"
+ type="android.database.sqlite.SQLiteCursor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="driver" type="android.database.sqlite.SQLiteCursorDriver">
+</parameter>
+<parameter name="editTable" type="java.lang.String">
+</parameter>
+<parameter name="query" type="android.database.sqlite.SQLiteQuery">
+</parameter>
+</constructor>
 <method name="getColumnNames"
  return="java.lang.String[]"
  abstract="false"
@@ -55220,6 +70127,17 @@
  visibility="public"
 >
 </method>
+<method name="beginTransactionNonExclusive"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="beginTransactionWithListener"
  return="void"
  abstract="false"
@@ -55233,6 +70151,19 @@
 <parameter name="transactionListener" type="android.database.sqlite.SQLiteTransactionListener">
 </parameter>
 </method>
+<method name="beginTransactionWithListenerNonExclusive"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transactionListener" type="android.database.sqlite.SQLiteTransactionListener">
+</parameter>
+</method>
 <method name="close"
  return="void"
  abstract="false"
@@ -55289,6 +70220,17 @@
 <parameter name="whereArgs" type="java.lang.String[]">
 </parameter>
 </method>
+<method name="enableWriteAheadLogging"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="endTransaction"
  return="void"
  abstract="false"
@@ -55345,6 +70287,17 @@
 <parameter name="tables" type="java.lang.String">
 </parameter>
 </method>
+<method name="getAttachedDbs"
+ return="java.util.ArrayList&lt;android.util.Pair&lt;java.lang.String, java.lang.String&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getMaximumSize"
  return="long"
  abstract="false"
@@ -55385,7 +70338,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -55466,6 +70419,17 @@
 <parameter name="conflictAlgorithm" type="int">
 </parameter>
 </method>
+<method name="isDatabaseIntegrityOk"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isDbLockedByCurrentThread"
  return="boolean"
  abstract="false"
@@ -55517,7 +70481,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="table" type="java.lang.String">
@@ -55532,7 +70496,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="table" type="java.lang.String">
@@ -55583,6 +70547,25 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
+<method name="openDatabase"
+ return="android.database.sqlite.SQLiteDatabase"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="factory" type="android.database.sqlite.SQLiteDatabase.CursorFactory">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+<parameter name="errorHandler" type="android.database.DatabaseErrorHandler">
+</parameter>
+</method>
 <method name="openOrCreateDatabase"
  return="android.database.sqlite.SQLiteDatabase"
  abstract="false"
@@ -55613,6 +70596,23 @@
 <parameter name="factory" type="android.database.sqlite.SQLiteDatabase.CursorFactory">
 </parameter>
 </method>
+<method name="openOrCreateDatabase"
+ return="android.database.sqlite.SQLiteDatabase"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="factory" type="android.database.sqlite.SQLiteDatabase.CursorFactory">
+</parameter>
+<parameter name="errorHandler" type="android.database.DatabaseErrorHandler">
+</parameter>
+</method>
 <method name="query"
  return="android.database.Cursor"
  abstract="false"
@@ -55832,6 +70832,19 @@
 <parameter name="lockingEnabled" type="boolean">
 </parameter>
 </method>
+<method name="setMaxSqlCacheSize"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cacheSize" type="int">
+</parameter>
+</method>
 <method name="setMaximumSize"
  return="long"
  abstract="false"
@@ -56034,6 +71047,17 @@
  visibility="public"
 >
 </field>
+<field name="MAX_SQL_CACHE_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="100"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="NO_LOCALIZED_COLLATORS"
  type="int"
  transient="false"
@@ -56133,6 +71157,60 @@
 </parameter>
 </constructor>
 </class>
+<class name="SQLiteDatabaseLockedException"
+ extends="android.database.sqlite.SQLiteException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SQLiteDatabaseLockedException"
+ type="android.database.sqlite.SQLiteDatabaseLockedException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SQLiteDatabaseLockedException"
+ type="android.database.sqlite.SQLiteDatabaseLockedException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="error" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="SQLiteDatatypeMismatchException"
+ extends="android.database.sqlite.SQLiteException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SQLiteDatatypeMismatchException"
+ type="android.database.sqlite.SQLiteDatatypeMismatchException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SQLiteDatatypeMismatchException"
+ type="android.database.sqlite.SQLiteDatatypeMismatchException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="error" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
 <class name="SQLiteDiskIOException"
  extends="android.database.sqlite.SQLiteException"
  abstract="false"
@@ -56292,6 +71370,24 @@
 <parameter name="version" type="int">
 </parameter>
 </constructor>
+<constructor name="SQLiteOpenHelper"
+ type="android.database.sqlite.SQLiteOpenHelper"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="factory" type="android.database.sqlite.SQLiteDatabase.CursorFactory">
+</parameter>
+<parameter name="version" type="int">
+</parameter>
+<parameter name="errorHandler" type="android.database.DatabaseErrorHandler">
+</parameter>
+</constructor>
 <method name="close"
  return="void"
  abstract="false"
@@ -56338,6 +71434,23 @@
 <parameter name="db" type="android.database.sqlite.SQLiteDatabase">
 </parameter>
 </method>
+<method name="onDowngrade"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="db" type="android.database.sqlite.SQLiteDatabase">
+</parameter>
+<parameter name="oldVersion" type="int">
+</parameter>
+<parameter name="newVersion" type="int">
+</parameter>
+</method>
 <method name="onOpen"
  return="void"
  abstract="false"
@@ -56369,6 +71482,33 @@
 </parameter>
 </method>
 </class>
+<class name="SQLiteOutOfMemoryException"
+ extends="android.database.sqlite.SQLiteException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SQLiteOutOfMemoryException"
+ type="android.database.sqlite.SQLiteOutOfMemoryException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SQLiteOutOfMemoryException"
+ type="android.database.sqlite.SQLiteOutOfMemoryException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="error" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
 <class name="SQLiteProgram"
  extends="android.database.sqlite.SQLiteClosable"
  abstract="true"
@@ -56377,6 +71517,19 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="bindAllArgsAsStrings"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bindArgs" type="java.lang.String[]">
+</parameter>
+</method>
 <method name="bindBlob"
  return="void"
  abstract="false"
@@ -56494,7 +71647,7 @@
  synchronized="false"
  static="false"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -56717,6 +71870,29 @@
 </parameter>
 <parameter name="selection" type="java.lang.String">
 </parameter>
+<parameter name="groupBy" type="java.lang.String">
+</parameter>
+<parameter name="having" type="java.lang.String">
+</parameter>
+<parameter name="sortOrder" type="java.lang.String">
+</parameter>
+<parameter name="limit" type="java.lang.String">
+</parameter>
+</method>
+<method name="buildQuery"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="projectionIn" type="java.lang.String[]">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
 <parameter name="selectionArgs" type="java.lang.String[]">
 </parameter>
 <parameter name="groupBy" type="java.lang.String">
@@ -56794,6 +71970,33 @@
 </parameter>
 <parameter name="selection" type="java.lang.String">
 </parameter>
+<parameter name="groupBy" type="java.lang.String">
+</parameter>
+<parameter name="having" type="java.lang.String">
+</parameter>
+</method>
+<method name="buildUnionSubQuery"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="typeDiscriminatorColumn" type="java.lang.String">
+</parameter>
+<parameter name="unionColumns" type="java.lang.String[]">
+</parameter>
+<parameter name="columnsPresentInTable" type="java.util.Set&lt;java.lang.String&gt;">
+</parameter>
+<parameter name="computedColumnsOffset" type="int">
+</parameter>
+<parameter name="typeDiscriminatorValue" type="java.lang.String">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
 <parameter name="selectionArgs" type="java.lang.String[]">
 </parameter>
 <parameter name="groupBy" type="java.lang.String">
@@ -56917,6 +72120,33 @@
 </parameter>
 </method>
 </class>
+<class name="SQLiteReadOnlyDatabaseException"
+ extends="android.database.sqlite.SQLiteException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SQLiteReadOnlyDatabaseException"
+ type="android.database.sqlite.SQLiteReadOnlyDatabaseException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SQLiteReadOnlyDatabaseException"
+ type="android.database.sqlite.SQLiteReadOnlyDatabaseException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="error" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
 <class name="SQLiteStatement"
  extends="android.database.sqlite.SQLiteProgram"
  abstract="false"
@@ -56947,6 +72177,28 @@
  visibility="public"
 >
 </method>
+<method name="executeUpdateDelete"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="simpleQueryForBlobFileDescriptor"
+ return="android.os.ParcelFileDescriptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="simpleQueryForLong"
  return="long"
  abstract="false"
@@ -56970,6 +72222,33 @@
 >
 </method>
 </class>
+<class name="SQLiteTableLockedException"
+ extends="android.database.sqlite.SQLiteException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SQLiteTableLockedException"
+ type="android.database.sqlite.SQLiteTableLockedException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SQLiteTableLockedException"
+ type="android.database.sqlite.SQLiteTableLockedException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="error" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
 <interface name="SQLiteTransactionListener"
  abstract="true"
  static="false"
@@ -57012,6 +72291,1928 @@
 </method>
 </interface>
 </package>
+<package name="android.drm"
+>
+<class name="DrmConvertedStatus"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmConvertedStatus"
+ type="android.drm.DrmConvertedStatus"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="_statusCode" type="int">
+</parameter>
+<parameter name="_convertedData" type="byte[]">
+</parameter>
+<parameter name="_offset" type="int">
+</parameter>
+</constructor>
+<field name="STATUS_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_INPUTDATA_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_OK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="convertedData"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="offset"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="statusCode"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="DrmErrorEvent"
+ extends="android.drm.DrmEvent"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmErrorEvent"
+ type="android.drm.DrmErrorEvent"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uniqueId" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<field name="TYPE_NOT_SUPPORTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2003"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_NO_INTERNET_CONNECTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2005"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_OUT_OF_MEMORY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2004"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_PROCESS_DRM_INFO_FAILED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2006"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_REMOVE_ALL_RIGHTS_FAILED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2007"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_RIGHTS_NOT_INSTALLED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2001"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_RIGHTS_RENEWAL_NOT_ALLOWED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2002"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="DrmEvent"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmEvent"
+ type="android.drm.DrmEvent"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="uniqueId" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<method name="getMessage"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUniqueId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="DRM_INFO_STATUS_OBJECT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;drm_info_status_object&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_ALL_RIGHTS_REMOVED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1001"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_DRM_INFO_PROCESSED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1002"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="DrmInfo"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmInfo"
+ type="android.drm.DrmInfo"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="infoType" type="int">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="DrmInfo"
+ type="android.drm.DrmInfo"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="infoType" type="int">
+</parameter>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</constructor>
+<method name="get"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.String">
+</parameter>
+</method>
+<method name="getData"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInfoType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMimeType"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="iterator"
+ return="java.util.Iterator&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="keyIterator"
+ return="java.util.Iterator&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="put"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.String">
+</parameter>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+</class>
+<class name="DrmInfoEvent"
+ extends="android.drm.DrmEvent"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmInfoEvent"
+ type="android.drm.DrmInfoEvent"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uniqueId" type="int">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+<field name="TYPE_ACCOUNT_ALREADY_REGISTERED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_REMOVE_RIGHTS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_RIGHTS_INSTALLED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_WAIT_FOR_RIGHTS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="DrmInfoRequest"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmInfoRequest"
+ type="android.drm.DrmInfoRequest"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="infoType" type="int">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</constructor>
+<method name="get"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.String">
+</parameter>
+</method>
+<method name="getInfoType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMimeType"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="iterator"
+ return="java.util.Iterator&lt;java.lang.Object&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="keyIterator"
+ return="java.util.Iterator&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="put"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.String">
+</parameter>
+<parameter name="value" type="java.lang.Object">
+</parameter>
+</method>
+<field name="ACCOUNT_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;account_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SUBSCRIPTION_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;subscription_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_REGISTRATION_INFO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_RIGHTS_ACQUISITION_INFO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_RIGHTS_ACQUISITION_PROGRESS_INFO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_UNREGISTRATION_INFO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="DrmInfoStatus"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmInfoStatus"
+ type="android.drm.DrmInfoStatus"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="_statusCode" type="int">
+</parameter>
+<parameter name="_infoType" type="int">
+</parameter>
+<parameter name="_data" type="android.drm.ProcessedData">
+</parameter>
+<parameter name="_mimeType" type="java.lang.String">
+</parameter>
+</constructor>
+<field name="STATUS_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_OK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="data"
+ type="android.drm.ProcessedData"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="infoType"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mimeType"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="statusCode"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="DrmManagerClient"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmManagerClient"
+ type="android.drm.DrmManagerClient"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<method name="acquireDrmInfo"
+ return="android.drm.DrmInfo"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="drmInfoRequest" type="android.drm.DrmInfoRequest">
+</parameter>
+</method>
+<method name="acquireRights"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="drmInfoRequest" type="android.drm.DrmInfoRequest">
+</parameter>
+</method>
+<method name="canHandle"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</method>
+<method name="canHandle"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</method>
+<method name="checkRightsStatus"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+</method>
+<method name="checkRightsStatus"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="checkRightsStatus"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="action" type="int">
+</parameter>
+</method>
+<method name="checkRightsStatus"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="action" type="int">
+</parameter>
+</method>
+<method name="closeConvertSession"
+ return="android.drm.DrmConvertedStatus"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="convertId" type="int">
+</parameter>
+</method>
+<method name="convertData"
+ return="android.drm.DrmConvertedStatus"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="convertId" type="int">
+</parameter>
+<parameter name="inputData" type="byte[]">
+</parameter>
+</method>
+<method name="getAvailableDrmEngines"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getConstraints"
+ return="android.content.ContentValues"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="action" type="int">
+</parameter>
+</method>
+<method name="getConstraints"
+ return="android.content.ContentValues"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="action" type="int">
+</parameter>
+</method>
+<method name="getDrmObjectType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</method>
+<method name="getDrmObjectType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</method>
+<method name="getMetadata"
+ return="android.content.ContentValues"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+</method>
+<method name="getMetadata"
+ return="android.content.ContentValues"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="getOriginalMimeType"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+</method>
+<method name="getOriginalMimeType"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="openConvertSession"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</method>
+<method name="processDrmInfo"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="drmInfo" type="android.drm.DrmInfo">
+</parameter>
+</method>
+<method name="removeAllRights"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="removeRights"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+</method>
+<method name="removeRights"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="saveRights"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="drmRights" type="android.drm.DrmRights">
+</parameter>
+<parameter name="rightsPath" type="java.lang.String">
+</parameter>
+<parameter name="contentPath" type="java.lang.String">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="setOnErrorListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="errorListener" type="android.drm.DrmManagerClient.OnErrorListener">
+</parameter>
+</method>
+<method name="setOnEventListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="eventListener" type="android.drm.DrmManagerClient.OnEventListener">
+</parameter>
+</method>
+<method name="setOnInfoListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="infoListener" type="android.drm.DrmManagerClient.OnInfoListener">
+</parameter>
+</method>
+<field name="ERROR_NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-2000"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="DrmManagerClient.OnErrorListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onError"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="client" type="android.drm.DrmManagerClient">
+</parameter>
+<parameter name="event" type="android.drm.DrmErrorEvent">
+</parameter>
+</method>
+</interface>
+<interface name="DrmManagerClient.OnEventListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onEvent"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="client" type="android.drm.DrmManagerClient">
+</parameter>
+<parameter name="event" type="android.drm.DrmEvent">
+</parameter>
+<parameter name="attributes" type="java.util.HashMap&lt;java.lang.String, java.lang.Object&gt;">
+</parameter>
+</method>
+</interface>
+<interface name="DrmManagerClient.OnInfoListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onInfo"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="client" type="android.drm.DrmManagerClient">
+</parameter>
+<parameter name="event" type="android.drm.DrmInfoEvent">
+</parameter>
+</method>
+</interface>
+<class name="DrmRights"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmRights"
+ type="android.drm.DrmRights"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rightsFilePath" type="java.lang.String">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="DrmRights"
+ type="android.drm.DrmRights"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rightsFilePath" type="java.lang.String">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+<parameter name="accountId" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="DrmRights"
+ type="android.drm.DrmRights"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rightsFilePath" type="java.lang.String">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+<parameter name="accountId" type="java.lang.String">
+</parameter>
+<parameter name="subscriptionId" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="DrmRights"
+ type="android.drm.DrmRights"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rightsFile" type="java.io.File">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="DrmRights"
+ type="android.drm.DrmRights"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="android.drm.ProcessedData">
+</parameter>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</constructor>
+<method name="getAccountId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getData"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMimeType"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSubscriptionId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="DrmStore"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmStore"
+ type="android.drm.DrmStore"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+</class>
+<class name="DrmStore.Action"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmStore.Action"
+ type="android.drm.DrmStore.Action"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="DEFAULT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISPLAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXECUTE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OUTPUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PLAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PREVIEW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RINGTONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TRANSFER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="DrmStore.ConstraintsColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="EXTENDED_METADATA"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;extended_metadata&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LICENSE_AVAILABLE_TIME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;license_available_time&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LICENSE_EXPIRY_TIME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;license_expiry_time&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LICENSE_START_TIME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;license_start_time&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MAX_REPEAT_COUNT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;max_repeat_count&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="REMAINING_REPEAT_COUNT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;remaining_repeat_count&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
+<class name="DrmStore.DrmObjectType"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmStore.DrmObjectType"
+ type="android.drm.DrmStore.DrmObjectType"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="CONTENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RIGHTS_OBJECT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TRIGGER_OBJECT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="DrmStore.Playback"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmStore.Playback"
+ type="android.drm.DrmStore.Playback"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="PAUSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RESUME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="START"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STOP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="DrmStore.RightsStatus"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmStore.RightsStatus"
+ type="android.drm.DrmStore.RightsStatus"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="RIGHTS_EXPIRED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RIGHTS_INVALID"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RIGHTS_NOT_ACQUIRED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RIGHTS_VALID"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="DrmSupportInfo"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmSupportInfo"
+ type="android.drm.DrmSupportInfo"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addFileSuffix"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fileSuffix" type="java.lang.String">
+</parameter>
+</method>
+<method name="addMimeType"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</method>
+<method name="getDescriprition"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFileSuffixIterator"
+ return="java.util.Iterator&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMimeTypeIterator"
+ return="java.util.Iterator&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setDescription"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="description" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="DrmUtils"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DrmUtils"
+ type="android.drm.DrmUtils"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getExtendedMetadataParser"
+ return="android.drm.DrmUtils.ExtendedMetadataParser"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="extendedMetadata" type="byte[]">
+</parameter>
+</method>
+</class>
+<class name="DrmUtils.ExtendedMetadataParser"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.String">
+</parameter>
+</method>
+<method name="iterator"
+ return="java.util.Iterator&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="keyIterator"
+ return="java.util.Iterator&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProcessedData"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getAccountId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getData"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSubscriptionId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+</package>
 <package name="android.gesture"
 >
 <class name="Gesture"
@@ -59774,6 +76975,16 @@
  visibility="public"
 >
 </method>
+<field name="inBitmap"
+ type="android.graphics.Bitmap"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="inDensity"
  type="int"
  transient="false"
@@ -59814,6 +77025,16 @@
  visibility="public"
 >
 </field>
+<field name="inPreferQualityOverSpeed"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="inPreferredConfig"
  type="android.graphics.Bitmap.Config"
  transient="false"
@@ -59926,6 +77147,146 @@
 >
 </field>
 </class>
+<class name="BitmapRegionDecoder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="decodeRegion"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rect" type="android.graphics.Rect">
+</parameter>
+<parameter name="options" type="android.graphics.BitmapFactory.Options">
+</parameter>
+</method>
+<method name="getHeight"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getWidth"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isRecycled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="newInstance"
+ return="android.graphics.BitmapRegionDecoder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+<parameter name="isShareable" type="boolean">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="newInstance"
+ return="android.graphics.BitmapRegionDecoder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="isShareable" type="boolean">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="newInstance"
+ return="android.graphics.BitmapRegionDecoder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="is" type="java.io.InputStream">
+</parameter>
+<parameter name="isShareable" type="boolean">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="newInstance"
+ return="android.graphics.BitmapRegionDecoder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pathName" type="java.lang.String">
+</parameter>
+<parameter name="isShareable" type="boolean">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="recycle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
 <class name="BitmapShader"
  extends="android.graphics.Shader"
  abstract="false"
@@ -60940,7 +78301,7 @@
 <method name="drawText"
  return="void"
  abstract="false"
- native="true"
+ native="false"
  synchronized="false"
  static="false"
  final="false"
@@ -61129,17 +78490,6 @@
  visibility="public"
 >
 </method>
-<method name="getGL"
- return="javax.microedition.khronos.opengles.GL"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getHeight"
  return="int"
  abstract="false"
@@ -61197,6 +78547,17 @@
  visibility="public"
 >
 </method>
+<method name="isHardwareAccelerated"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isOpaque"
  return="boolean"
  abstract="false"
@@ -64900,7 +82261,7 @@
 <method name="setShadowLayer"
  return="void"
  abstract="false"
- native="true"
+ native="false"
  synchronized="false"
  static="false"
  final="false"
@@ -68852,6 +86213,110 @@
 </parameter>
 </constructor>
 </class>
+<class name="SurfaceTexture"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SurfaceTexture"
+ type="android.graphics.SurfaceTexture"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="texName" type="int">
+</parameter>
+</constructor>
+<method name="getTransformMatrix"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mtx" type="float[]">
+</parameter>
+</method>
+<method name="setOnFrameAvailableListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="l" type="android.graphics.SurfaceTexture.OnFrameAvailableListener">
+</parameter>
+</method>
+<method name="updateTexImage"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="SurfaceTexture.OnFrameAvailableListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onFrameAvailable"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="surfaceTexture" type="android.graphics.SurfaceTexture">
+</parameter>
+</method>
+</interface>
+<class name="SurfaceTexture.OutOfResourcesException"
+ extends="java.lang.Exception"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SurfaceTexture.OutOfResourcesException"
+ type="android.graphics.SurfaceTexture.OutOfResourcesException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SurfaceTexture.OutOfResourcesException"
+ type="android.graphics.SurfaceTexture.OutOfResourcesException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
 <class name="SweepGradient"
  extends="android.graphics.Shader"
  abstract="false"
@@ -69921,6 +87386,17 @@
  visibility="public"
 >
 </method>
+<method name="getColor"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getOpacity"
  return="int"
  abstract="false"
@@ -69945,6 +87421,19 @@
 <parameter name="alpha" type="int">
 </parameter>
 </method>
+<method name="setColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="color" type="int">
+</parameter>
+</method>
 <method name="setColorFilter"
  return="void"
  abstract="false"
@@ -70142,6 +87631,17 @@
  visibility="public"
 >
 </method>
+<method name="getCallback"
+ return="android.graphics.drawable.Drawable.Callback"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getChangingConfigurations"
  return="int"
  abstract="false"
@@ -70330,6 +87830,17 @@
  visibility="public"
 >
 </method>
+<method name="jumpToCurrentState"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="mutate"
  return="android.graphics.drawable.Drawable"
  abstract="false"
@@ -70819,6 +88330,32 @@
 <parameter name="state" type="android.graphics.drawable.DrawableContainer.DrawableContainerState">
 </parameter>
 </method>
+<method name="setEnterFadeDuration"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ms" type="int">
+</parameter>
+</method>
+<method name="setExitFadeDuration"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ms" type="int">
+</parameter>
+</method>
 <method name="unscheduleDrawable"
  return="void"
  abstract="false"
@@ -70867,6 +88404,17 @@
  visibility="public"
 >
 </method>
+<method name="computeConstantSize"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
 <method name="getChangingConfigurations"
  return="int"
  abstract="false"
@@ -70955,6 +88503,28 @@
  visibility="public"
 >
 </method>
+<method name="getEnterFadeDuration"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExitFadeDuration"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getOpacity"
  return="int"
  abstract="false"
@@ -71016,6 +88586,32 @@
 <parameter name="constant" type="boolean">
 </parameter>
 </method>
+<method name="setEnterFadeDuration"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="duration" type="int">
+</parameter>
+</method>
+<method name="setExitFadeDuration"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="duration" type="int">
+</parameter>
+</method>
 <method name="setVariablePadding"
  return="void"
  abstract="false"
@@ -71711,6 +89307,19 @@
 <parameter name="b" type="int">
 </parameter>
 </method>
+<method name="setOpacity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="opacity" type="int">
+</parameter>
+</method>
 <method name="unscheduleDrawable"
  return="void"
  abstract="false"
@@ -73198,6 +90807,19 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="setPreviewTexture"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="surfaceTexture" type="android.graphics.SurfaceTexture">
+</parameter>
+</method>
 <method name="setZoomChangeListener"
  return="void"
  abstract="false"
@@ -73691,6 +91313,17 @@
  visibility="public"
 >
 </method>
+<method name="getPreferredPreviewSizeForVideo"
+ return="android.hardware.Camera.Size"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getPreviewFormat"
  return="int"
  abstract="false"
@@ -73880,6 +91513,17 @@
  visibility="public"
 >
 </method>
+<method name="getSupportedVideoSizes"
+ return="java.util.List&lt;android.hardware.Camera.Size&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getSupportedWhiteBalance"
  return="java.util.List&lt;java.lang.String&gt;"
  abstract="false"
@@ -77013,6 +94657,19 @@
  visibility="public"
 >
 </method>
+<method name="onCurrentInputMethodSubtypeChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="newSubtype" type="android.view.inputmethod.InputMethodSubtype">
+</parameter>
+</method>
 <method name="onDisplayCompletions"
  return="void"
  abstract="false"
@@ -77616,6 +95273,19 @@
 <parameter name="binding" type="android.view.inputmethod.InputBinding">
 </parameter>
 </method>
+<method name="changeInputMethodSubtype"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="subtype" type="android.view.inputmethod.InputMethodSubtype">
+</parameter>
+</method>
 <method name="hideSoftInput"
  return="void"
  abstract="false"
@@ -77923,6 +95593,24 @@
 </parameter>
 <parameter name="modeId" type="int">
 </parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+</constructor>
+<constructor name="Keyboard"
+ type="android.inputmethodservice.Keyboard"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="xmlLayoutResId" type="int">
+</parameter>
+<parameter name="modeId" type="int">
+</parameter>
 </constructor>
 <constructor name="Keyboard"
  type="android.inputmethodservice.Keyboard"
@@ -83218,6 +100906,17 @@
  visibility="public"
 >
 </field>
+<field name="MODE_IN_COMMUNICATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MODE_NORMAL"
  type="int"
  transient="false"
@@ -84697,6 +102396,78 @@
 <parameter name="quality" type="int">
 </parameter>
 </method>
+<method name="hasProfile"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="quality" type="int">
+</parameter>
+</method>
+<method name="hasProfile"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cameraId" type="int">
+</parameter>
+<parameter name="quality" type="int">
+</parameter>
+</method>
+<field name="QUALITY_1080P"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="QUALITY_480P"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="QUALITY_720P"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="QUALITY_CIF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="QUALITY_HIGH"
  type="int"
  transient="false"
@@ -84719,6 +102490,94 @@
  visibility="public"
 >
 </field>
+<field name="QUALITY_QCIF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="QUALITY_TIME_LAPSE_1080P"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1006"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="QUALITY_TIME_LAPSE_480P"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1004"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="QUALITY_TIME_LAPSE_720P"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1005"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="QUALITY_TIME_LAPSE_CIF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1003"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="QUALITY_TIME_LAPSE_HIGH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1001"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="QUALITY_TIME_LAPSE_LOW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1000"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="QUALITY_TIME_LAPSE_QCIF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1002"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="audioBitRate"
  type="int"
  transient="false"
@@ -85156,6 +103015,17 @@
  visibility="public"
 >
 </field>
+<field name="TAG_APERTURE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;FNumber&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TAG_DATETIME"
  type="java.lang.String"
  transient="false"
@@ -85167,6 +103037,17 @@
  visibility="public"
 >
 </field>
+<field name="TAG_EXPOSURE_TIME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;ExposureTime&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TAG_FLASH"
  type="java.lang.String"
  transient="false"
@@ -85310,6 +103191,17 @@
  visibility="public"
 >
 </field>
+<field name="TAG_ISO"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;ISOSpeedRatings&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TAG_MAKE"
  type="java.lang.String"
  transient="false"
@@ -85853,6 +103745,385 @@
 </parameter>
 </method>
 </interface>
+<class name="MediaMetadataRetriever"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="MediaMetadataRetriever"
+ type="android.media.MediaMetadataRetriever"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="extractMetadata"
+ return="java.lang.String"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+</method>
+<method name="getEmbeddedPicture"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFrameAtTime"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="timeUs" type="long">
+</parameter>
+<parameter name="option" type="int">
+</parameter>
+</method>
+<method name="getFrameAtTime"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="timeUs" type="long">
+</parameter>
+</method>
+<method name="getFrameAtTime"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="release"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setDataSource"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="setDataSource"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="offset" type="long">
+</parameter>
+<parameter name="length" type="long">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="setDataSource"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="setDataSource"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="SecurityException" type="java.lang.SecurityException">
+</exception>
+</method>
+<field name="METADATA_KEY_ALBUM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_ALBUMARTIST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="13"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_ARTIST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_AUTHOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_CD_TRACK_NUMBER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_COMPILATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="15"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_COMPOSER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_DATE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_DISC_NUMBER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="14"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_DURATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_GENRE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_MIMETYPE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="12"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_NUM_TRACKS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_TITLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_WRITER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="11"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_YEAR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OPTION_CLOSEST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OPTION_CLOSEST_SYNC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OPTION_NEXT_SYNC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OPTION_PREVIOUS_SYNC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="MediaPlayer"
  extends="java.lang.Object"
  abstract="false"
@@ -86815,6 +105086,32 @@
 <exception name="IllegalStateException" type="java.lang.IllegalStateException">
 </exception>
 </method>
+<method name="setAuxiliaryOutputFile"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+</method>
+<method name="setAuxiliaryOutputFile"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+</method>
 <method name="setCamera"
  return="void"
  abstract="false"
@@ -86828,6 +105125,19 @@
 <parameter name="c" type="android.hardware.Camera">
 </parameter>
 </method>
+<method name="setCaptureRate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fps" type="double">
+</parameter>
+</method>
 <method name="setMaxDuration"
  return="void"
  abstract="false"
@@ -87122,6 +105432,17 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<field name="AAC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="AMR_NB"
  type="int"
  transient="false"
@@ -87133,6 +105454,17 @@
  visibility="public"
 >
 </field>
+<field name="AMR_WB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="DEFAULT"
  type="int"
  transient="false"
@@ -87197,6 +105529,17 @@
  visibility="public"
 >
 </field>
+<field name="VOICE_COMMUNICATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="VOICE_DOWNLINK"
  type="int"
  transient="false"
@@ -87289,6 +105632,28 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<field name="AMR_NB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AMR_WB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="DEFAULT"
  type="int"
  transient="false"
@@ -93725,7 +112090,7 @@
  synchronized="false"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -93736,7 +112101,7 @@
  synchronized="false"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -93747,7 +112112,7 @@
  synchronized="false"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="ctx" type="android.content.Context">
@@ -93760,7 +112125,7 @@
  synchronized="false"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="ctx" type="android.content.Context">
@@ -94265,6 +112630,21 @@
  visibility="public"
 >
 </method>
+<method name="getBooleanQueryParameter"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.String">
+</parameter>
+<parameter name="defaultValue" type="boolean">
+</parameter>
+</method>
 <method name="getEncodedAuthority"
  return="java.lang.String"
  abstract="true"
@@ -94421,6 +112801,17 @@
 <parameter name="key" type="java.lang.String">
 </parameter>
 </method>
+<method name="getQueryParameterNames"
+ return="java.util.Set&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getQueryParameters"
  return="java.util.List&lt;java.lang.String&gt;"
  abstract="false"
@@ -94667,6 +113058,17 @@
  visibility="public"
 >
 </method>
+<method name="clearQuery"
+ return="android.net.Uri.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="encodedAuthority"
  return="android.net.Uri.Builder"
  abstract="false"
@@ -100110,6 +118512,19 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="context" type="android.content.Context">
+</parameter>
+</method>
+<method name="getDefaultAdapter"
+ return="android.nfc.NfcAdapter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
 </method>
 <method name="isEnabled"
  return="boolean"
@@ -100156,6 +118571,26 @@
 >
 </field>
 </class>
+<class name="NfcManager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getDefaultAdapter"
+ return="android.nfc.NfcAdapter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
 </package>
 <package name="android.opengl"
 >
@@ -119115,6 +137550,19 @@
  deprecated="not deprecated"
  visibility="protected"
 >
+<parameter name="result" type="Result">
+</parameter>
+</method>
+<method name="onCancelled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
 </method>
 <method name="onPostExecute"
  return="void"
@@ -119245,6 +137693,17 @@
  visibility="public"
 >
 </constructor>
+<field name="BATTERY_HEALTH_COLD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="BATTERY_HEALTH_DEAD"
  type="int"
  transient="false"
@@ -120172,6 +138631,17 @@
  visibility="public"
 >
 </field>
+<field name="HONEYCOMB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10000"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="Bundle"
  extends="java.lang.Object"
@@ -120457,6 +138927,17 @@
 <parameter name="key" type="java.lang.String">
 </parameter>
 </method>
+<method name="getClassLoader"
+ return="java.lang.ClassLoader"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getDouble"
  return="double"
  abstract="false"
@@ -121673,7 +140154,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -121684,7 +140165,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -121695,7 +140176,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -121706,7 +140187,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -121829,7 +140310,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -121840,7 +140321,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -121941,7 +140422,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -121952,7 +140433,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -121963,7 +140444,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -121974,7 +140455,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -122040,7 +140521,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -122051,7 +140532,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -122073,7 +140554,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="limit" type="int">
@@ -122086,7 +140567,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="limit" type="int">
@@ -122628,6 +141109,39 @@
 <parameter name="tag" type="java.lang.String">
 </parameter>
 </method>
+<field name="ACTION_DROPBOX_ENTRY_ADDED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.DROPBOX_ENTRY_ADDED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_TAG"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;tag&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_TIME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;time&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="IS_EMPTY"
  type="int"
  transient="false"
@@ -122941,6 +141455,17 @@
  visibility="public"
 >
 </method>
+<method name="isExternalStorageEmulated"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isExternalStorageRemovable"
  return="boolean"
  abstract="false"
@@ -124904,6 +143429,23 @@
 >
 </field>
 </class>
+<class name="NetworkOnMainThreadException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="NetworkOnMainThreadException"
+ type="android.os.NetworkOnMainThreadException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+</class>
 <class name="Parcel"
  extends="java.lang.Object"
  abstract="false"
@@ -127860,6 +146402,19 @@
  visibility="public"
 >
 </method>
+<method name="noteSlowCall"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
 <method name="setThreadPolicy"
  return="void"
  abstract="false"
@@ -127954,6 +146509,17 @@
  visibility="public"
 >
 </method>
+<method name="detectCustomSlowCalls"
+ return="android.os.StrictMode.ThreadPolicy.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="detectDiskReads"
  return="android.os.StrictMode.ThreadPolicy.Builder"
  abstract="false"
@@ -127998,6 +146564,17 @@
  visibility="public"
 >
 </method>
+<method name="penaltyDeathOnNetwork"
+ return="android.os.StrictMode.ThreadPolicy.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="penaltyDialog"
  return="android.os.StrictMode.ThreadPolicy.Builder"
  abstract="false"
@@ -128020,6 +146597,17 @@
  visibility="public"
 >
 </method>
+<method name="penaltyFlashScreen"
+ return="android.os.StrictMode.ThreadPolicy.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="penaltyLog"
  return="android.os.StrictMode.ThreadPolicy.Builder"
  abstract="false"
@@ -128042,6 +146630,17 @@
  visibility="public"
 >
 </method>
+<method name="permitCustomSlowCalls"
+ return="android.os.StrictMode.ThreadPolicy.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="permitDiskReads"
  return="android.os.StrictMode.ThreadPolicy.Builder"
  abstract="false"
@@ -128133,6 +146732,17 @@
  visibility="public"
 >
 </method>
+<method name="detectLeakedClosableObjects"
+ return="android.os.StrictMode.VmPolicy.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="detectLeakedSqlLiteObjects"
  return="android.os.StrictMode.VmPolicy.Builder"
  abstract="false"
@@ -128373,6 +146983,17 @@
  visibility="public"
 >
 </method>
+<method name="hasVibrator"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="vibrate"
  return="void"
  abstract="false"
@@ -128653,6 +147274,53 @@
 >
 </field>
 </class>
+<class name="StorageEventListener"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="StorageEventListener"
+ type="android.os.storage.StorageEventListener"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="onStorageStateChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="oldState" type="java.lang.String">
+</parameter>
+<parameter name="newState" type="java.lang.String">
+</parameter>
+</method>
+<method name="onUsbMassStorageConnectionChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="connected" type="boolean">
+</parameter>
+</method>
+</class>
 <class name="StorageManager"
  extends="java.lang.Object"
  abstract="false"
@@ -128661,6 +147329,28 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="disableUsbMassStorage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="enableUsbMassStorage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getMountedObbPath"
  return="java.lang.String"
  abstract="false"
@@ -128687,6 +147377,28 @@
 <parameter name="filename" type="java.lang.String">
 </parameter>
 </method>
+<method name="isUsbMassStorageConnected"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isUsbMassStorageEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="mountObb"
  return="boolean"
  abstract="false"
@@ -128704,6 +147416,19 @@
 <parameter name="listener" type="android.os.storage.OnObbStateChangeListener">
 </parameter>
 </method>
+<method name="registerListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.os.storage.StorageEventListener">
+</parameter>
+</method>
 <method name="unmountObb"
  return="boolean"
  abstract="false"
@@ -128721,6 +147446,124 @@
 <parameter name="listener" type="android.os.storage.OnObbStateChangeListener">
 </parameter>
 </method>
+<method name="unregisterListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.os.storage.StorageEventListener">
+</parameter>
+</method>
+</class>
+<class name="StorageResultCode"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="StorageResultCode"
+ type="android.os.storage.StorageResultCode"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="OperationFailedInternalError"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OperationFailedMediaBlank"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OperationFailedMediaCorrupt"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OperationFailedNoMedia"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OperationFailedStorageBusy"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OperationFailedStorageMounted"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OperationFailedStorageNotMounted"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OperationSucceeded"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 </package>
 <package name="android.preference"
@@ -129516,6 +148359,148 @@
 </parameter>
 </method>
 </class>
+<class name="MultiSelectListPreference"
+ extends="android.preference.DialogPreference"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="MultiSelectListPreference"
+ type="android.preference.MultiSelectListPreference"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="MultiSelectListPreference"
+ type="android.preference.MultiSelectListPreference"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<method name="findIndexOfValue"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.String">
+</parameter>
+</method>
+<method name="getEntries"
+ return="java.lang.CharSequence[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEntryValues"
+ return="java.lang.CharSequence[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getValues"
+ return="java.util.Set&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setEntries"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entries" type="java.lang.CharSequence[]">
+</parameter>
+</method>
+<method name="setEntries"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entriesResId" type="int">
+</parameter>
+</method>
+<method name="setEntryValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entryValues" type="java.lang.CharSequence[]">
+</parameter>
+</method>
+<method name="setEntryValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entryValuesResId" type="int">
+</parameter>
+</method>
+<method name="setValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="values" type="java.util.Set&lt;java.lang.String&gt;">
+</parameter>
+</method>
+</class>
 <class name="Preference"
  extends="java.lang.Object"
  abstract="false"
@@ -129634,6 +148619,39 @@
  visibility="public"
 >
 </method>
+<method name="getExtras"
+ return="android.os.Bundle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFragment"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getIcon"
+ return="android.graphics.drawable.Drawable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getIntent"
  return="android.content.Intent"
  abstract="false"
@@ -130066,6 +149084,17 @@
 <parameter name="defaultValue" type="java.lang.Object">
 </parameter>
 </method>
+<method name="peekExtras"
+ return="android.os.Bundle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="persistBoolean"
  return="boolean"
  abstract="false"
@@ -130196,6 +149225,45 @@
 <parameter name="enabled" type="boolean">
 </parameter>
 </method>
+<method name="setFragment"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragment" type="java.lang.String">
+</parameter>
+</method>
+<method name="setIcon"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="icon" type="android.graphics.drawable.Drawable">
+</parameter>
+</method>
+<method name="setIcon"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="iconResId" type="int">
+</parameter>
+</method>
 <method name="setIntent"
  return="void"
  abstract="false"
@@ -130514,6 +149582,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.preference.PreferenceFragment.OnPreferenceStartFragmentCallback">
+</implements>
 <constructor name="PreferenceActivity"
  type="android.preference.PreferenceActivity"
  static="false"
@@ -130529,6 +149599,743 @@
  synchronized="false"
  static="false"
  final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="addPreferencesFromResource"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="preferencesResId" type="int">
+</parameter>
+</method>
+<method name="findPreference"
+ return="android.preference.Preference"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="finishPreferencePanel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="caller" type="android.app.Fragment">
+</parameter>
+<parameter name="resultCode" type="int">
+</parameter>
+<parameter name="resultData" type="android.content.Intent">
+</parameter>
+</method>
+<method name="getPreferenceManager"
+ return="android.preference.PreferenceManager"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPreferenceScreen"
+ return="android.preference.PreferenceScreen"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasHeaders"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="invalidateHeaders"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isMultiPane"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="loadHeadersFromResource"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resid" type="int">
+</parameter>
+<parameter name="target" type="java.util.List&lt;android.preference.PreferenceActivity.Header&gt;">
+</parameter>
+</method>
+<method name="onBuildHeaders"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="java.util.List&lt;android.preference.PreferenceActivity.Header&gt;">
+</parameter>
+</method>
+<method name="onGetInitialHeader"
+ return="android.preference.PreferenceActivity.Header"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onGetNewHeader"
+ return="android.preference.PreferenceActivity.Header"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onHeaderClick"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="header" type="android.preference.PreferenceActivity.Header">
+</parameter>
+<parameter name="position" type="int">
+</parameter>
+</method>
+<method name="onIsHidingHeaders"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onIsMultiPane"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onPreferenceStartFragment"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="caller" type="android.preference.PreferenceFragment">
+</parameter>
+<parameter name="pref" type="android.preference.Preference">
+</parameter>
+</method>
+<method name="onPreferenceTreeClick"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="preferenceScreen" type="android.preference.PreferenceScreen">
+</parameter>
+<parameter name="preference" type="android.preference.Preference">
+</parameter>
+</method>
+<method name="setListFooter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
+<method name="setParentTitle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+<parameter name="shortTitle" type="java.lang.CharSequence">
+</parameter>
+<parameter name="listener" type="android.view.View.OnClickListener">
+</parameter>
+</method>
+<method name="setPreferenceScreen"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="preferenceScreen" type="android.preference.PreferenceScreen">
+</parameter>
+</method>
+<method name="showBreadCrumbs"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+<parameter name="shortTitle" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="startPreferenceFragment"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+<parameter name="push" type="boolean">
+</parameter>
+</method>
+<method name="startPreferencePanel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragmentClass" type="java.lang.String">
+</parameter>
+<parameter name="args" type="android.os.Bundle">
+</parameter>
+<parameter name="titleRes" type="int">
+</parameter>
+<parameter name="titleText" type="java.lang.CharSequence">
+</parameter>
+<parameter name="resultTo" type="android.app.Fragment">
+</parameter>
+<parameter name="resultRequestCode" type="int">
+</parameter>
+</method>
+<method name="startWithFragment"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragmentName" type="java.lang.String">
+</parameter>
+<parameter name="args" type="android.os.Bundle">
+</parameter>
+<parameter name="resultTo" type="android.app.Fragment">
+</parameter>
+<parameter name="resultRequestCode" type="int">
+</parameter>
+</method>
+<method name="switchToHeader"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragmentName" type="java.lang.String">
+</parameter>
+<parameter name="args" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="switchToHeader"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="header" type="android.preference.PreferenceActivity.Header">
+</parameter>
+</method>
+<field name="EXTRA_NO_HEADERS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;:android:no_headers&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_SHOW_FRAGMENT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;:android:show_fragment&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_SHOW_FRAGMENT_ARGUMENTS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;:android:show_fragment_args&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="HEADER_ID_UNDEFINED"
+ type="long"
+ transient="false"
+ volatile="false"
+ value="-1L"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="PreferenceActivity.Header"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<constructor name="PreferenceActivity.Header"
+ type="android.preference.PreferenceActivity.Header"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBreadCrumbShortTitle"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+</method>
+<method name="getBreadCrumbTitle"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+</method>
+<method name="getSummary"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+</method>
+<method name="getTitle"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+</method>
+<method name="readFromParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="in" type="android.os.Parcel">
+</parameter>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="breadCrumbShortTitle"
+ type="java.lang.CharSequence"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="breadCrumbShortTitleRes"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="breadCrumbTitle"
+ type="java.lang.CharSequence"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="breadCrumbTitleRes"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="extras"
+ type="android.os.Bundle"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fragment"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fragmentArguments"
+ type="android.os.Bundle"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="iconRes"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="id"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="intent"
+ type="android.content.Intent"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="summary"
+ type="java.lang.CharSequence"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="summaryRes"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="title"
+ type="java.lang.CharSequence"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="titleRes"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="PreferenceCategory"
+ extends="android.preference.PreferenceGroup"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="PreferenceCategory"
+ type="android.preference.PreferenceCategory"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
+<constructor name="PreferenceCategory"
+ type="android.preference.PreferenceCategory"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="PreferenceCategory"
+ type="android.preference.PreferenceCategory"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+</class>
+<class name="PreferenceFragment"
+ extends="android.app.Fragment"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="PreferenceFragment"
+ type="android.preference.PreferenceFragment"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addPreferencesFromIntent"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -130612,51 +150419,29 @@
 </parameter>
 </method>
 </class>
-<class name="PreferenceCategory"
- extends="android.preference.PreferenceGroup"
- abstract="false"
+<interface name="PreferenceFragment.OnPreferenceStartFragmentCallback"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onPreferenceStartFragment"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<constructor name="PreferenceCategory"
- type="android.preference.PreferenceCategory"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
+<parameter name="caller" type="android.preference.PreferenceFragment">
 </parameter>
-<parameter name="attrs" type="android.util.AttributeSet">
+<parameter name="pref" type="android.preference.Preference">
 </parameter>
-<parameter name="defStyle" type="int">
-</parameter>
-</constructor>
-<constructor name="PreferenceCategory"
- type="android.preference.PreferenceCategory"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="attrs" type="android.util.AttributeSet">
-</parameter>
-</constructor>
-<constructor name="PreferenceCategory"
- type="android.preference.PreferenceCategory"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-</constructor>
-</class>
+</method>
+</interface>
 <class name="PreferenceGroup"
  extends="android.preference.Preference"
  abstract="true"
@@ -131410,6 +151195,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_SKIP_UI"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.extra.alarm.SKIP_UI&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <interface name="BaseColumns"
  abstract="true"
@@ -131617,9 +151413,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="c" type="android.content.Context">
+<parameter name="context" type="android.content.Context">
 </parameter>
-<parameter name="s" type="java.lang.String">
+<parameter name="string" type="java.lang.String">
 </parameter>
 </method>
 <method name="truncateHistory"
@@ -132003,7 +151799,7 @@
  value="&quot;url&quot;"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -135062,6 +154858,28 @@
  visibility="public"
 >
 </field>
+<field name="DIRECTORY_PARAM_KEY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;directory&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LIMIT_PARAM_KEY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;limit&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="ContactsContract.AggregationExceptions"
  extends="java.lang.Object"
@@ -135337,6 +155155,17 @@
 <parameter name="type" type="int">
 </parameter>
 </method>
+<field name="ADDRESS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data1&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="CONTENT_FILTER_URI"
  type="android.net.Uri"
  transient="false"
@@ -136467,6 +156296,36 @@
 </implements>
 <implements name="android.provider.ContactsContract.DataColumnsWithJoins">
 </implements>
+<method name="getTypeLabel"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="label" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="getTypeLabelResource"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="int">
+</parameter>
+</method>
 <field name="CONTENT_ITEM_TYPE"
  type="java.lang.String"
  transient="false"
@@ -137171,6 +157030,91 @@
 >
 </field>
 </class>
+<interface name="ContactsContract.ContactNameColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<field name="DISPLAY_NAME_ALTERNATIVE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;display_name_alt&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISPLAY_NAME_PRIMARY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;display_name&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISPLAY_NAME_SOURCE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;display_name_source&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHONETIC_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;phonetic_name&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHONETIC_NAME_STYLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;phonetic_name_style&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SORT_KEY_ALTERNATIVE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;sort_key_alt&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SORT_KEY_PRIMARY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;sort_key&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <interface name="ContactsContract.ContactOptionsColumns"
  abstract="true"
  static="true"
@@ -137241,6 +157185,17 @@
  deprecated="not deprecated"
  visibility="protected"
 >
+<field name="CONTACT_CHAT_CAPABILITY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;contact_chat_capability&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="CONTACT_PRESENCE"
  type="java.lang.String"
  transient="false"
@@ -137318,6 +157273,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.ContactNameColumns">
+</implements>
 <implements name="android.provider.ContactsContract.ContactOptionsColumns">
 </implements>
 <implements name="android.provider.ContactsContract.ContactStatusColumns">
@@ -137513,6 +157470,10 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.ContactOptionsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactStatusColumns">
+</implements>
 <implements name="android.provider.ContactsContract.ContactsColumns">
 </implements>
 <field name="CONTENT_DIRECTORY"
@@ -137551,6 +157512,68 @@
 >
 </field>
 </class>
+<class name="ContactsContract.Contacts.Entity"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.provider.BaseColumns">
+</implements>
+<implements name="android.provider.ContactsContract.BaseSyncColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactNameColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactOptionsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactStatusColumns">
+</implements>
+<implements name="android.provider.ContactsContract.ContactsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.DataColumns">
+</implements>
+<implements name="android.provider.ContactsContract.RawContactsColumns">
+</implements>
+<implements name="android.provider.ContactsContract.StatusColumns">
+</implements>
+<implements name="android.provider.ContactsContract.SyncColumns">
+</implements>
+<field name="CONTENT_DIRECTORY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;entities&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DATA_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RAW_CONTACT_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;raw_contact_id&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="ContactsContract.Contacts.Photo"
  extends="java.lang.Object"
  abstract="false"
@@ -137561,7 +157584,7 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
-<implements name="android.provider.ContactsContract.DataColumns">
+<implements name="android.provider.ContactsContract.DataColumnsWithJoins">
 </implements>
 <field name="CONTENT_DIRECTORY"
  type="java.lang.String"
@@ -137574,6 +157597,17 @@
  visibility="public"
 >
 </field>
+<field name="PHOTO"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data15&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <interface name="ContactsContract.ContactsColumns"
  abstract="true"
@@ -137637,6 +157671,28 @@
  visibility="public"
 >
 </field>
+<field name="PHOTO_THUMBNAIL_URI"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;photo_thumb_uri&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_URI"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;photo_uri&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </interface>
 <class name="ContactsContract.Data"
  extends="java.lang.Object"
@@ -137879,6 +157935,17 @@
  visibility="public"
 >
 </field>
+<field name="IS_READ_ONLY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;is_read_only&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="IS_SUPER_PRIMARY"
  type="java.lang.String"
  transient="false"
@@ -137966,6 +158033,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.ContactNameColumns">
+</implements>
 <implements name="android.provider.ContactsContract.ContactOptionsColumns">
 </implements>
 <implements name="android.provider.ContactsContract.ContactStatusColumns">
@@ -137979,6 +158048,441 @@
 <implements name="android.provider.ContactsContract.StatusColumns">
 </implements>
 </interface>
+<class name="ContactsContract.Directory"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.provider.BaseColumns">
+</implements>
+<method name="notifyDirectoryChange"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resolver" type="android.content.ContentResolver">
+</parameter>
+</method>
+<field name="ACCOUNT_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;accountName&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACCOUNT_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;accountType&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_ITEM_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;vnd.android.cursor.item/contact_directory&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;vnd.android.cursor.dir/contact_directories&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_URI"
+ type="android.net.Uri"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DEFAULT"
+ type="long"
+ transient="false"
+ volatile="false"
+ value="0L"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DIRECTORY_AUTHORITY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;authority&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISPLAY_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;displayName&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXPORT_SUPPORT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;exportSupport&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXPORT_SUPPORT_ANY_ACCOUNT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXPORT_SUPPORT_NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXPORT_SUPPORT_SAME_ACCOUNT_ONLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LOCAL_INVISIBLE"
+ type="long"
+ transient="false"
+ volatile="false"
+ value="1L"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PACKAGE_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;packageName&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_SUPPORT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;photoSupport&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_SUPPORT_FULL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_SUPPORT_FULL_SIZE_ONLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_SUPPORT_NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_SUPPORT_THUMBNAIL_ONLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHORTCUT_SUPPORT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;shortcutSupport&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHORTCUT_SUPPORT_DATA_ITEMS_ONLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHORTCUT_SUPPORT_FULL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHORTCUT_SUPPORT_NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_RESOURCE_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;typeResourceId&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="ContactsContract.DisplayNameSources"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="EMAIL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NICKNAME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORGANIZATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="30"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="20"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STRUCTURED_NAME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="40"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="UNDEFINED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
+<interface name="ContactsContract.FullNameStyle"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="CHINESE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CJK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="JAPANESE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KOREAN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="UNDEFINED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="WESTERN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.Groups"
  extends="java.lang.Object"
  abstract="false"
@@ -138056,6 +158560,17 @@
  deprecated="not deprecated"
  visibility="protected"
 >
+<field name="AUTO_ADD"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;auto_add&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="DELETED"
  type="java.lang.String"
  transient="false"
@@ -138067,6 +158582,28 @@
  visibility="public"
 >
 </field>
+<field name="FAVORITES"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;favorites&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GROUP_IS_READ_ONLY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;group_is_read_only&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="GROUP_VISIBLE"
  type="java.lang.String"
  transient="false"
@@ -138277,6 +158814,17 @@
  visibility="public"
 >
 </field>
+<field name="DATA"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;data&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EMAIL"
  type="java.lang.String"
  transient="false"
@@ -138621,6 +159169,58 @@
 >
 </field>
 </interface>
+<interface name="ContactsContract.PhoneticNameStyle"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="JAPANESE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KOREAN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PINYIN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="UNDEFINED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="ContactsContract.Presence"
  extends="android.provider.ContactsContract.StatusUpdates"
  abstract="false"
@@ -138803,6 +159403,8 @@
 >
 <implements name="android.provider.BaseColumns">
 </implements>
+<implements name="android.provider.ContactsContract.ContactNameColumns">
+</implements>
 <implements name="android.provider.ContactsContract.ContactOptionsColumns">
 </implements>
 <implements name="android.provider.ContactsContract.RawContactsColumns">
@@ -138866,7 +159468,7 @@
  value="1"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -139013,6 +159615,17 @@
  visibility="public"
 >
 </field>
+<field name="RAW_CONTACT_IS_READ_ONLY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;raw_contact_is_read_only&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </interface>
 <class name="ContactsContract.RawContactsEntity"
  extends="java.lang.Object"
@@ -139218,6 +159831,50 @@
  visibility="public"
 >
 </field>
+<field name="CAPABILITY_HAS_CAMERA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CAPABILITY_HAS_VIDEO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CAPABILITY_HAS_VOICE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CHAT_CAPABILITY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;chat_capability&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="DO_NOT_DISTURB"
  type="int"
  transient="false"
@@ -139779,6 +160436,17 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_MTP_SESSION_END"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.provider.action.MTP_SESSION_END&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_VIDEO_CAPTURE"
  type="java.lang.String"
  transient="false"
@@ -140660,6 +161328,21 @@
 <parameter name="volumeName" type="java.lang.String">
 </parameter>
 </method>
+<method name="getContentUriForAudioId"
+ return="android.net.Uri"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="volumeName" type="java.lang.String">
+</parameter>
+<parameter name="audioId" type="int">
+</parameter>
+</method>
 <field name="CONTENT_TYPE"
  type="java.lang.String"
  transient="false"
@@ -141178,6 +161861,160 @@
 >
 </field>
 </interface>
+<class name="MediaStore.Files"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="MediaStore.Files"
+ type="android.provider.MediaStore.Files"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getContentUri"
+ return="android.net.Uri"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="volumeName" type="java.lang.String">
+</parameter>
+</method>
+<method name="getContentUri"
+ return="android.net.Uri"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="volumeName" type="java.lang.String">
+</parameter>
+<parameter name="rowId" type="long">
+</parameter>
+</method>
+</class>
+<interface name="MediaStore.Files.FileColumns"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.provider.MediaStore.MediaColumns">
+</implements>
+<field name="MEDIA_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;media_type&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MEDIA_TYPE_AUDIO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MEDIA_TYPE_IMAGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MEDIA_TYPE_NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MEDIA_TYPE_PLAYLIST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MEDIA_TYPE_VIDEO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MIME_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;mime_type&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARENT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;parent&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TITLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;title&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 <class name="MediaStore.Images"
  extends="java.lang.Object"
  abstract="false"
@@ -142721,6 +163558,17 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_INPUT_METHOD_AND_SUBTYPE_ENABLER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.settings.INPUT_METHOD_AND_SUBTYPE_ENABLER&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_INPUT_METHOD_SETTINGS"
  type="java.lang.String"
  transient="false"
@@ -143427,6 +164275,17 @@
  visibility="public"
 >
 </field>
+<field name="INPUT_METHOD_SELECTOR_VISIBILITY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;input_method_selector_visibility&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="INSTALL_NON_MARKET_APPS"
  type="java.lang.String"
  transient="false"
@@ -143537,6 +164396,17 @@
  visibility="public"
 >
 </field>
+<field name="SELECTED_INPUT_METHOD_SUBTYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;selected_input_method_subtype&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SETTINGS_CLASSNAME"
  type="java.lang.String"
  transient="false"
@@ -144258,6 +165128,17 @@
  visibility="public"
 >
 </field>
+<field name="AUTO_TIME_ZONE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;auto_time_zone&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="BLUETOOTH_DISCOVERABILITY"
  type="java.lang.String"
  transient="false"
@@ -144756,7 +165637,7 @@
  value="&quot;show_web_suggestions&quot;"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -144870,6 +165751,17 @@
  visibility="public"
 >
 </field>
+<field name="USER_ROTATION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;user_rotation&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="USE_GOOGLE_MAIL"
  type="java.lang.String"
  transient="false"
@@ -145746,6 +166638,6877 @@
 </field>
 </class>
 </package>
+<package name="android.renderscript"
+>
+<class name="Allocation"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="copy1DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="int[]">
+</parameter>
+</method>
+<method name="copy1DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="short[]">
+</parameter>
+</method>
+<method name="copy1DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="byte[]">
+</parameter>
+</method>
+<method name="copy1DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="float[]">
+</parameter>
+</method>
+<method name="copy2DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+</method>
+<method name="copy2DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="data" type="short[]">
+</parameter>
+</method>
+<method name="copy2DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="data" type="int[]">
+</parameter>
+</method>
+<method name="copy2DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="data" type="float[]">
+</parameter>
+</method>
+<method name="copy2DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="data" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="copyFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="android.renderscript.BaseObj[]">
+</parameter>
+</method>
+<method name="copyFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="int[]">
+</parameter>
+</method>
+<method name="copyFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="short[]">
+</parameter>
+</method>
+<method name="copyFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="byte[]">
+</parameter>
+</method>
+<method name="copyFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="float[]">
+</parameter>
+</method>
+<method name="copyFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="copyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="copyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="byte[]">
+</parameter>
+</method>
+<method name="copyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="short[]">
+</parameter>
+</method>
+<method name="copyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="int[]">
+</parameter>
+</method>
+<method name="copyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="float[]">
+</parameter>
+</method>
+<method name="createCubemapFromBitmap"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createCubemapFromBitmap"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="createCubemapFromCubeFaces"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="xpos" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="xneg" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="ypos" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="yneg" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="zpos" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="zneg" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createCubemapFromCubeFaces"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="xpos" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="xneg" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="ypos" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="yneg" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="zpos" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="zneg" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="createFromBitmap"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createFromBitmap"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="createFromBitmapResource"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createFromBitmapResource"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="id" type="int">
+</parameter>
+</method>
+<method name="createFromString"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="str" type="java.lang.String">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createSized"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="e" type="android.renderscript.Element">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createSized"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="e" type="android.renderscript.Element">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+</method>
+<method name="createTyped"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="type" type="android.renderscript.Type">
+</parameter>
+<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createTyped"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="type" type="android.renderscript.Type">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createTyped"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="type" type="android.renderscript.Type">
+</parameter>
+</method>
+<method name="generateMipmaps"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="android.renderscript.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="resize"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dimX" type="int">
+</parameter>
+</method>
+<method name="syncAll"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="srcLocation" type="int">
+</parameter>
+</method>
+<field name="USAGE_GRAPHICS_CONSTANTS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="USAGE_GRAPHICS_TEXTURE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="USAGE_GRAPHICS_VERTEX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="USAGE_SCRIPT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Allocation.MipmapControl"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Allocation.MipmapControl"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Allocation.MipmapControl[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="AllocationAdapter"
+ extends="android.renderscript.Allocation"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="create2D"
+ return="android.renderscript.AllocationAdapter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="a" type="android.renderscript.Allocation">
+</parameter>
+</method>
+<method name="readData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="int[]">
+</parameter>
+</method>
+<method name="readData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="float[]">
+</parameter>
+</method>
+<method name="setFace"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cf" type="android.renderscript.Type.CubemapFace">
+</parameter>
+</method>
+<method name="setLOD"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lod" type="int">
+</parameter>
+</method>
+<method name="setY"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="y" type="int">
+</parameter>
+</method>
+<method name="setZ"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="z" type="int">
+</parameter>
+</method>
+<method name="subData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="fp" type="android.renderscript.FieldPacker">
+</parameter>
+</method>
+<method name="subData1D"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="int[]">
+</parameter>
+</method>
+<method name="subData1D"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="short[]">
+</parameter>
+</method>
+<method name="subData1D"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="byte[]">
+</parameter>
+</method>
+<method name="subData1D"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="float[]">
+</parameter>
+</method>
+<method name="subData2D"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="d" type="int[]">
+</parameter>
+</method>
+<method name="subData2D"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="d" type="float[]">
+</parameter>
+</method>
+<method name="subElementData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="component_number" type="int">
+</parameter>
+<parameter name="fp" type="android.renderscript.FieldPacker">
+</parameter>
+</method>
+</class>
+<class name="BaseObj"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility=""
+>
+<method name="destroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setName"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="Byte2"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Byte2"
+ type="android.renderscript.Byte2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Byte3"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Byte3"
+ type="android.renderscript.Byte3"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Byte4"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Byte4"
+ type="android.renderscript.Byte4"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="w"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Element"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="ALLOCATION"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="A_8"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="BOOLEAN"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="ELEMENT"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="F32"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="F32_2"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="F32_3"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="F32_4"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="F64"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="I16"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="I32"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="I64"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="I8"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="MATRIX4X4"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="MATRIX_2X2"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="MATRIX_3X3"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="MATRIX_4X4"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="MESH"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="PROGRAM_FRAGMENT"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="PROGRAM_RASTER"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="PROGRAM_STORE"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="PROGRAM_VERTEX"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="RGBA_4444"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="RGBA_5551"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="RGBA_8888"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="RGB_565"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="RGB_888"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="SAMPLER"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="SCRIPT"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="TYPE"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="U16"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="U32"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="U64"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="U8"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="U8_4"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="createPixel"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="dt" type="android.renderscript.Element.DataType">
+</parameter>
+<parameter name="dk" type="android.renderscript.Element.DataKind">
+</parameter>
+</method>
+<method name="createVector"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="dt" type="android.renderscript.Element.DataType">
+</parameter>
+<parameter name="size" type="int">
+</parameter>
+</method>
+<method name="isComplex"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Element.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Element.Builder"
+ type="android.renderscript.Element.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="add"
+ return="android.renderscript.Element.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="element" type="android.renderscript.Element">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="arraySize" type="int">
+</parameter>
+</method>
+<method name="add"
+ return="android.renderscript.Element.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="element" type="android.renderscript.Element">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="create"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Element.DataKind"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Element.DataKind"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Element.DataKind[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Element.DataType"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Element.DataType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Element.DataType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="FieldPacker"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="FieldPacker"
+ type="android.renderscript.FieldPacker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="len" type="int">
+</parameter>
+</constructor>
+<method name="addBoolean"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="boolean">
+</parameter>
+</method>
+<method name="addF32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="float">
+</parameter>
+</method>
+<method name="addF32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Float2">
+</parameter>
+</method>
+<method name="addF32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Float3">
+</parameter>
+</method>
+<method name="addF32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Float4">
+</parameter>
+</method>
+<method name="addF64"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="double">
+</parameter>
+</method>
+<method name="addI16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="short">
+</parameter>
+</method>
+<method name="addI16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Short2">
+</parameter>
+</method>
+<method name="addI16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Short3">
+</parameter>
+</method>
+<method name="addI16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Short4">
+</parameter>
+</method>
+<method name="addI32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="int">
+</parameter>
+</method>
+<method name="addI32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int2">
+</parameter>
+</method>
+<method name="addI32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int3">
+</parameter>
+</method>
+<method name="addI32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int4">
+</parameter>
+</method>
+<method name="addI64"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="long">
+</parameter>
+</method>
+<method name="addI8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="byte">
+</parameter>
+</method>
+<method name="addI8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Byte2">
+</parameter>
+</method>
+<method name="addI8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Byte3">
+</parameter>
+</method>
+<method name="addI8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Byte4">
+</parameter>
+</method>
+<method name="addMatrix"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+<method name="addMatrix"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Matrix3f">
+</parameter>
+</method>
+<method name="addMatrix"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Matrix2f">
+</parameter>
+</method>
+<method name="addObj"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="obj" type="android.renderscript.BaseObj">
+</parameter>
+</method>
+<method name="addU16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="int">
+</parameter>
+</method>
+<method name="addU16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int2">
+</parameter>
+</method>
+<method name="addU16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int3">
+</parameter>
+</method>
+<method name="addU16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int4">
+</parameter>
+</method>
+<method name="addU32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="long">
+</parameter>
+</method>
+<method name="addU32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int2">
+</parameter>
+</method>
+<method name="addU32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int3">
+</parameter>
+</method>
+<method name="addU32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int4">
+</parameter>
+</method>
+<method name="addU64"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="long">
+</parameter>
+</method>
+<method name="addU8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="short">
+</parameter>
+</method>
+<method name="addU8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Short2">
+</parameter>
+</method>
+<method name="addU8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Short3">
+</parameter>
+</method>
+<method name="addU8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Short4">
+</parameter>
+</method>
+<method name="align"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="int">
+</parameter>
+</method>
+<method name="getData"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="reset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="reset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+</method>
+<method name="skip"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+</method>
+</class>
+<class name="FileA3D"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="createFromAsset"
+ return="android.renderscript.FileA3D"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="mgr" type="android.content.res.AssetManager">
+</parameter>
+<parameter name="path" type="java.lang.String">
+</parameter>
+</method>
+<method name="createFromFile"
+ return="android.renderscript.FileA3D"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="path" type="java.lang.String">
+</parameter>
+</method>
+<method name="createFromFile"
+ return="android.renderscript.FileA3D"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="path" type="java.io.File">
+</parameter>
+</method>
+<method name="createFromResource"
+ return="android.renderscript.FileA3D"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="id" type="int">
+</parameter>
+</method>
+<method name="getIndexEntry"
+ return="android.renderscript.FileA3D.IndexEntry"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+</method>
+<method name="getIndexEntryCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="FileA3D.EntryType"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.FileA3D.EntryType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.FileA3D.EntryType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="FileA3D.IndexEntry"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getEntryType"
+ return="android.renderscript.FileA3D.EntryType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMesh"
+ return="android.renderscript.Mesh"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getObject"
+ return="android.renderscript.BaseObj"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Float2"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Float2"
+ type="android.renderscript.Float2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Float2"
+ type="android.renderscript.Float2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="initX" type="float">
+</parameter>
+<parameter name="initY" type="float">
+</parameter>
+</constructor>
+<field name="x"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Float3"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Float3"
+ type="android.renderscript.Float3"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Float3"
+ type="android.renderscript.Float3"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="initX" type="float">
+</parameter>
+<parameter name="initY" type="float">
+</parameter>
+<parameter name="initZ" type="float">
+</parameter>
+</constructor>
+<field name="x"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Float4"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Float4"
+ type="android.renderscript.Float4"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Float4"
+ type="android.renderscript.Float4"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="initX" type="float">
+</parameter>
+<parameter name="initY" type="float">
+</parameter>
+<parameter name="initZ" type="float">
+</parameter>
+<parameter name="initW" type="float">
+</parameter>
+</constructor>
+<field name="w"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Font"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="create"
+ return="android.renderscript.Font"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="familyName" type="java.lang.String">
+</parameter>
+<parameter name="fontStyle" type="android.renderscript.Font.Style">
+</parameter>
+<parameter name="pointSize" type="float">
+</parameter>
+</method>
+<method name="createFromAsset"
+ return="android.renderscript.Font"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="pointSize" type="float">
+</parameter>
+</method>
+<method name="createFromFile"
+ return="android.renderscript.Font"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="pointSize" type="float">
+</parameter>
+</method>
+<method name="createFromFile"
+ return="android.renderscript.Font"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="path" type="java.io.File">
+</parameter>
+<parameter name="pointSize" type="float">
+</parameter>
+</method>
+<method name="createFromResource"
+ return="android.renderscript.Font"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="pointSize" type="float">
+</parameter>
+</method>
+</class>
+<class name="Font.Style"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Font.Style"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Font.Style[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Int2"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Int2"
+ type="android.renderscript.Int2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Int3"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Int3"
+ type="android.renderscript.Int3"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Int4"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Int4"
+ type="android.renderscript.Int4"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="w"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Long2"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Long2"
+ type="android.renderscript.Long2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Long3"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Long3"
+ type="android.renderscript.Long3"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Long4"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Long4"
+ type="android.renderscript.Long4"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="w"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Matrix2f"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Matrix2f"
+ type="android.renderscript.Matrix2f"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Matrix2f"
+ type="android.renderscript.Matrix2f"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dataArray" type="float[]">
+</parameter>
+</constructor>
+<method name="get"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="j" type="int">
+</parameter>
+</method>
+<method name="getArray"
+ return="float[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="load"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="src" type="android.renderscript.Matrix2f">
+</parameter>
+</method>
+<method name="loadIdentity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="loadMultiply"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lhs" type="android.renderscript.Matrix2f">
+</parameter>
+<parameter name="rhs" type="android.renderscript.Matrix2f">
+</parameter>
+</method>
+<method name="loadRotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+</method>
+<method name="loadScale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="multiply"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rhs" type="android.renderscript.Matrix2f">
+</parameter>
+</method>
+<method name="rotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+</method>
+<method name="scale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="set"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="j" type="int">
+</parameter>
+<parameter name="v" type="float">
+</parameter>
+</method>
+<method name="transpose"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Matrix3f"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Matrix3f"
+ type="android.renderscript.Matrix3f"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Matrix3f"
+ type="android.renderscript.Matrix3f"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dataArray" type="float[]">
+</parameter>
+</constructor>
+<method name="get"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="j" type="int">
+</parameter>
+</method>
+<method name="getArray"
+ return="float[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="load"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="src" type="android.renderscript.Matrix3f">
+</parameter>
+</method>
+<method name="loadIdentity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="loadMultiply"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lhs" type="android.renderscript.Matrix3f">
+</parameter>
+<parameter name="rhs" type="android.renderscript.Matrix3f">
+</parameter>
+</method>
+<method name="loadRotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="loadRotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+</method>
+<method name="loadScale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="loadScale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="loadTranslate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="multiply"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rhs" type="android.renderscript.Matrix3f">
+</parameter>
+</method>
+<method name="rotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="rotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+</method>
+<method name="scale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="scale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="set"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="j" type="int">
+</parameter>
+<parameter name="v" type="float">
+</parameter>
+</method>
+<method name="translate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="transpose"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Matrix4f"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Matrix4f"
+ type="android.renderscript.Matrix4f"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Matrix4f"
+ type="android.renderscript.Matrix4f"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dataArray" type="float[]">
+</parameter>
+</constructor>
+<method name="get"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="j" type="int">
+</parameter>
+</method>
+<method name="getArray"
+ return="float[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="inverse"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="inverseTranspose"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="load"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="src" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+<method name="loadFrustum"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="l" type="float">
+</parameter>
+<parameter name="r" type="float">
+</parameter>
+<parameter name="b" type="float">
+</parameter>
+<parameter name="t" type="float">
+</parameter>
+<parameter name="n" type="float">
+</parameter>
+<parameter name="f" type="float">
+</parameter>
+</method>
+<method name="loadIdentity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="loadMultiply"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lhs" type="android.renderscript.Matrix4f">
+</parameter>
+<parameter name="rhs" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+<method name="loadOrtho"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="l" type="float">
+</parameter>
+<parameter name="r" type="float">
+</parameter>
+<parameter name="b" type="float">
+</parameter>
+<parameter name="t" type="float">
+</parameter>
+<parameter name="n" type="float">
+</parameter>
+<parameter name="f" type="float">
+</parameter>
+</method>
+<method name="loadOrthoWindow"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+</method>
+<method name="loadPerspective"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fovy" type="float">
+</parameter>
+<parameter name="aspect" type="float">
+</parameter>
+<parameter name="near" type="float">
+</parameter>
+<parameter name="far" type="float">
+</parameter>
+</method>
+<method name="loadProjectionNormalized"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+</method>
+<method name="loadRotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="loadScale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="loadTranslate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="multiply"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rhs" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+<method name="rotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="scale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="set"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="j" type="int">
+</parameter>
+<parameter name="v" type="float">
+</parameter>
+</method>
+<method name="translate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="transpose"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Mesh"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getIndexSetAllocation"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="slot" type="int">
+</parameter>
+</method>
+<method name="getPrimitive"
+ return="android.renderscript.Mesh.Primitive"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="slot" type="int">
+</parameter>
+</method>
+<method name="getPrimitiveCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getVertexAllocation"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="slot" type="int">
+</parameter>
+</method>
+<method name="getVertexAllocationCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Mesh.AllocationBuilder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Mesh.AllocationBuilder"
+ type="android.renderscript.Mesh.AllocationBuilder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="addIndexSetAllocation"
+ return="android.renderscript.Mesh.AllocationBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="a" type="android.renderscript.Allocation">
+</parameter>
+<parameter name="p" type="android.renderscript.Mesh.Primitive">
+</parameter>
+</method>
+<method name="addIndexSetType"
+ return="android.renderscript.Mesh.AllocationBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.Mesh.Primitive">
+</parameter>
+</method>
+<method name="addVertexAllocation"
+ return="android.renderscript.Mesh.AllocationBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="a" type="android.renderscript.Allocation">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="create"
+ return="android.renderscript.Mesh"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentIndexSetIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentVertexTypeIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Mesh.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Mesh.Builder"
+ type="android.renderscript.Mesh.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</constructor>
+<method name="addIndexSetType"
+ return="android.renderscript.Mesh.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="android.renderscript.Type">
+</parameter>
+<parameter name="p" type="android.renderscript.Mesh.Primitive">
+</parameter>
+</method>
+<method name="addIndexSetType"
+ return="android.renderscript.Mesh.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.Mesh.Primitive">
+</parameter>
+</method>
+<method name="addIndexSetType"
+ return="android.renderscript.Mesh.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="e" type="android.renderscript.Element">
+</parameter>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="p" type="android.renderscript.Mesh.Primitive">
+</parameter>
+</method>
+<method name="addVertexType"
+ return="android.renderscript.Mesh.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="android.renderscript.Type">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="addVertexType"
+ return="android.renderscript.Mesh.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="e" type="android.renderscript.Element">
+</parameter>
+<parameter name="size" type="int">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="create"
+ return="android.renderscript.Mesh"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentIndexSetIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentVertexTypeIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Mesh.Primitive"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Mesh.Primitive"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Mesh.Primitive[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Mesh.TriangleMeshBuilder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Mesh.TriangleMeshBuilder"
+ type="android.renderscript.Mesh.TriangleMeshBuilder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="vtxSize" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</constructor>
+<method name="addTriangle"
+ return="android.renderscript.Mesh.TriangleMeshBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="idx1" type="int">
+</parameter>
+<parameter name="idx2" type="int">
+</parameter>
+<parameter name="idx3" type="int">
+</parameter>
+</method>
+<method name="addVertex"
+ return="android.renderscript.Mesh.TriangleMeshBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="addVertex"
+ return="android.renderscript.Mesh.TriangleMeshBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="create"
+ return="android.renderscript.Mesh"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uploadToBufferObject" type="boolean">
+</parameter>
+</method>
+<method name="setColor"
+ return="android.renderscript.Mesh.TriangleMeshBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="r" type="float">
+</parameter>
+<parameter name="g" type="float">
+</parameter>
+<parameter name="b" type="float">
+</parameter>
+<parameter name="a" type="float">
+</parameter>
+</method>
+<method name="setNormal"
+ return="android.renderscript.Mesh.TriangleMeshBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="setTexture"
+ return="android.renderscript.Mesh.TriangleMeshBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="s" type="float">
+</parameter>
+<parameter name="t" type="float">
+</parameter>
+</method>
+<field name="COLOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TEXTURE_0"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="256"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Program"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bindConstants"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="a" type="android.renderscript.Allocation">
+</parameter>
+<parameter name="slot" type="int">
+</parameter>
+</method>
+<method name="bindSampler"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="vs" type="android.renderscript.Sampler">
+</parameter>
+<parameter name="slot" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="bindTexture"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="va" type="android.renderscript.Allocation">
+</parameter>
+<parameter name="slot" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+</class>
+<class name="Program.BaseProgramBuilder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Program.BaseProgramBuilder"
+ type="android.renderscript.Program.BaseProgramBuilder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="addConstant"
+ return="android.renderscript.Program.BaseProgramBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="android.renderscript.Type">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="addTexture"
+ return="android.renderscript.Program.BaseProgramBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="texType" type="android.renderscript.Program.TextureType">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="getCurrentConstantIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentTextureIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="initProgram"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="p" type="android.renderscript.Program">
+</parameter>
+</method>
+<method name="setShader"
+ return="android.renderscript.Program.BaseProgramBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="s" type="java.lang.String">
+</parameter>
+</method>
+<method name="setShader"
+ return="android.renderscript.Program.BaseProgramBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resources" type="android.content.res.Resources">
+</parameter>
+<parameter name="resourceID" type="int">
+</parameter>
+</method>
+</class>
+<class name="Program.TextureType"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Program.TextureType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Program.TextureType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramFragment"
+ extends="android.renderscript.Program"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="ProgramFragment.Builder"
+ extends="android.renderscript.Program.BaseProgramBuilder"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramFragment.Builder"
+ type="android.renderscript.ProgramFragment.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.ProgramFragment"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramFragmentFixedFunction"
+ extends="android.renderscript.ProgramFragment"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="ProgramFragmentFixedFunction.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramFragmentFixedFunction.Builder"
+ type="android.renderscript.ProgramFragmentFixedFunction.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.ProgramFragmentFixedFunction"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setPointSpriteTexCoordinateReplacement"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+<method name="setTexture"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="env" type="android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode">
+</parameter>
+<parameter name="fmt" type="android.renderscript.ProgramFragmentFixedFunction.Builder.Format">
+</parameter>
+<parameter name="slot" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="setVaryingColor"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+<field name="MAX_TEXTURE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="ProgramFragmentFixedFunction.Builder.EnvMode"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramFragmentFixedFunction.Builder.Format"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder.Format"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder.Format[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramRaster"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="CULL_BACK"
+ return="android.renderscript.ProgramRaster"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="CULL_FRONT"
+ return="android.renderscript.ProgramRaster"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="CULL_NONE"
+ return="android.renderscript.ProgramRaster"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+</class>
+<class name="ProgramRaster.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramRaster.Builder"
+ type="android.renderscript.ProgramRaster.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.ProgramRaster"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setCullMode"
+ return="android.renderscript.ProgramRaster.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="android.renderscript.ProgramRaster.CullMode">
+</parameter>
+</method>
+<method name="setPointSpriteEnabled"
+ return="android.renderscript.ProgramRaster.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+</class>
+<class name="ProgramRaster.CullMode"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.ProgramRaster.CullMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.ProgramRaster.CullMode[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramStore"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="BLEND_ALPHA_DEPTH_NONE"
+ return="android.renderscript.ProgramStore"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="BLEND_ALPHA_DEPTH_TEST"
+ return="android.renderscript.ProgramStore"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="BLEND_NONE_DEPTH_NONE"
+ return="android.renderscript.ProgramStore"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="BLEND_NONE_DEPTH_TEST"
+ return="android.renderscript.ProgramStore"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+</class>
+<class name="ProgramStore.BlendDstFunc"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.ProgramStore.BlendDstFunc"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.ProgramStore.BlendDstFunc[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramStore.BlendSrcFunc"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.ProgramStore.BlendSrcFunc"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.ProgramStore.BlendSrcFunc[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramStore.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramStore.Builder"
+ type="android.renderscript.ProgramStore.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.ProgramStore"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setBlendFunc"
+ return="android.renderscript.ProgramStore.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="src" type="android.renderscript.ProgramStore.BlendSrcFunc">
+</parameter>
+<parameter name="dst" type="android.renderscript.ProgramStore.BlendDstFunc">
+</parameter>
+</method>
+<method name="setColorMaskEnabled"
+ return="android.renderscript.ProgramStore.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="r" type="boolean">
+</parameter>
+<parameter name="g" type="boolean">
+</parameter>
+<parameter name="b" type="boolean">
+</parameter>
+<parameter name="a" type="boolean">
+</parameter>
+</method>
+<method name="setDepthFunc"
+ return="android.renderscript.ProgramStore.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="func" type="android.renderscript.ProgramStore.DepthFunc">
+</parameter>
+</method>
+<method name="setDepthMaskEnabled"
+ return="android.renderscript.ProgramStore.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+<method name="setDitherEnabled"
+ return="android.renderscript.ProgramStore.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+</class>
+<class name="ProgramStore.DepthFunc"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.ProgramStore.DepthFunc"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.ProgramStore.DepthFunc[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramVertex"
+ extends="android.renderscript.Program"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="ProgramVertex.Builder"
+ extends="android.renderscript.Program.BaseProgramBuilder"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramVertex.Builder"
+ type="android.renderscript.ProgramVertex.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="addInput"
+ return="android.renderscript.ProgramVertex.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="e" type="android.renderscript.Element">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="create"
+ return="android.renderscript.ProgramVertex"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramVertexFixedFunction"
+ extends="android.renderscript.ProgramVertex"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bindConstants"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="va" type="android.renderscript.ProgramVertexFixedFunction.Constants">
+</parameter>
+</method>
+</class>
+<class name="ProgramVertexFixedFunction.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramVertexFixedFunction.Builder"
+ type="android.renderscript.ProgramVertexFixedFunction.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.ProgramVertexFixedFunction"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setTextureMatrixEnable"
+ return="android.renderscript.ProgramVertexFixedFunction.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+</class>
+<class name="ProgramVertexFixedFunction.Constants"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramVertexFixedFunction.Constants"
+ type="android.renderscript.ProgramVertexFixedFunction.Constants"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="destroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setModelview"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+<method name="setProjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+<method name="setTexture"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+</class>
+<class name="RSDriverException"
+ extends="android.renderscript.RSRuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RSDriverException"
+ type="android.renderscript.RSDriverException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="string" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="RSIllegalArgumentException"
+ extends="android.renderscript.RSRuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RSIllegalArgumentException"
+ type="android.renderscript.RSIllegalArgumentException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="string" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="RSInvalidStateException"
+ extends="android.renderscript.RSRuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RSInvalidStateException"
+ type="android.renderscript.RSInvalidStateException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="string" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="RSRuntimeException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RSRuntimeException"
+ type="android.renderscript.RSRuntimeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="string" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="RSSurfaceView"
+ extends="android.view.SurfaceView"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.SurfaceHolder.Callback">
+</implements>
+<constructor name="RSSurfaceView"
+ type="android.renderscript.RSSurfaceView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="RSSurfaceView"
+ type="android.renderscript.RSSurfaceView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<method name="createRenderScriptGL"
+ return="android.renderscript.RenderScriptGL"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sc" type="android.renderscript.RenderScriptGL.SurfaceConfig">
+</parameter>
+</method>
+<method name="destroyRenderScriptGL"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRenderScriptGL"
+ return="android.renderscript.RenderScriptGL"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="pause"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="resume"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setRenderScriptGL"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScriptGL">
+</parameter>
+</method>
+<method name="surfaceChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="holder" type="android.view.SurfaceHolder">
+</parameter>
+<parameter name="format" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+</method>
+<method name="surfaceCreated"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="holder" type="android.view.SurfaceHolder">
+</parameter>
+</method>
+<method name="surfaceDestroyed"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="holder" type="android.view.SurfaceHolder">
+</parameter>
+</method>
+</class>
+<class name="RenderScript"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="contextDump"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="create"
+ return="android.renderscript.RenderScript"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ctx" type="android.content.Context">
+</parameter>
+</method>
+<method name="destroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="finish"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getApplicationContext"
+ return="android.content.Context"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getErrorHandler"
+ return="android.renderscript.RenderScript.RSErrorHandler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMessageHandler"
+ return="android.renderscript.RenderScript.RSMessageHandler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setErrorHandler"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="msg" type="android.renderscript.RenderScript.RSErrorHandler">
+</parameter>
+</method>
+<method name="setMessageHandler"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="msg" type="android.renderscript.RenderScript.RSMessageHandler">
+</parameter>
+</method>
+<method name="setPriority"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.RenderScript.Priority">
+</parameter>
+</method>
+</class>
+<class name="RenderScript.Priority"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.RenderScript.Priority"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.RenderScript.Priority[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="RenderScript.RSErrorHandler"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.Runnable">
+</implements>
+<constructor name="RenderScript.RSErrorHandler"
+ type="android.renderscript.RenderScript.RSErrorHandler"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="run"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="mErrorMessage"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+<field name="mErrorNum"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+</class>
+<class name="RenderScript.RSMessageHandler"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.Runnable">
+</implements>
+<constructor name="RenderScript.RSMessageHandler"
+ type="android.renderscript.RenderScript.RSMessageHandler"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="run"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="mData"
+ type="int[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+<field name="mID"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+<field name="mLength"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+</class>
+<class name="RenderScriptGL"
+ extends="android.renderscript.RenderScript"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RenderScriptGL"
+ type="android.renderscript.RenderScriptGL"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ctx" type="android.content.Context">
+</parameter>
+<parameter name="sc" type="android.renderscript.RenderScriptGL.SurfaceConfig">
+</parameter>
+</constructor>
+<method name="bindProgramFragment"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.ProgramFragment">
+</parameter>
+</method>
+<method name="bindProgramRaster"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.ProgramRaster">
+</parameter>
+</method>
+<method name="bindProgramStore"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.ProgramStore">
+</parameter>
+</method>
+<method name="bindProgramVertex"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.ProgramVertex">
+</parameter>
+</method>
+<method name="bindRootScript"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="s" type="android.renderscript.Script">
+</parameter>
+</method>
+<method name="getHeight"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getWidth"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="pause"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="resume"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setSurface"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sur" type="android.view.SurfaceHolder">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+</method>
+</class>
+<class name="RenderScriptGL.SurfaceConfig"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RenderScriptGL.SurfaceConfig"
+ type="android.renderscript.RenderScriptGL.SurfaceConfig"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="RenderScriptGL.SurfaceConfig"
+ type="android.renderscript.RenderScriptGL.SurfaceConfig"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sc" type="android.renderscript.RenderScriptGL.SurfaceConfig">
+</parameter>
+</constructor>
+<method name="setAlpha"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minimum" type="int">
+</parameter>
+<parameter name="preferred" type="int">
+</parameter>
+</method>
+<method name="setColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minimum" type="int">
+</parameter>
+<parameter name="preferred" type="int">
+</parameter>
+</method>
+<method name="setDepth"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minimum" type="int">
+</parameter>
+<parameter name="preferred" type="int">
+</parameter>
+</method>
+<method name="setSamples"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minimum" type="int">
+</parameter>
+<parameter name="preferred" type="int">
+</parameter>
+<parameter name="Q" type="float">
+</parameter>
+</method>
+</class>
+<class name="Sampler"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="CLAMP_LINEAR"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="CLAMP_LINEAR_MIP_LINEAR"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="CLAMP_NEAREST"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="WRAP_LINEAR"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="WRAP_LINEAR_MIP_LINEAR"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="WRAP_NEAREST"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+</class>
+<class name="Sampler.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Sampler.Builder"
+ type="android.renderscript.Sampler.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setAnisotropy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="float">
+</parameter>
+</method>
+<method name="setMagnification"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Sampler.Value">
+</parameter>
+</method>
+<method name="setMinification"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Sampler.Value">
+</parameter>
+</method>
+<method name="setWrapS"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Sampler.Value">
+</parameter>
+</method>
+<method name="setWrapT"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Sampler.Value">
+</parameter>
+</method>
+</class>
+<class name="Sampler.Value"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Sampler.Value"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Sampler.Value[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Script"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="setTimeZone"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="timeZone" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="Script.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="Script.FieldBase"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Script.FieldBase"
+ type="android.renderscript.Script.FieldBase"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</constructor>
+<method name="getAllocation"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getElement"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="android.renderscript.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="init"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="dimx" type="int">
+</parameter>
+</method>
+<method name="init"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="dimx" type="int">
+</parameter>
+<parameter name="usages" type="int">
+</parameter>
+</method>
+<method name="updateAllocation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="mAllocation"
+ type="android.renderscript.Allocation"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+<field name="mElement"
+ type="android.renderscript.Element"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+</class>
+<class name="ScriptC"
+ extends="android.renderscript.Script"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="Short2"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Short2"
+ type="android.renderscript.Short2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Short3"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Short3"
+ type="android.renderscript.Short3"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Short4"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Short4"
+ type="android.renderscript.Short4"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="w"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Type"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getElement"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getX"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getY"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getZ"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasFaces"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasMipmaps"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Type.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Type.Builder"
+ type="android.renderscript.Type.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="e" type="android.renderscript.Element">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setFaces"
+ return="android.renderscript.Type.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="boolean">
+</parameter>
+</method>
+<method name="setMipmaps"
+ return="android.renderscript.Type.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="boolean">
+</parameter>
+</method>
+<method name="setX"
+ return="android.renderscript.Type.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+<method name="setY"
+ return="android.renderscript.Type.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+</class>
+<class name="Type.CubemapFace"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Type.CubemapFace"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Type.CubemapFace[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+</package>
 <package name="android.sax"
 >
 <class name="Element"
@@ -146899,6 +174662,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_WEB_SEARCH_ONLY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extra.WEB_SEARCH_ONLY&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="LANGUAGE_MODEL_FREE_FORM"
  type="java.lang.String"
  transient="false"
@@ -146977,6 +174751,92 @@
 >
 </field>
 </class>
+<class name="RecognizerResultsIntent"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="ACTION_VOICE_SEARCH_RESULTS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.action.VOICE_SEARCH_RESULTS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VOICE_SEARCH_RESULT_HTML"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extras.VOICE_SEARCH_RESULT_HTML&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VOICE_SEARCH_RESULT_HTML_BASE_URLS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extras.VOICE_SEARCH_RESULT_HTML_BASE_URLS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VOICE_SEARCH_RESULT_HTTP_HEADERS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extras.EXTRA_VOICE_SEARCH_RESULT_HTTP_HEADERS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VOICE_SEARCH_RESULT_STRINGS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extras.VOICE_SEARCH_RESULT_STRINGS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VOICE_SEARCH_RESULT_URLS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extras.VOICE_SEARCH_RESULT_URLS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="URI_SCHEME_INLINE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;inline&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="SpeechRecognizer"
  extends="java.lang.Object"
  abstract="false"
@@ -148127,7 +175987,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="text" type="android.text.Editable">
+<parameter name="s" type="android.text.Editable">
 </parameter>
 </method>
 <method name="beforeTextChanged"
@@ -150590,6 +178450,17 @@
  visibility="public"
 >
 </field>
+<field name="NETWORK_TYPE_EHRPD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="14"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="NETWORK_TYPE_EVDO_0"
  type="int"
  transient="false"
@@ -150678,6 +178549,17 @@
  visibility="public"
 >
 </field>
+<field name="NETWORK_TYPE_LTE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="13"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="NETWORK_TYPE_UMTS"
  type="int"
  transient="false"
@@ -150733,6 +178615,17 @@
  visibility="public"
 >
 </field>
+<field name="PHONE_TYPE_SIP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SIM_STATE_ABSENT"
  type="int"
  transient="false"
@@ -152969,6 +180862,36 @@
 >
 </method>
 </class>
+<class name="LoaderTestCase"
+ extends="android.test.AndroidTestCase"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="LoaderTestCase"
+ type="android.test.LoaderTestCase"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getLoaderResultSynchronously"
+ return="T"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="loader" type="android.content.Loader&lt;T&gt;">
+</parameter>
+</method>
+</class>
 <class name="MoreAsserts"
  extends="java.lang.Object"
  abstract="false"
@@ -155889,6 +183812,25 @@
 <parameter name="factory" type="android.database.sqlite.SQLiteDatabase.CursorFactory">
 </parameter>
 </method>
+<method name="openOrCreateDatabase"
+ return="android.database.sqlite.SQLiteDatabase"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="file" type="java.lang.String">
+</parameter>
+<parameter name="mode" type="int">
+</parameter>
+<parameter name="factory" type="android.database.sqlite.SQLiteDatabase.CursorFactory">
+</parameter>
+<parameter name="errorHandler" type="android.database.DatabaseErrorHandler">
+</parameter>
+</method>
 <method name="peekWallpaper"
  return="android.graphics.drawable.Drawable"
  abstract="false"
@@ -156109,6 +184051,19 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="startActivities"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intents" type="android.content.Intent[]">
+</parameter>
+</method>
 <method name="startActivity"
  return="void"
  abstract="false"
@@ -156455,6 +184410,19 @@
 <parameter name="columnIndex" type="int">
 </parameter>
 </method>
+<method name="getType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="columnIndex" type="int">
+</parameter>
+</method>
 <method name="getWantsAllOnMoveCalls"
  return="boolean"
  abstract="false"
@@ -157708,6 +185676,21 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
+<method name="setInstallerPackageName"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetPackage" type="java.lang.String">
+</parameter>
+<parameter name="installerPackageName" type="java.lang.String">
+</parameter>
+</method>
 <method name="setPackageObbPath"
  return="void"
  abstract="false"
@@ -158847,15 +186830,23 @@
 </class>
 <class name="ClipboardManager"
  extends="java.lang.Object"
- abstract="false"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<constructor name="ClipboardManager"
+ type="android.text.ClipboardManager"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
+</constructor>
 <method name="getText"
  return="java.lang.CharSequence"
- abstract="false"
+ abstract="true"
  native="false"
  synchronized="false"
  static="false"
@@ -158866,7 +186857,7 @@
 </method>
 <method name="hasText"
  return="boolean"
- abstract="false"
+ abstract="true"
  native="false"
  synchronized="false"
  static="false"
@@ -158877,7 +186868,7 @@
 </method>
 <method name="setText"
  return="void"
- abstract="false"
+ abstract="true"
  native="false"
  synchronized="false"
  static="false"
@@ -159738,6 +187729,28 @@
  visibility="public"
 >
 </field>
+<field name="TYPE_NUMBER_VARIATION_NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_NUMBER_VARIATION_PASSWORD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TYPE_TEXT_FLAG_AUTO_COMPLETE"
  type="int"
  transient="false"
@@ -159969,6 +187982,28 @@
  visibility="public"
 >
 </field>
+<field name="TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="208"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_TEXT_VARIATION_WEB_PASSWORD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="224"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </interface>
 <class name="Layout"
  extends="java.lang.Object"
@@ -161702,6 +189737,29 @@
 <parameter name="kind" type="java.lang.Class&lt;T&gt;">
 </parameter>
 </method>
+<method name="getTextRunCursor"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="contextStart" type="int">
+</parameter>
+<parameter name="contextEnd" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+<parameter name="cursorOpt" type="int">
+</parameter>
+<parameter name="p" type="android.graphics.Paint">
+</parameter>
+</method>
 <method name="insert"
  return="android.text.SpannableStringBuilder"
  abstract="false"
@@ -162762,7 +190820,7 @@
 >
 <parameter name="text" type="java.lang.CharSequence">
 </parameter>
-<parameter name="p" type="android.text.TextPaint">
+<parameter name="paint" type="android.text.TextPaint">
 </parameter>
 <parameter name="avail" type="float">
 </parameter>
@@ -164815,6 +192873,19 @@
 <parameter name="gmtoff" type="long">
 </parameter>
 </method>
+<method name="getJulianMondayFromWeeksSinceEpoch"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="week" type="int">
+</parameter>
+</method>
 <method name="getWeekNumber"
  return="int"
  abstract="false"
@@ -164826,6 +192897,21 @@
  visibility="public"
 >
 </method>
+<method name="getWeeksSinceEpochFromJulianDay"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="julianDay" type="int">
+</parameter>
+<parameter name="firstDayOfWeek" type="int">
+</parameter>
+</method>
 <method name="isEpoch"
  return="boolean"
  abstract="false"
@@ -165049,6 +193135,17 @@
  visibility="public"
 >
 </field>
+<field name="MONDAY_BEFORE_JULIAN_EPOCH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2440585"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MONTH"
  type="int"
  transient="false"
@@ -165317,7 +193414,7 @@
 <package name="android.text.method"
 >
 <class name="ArrowKeyMovementMethod"
- extends="java.lang.Object"
+ extends="android.text.method.BaseMovementMethod"
  abstract="false"
  static="false"
  final="false"
@@ -165334,17 +193431,6 @@
  visibility="public"
 >
 </constructor>
-<method name="canSelectArbitrarily"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getInstance"
  return="android.text.method.MovementMethod"
  abstract="false"
@@ -165356,127 +193442,6 @@
  visibility="public"
 >
 </method>
-<method name="initialize"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-</method>
-<method name="onKeyDown"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-<parameter name="keyCode" type="int">
-</parameter>
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="onKeyOther"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="view" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="onKeyUp"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-<parameter name="keyCode" type="int">
-</parameter>
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="onTakeFocus"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="view" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-<parameter name="dir" type="int">
-</parameter>
-</method>
-<method name="onTouchEvent"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-<parameter name="event" type="android.view.MotionEvent">
-</parameter>
-</method>
-<method name="onTrackballEvent"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-<parameter name="event" type="android.view.MotionEvent">
-</parameter>
-</method>
 </class>
 <class name="BaseKeyListener"
  extends="android.text.method.MetaKeyKeyListener"
@@ -165515,6 +193480,25 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="forwardDelete"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+<parameter name="content" type="android.text.Editable">
+</parameter>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="onKeyOther"
  return="boolean"
  abstract="false"
@@ -165533,6 +193517,373 @@
 </parameter>
 </method>
 </class>
+<class name="BaseMovementMethod"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.text.method.MovementMethod">
+</implements>
+<constructor name="BaseMovementMethod"
+ type="android.text.method.BaseMovementMethod"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="bottom"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="canSelectArbitrarily"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="down"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="end"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="getMovementMetaState"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="handleMovementKey"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="movementMetaState" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="home"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="initialize"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="left"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="lineEnd"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="lineStart"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="onKeyDown"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="onKeyOther"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="onKeyUp"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="onTakeFocus"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="direction" type="int">
+</parameter>
+</method>
+<method name="onTouchEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="onTrackballEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="pageDown"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="pageUp"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="right"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="top"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="up"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+</class>
 <class name="CharacterPickerDialog"
  extends="android.app.Dialog"
  abstract="false"
@@ -166860,7 +195211,7 @@
 >
 <parameter name="cap" type="android.text.method.TextKeyListener.Capitalize">
 </parameter>
-<parameter name="autotext" type="boolean">
+<parameter name="autoText" type="boolean">
 </parameter>
 </constructor>
 <method name="getInputType"
@@ -166884,11 +195235,22 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="autotext" type="boolean">
+<parameter name="autoText" type="boolean">
 </parameter>
 <parameter name="cap" type="android.text.method.TextKeyListener.Capitalize">
 </parameter>
 </method>
+<method name="getInstanceForFullKeyboard"
+ return="android.text.method.QwertyKeyListener"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="markAsReplaced"
  return="void"
  abstract="false"
@@ -166987,7 +195349,7 @@
 </method>
 </class>
 <class name="ScrollingMovementMethod"
- extends="java.lang.Object"
+ extends="android.text.method.BaseMovementMethod"
  abstract="false"
  static="false"
  final="false"
@@ -167004,32 +195366,6 @@
  visibility="public"
 >
 </constructor>
-<method name="canSelectArbitrarily"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="down"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-</method>
 <method name="getInstance"
  return="android.text.method.MovementMethod"
  abstract="false"
@@ -167041,172 +195377,6 @@
  visibility="public"
 >
 </method>
-<method name="initialize"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-</method>
-<method name="left"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-</method>
-<method name="onKeyDown"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-<parameter name="keyCode" type="int">
-</parameter>
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="onKeyOther"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="view" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="onKeyUp"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-<parameter name="keyCode" type="int">
-</parameter>
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="onTakeFocus"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-<parameter name="dir" type="int">
-</parameter>
-</method>
-<method name="onTouchEvent"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-<parameter name="event" type="android.view.MotionEvent">
-</parameter>
-</method>
-<method name="onTrackballEvent"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-<parameter name="event" type="android.view.MotionEvent">
-</parameter>
-</method>
-<method name="right"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-</method>
-<method name="up"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-</method>
 </class>
 <class name="SingleLineTransformationMethod"
  extends="android.text.method.ReplacementTransformationMethod"
@@ -171149,6 +199319,18 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<constructor name="AndroidException"
+ type="android.util.AndroidException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
 <parameter name="cause" type="java.lang.Exception">
 </parameter>
 </constructor>
@@ -171186,6 +199368,18 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="cause" type="java.lang.Throwable">
+</parameter>
+</constructor>
+<constructor name="AndroidRuntimeException"
+ type="android.util.AndroidRuntimeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
 <parameter name="cause" type="java.lang.Exception">
 </parameter>
 </constructor>
@@ -172360,6 +200554,518 @@
 </parameter>
 </method>
 </class>
+<class name="JsonReader"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.io.Closeable">
+</implements>
+<constructor name="JsonReader"
+ type="android.util.JsonReader"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="in" type="java.io.Reader">
+</parameter>
+</constructor>
+<method name="beginArray"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="beginObject"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="close"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="endArray"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="endObject"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="hasNext"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="isLenient"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="nextBoolean"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="nextDouble"
+ return="double"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="nextInt"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="nextLong"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="nextName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="nextNull"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="nextString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="peek"
+ return="android.util.JsonToken"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="setLenient"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lenient" type="boolean">
+</parameter>
+</method>
+<method name="skipValue"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="JsonToken"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.util.JsonToken"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.util.JsonToken[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="JsonWriter"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.io.Closeable">
+</implements>
+<constructor name="JsonWriter"
+ type="android.util.JsonWriter"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="out" type="java.io.Writer">
+</parameter>
+</constructor>
+<method name="beginArray"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="beginObject"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="close"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="endArray"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="endObject"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="flush"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="isLenient"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="name"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="nullValue"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="setIndent"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="indent" type="java.lang.String">
+</parameter>
+</method>
+<method name="setLenient"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lenient" type="boolean">
+</parameter>
+</method>
+<method name="value"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.String">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="value"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="boolean">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="value"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="double">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="value"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="long">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="value"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Number">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
 <class name="Log"
  extends="java.lang.Object"
  abstract="false"
@@ -172738,6 +201444,25 @@
 </parameter>
 </method>
 </class>
+<class name="MalformedJsonException"
+ extends="java.io.IOException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="MalformedJsonException"
+ type="android.util.MalformedJsonException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
 <class name="MonthDisplayHelper"
  extends="java.lang.Object"
  abstract="false"
@@ -173363,6 +202088,19 @@
 <parameter name="key" type="int">
 </parameter>
 </method>
+<method name="removeAt"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+</method>
 <method name="setValueAt"
  return="void"
  abstract="false"
@@ -173847,6 +202585,17 @@
 <parameter name="newSize" type="int">
 </parameter>
 </method>
+<field name="NOTHING"
+ type="int[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="WILD_CARD"
  type="int[]"
  transient="false"
@@ -174968,6 +203717,231 @@
 >
 </field>
 </class>
+<class name="ActionMode"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ActionMode"
+ type="android.view.ActionMode"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="finish"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCustomView"
+ return="android.view.View"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMenu"
+ return="android.view.Menu"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMenuInflater"
+ return="android.view.MenuInflater"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSubtitle"
+ return="java.lang.CharSequence"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTitle"
+ return="java.lang.CharSequence"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="invalidate"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setCustomView"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
+<method name="setSubtitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="subtitle" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setSubtitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
+<method name="setTitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setTitle"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
+</class>
+<interface name="ActionMode.Callback"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onActionItemClicked"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+<parameter name="item" type="android.view.MenuItem">
+</parameter>
+</method>
+<method name="onCreateActionMode"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+<parameter name="menu" type="android.view.Menu">
+</parameter>
+</method>
+<method name="onDestroyActionMode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
+<method name="onPrepareActionMode"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+<parameter name="menu" type="android.view.Menu">
+</parameter>
+</method>
+</interface>
 <interface name="ContextMenu"
  abstract="true"
  static="false"
@@ -175218,6 +204192,196 @@
 >
 </field>
 </class>
+<class name="DragEvent"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAction"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getClipData"
+ return="android.content.ClipData"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getClipDescription"
+ return="android.content.ClipDescription"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLocalState"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getResult"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="ACTION_DRAG_ENDED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_DRAG_ENTERED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_DRAG_EXITED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_DRAG_LOCATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_DRAG_STARTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_DROP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="FocusFinder"
  extends="java.lang.Object"
  abstract="false"
@@ -176815,7 +205979,7 @@
 >
 <parameter name="keyCode" type="int">
 </parameter>
-<parameter name="meta" type="int">
+<parameter name="metaState" type="int">
 </parameter>
 </method>
 <method name="getDeadChar"
@@ -176866,7 +206030,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="keyCode" type="int">
@@ -176914,9 +206078,20 @@
 </parameter>
 <parameter name="chars" type="char[]">
 </parameter>
-<parameter name="modifiers" type="int">
+<parameter name="metaState" type="int">
 </parameter>
 </method>
+<method name="getModifierBehavior"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getNumber"
  return="char"
  abstract="false"
@@ -176953,7 +206128,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="keyboard" type="int">
+<parameter name="deviceId" type="int">
 </parameter>
 </method>
 <field name="ALPHA"
@@ -176974,7 +206149,7 @@
  value="0"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -177000,6 +206175,17 @@
  visibility="public"
 >
 </field>
+<field name="FULL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="HEX_INPUT"
  type="char"
  transient="false"
@@ -177011,6 +206197,28 @@
  visibility="public"
 >
 </field>
+<field name="MODIFIER_BEHAVIOR_CHORDED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="NUMERIC"
  type="int"
  transient="false"
@@ -177044,13 +206252,54 @@
  visibility="public"
 >
 </field>
+<field name="SPECIAL_FUNCTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="VIRTUAL_KEYBOARD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="KeyCharacterMap.KeyCharacterMapUnavailableException"
+ extends="android.util.AndroidRuntimeException"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="KeyCharacterMap.KeyCharacterMapUnavailableException"
+ type="android.view.KeyCharacterMap.KeyCharacterMapUnavailableException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="msg" type="java.lang.String">
+</parameter>
+</constructor>
 </class>
 <class name="KeyCharacterMap.KeyData"
  extends="java.lang.Object"
  abstract="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="KeyCharacterMap.KeyData"
@@ -177459,6 +206708,17 @@
  visibility="public"
 >
 </method>
+<method name="getKeyCharacterMap"
+ return="android.view.KeyCharacterMap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getKeyCode"
  return="int"
  abstract="false"
@@ -177477,7 +206737,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="results" type="android.view.KeyCharacterMap.KeyData">
@@ -177508,7 +206768,7 @@
 >
 <parameter name="chars" type="char[]">
 </parameter>
-<parameter name="modifiers" type="int">
+<parameter name="metaState" type="int">
 </parameter>
 </method>
 <method name="getMaxKeyCode"
@@ -177533,6 +206793,17 @@
  visibility="public"
 >
 </method>
+<method name="getModifierMetaStateMask"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getNumber"
  return="char"
  abstract="false"
@@ -177587,9 +206858,33 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="meta" type="int">
+<parameter name="metaState" type="int">
 </parameter>
 </method>
+<method name="hasModifiers"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modifiers" type="int">
+</parameter>
+</method>
+<method name="hasNoModifiers"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isAltPressed"
  return="boolean"
  abstract="false"
@@ -177612,6 +206907,39 @@
  visibility="public"
 >
 </method>
+<method name="isCapsLockOn"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isCtrlPressed"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isFunctionPressed"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isLongPress"
  return="boolean"
  abstract="false"
@@ -177623,6 +206951,17 @@
  visibility="public"
 >
 </method>
+<method name="isMetaPressed"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isModifierKey"
  return="boolean"
  abstract="false"
@@ -177636,6 +206975,17 @@
 <parameter name="keyCode" type="int">
 </parameter>
 </method>
+<method name="isNumLockOn"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isPrintingKey"
  return="boolean"
  abstract="false"
@@ -177647,6 +206997,17 @@
  visibility="public"
 >
 </method>
+<method name="isScrollLockOn"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isShiftPressed"
  return="boolean"
  abstract="false"
@@ -177691,6 +207052,47 @@
  visibility="public"
 >
 </method>
+<method name="metaStateHasModifiers"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="metaState" type="int">
+</parameter>
+<parameter name="modifiers" type="int">
+</parameter>
+</method>
+<method name="metaStateHasNoModifiers"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="metaState" type="int">
+</parameter>
+</method>
+<method name="normalizeMetaState"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="metaState" type="int">
+</parameter>
+</method>
 <method name="startTracking"
  return="void"
  abstract="false"
@@ -177793,6 +207195,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_FALLBACK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1024"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_FROM_SYSTEM"
  type="int"
  transient="false"
@@ -178024,6 +207437,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_APP_SWITCH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="187"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_AT"
  type="int"
  transient="false"
@@ -178035,6 +207459,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_AVR_INPUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="182"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_AVR_POWER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="181"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_B"
  type="int"
  transient="false"
@@ -178068,6 +207514,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_BOOKMARK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="174"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_BREAK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="121"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_BUTTON_A"
  type="int"
  transient="false"
@@ -178266,6 +207734,50 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_CAPS_LOCK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="115"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_CAPTIONS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="175"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_CHANNEL_DOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="167"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_CHANNEL_UP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="166"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_CLEAR"
  type="int"
  transient="false"
@@ -178288,6 +207800,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_CTRL_LEFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="113"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_CTRL_RIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="114"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_D"
  type="int"
  transient="false"
@@ -178365,6 +207899,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_DVR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="173"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_E"
  type="int"
  transient="false"
@@ -178420,6 +207965,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_ESCAPE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="111"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_EXPLORER"
  type="int"
  transient="false"
@@ -178442,6 +207998,138 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_F1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="131"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="140"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="141"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="142"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="132"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="133"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="134"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="135"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="136"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="137"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="138"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="139"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_FOCUS"
  type="int"
  transient="false"
@@ -178453,6 +208141,39 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_FORWARD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="125"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_FORWARD_DEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="112"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_FUNCTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="119"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_G"
  type="int"
  transient="false"
@@ -178475,6 +208196,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_GUIDE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="172"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_H"
  type="int"
  transient="false"
@@ -178519,6 +208251,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_INFO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="165"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_INSERT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="124"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_J"
  type="int"
  transient="false"
@@ -178574,6 +208328,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_MEDIA_CLOSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="128"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_MEDIA_EJECT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="129"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_MEDIA_FAST_FORWARD"
  type="int"
  transient="false"
@@ -178596,6 +208372,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_MEDIA_PAUSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="127"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_MEDIA_PLAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="126"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_MEDIA_PLAY_PAUSE"
  type="int"
  transient="false"
@@ -178618,6 +208416,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_MEDIA_RECORD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="130"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_MEDIA_REWIND"
  type="int"
  transient="false"
@@ -178651,6 +208460,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_META_LEFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="117"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_META_RIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="118"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_MINUS"
  type="int"
  transient="false"
@@ -178662,6 +208493,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_MOVE_END"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="123"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_MOVE_HOME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="122"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_MUTE"
  type="int"
  transient="false"
@@ -178706,6 +208559,237 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_NUMPAD_0"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="144"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="145"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="146"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="147"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="148"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="149"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="150"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="151"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="152"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="153"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_ADD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="157"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_COMMA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="159"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_DIVIDE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="154"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_DOT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="158"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_ENTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="160"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_EQUALS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="161"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_LEFT_PAREN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="162"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_MULTIPLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="155"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_RIGHT_PAREN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="163"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_SUBTRACT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="156"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUM_LOCK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="143"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_O"
  type="int"
  transient="false"
@@ -178805,6 +208889,50 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_PROG_BLUE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="186"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_PROG_GREEN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="184"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_PROG_RED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="183"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_PROG_YELLOW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="185"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_Q"
  type="int"
  transient="false"
@@ -178849,6 +208977,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_SCROLL_LOCK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="116"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_SEARCH"
  type="int"
  transient="false"
@@ -178871,6 +209010,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_SETTINGS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="176"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_SHIFT_LEFT"
  type="int"
  transient="false"
@@ -178948,6 +209098,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_STB_INPUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="180"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_STB_POWER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="179"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_SWITCH_CHARSET"
  type="int"
  transient="false"
@@ -178970,6 +209142,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_SYSRQ"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="120"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_T"
  type="int"
  transient="false"
@@ -178992,6 +209175,39 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_TV"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="170"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_TV_INPUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="178"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_TV_POWER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="177"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_U"
  type="int"
  transient="false"
@@ -179036,6 +209252,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_VOLUME_MUTE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="164"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_VOLUME_UP"
  type="int"
  transient="false"
@@ -179058,6 +209285,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_WINDOW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="171"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_X"
  type="int"
  transient="false"
@@ -179091,6 +209329,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_ZOOM_IN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="168"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_ZOOM_OUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="169"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MAX_KEYCODE"
  type="int"
  transient="false"
@@ -179113,6 +209373,17 @@
  visibility="public"
 >
 </field>
+<field name="META_ALT_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="50"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="META_ALT_ON"
  type="int"
  transient="false"
@@ -179135,6 +209406,138 @@
  visibility="public"
 >
 </field>
+<field name="META_CAPS_LOCK_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1048576"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_CTRL_LEFT_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8192"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_CTRL_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="28672"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_CTRL_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4096"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_CTRL_RIGHT_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16384"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_FUNCTION_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_META_LEFT_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="131072"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_META_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="458752"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_META_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="65536"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_META_RIGHT_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="262144"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_NUM_LOCK_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2097152"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_SCROLL_LOCK_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4194304"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="META_SHIFT_LEFT_ON"
  type="int"
  transient="false"
@@ -179146,6 +209549,17 @@
  visibility="public"
 >
 </field>
+<field name="META_SHIFT_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="193"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="META_SHIFT_ON"
  type="int"
  transient="false"
@@ -179444,6 +209858,17 @@
  visibility="public"
 >
 </method>
+<method name="getFactory2"
+ return="android.view.LayoutInflater.Factory2"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getFilter"
  return="android.view.LayoutInflater.Filter"
  abstract="false"
@@ -179536,6 +209961,25 @@
 <exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException">
 </exception>
 </method>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="parent" type="android.view.View">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException">
+</exception>
+</method>
 <method name="setFactory"
  return="void"
  abstract="false"
@@ -179549,6 +209993,19 @@
 <parameter name="factory" type="android.view.LayoutInflater.Factory">
 </parameter>
 </method>
+<method name="setFactory2"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factory" type="android.view.LayoutInflater.Factory2">
+</parameter>
+</method>
 <method name="setFilter"
  return="void"
  abstract="false"
@@ -179588,6 +210045,35 @@
 </parameter>
 </method>
 </interface>
+<interface name="LayoutInflater.Factory2"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.LayoutInflater.Factory">
+</implements>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.View">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</method>
+</interface>
 <interface name="LayoutInflater.Filter"
  abstract="true"
  static="true"
@@ -180115,6 +210601,17 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="getActionView"
+ return="android.view.View"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getAlphabeticShortcut"
  return="char"
  abstract="true"
@@ -180291,6 +210788,32 @@
  visibility="public"
 >
 </method>
+<method name="setActionView"
+ return="android.view.MenuItem"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
+<method name="setActionView"
+ return="android.view.MenuItem"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
 <method name="setAlphabeticShortcut"
  return="android.view.MenuItem"
  abstract="true"
@@ -180423,6 +210946,19 @@
 <parameter name="alphaChar" type="char">
 </parameter>
 </method>
+<method name="setShowAsAction"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="actionEnum" type="int">
+</parameter>
+</method>
 <method name="setTitle"
  return="android.view.MenuItem"
  abstract="true"
@@ -180475,6 +211011,50 @@
 <parameter name="visible" type="boolean">
 </parameter>
 </method>
+<field name="SHOW_AS_ACTION_ALWAYS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHOW_AS_ACTION_IF_ROOM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHOW_AS_ACTION_NEVER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHOW_AS_ACTION_WITH_TEXT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </interface>
 <interface name="MenuItem.OnMenuItemClickListener"
  abstract="true"
@@ -181465,6 +212045,19 @@
 <parameter name="y" type="float">
 </parameter>
 </method>
+<method name="transform"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="matrix" type="android.graphics.Matrix">
+</parameter>
+</method>
 <method name="writeToParcel"
  return="void"
  abstract="false"
@@ -182079,6 +212672,28 @@
  visibility="public"
 >
 </method>
+<method name="getCurrentSpanX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentSpanY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getEventTime"
  return="long"
  abstract="false"
@@ -182123,6 +212738,28 @@
  visibility="public"
 >
 </method>
+<method name="getPreviousSpanX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPreviousSpanY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getScaleFactor"
  return="float"
  abstract="false"
@@ -182858,7 +213495,7 @@
  value="512"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -183149,7 +213786,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="type" type="int">
@@ -183197,7 +213834,7 @@
  value="0"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -183208,7 +213845,7 @@
  value="3"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -183702,6 +214339,19 @@
 <parameter name="focusableMode" type="int">
 </parameter>
 </method>
+<method name="addOnLayoutChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.view.View.OnLayoutChangeListener">
+</parameter>
+</method>
 <method name="addTouchables"
  return="void"
  abstract="false"
@@ -183835,6 +214485,21 @@
  visibility="public"
 >
 </method>
+<method name="combineMeasuredStates"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="curState" type="int">
+</parameter>
+<parameter name="newState" type="int">
+</parameter>
+</method>
 <method name="computeHorizontalScrollExtent"
  return="int"
  abstract="false"
@@ -183962,6 +214627,19 @@
 <parameter name="hint" type="int">
 </parameter>
 </method>
+<method name="dispatchDragEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.DragEvent">
+</parameter>
+</method>
 <method name="dispatchDraw"
  return="void"
  abstract="false"
@@ -184053,6 +214731,19 @@
 <parameter name="container" type="android.util.SparseArray&lt;android.os.Parcelable&gt;">
 </parameter>
 </method>
+<method name="dispatchSetActivated"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="activated" type="boolean">
+</parameter>
+</method>
 <method name="dispatchSetPressed"
  return="void"
  abstract="false"
@@ -184259,6 +214950,17 @@
  visibility="public"
 >
 </method>
+<method name="getAlpha"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getAnimation"
  return="android.view.animation.Animation"
  abstract="false"
@@ -184620,6 +215322,17 @@
  visibility="public"
 >
 </method>
+<method name="getLayerType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getLayoutParams"
  return="android.view.ViewGroup.LayoutParams"
  abstract="false"
@@ -184703,6 +215416,17 @@
 <parameter name="location" type="int[]">
 </parameter>
 </method>
+<method name="getMatrix"
+ return="android.graphics.Matrix"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getMeasuredHeight"
  return="int"
  abstract="false"
@@ -184714,6 +215438,28 @@
  visibility="public"
 >
 </method>
+<method name="getMeasuredHeightAndState"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMeasuredState"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getMeasuredWidth"
  return="int"
  abstract="false"
@@ -184725,6 +215471,17 @@
  visibility="public"
 >
 </method>
+<method name="getMeasuredWidthAndState"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getNextFocusDownId"
  return="int"
  abstract="false"
@@ -184736,6 +215493,17 @@
  visibility="public"
 >
 </method>
+<method name="getNextFocusForwardId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getNextFocusLeftId"
  return="int"
  abstract="false"
@@ -184780,6 +215548,17 @@
  visibility="public"
 >
 </method>
+<method name="getOnLayoutChangeListeners"
+ return="java.util.List&lt;android.view.View.OnLayoutChangeListener&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getOverScrollMode"
  return="int"
  abstract="false"
@@ -184846,6 +215625,28 @@
  visibility="public"
 >
 </method>
+<method name="getPivotX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPivotY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getResources"
  return="android.content.res.Resources"
  abstract="false"
@@ -184901,6 +215702,61 @@
  visibility="public"
 >
 </method>
+<method name="getRotation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRotationX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRotationY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getScaleX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getScaleY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getScrollBarStyle"
  return="int"
  abstract="false"
@@ -185046,6 +215902,28 @@
  visibility="public"
 >
 </method>
+<method name="getTranslationX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTranslationY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getVerticalFadingEdgeLength"
  return="int"
  abstract="false"
@@ -185057,6 +215935,17 @@
  visibility="public"
 >
 </method>
+<method name="getVerticalScrollbarPosition"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getVerticalScrollbarWidth"
  return="int"
  abstract="false"
@@ -185147,6 +216036,28 @@
 <parameter name="outRect" type="android.graphics.Rect">
 </parameter>
 </method>
+<method name="getX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="hasFocus"
  return="boolean"
  abstract="false"
@@ -185279,6 +216190,17 @@
 <parameter name="drawable" type="android.graphics.drawable.Drawable">
 </parameter>
 </method>
+<method name="isActivated"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isClickable"
  return="boolean"
  abstract="false"
@@ -185290,6 +216212,17 @@
  visibility="public"
 >
 </method>
+<method name="isDirty"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isDrawingCacheEnabled"
  return="boolean"
  abstract="false"
@@ -185367,6 +216300,17 @@
  visibility="public"
 >
 </method>
+<method name="isHardwareAccelerated"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isHorizontalFadingEdgeEnabled"
  return="boolean"
  abstract="false"
@@ -185477,6 +216421,17 @@
  visibility="public"
 >
 </method>
+<method name="isSaveFromParentEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isScrollbarFadingEnabled"
  return="boolean"
  abstract="false"
@@ -185543,13 +216498,24 @@
  visibility="public"
 >
 </method>
+<method name="jumpDrawablesToCurrentState"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="layout"
  return="void"
  abstract="false"
  native="false"
  synchronized="false"
  static="false"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -185738,6 +216704,19 @@
 <parameter name="hint" type="int">
 </parameter>
 </method>
+<method name="onDragEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.DragEvent">
+</parameter>
+</method>
 <method name="onDraw"
  return="void"
  abstract="false"
@@ -186324,6 +217303,19 @@
 <parameter name="action" type="java.lang.Runnable">
 </parameter>
 </method>
+<method name="removeOnLayoutChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.view.View.OnLayoutChangeListener">
+</parameter>
+</method>
 <method name="requestFocus"
  return="boolean"
  abstract="false"
@@ -186428,6 +217420,23 @@
 <parameter name="measureSpec" type="int">
 </parameter>
 </method>
+<method name="resolveSizeAndState"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="measureSpec" type="int">
+</parameter>
+<parameter name="childMeasuredState" type="int">
+</parameter>
+</method>
 <method name="restoreHierarchyState"
  return="void"
  abstract="false"
@@ -186527,6 +217536,32 @@
 <parameter name="event" type="android.view.accessibility.AccessibilityEvent">
 </parameter>
 </method>
+<method name="setActivated"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="activated" type="boolean">
+</parameter>
+</method>
+<method name="setAlpha"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="alpha" type="float">
+</parameter>
+</method>
 <method name="setAnimation"
  return="void"
  abstract="false"
@@ -186579,6 +217614,19 @@
 <parameter name="resid" type="int">
 </parameter>
 </method>
+<method name="setBottom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bottom" type="int">
+</parameter>
+</method>
 <method name="setClickable"
  return="void"
  abstract="false"
@@ -186787,6 +217835,21 @@
 <parameter name="keepScreenOn" type="boolean">
 </parameter>
 </method>
+<method name="setLayerType"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="layerType" type="int">
+</parameter>
+<parameter name="paint" type="android.graphics.Paint">
+</parameter>
+</method>
 <method name="setLayoutParams"
  return="void"
  abstract="false"
@@ -186800,6 +217863,19 @@
 <parameter name="params" type="android.view.ViewGroup.LayoutParams">
 </parameter>
 </method>
+<method name="setLeft"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="left" type="int">
+</parameter>
+</method>
 <method name="setLongClickable"
  return="void"
  abstract="false"
@@ -186867,6 +217943,19 @@
 <parameter name="nextFocusDownId" type="int">
 </parameter>
 </method>
+<method name="setNextFocusForwardId"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="nextFocusForwardId" type="int">
+</parameter>
+</method>
 <method name="setNextFocusLeftId"
  return="void"
  abstract="false"
@@ -186932,6 +218021,19 @@
 <parameter name="l" type="android.view.View.OnCreateContextMenuListener">
 </parameter>
 </method>
+<method name="setOnDragListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="l" type="android.view.View.OnDragListener">
+</parameter>
+</method>
 <method name="setOnFocusChangeListener"
  return="void"
  abstract="false"
@@ -187016,6 +218118,32 @@
 <parameter name="bottom" type="int">
 </parameter>
 </method>
+<method name="setPivotX"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pivotX" type="float">
+</parameter>
+</method>
+<method name="setPivotY"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pivotY" type="float">
+</parameter>
+</method>
 <method name="setPressed"
  return="void"
  abstract="false"
@@ -187029,6 +218157,58 @@
 <parameter name="pressed" type="boolean">
 </parameter>
 </method>
+<method name="setRight"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="right" type="int">
+</parameter>
+</method>
+<method name="setRotation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rotation" type="float">
+</parameter>
+</method>
+<method name="setRotationX"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rotationX" type="float">
+</parameter>
+</method>
+<method name="setRotationY"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rotationY" type="float">
+</parameter>
+</method>
 <method name="setSaveEnabled"
  return="void"
  abstract="false"
@@ -187042,6 +218222,45 @@
 <parameter name="enabled" type="boolean">
 </parameter>
 </method>
+<method name="setSaveFromParentEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
+<method name="setScaleX"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scaleX" type="float">
+</parameter>
+</method>
+<method name="setScaleY"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scaleY" type="float">
+</parameter>
+</method>
 <method name="setScrollBarStyle"
  return="void"
  abstract="false"
@@ -187135,6 +218354,19 @@
 <parameter name="tag" type="java.lang.Object">
 </parameter>
 </method>
+<method name="setTop"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="top" type="int">
+</parameter>
+</method>
 <method name="setTouchDelegate"
  return="void"
  abstract="false"
@@ -187148,6 +218380,32 @@
 <parameter name="delegate" type="android.view.TouchDelegate">
 </parameter>
 </method>
+<method name="setTranslationX"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="translationX" type="float">
+</parameter>
+</method>
+<method name="setTranslationY"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="translationY" type="float">
+</parameter>
+</method>
 <method name="setVerticalFadingEdgeEnabled"
  return="void"
  abstract="false"
@@ -187174,6 +218432,19 @@
 <parameter name="verticalScrollBarEnabled" type="boolean">
 </parameter>
 </method>
+<method name="setVerticalScrollbarPosition"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
 <method name="setVisibility"
  return="void"
  abstract="false"
@@ -187213,6 +218484,32 @@
 <parameter name="willNotDraw" type="boolean">
 </parameter>
 </method>
+<method name="setX"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+</method>
+<method name="setY"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="y" type="float">
+</parameter>
+</method>
 <method name="showContextMenu"
  return="boolean"
  abstract="false"
@@ -187224,6 +218521,19 @@
  visibility="public"
 >
 </method>
+<method name="startActionMode"
+ return="android.view.ActionMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
 <method name="startAnimation"
  return="void"
  abstract="false"
@@ -187237,6 +218547,25 @@
 <parameter name="animation" type="android.view.animation.Animation">
 </parameter>
 </method>
+<method name="startDrag"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="android.content.ClipData">
+</parameter>
+<parameter name="shadowBuilder" type="android.view.View.DragShadowBuilder">
+</parameter>
+<parameter name="myLocalState" type="java.lang.Object">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
 <method name="unscheduleDrawable"
  return="void"
  abstract="false"
@@ -187608,6 +218937,83 @@
  visibility="public"
 >
 </field>
+<field name="LAYER_TYPE_HARDWARE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LAYER_TYPE_NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LAYER_TYPE_SOFTWARE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MEASURED_HEIGHT_STATE_SHIFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MEASURED_SIZE_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16777215"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MEASURED_STATE_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-16777216"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MEASURED_STATE_TOO_SMALL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16777216"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="NO_ID"
  type="int"
  transient="false"
@@ -187861,6 +219267,39 @@
  visibility="public"
 >
 </field>
+<field name="SCROLLBAR_POSITION_DEFAULT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCROLLBAR_POSITION_LEFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCROLLBAR_POSITION_RIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SELECTED_STATE_SET"
  type="int[]"
  transient="false"
@@ -187967,6 +219406,64 @@
 >
 </field>
 </class>
+<class name="View.DragShadowBuilder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="View.DragShadowBuilder"
+ type="android.view.View.DragShadowBuilder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</constructor>
+<method name="getView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onDrawShadow"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="canvas" type="android.graphics.Canvas">
+</parameter>
+</method>
+<method name="onProvideShadowMetrics"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="shadowSize" type="android.graphics.Point">
+</parameter>
+<parameter name="shadowTouchPoint" type="android.graphics.Point">
+</parameter>
+</method>
+</class>
 <class name="View.MeasureSpec"
  extends="java.lang.Object"
  abstract="false"
@@ -188117,6 +219614,29 @@
 </parameter>
 </method>
 </interface>
+<interface name="View.OnDragListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onDrag"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.view.View">
+</parameter>
+<parameter name="event" type="android.view.DragEvent">
+</parameter>
+</method>
+</interface>
 <interface name="View.OnFocusChangeListener"
  abstract="true"
  static="true"
@@ -188165,6 +219685,43 @@
 </parameter>
 </method>
 </interface>
+<interface name="View.OnLayoutChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onLayoutChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.view.View">
+</parameter>
+<parameter name="left" type="int">
+</parameter>
+<parameter name="top" type="int">
+</parameter>
+<parameter name="right" type="int">
+</parameter>
+<parameter name="bottom" type="int">
+</parameter>
+<parameter name="oldLeft" type="int">
+</parameter>
+<parameter name="oldTop" type="int">
+</parameter>
+<parameter name="oldRight" type="int">
+</parameter>
+<parameter name="oldBottom" type="int">
+</parameter>
+</method>
+</interface>
 <interface name="View.OnLongClickListener"
  abstract="true"
  static="true"
@@ -189190,6 +220747,19 @@
 <parameter name="container" type="android.util.SparseArray&lt;android.os.Parcelable&gt;">
 </parameter>
 </method>
+<method name="dispatchSetActivated"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="activated" type="boolean">
+</parameter>
+</method>
 <method name="dispatchSetSelected"
  return="void"
  abstract="false"
@@ -189233,6 +220803,19 @@
 <parameter name="drawingTime" type="long">
 </parameter>
 </method>
+<method name="endViewTransition"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
 <method name="focusSearch"
  return="android.view.View"
  abstract="false"
@@ -189443,6 +221026,17 @@
  visibility="public"
 >
 </method>
+<method name="getLayoutTransition"
+ return="android.animation.LayoutTransition"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getPersistentDrawingCache"
  return="int"
  abstract="false"
@@ -189541,6 +221135,36 @@
  visibility="protected"
 >
 </method>
+<method name="isMotionEventSplittingEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="layout"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="l" type="int">
+</parameter>
+<parameter name="t" type="int">
+</parameter>
+<parameter name="r" type="int">
+</parameter>
+<parameter name="b" type="int">
+</parameter>
+</method>
 <method name="measureChild"
  return="void"
  abstract="false"
@@ -190004,6 +221628,32 @@
 <parameter name="animationListener" type="android.view.animation.Animation.AnimationListener">
 </parameter>
 </method>
+<method name="setLayoutTransition"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="transition" type="android.animation.LayoutTransition">
+</parameter>
+</method>
+<method name="setMotionEventSplittingEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="split" type="boolean">
+</parameter>
+</method>
 <method name="setOnHierarchyChangeListener"
  return="void"
  abstract="false"
@@ -190056,6 +221706,21 @@
 <parameter name="originalView" type="android.view.View">
 </parameter>
 </method>
+<method name="startActionModeForChild"
+ return="android.view.ActionMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="originalView" type="android.view.View">
+</parameter>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
 <method name="startLayoutAnimation"
  return="void"
  abstract="false"
@@ -190067,6 +221732,19 @@
  visibility="public"
 >
 </method>
+<method name="startViewTransition"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
 <method name="updateViewLayout"
  return="void"
  abstract="false"
@@ -190746,6 +222424,21 @@
 <parameter name="originalView" type="android.view.View">
 </parameter>
 </method>
+<method name="startActionModeForChild"
+ return="android.view.ActionMode"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="originalView" type="android.view.View">
+</parameter>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
 </interface>
 <class name="ViewStub"
  extends="android.view.View"
@@ -191422,6 +223115,19 @@
  visibility="public"
 >
 </method>
+<method name="hasFeature"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="feature" type="int">
+</parameter>
+</method>
 <method name="hasSoftInputMode"
  return="boolean"
  abstract="false"
@@ -191433,6 +223139,19 @@
  visibility="protected"
 >
 </method>
+<method name="invalidatePanelMenu"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="featureId" type="int">
+</parameter>
+</method>
 <method name="isActive"
  return="boolean"
  abstract="false"
@@ -191994,6 +223713,25 @@
 <parameter name="appName" type="java.lang.String">
 </parameter>
 </method>
+<method name="setWindowManager"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="wm" type="android.view.WindowManager">
+</parameter>
+<parameter name="appToken" type="android.os.IBinder">
+</parameter>
+<parameter name="appName" type="java.lang.String">
+</parameter>
+<parameter name="hardwareAccelerated" type="boolean">
+</parameter>
+</method>
 <method name="superDispatchKeyEvent"
  return="boolean"
  abstract="true"
@@ -192007,6 +223745,19 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="superDispatchKeyShortcutEvent"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="superDispatchTouchEvent"
  return="boolean"
  abstract="true"
@@ -192098,6 +223849,39 @@
  visibility="protected"
 >
 </field>
+<field name="FEATURE_ACTION_BAR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FEATURE_ACTION_BAR_OVERLAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FEATURE_ACTION_MODE_OVERLAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FEATURE_CONTEXT_MENU"
  type="int"
  transient="false"
@@ -192306,6 +224090,19 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="dispatchKeyShortcutEvent"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="dispatchPopulateAccessibilityEvent"
  return="boolean"
  abstract="true"
@@ -192345,6 +224142,32 @@
 <parameter name="event" type="android.view.MotionEvent">
 </parameter>
 </method>
+<method name="onActionModeFinished"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
+<method name="onActionModeStarted"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+</method>
 <method name="onAttachedToWindow"
  return="void"
  abstract="true"
@@ -192505,6 +224328,19 @@
 <parameter name="hasFocus" type="boolean">
 </parameter>
 </method>
+<method name="onWindowStartingActionMode"
+ return="android.view.ActionMode"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="callback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
 </interface>
 <interface name="WindowManager"
  abstract="true"
@@ -192968,6 +224804,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_HARDWARE_ACCELERATED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16777216"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_IGNORE_CHEEK_PRESSES"
  type="int"
  transient="false"
@@ -193100,6 +224947,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_SPLIT_TOUCH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8388608"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_TOUCHABLE_WHEN_WAKING"
  type="int"
  transient="false"
@@ -193228,7 +225086,7 @@
  value="0"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -193239,7 +225097,7 @@
  value="3"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -193265,6 +225123,17 @@
  visibility="public"
 >
 </field>
+<field name="SOFT_INPUT_ADJUST_NOTHING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="48"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="SOFT_INPUT_ADJUST_PAN"
  type="int"
  transient="false"
@@ -193758,7 +225627,7 @@
  volatile="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -194854,6 +226723,17 @@
  visibility="public"
 >
 </method>
+<method name="getScaleFactor"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
 <method name="getStartOffset"
  return="long"
  abstract="false"
@@ -194891,6 +226771,23 @@
 <parameter name="outTransformation" type="android.view.animation.Transformation">
 </parameter>
 </method>
+<method name="getTransformation"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="currentTime" type="long">
+</parameter>
+<parameter name="outTransformation" type="android.view.animation.Transformation">
+</parameter>
+<parameter name="scale" type="float">
+</parameter>
+</method>
 <method name="getZAdjustment"
  return="int"
  abstract="false"
@@ -196176,19 +228073,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<method name="getInterpolation"
- return="float"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="input" type="float">
-</parameter>
-</method>
+<implements name="android.animation.TimeInterpolator">
+</implements>
 </interface>
 <class name="LayoutAnimationController"
  extends="java.lang.Object"
@@ -197096,6 +228982,19 @@
 <parameter name="text" type="android.view.inputmethod.CompletionInfo">
 </parameter>
 </method>
+<method name="commitCorrection"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="correctionInfo" type="android.view.inputmethod.CorrectionInfo">
+</parameter>
+</method>
 <method name="commitText"
  return="boolean"
  abstract="false"
@@ -197516,6 +229415,100 @@
 >
 </field>
 </class>
+<class name="CorrectionInfo"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<constructor name="CorrectionInfo"
+ type="android.view.inputmethod.CorrectionInfo"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="offset" type="int">
+</parameter>
+<parameter name="oldText" type="java.lang.CharSequence">
+</parameter>
+<parameter name="newText" type="java.lang.CharSequence">
+</parameter>
+</constructor>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNewText"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getOffset"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getOldText"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="EditorInfo"
  extends="java.lang.Object"
  abstract="false"
@@ -197562,6 +229555,19 @@
 <parameter name="prefix" type="java.lang.String">
 </parameter>
 </method>
+<method name="makeCompatible"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetSdkVersion" type="int">
+</parameter>
+</method>
 <method name="writeToParcel"
  return="void"
  abstract="false"
@@ -197631,6 +229637,17 @@
  visibility="public"
 >
 </field>
+<field name="IME_ACTION_PREVIOUS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="IME_ACTION_SEARCH"
  type="int"
  transient="false"
@@ -197664,6 +229681,28 @@
  visibility="public"
 >
 </field>
+<field name="IME_FLAG_NAVIGATE_NEXT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="134217728"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IME_FLAG_NAVIGATE_PREVIOUS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="67108864"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="IME_FLAG_NO_ACCESSORY_ACTION"
  type="int"
  transient="false"
@@ -197697,6 +229736,17 @@
  visibility="public"
 >
 </field>
+<field name="IME_FLAG_NO_FULLSCREEN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="33554432"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="IME_MASK_ACTION"
  type="int"
  transient="false"
@@ -198265,6 +230315,19 @@
 <parameter name="text" type="android.view.inputmethod.CompletionInfo">
 </parameter>
 </method>
+<method name="commitCorrection"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="correctionInfo" type="android.view.inputmethod.CorrectionInfo">
+</parameter>
+</method>
 <method name="commitText"
  return="boolean"
  abstract="true"
@@ -198582,6 +230645,19 @@
 <parameter name="text" type="android.view.inputmethod.CompletionInfo">
 </parameter>
 </method>
+<method name="commitCorrection"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="correctionInfo" type="android.view.inputmethod.CorrectionInfo">
+</parameter>
+</method>
 <method name="commitText"
  return="boolean"
  abstract="false"
@@ -198864,6 +230940,19 @@
 <parameter name="binding" type="android.view.inputmethod.InputBinding">
 </parameter>
 </method>
+<method name="changeInputMethodSubtype"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="subtype" type="android.view.inputmethod.InputMethodSubtype">
+</parameter>
+</method>
 <method name="createSession"
  return="void"
  abstract="true"
@@ -199187,6 +231276,17 @@
  visibility="public"
 >
 </method>
+<method name="getSubtypes"
+ return="java.util.ArrayList&lt;android.view.inputmethod.InputMethodSubtype&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="loadIcon"
  return="android.graphics.drawable.Drawable"
  abstract="false"
@@ -199262,6 +231362,17 @@
 <parameter name="completions" type="android.view.inputmethod.CompletionInfo[]">
 </parameter>
 </method>
+<method name="getCurrentInputMethodSubtype"
+ return="android.view.inputmethod.InputMethodSubtype"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getEnabledInputMethodList"
  return="java.util.List&lt;android.view.inputmethod.InputMethodInfo&gt;"
  abstract="false"
@@ -199273,6 +231384,21 @@
  visibility="public"
 >
 </method>
+<method name="getEnabledInputMethodSubtypeList"
+ return="java.util.List&lt;android.view.inputmethod.InputMethodSubtype&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="imi" type="android.view.inputmethod.InputMethodInfo">
+</parameter>
+<parameter name="allowsImplicitlySelectedSubtypes" type="boolean">
+</parameter>
+</method>
 <method name="getInputMethodList"
  return="java.util.List&lt;android.view.inputmethod.InputMethodInfo&gt;"
  abstract="false"
@@ -199284,6 +231410,17 @@
  visibility="public"
 >
 </method>
+<method name="getShortcutInputMethodsAndSubtypes"
+ return="java.util.Map&lt;android.view.inputmethod.InputMethodInfo, java.util.List&lt;android.view.inputmethod.InputMethodSubtype&gt;&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="hideSoftInputFromInputMethod"
  return="void"
  abstract="false"
@@ -199433,6 +231570,19 @@
 <parameter name="data" type="android.os.Bundle">
 </parameter>
 </method>
+<method name="setCurrentInputMethodSubtype"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="subtype" type="android.view.inputmethod.InputMethodSubtype">
+</parameter>
+</method>
 <method name="setInputMethod"
  return="void"
  abstract="false"
@@ -199448,6 +231598,36 @@
 <parameter name="id" type="java.lang.String">
 </parameter>
 </method>
+<method name="setInputMethodAndSubtype"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="token" type="android.os.IBinder">
+</parameter>
+<parameter name="id" type="java.lang.String">
+</parameter>
+<parameter name="subtype" type="android.view.inputmethod.InputMethodSubtype">
+</parameter>
+</method>
+<method name="showInputMethodAndSubtypeEnabler"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="topId" type="java.lang.String">
+</parameter>
+</method>
 <method name="showInputMethodPicker"
  return="void"
  abstract="false"
@@ -199523,6 +231703,19 @@
 <parameter name="iconId" type="int">
 </parameter>
 </method>
+<method name="switchToLastInputMethod"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="imeToken" type="android.os.IBinder">
+</parameter>
+</method>
 <method name="toggleSoftInput"
  return="void"
  abstract="false"
@@ -199873,6 +232066,108 @@
 </parameter>
 </method>
 </interface>
+<class name="InputMethodSubtype"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExtraValue"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getIconResId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLocale"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMode"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNameResId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="parcelableFlags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 </package>
 <package name="android.webkit"
 >
@@ -199881,7 +232176,7 @@
  abstract="false"
  static="false"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="CacheManager"
@@ -199899,7 +232194,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -199921,7 +232216,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="url" type="java.lang.String">
@@ -199936,7 +232231,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -199947,7 +232242,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="url" type="java.lang.String">
@@ -199972,7 +232267,7 @@
  abstract="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="CacheManager.CacheResult"
@@ -202246,6 +234541,101 @@
 </parameter>
 </method>
 </interface>
+<class name="WebResourceResponse"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="WebResourceResponse"
+ type="android.webkit.WebResourceResponse"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+<parameter name="encoding" type="java.lang.String">
+</parameter>
+<parameter name="data" type="java.io.InputStream">
+</parameter>
+</constructor>
+<method name="getData"
+ return="java.io.InputStream"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEncoding"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMimeType"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="java.io.InputStream">
+</parameter>
+</method>
+<method name="setEncoding"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="encoding" type="java.lang.String">
+</parameter>
+</method>
+<method name="setMimeType"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</method>
+</class>
 <class name="WebSettings"
  extends="java.lang.Object"
  abstract="false"
@@ -202254,6 +234644,28 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="enableSmoothTransition"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAllowContentAccess"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getAllowFileAccess"
  return="boolean"
  abstract="false"
@@ -202672,6 +235084,19 @@
  visibility="public"
 >
 </method>
+<method name="setAllowContentAccess"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="allow" type="boolean">
+</parameter>
+</method>
 <method name="setAllowFileAccess"
  return="void"
  abstract="false"
@@ -202880,6 +235305,19 @@
 <parameter name="flag" type="boolean">
 </parameter>
 </method>
+<method name="setEnableSmoothTransition"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
 <method name="setFantasyFontFamily"
  return="void"
  abstract="false"
@@ -203825,6 +236263,22 @@
 <parameter name="defStyle" type="int">
 </parameter>
 </constructor>
+<constructor name="WebView"
+ type="android.webkit.WebView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+<parameter name="privateBrowsing" type="boolean">
+</parameter>
+</constructor>
 <method name="addJavascriptInterface"
  return="void"
  abstract="false"
@@ -203875,6 +236329,28 @@
  visibility="public"
 >
 </method>
+<method name="canZoomIn"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="canZoomOut"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="capturePicture"
  return="android.graphics.Picture"
  abstract="false"
@@ -204234,6 +236710,17 @@
  visibility="public"
 >
 </method>
+<method name="getVisibleTitleHeight"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getZoomControls"
  return="android.view.View"
  abstract="false"
@@ -204291,6 +236778,17 @@
  visibility="public"
 >
 </method>
+<method name="isPrivateBrowsingEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="loadData"
  return="void"
  abstract="false"
@@ -204402,6 +236900,28 @@
 <parameter name="newFocus" type="android.view.View">
 </parameter>
 </method>
+<method name="onPause"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onResume"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="overlayHorizontalScrollbar"
  return="boolean"
  abstract="false"
@@ -204500,6 +237020,19 @@
  visibility="public"
 >
 </method>
+<method name="removeJavascriptInterface"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="interfaceName" type="java.lang.String">
+</parameter>
+</method>
 <method name="requestFocusNodeHref"
  return="void"
  abstract="false"
@@ -204610,6 +237143,36 @@
 <parameter name="outState" type="android.os.Bundle">
 </parameter>
 </method>
+<method name="saveWebArchive"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filename" type="java.lang.String">
+</parameter>
+</method>
+<method name="saveWebArchive"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="basename" type="java.lang.String">
+</parameter>
+<parameter name="autoname" type="boolean">
+</parameter>
+<parameter name="callback" type="android.webkit.ValueCallback&lt;java.lang.String&gt;">
+</parameter>
+</method>
 <method name="setCertificate"
  return="void"
  abstract="false"
@@ -204759,6 +237322,21 @@
 <parameter name="client" type="android.webkit.WebViewClient">
 </parameter>
 </method>
+<method name="showFindDialog"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.String">
+</parameter>
+<parameter name="showIme" type="boolean">
+</parameter>
+</method>
 <method name="stopLoading"
  return="void"
  abstract="false"
@@ -205232,6 +237810,21 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="shouldInterceptRequest"
+ return="android.webkit.WebResourceResponse"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.webkit.WebView">
+</parameter>
+<parameter name="url" type="java.lang.String">
+</parameter>
+</method>
 <method name="shouldOverrideKeyEvent"
  return="boolean"
  abstract="false"
@@ -205614,6 +238207,17 @@
 <parameter name="after" type="int">
 </parameter>
 </method>
+<method name="clearChoices"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="clearTextFilter"
  return="void"
  abstract="false"
@@ -205636,6 +238240,61 @@
  visibility="public"
 >
 </method>
+<method name="getCheckedItemCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCheckedItemIds"
+ return="long[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCheckedItemPosition"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCheckedItemPositions"
+ return="android.util.SparseBooleanArray"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getChoiceMode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getListPaddingBottom"
  return="int"
  abstract="false"
@@ -205757,6 +238416,17 @@
  visibility="public"
 >
 </method>
+<method name="isFastScrollAlwaysVisible"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isFastScrollEnabled"
  return="boolean"
  abstract="false"
@@ -205779,6 +238449,19 @@
  visibility="protected"
 >
 </method>
+<method name="isItemChecked"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
 <method name="isScrollingCacheEnabled"
  return="boolean"
  abstract="false"
@@ -205858,6 +238541,28 @@
  visibility="public"
 >
 </method>
+<method name="onRemoteAdapterConnected"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onRemoteAdapterDisconnected"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="onRestoreInstanceState"
  return="void"
  abstract="false"
@@ -205957,6 +238662,19 @@
 <parameter name="views" type="java.util.List&lt;android.view.View&gt;">
 </parameter>
 </method>
+<method name="setAdapter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.widget.ListAdapter">
+</parameter>
+</method>
 <method name="setCacheColorHint"
  return="void"
  abstract="false"
@@ -205970,6 +238688,19 @@
 <parameter name="color" type="int">
 </parameter>
 </method>
+<method name="setChoiceMode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="choiceMode" type="int">
+</parameter>
+</method>
 <method name="setDrawSelectorOnTop"
  return="void"
  abstract="false"
@@ -205983,6 +238714,19 @@
 <parameter name="onTop" type="boolean">
 </parameter>
 </method>
+<method name="setFastScrollAlwaysVisible"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="alwaysShow" type="boolean">
+</parameter>
+</method>
 <method name="setFastScrollEnabled"
  return="void"
  abstract="false"
@@ -206009,6 +238753,47 @@
 <parameter name="filterText" type="java.lang.String">
 </parameter>
 </method>
+<method name="setFriction"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="friction" type="float">
+</parameter>
+</method>
+<method name="setItemChecked"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+<parameter name="value" type="boolean">
+</parameter>
+</method>
+<method name="setMultiChoiceModeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.widget.AbsListView.MultiChoiceModeListener">
+</parameter>
+</method>
 <method name="setOnScrollListener"
  return="void"
  abstract="false"
@@ -206035,6 +238820,19 @@
 <parameter name="listener" type="android.widget.AbsListView.RecyclerListener">
 </parameter>
 </method>
+<method name="setRemoteViewsAdapter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
 <method name="setScrollIndicators"
  return="void"
  abstract="false"
@@ -206141,6 +238939,19 @@
 <parameter name="mode" type="int">
 </parameter>
 </method>
+<method name="setVelocityScale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scale" type="float">
+</parameter>
+</method>
 <method name="smoothScrollBy"
  return="void"
  abstract="false"
@@ -206184,6 +238995,38 @@
 <parameter name="boundPosition" type="int">
 </parameter>
 </method>
+<method name="smoothScrollToPositionFromTop"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+<parameter name="duration" type="int">
+</parameter>
+</method>
+<method name="smoothScrollToPositionFromTop"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
 <method name="verifyDrawable"
  return="boolean"
  abstract="false"
@@ -206208,6 +239051,17 @@
  visibility="public"
 >
 </field>
+<field name="CHOICE_MODE_MULTIPLE_MODAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="CHOICE_MODE_NONE"
  type="int"
  transient="false"
@@ -206321,6 +239175,35 @@
 </parameter>
 </constructor>
 </class>
+<interface name="AbsListView.MultiChoiceModeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.ActionMode.Callback">
+</implements>
+<method name="onItemCheckedStateChanged"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="android.view.ActionMode">
+</parameter>
+<parameter name="position" type="int">
+</parameter>
+<parameter name="id" type="long">
+</parameter>
+<parameter name="checked" type="boolean">
+</parameter>
+</method>
+</interface>
 <interface name="AbsListView.OnScrollListener"
  abstract="true"
  static="true"
@@ -206417,6 +239300,27 @@
 </parameter>
 </method>
 </interface>
+<interface name="AbsListView.SelectionBoundsAdjuster"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="adjustListItemSelectionBounds"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bounds" type="android.graphics.Rect">
+</parameter>
+</method>
+</interface>
 <class name="AbsSeekBar"
  extends="android.widget.ProgressBar"
  abstract="true"
@@ -207497,6 +240401,415 @@
 </parameter>
 </method>
 </interface>
+<class name="AdapterViewAnimator"
+ extends="android.widget.AdapterView"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="AdapterViewAnimator"
+ type="android.widget.AdapterViewAnimator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="AdapterViewAnimator"
+ type="android.widget.AdapterViewAnimator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<method name="advance"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAdapter"
+ return="android.widget.Adapter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDisplayedChild"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInAnimation"
+ return="android.animation.ObjectAnimator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getOutAnimation"
+ return="android.animation.ObjectAnimator"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSelectedView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onRemoteAdapterConnected"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onRemoteAdapterDisconnected"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onRestoreInstanceState"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="state" type="android.os.Parcelable">
+</parameter>
+</method>
+<method name="onSaveInstanceState"
+ return="android.os.Parcelable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setAdapter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.widget.Adapter">
+</parameter>
+</method>
+<method name="setAnimateFirstView"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animate" type="boolean">
+</parameter>
+</method>
+<method name="setDisplayedChild"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="whichChild" type="int">
+</parameter>
+</method>
+<method name="setInAnimation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="inAnimation" type="android.animation.ObjectAnimator">
+</parameter>
+</method>
+<method name="setInAnimation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="resourceID" type="int">
+</parameter>
+</method>
+<method name="setOutAnimation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="outAnimation" type="android.animation.ObjectAnimator">
+</parameter>
+</method>
+<method name="setOutAnimation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="resourceID" type="int">
+</parameter>
+</method>
+<method name="setRemoteViewsAdapter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="setSelection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+<method name="showNext"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="showPrevious"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="willBeAdvancedByHost"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="AdapterViewFlipper"
+ extends="android.widget.AdapterViewAnimator"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="AdapterViewFlipper"
+ type="android.widget.AdapterViewFlipper"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="AdapterViewFlipper"
+ type="android.widget.AdapterViewFlipper"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<method name="isAutoStart"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isFlipping"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setAutoStart"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="autoStart" type="boolean">
+</parameter>
+</method>
+<method name="setFlipInterval"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="milliseconds" type="int">
+</parameter>
+</method>
+<method name="startFlipping"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="stopFlipping"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
 <class name="AlphabetIndexer"
  extends="android.database.DataSetObserver"
  abstract="false"
@@ -207771,6 +241084,32 @@
 <parameter name="object" type="T">
 </parameter>
 </method>
+<method name="addAll"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="collection" type="java.util.Collection&lt;? extends T&gt;">
+</parameter>
+</method>
+<method name="addAll"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="items" type="T...">
+</parameter>
+</method>
 <method name="clear"
  return="void"
  abstract="false"
@@ -208922,6 +242261,228 @@
 </parameter>
 </constructor>
 </class>
+<class name="CalendarView"
+ extends="android.widget.FrameLayout"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="CalendarView"
+ type="android.widget.CalendarView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="CalendarView"
+ type="android.widget.CalendarView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="CalendarView"
+ type="android.widget.CalendarView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
+<method name="getDate"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFirstDayOfWeek"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMaxDate"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMinDate"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getShowWeekNumber"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setDate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="date" type="long">
+</parameter>
+</method>
+<method name="setDate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="date" type="long">
+</parameter>
+<parameter name="animate" type="boolean">
+</parameter>
+<parameter name="center" type="boolean">
+</parameter>
+</method>
+<method name="setFirstDayOfWeek"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="firstDayOfWeek" type="int">
+</parameter>
+</method>
+<method name="setMaxDate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="maxDate" type="long">
+</parameter>
+</method>
+<method name="setMinDate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minDate" type="long">
+</parameter>
+</method>
+<method name="setOnDateChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.widget.CalendarView.OnDateChangeListener">
+</parameter>
+</method>
+<method name="setShowWeekNumber"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="showWeekNumber" type="boolean">
+</parameter>
+</method>
+</class>
+<interface name="CalendarView.OnDateChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onSelectedDayChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.widget.CalendarView">
+</parameter>
+<parameter name="year" type="int">
+</parameter>
+<parameter name="month" type="int">
+</parameter>
+<parameter name="dayOfMonth" type="int">
+</parameter>
+</method>
+</interface>
 <class name="CheckBox"
  extends="android.widget.CompoundButton"
  abstract="false"
@@ -209436,7 +242997,7 @@
  type="android.widget.CursorAdapter"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="context" type="android.content.Context">
@@ -209458,6 +243019,20 @@
 <parameter name="autoRequery" type="boolean">
 </parameter>
 </constructor>
+<constructor name="CursorAdapter"
+ type="android.widget.CursorAdapter"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="c" type="android.database.Cursor">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</constructor>
 <method name="bindView"
  return="void"
  abstract="true"
@@ -209595,7 +243170,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="protected"
 >
 <parameter name="context" type="android.content.Context">
@@ -209676,6 +243251,41 @@
 <parameter name="filterQueryProvider" type="android.widget.FilterQueryProvider">
 </parameter>
 </method>
+<method name="swapCursor"
+ return="android.database.Cursor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="newCursor" type="android.database.Cursor">
+</parameter>
+</method>
+<field name="FLAG_AUTO_REQUERY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="deprecated"
+ visibility="public"
+>
+</field>
+<field name="FLAG_REGISTER_CONTENT_OBSERVER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="CursorTreeAdapter"
  extends="android.widget.BaseExpandableListAdapter"
@@ -210119,6 +243729,17 @@
 <parameter name="defStyle" type="int">
 </parameter>
 </constructor>
+<method name="getCalendarViewShown"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getDayOfMonth"
  return="int"
  abstract="false"
@@ -210130,6 +243751,28 @@
  visibility="public"
 >
 </method>
+<method name="getMaxDate"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMinDate"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getMonth"
  return="int"
  abstract="false"
@@ -210141,6 +243784,17 @@
  visibility="public"
 >
 </method>
+<method name="getSpinnersShown"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getYear"
  return="int"
  abstract="false"
@@ -210171,6 +243825,58 @@
 <parameter name="onDateChangedListener" type="android.widget.DatePicker.OnDateChangedListener">
 </parameter>
 </method>
+<method name="setCalendarViewShown"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="shown" type="boolean">
+</parameter>
+</method>
+<method name="setMaxDate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="maxDate" type="long">
+</parameter>
+</method>
+<method name="setMinDate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minDate" type="long">
+</parameter>
+</method>
+<method name="setSpinnersShown"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="shown" type="boolean">
+</parameter>
+</method>
 <method name="updateDate"
  return="void"
  abstract="false"
@@ -210183,7 +243889,7 @@
 >
 <parameter name="year" type="int">
 </parameter>
-<parameter name="monthOfYear" type="int">
+<parameter name="month" type="int">
 </parameter>
 <parameter name="dayOfMonth" type="int">
 </parameter>
@@ -212115,7 +245821,7 @@
  visibility="public"
 >
 </method>
-<method name="getStretchMode"
+<method name="getNumColumns"
  return="int"
  abstract="false"
  native="false"
@@ -212126,8 +245832,8 @@
  visibility="public"
 >
 </method>
-<method name="setAdapter"
- return="void"
+<method name="getStretchMode"
+ return="int"
  abstract="false"
  native="false"
  synchronized="false"
@@ -212136,8 +245842,6 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="adapter" type="android.widget.ListAdapter">
-</parameter>
 </method>
 <method name="setColumnWidth"
  return="void"
@@ -212230,6 +245934,19 @@
 <parameter name="verticalSpacing" type="int">
 </parameter>
 </method>
+<method name="smoothScrollByOffset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="offset" type="int">
+</parameter>
+</method>
 <field name="AUTO_FIT"
  type="int"
  transient="false"
@@ -212973,6 +246690,17 @@
  visibility="public"
 >
 </method>
+<method name="getBaselineAlignBottom"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getDrawable"
  return="android.graphics.drawable.Drawable"
  abstract="false"
@@ -213045,6 +246773,32 @@
 <parameter name="alpha" type="int">
 </parameter>
 </method>
+<method name="setBaseline"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="baseline" type="int">
+</parameter>
+</method>
+<method name="setBaselineAlignBottom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="aligned" type="boolean">
+</parameter>
+</method>
 <method name="setColorFilter"
  return="void"
  abstract="false"
@@ -213301,6 +247055,20 @@
 <parameter name="attrs" type="android.util.AttributeSet">
 </parameter>
 </constructor>
+<constructor name="LinearLayout"
+ type="android.widget.LinearLayout"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
 <method name="getBaselineAlignedChildIndex"
  return="int"
  abstract="false"
@@ -213323,6 +247091,17 @@
  visibility="public"
 >
 </method>
+<method name="getShowDividers"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getWeightSum"
  return="float"
  abstract="false"
@@ -213345,6 +247124,17 @@
  visibility="public"
 >
 </method>
+<method name="isMeasureWithLargestChildEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="onLayout"
  return="void"
  abstract="false"
@@ -213392,6 +247182,19 @@
 <parameter name="i" type="int">
 </parameter>
 </method>
+<method name="setDividerDrawable"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="divider" type="android.graphics.drawable.Drawable">
+</parameter>
+</method>
 <method name="setGravity"
  return="void"
  abstract="false"
@@ -213418,6 +247221,19 @@
 <parameter name="horizontalGravity" type="int">
 </parameter>
 </method>
+<method name="setMeasureWithLargestChildEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
 <method name="setOrientation"
  return="void"
  abstract="false"
@@ -213431,6 +247247,19 @@
 <parameter name="orientation" type="int">
 </parameter>
 </method>
+<method name="setShowDividers"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="showDividers" type="int">
+</parameter>
+</method>
 <method name="setVerticalGravity"
  return="void"
  abstract="false"
@@ -213468,6 +247297,50 @@
  visibility="public"
 >
 </field>
+<field name="SHOW_DIVIDER_BEGINNING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHOW_DIVIDER_END"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHOW_DIVIDER_MIDDLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SHOW_DIVIDER_NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="VERTICAL"
  type="int"
  transient="false"
@@ -213614,6 +247487,691 @@
 </parameter>
 </method>
 </interface>
+<class name="ListPopupWindow"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ListPopupWindow"
+ type="android.widget.ListPopupWindow"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="ListPopupWindow"
+ type="android.widget.ListPopupWindow"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="ListPopupWindow"
+ type="android.widget.ListPopupWindow"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyleAttr" type="int">
+</parameter>
+</constructor>
+<constructor name="ListPopupWindow"
+ type="android.widget.ListPopupWindow"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyleAttr" type="int">
+</parameter>
+<parameter name="defStyleRes" type="int">
+</parameter>
+</constructor>
+<method name="clearListSelection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="dismiss"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAnchorView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAnimationStyle"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBackground"
+ return="android.graphics.drawable.Drawable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHeight"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHorizontalOffset"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInputMethodMode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getListView"
+ return="android.widget.ListView"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPromptPosition"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSelectedItem"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSelectedItemId"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSelectedItemPosition"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSelectedView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSoftInputMode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getVerticalOffset"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getWidth"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isInputMethodNotNeeded"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isModal"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isShowing"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onKeyDown"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="onKeyPreIme"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="onKeyUp"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="performItemClick"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+<method name="postShow"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setAdapter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.widget.ListAdapter">
+</parameter>
+</method>
+<method name="setAnchorView"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="anchor" type="android.view.View">
+</parameter>
+</method>
+<method name="setAnimationStyle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animationStyle" type="int">
+</parameter>
+</method>
+<method name="setBackgroundDrawable"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="android.graphics.drawable.Drawable">
+</parameter>
+</method>
+<method name="setContentWidth"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+</method>
+<method name="setHeight"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="height" type="int">
+</parameter>
+</method>
+<method name="setHorizontalOffset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="setInputMethodMode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<method name="setListSelector"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="selector" type="android.graphics.drawable.Drawable">
+</parameter>
+</method>
+<method name="setModal"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="modal" type="boolean">
+</parameter>
+</method>
+<method name="setOnDismissListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.widget.PopupWindow.OnDismissListener">
+</parameter>
+</method>
+<method name="setOnItemClickListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="clickListener" type="android.widget.AdapterView.OnItemClickListener">
+</parameter>
+</method>
+<method name="setOnItemSelectedListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="selectedListener" type="android.widget.AdapterView.OnItemSelectedListener">
+</parameter>
+</method>
+<method name="setPromptPosition"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+<method name="setPromptView"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prompt" type="android.view.View">
+</parameter>
+</method>
+<method name="setSelection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+<method name="setSoftInputMode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<method name="setVerticalOffset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="setWidth"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+</method>
+<method name="show"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="INPUT_METHOD_FROM_FOCUSABLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INPUT_METHOD_NEEDED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INPUT_METHOD_NOT_NEEDED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MATCH_PARENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="POSITION_PROMPT_ABOVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="POSITION_PROMPT_BELOW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="WRAP_CONTENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="ListView"
  extends="android.widget.AbsListView"
  abstract="false"
@@ -213718,17 +248276,6 @@
 <parameter name="v" type="android.view.View">
 </parameter>
 </method>
-<method name="clearChoices"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="findViewTraversal"
  return="android.view.View"
  abstract="false"
@@ -213777,50 +248324,6 @@
  visibility="public"
 >
 </method>
-<method name="getCheckedItemIds"
- return="long[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getCheckedItemPosition"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getCheckedItemPositions"
- return="android.util.SparseBooleanArray"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getChoiceMode"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getDivider"
  return="android.graphics.drawable.Drawable"
  abstract="false"
@@ -213909,19 +248412,6 @@
  visibility="public"
 >
 </method>
-<method name="isItemChecked"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="position" type="int">
-</parameter>
-</method>
 <method name="removeFooterView"
  return="boolean"
  abstract="false"
@@ -213948,32 +248438,6 @@
 <parameter name="v" type="android.view.View">
 </parameter>
 </method>
-<method name="setAdapter"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="adapter" type="android.widget.ListAdapter">
-</parameter>
-</method>
-<method name="setChoiceMode"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="choiceMode" type="int">
-</parameter>
-</method>
 <method name="setDivider"
  return="void"
  abstract="false"
@@ -214026,21 +248490,6 @@
 <parameter name="headerDividersEnabled" type="boolean">
 </parameter>
 </method>
-<method name="setItemChecked"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="position" type="int">
-</parameter>
-<parameter name="value" type="boolean">
-</parameter>
-</method>
 <method name="setItemsCanFocus"
  return="void"
  abstract="false"
@@ -214119,6 +248568,19 @@
 <parameter name="y" type="int">
 </parameter>
 </method>
+<method name="smoothScrollByOffset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="offset" type="int">
+</parameter>
+</method>
 </class>
 <class name="ListView.FixedViewInfo"
  extends="java.lang.Object"
@@ -214618,6 +249080,325 @@
 </parameter>
 </method>
 </interface>
+<class name="NumberPicker"
+ extends="android.widget.LinearLayout"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="NumberPicker"
+ type="android.widget.NumberPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="NumberPicker"
+ type="android.widget.NumberPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="NumberPicker"
+ type="android.widget.NumberPicker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
+<method name="getDisplayedValues"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMaxValue"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMinValue"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getValue"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getWrapSelectorWheel"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setDisplayedValues"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="displayedValues" type="java.lang.String[]">
+</parameter>
+</method>
+<method name="setFormatter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="formatter" type="android.widget.NumberPicker.Formatter">
+</parameter>
+</method>
+<method name="setMaxValue"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="maxValue" type="int">
+</parameter>
+</method>
+<method name="setMinValue"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minValue" type="int">
+</parameter>
+</method>
+<method name="setOnLongPressUpdateInterval"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intervalMillis" type="long">
+</parameter>
+</method>
+<method name="setOnScrollListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="onScrollListener" type="android.widget.NumberPicker.OnScrollListener">
+</parameter>
+</method>
+<method name="setOnValueChangedListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="onValueChangedListener" type="android.widget.NumberPicker.OnValueChangedListener">
+</parameter>
+</method>
+<method name="setValue"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+<method name="setWrapSelectorWheel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="wrapSelector" type="boolean">
+</parameter>
+</method>
+</class>
+<interface name="NumberPicker.Formatter"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="format"
+ return="java.lang.String"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+</interface>
+<interface name="NumberPicker.OnScrollListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onScrollStateChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.widget.NumberPicker">
+</parameter>
+<parameter name="scrollState" type="int">
+</parameter>
+</method>
+<field name="SCROLL_STATE_FLING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCROLL_STATE_IDLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCROLL_STATE_TOUCH_SCROLL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
+<interface name="NumberPicker.OnValueChangedListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onValueChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="picker" type="android.widget.NumberPicker">
+</parameter>
+<parameter name="oldVal" type="int">
+</parameter>
+<parameter name="newVal" type="int">
+</parameter>
+</method>
+</interface>
 <class name="OverScroller"
  extends="java.lang.Object"
  abstract="false"
@@ -214664,6 +249445,24 @@
 <parameter name="bounceCoefficientY" type="float">
 </parameter>
 </constructor>
+<constructor name="OverScroller"
+ type="android.widget.OverScroller"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="interpolator" type="android.view.animation.Interpolator">
+</parameter>
+<parameter name="bounceCoefficientX" type="float">
+</parameter>
+<parameter name="bounceCoefficientY" type="float">
+</parameter>
+<parameter name="flywheel" type="boolean">
+</parameter>
+</constructor>
 <method name="abortAnimation"
  return="void"
  abstract="false"
@@ -214879,6 +249678,19 @@
 <parameter name="overY" type="int">
 </parameter>
 </method>
+<method name="setFriction"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="friction" type="float">
+</parameter>
+</method>
 <method name="springBack"
  return="boolean"
  abstract="false"
@@ -214943,6 +249755,105 @@
 </parameter>
 </method>
 </class>
+<class name="PopupMenu"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="PopupMenu"
+ type="android.widget.PopupMenu"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="anchor" type="android.view.View">
+</parameter>
+</constructor>
+<method name="dismiss"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMenu"
+ return="android.view.Menu"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMenuInflater"
+ return="android.view.MenuInflater"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setOnMenuItemClickListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.widget.PopupMenu.OnMenuItemClickListener">
+</parameter>
+</method>
+<method name="show"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="PopupMenu.OnMenuItemClickListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onMenuItemClick"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="item" type="android.view.MenuItem">
+</parameter>
+</method>
+</interface>
 <class name="PopupWindow"
  extends="java.lang.Object"
  abstract="false"
@@ -214994,6 +249905,22 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyleAttr" type="int">
+</parameter>
+<parameter name="defStyleRes" type="int">
+</parameter>
+</constructor>
+<constructor name="PopupWindow"
+ type="android.widget.PopupWindow"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
 </constructor>
 <constructor name="PopupWindow"
  type="android.widget.PopupWindow"
@@ -215218,6 +250145,17 @@
  visibility="public"
 >
 </method>
+<method name="isSplitTouchEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isTouchable"
  return="boolean"
  abstract="false"
@@ -215370,6 +250308,19 @@
 <parameter name="mode" type="int">
 </parameter>
 </method>
+<method name="setSplitTouchEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
 <method name="setTouchInterceptor"
  return="void"
  abstract="false"
@@ -216023,6 +250974,17 @@
 <parameter name="excludeMimes" type="java.lang.String[]">
 </parameter>
 </method>
+<method name="setImageToDefault"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="setMode"
  return="void"
  abstract="false"
@@ -217159,6 +252121,21 @@
 <parameter name="value" type="double">
 </parameter>
 </method>
+<method name="setEmptyView"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+<parameter name="emptyViewId" type="int">
+</parameter>
+</method>
 <method name="setFloat"
  return="void"
  abstract="false"
@@ -217238,6 +252215,23 @@
 <parameter name="value" type="int">
 </parameter>
 </method>
+<method name="setIntent"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+<parameter name="methodName" type="java.lang.String">
+</parameter>
+<parameter name="value" type="android.content.Intent">
+</parameter>
+</method>
 <method name="setLong"
  return="void"
  abstract="false"
@@ -217255,6 +252249,21 @@
 <parameter name="value" type="long">
 </parameter>
 </method>
+<method name="setOnClickFillInIntent"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+<parameter name="fillInIntent" type="android.content.Intent">
+</parameter>
+</method>
 <method name="setOnClickPendingIntent"
  return="void"
  abstract="false"
@@ -217270,6 +252279,21 @@
 <parameter name="pendingIntent" type="android.app.PendingIntent">
 </parameter>
 </method>
+<method name="setPendingIntentTemplate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+<parameter name="pendingIntentTemplate" type="android.app.PendingIntent">
+</parameter>
+</method>
 <method name="setProgressBar"
  return="void"
  abstract="false"
@@ -217289,6 +252313,51 @@
 <parameter name="indeterminate" type="boolean">
 </parameter>
 </method>
+<method name="setRelativeScrollPosition"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+</method>
+<method name="setRemoteAdapter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="setScrollPosition"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+<parameter name="position" type="int">
+</parameter>
+</method>
 <method name="setShort"
  return="void"
  abstract="false"
@@ -217385,6 +252454,32 @@
 <parameter name="visibility" type="int">
 </parameter>
 </method>
+<method name="showNext"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+</method>
+<method name="showPrevious"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+</method>
 <method name="writeToParcel"
  return="void"
  abstract="false"
@@ -217451,6 +252546,160 @@
 <implements name="java.lang.annotation.Annotation">
 </implements>
 </class>
+<class name="RemoteViewsService"
+ extends="android.app.Service"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RemoteViewsService"
+ type="android.widget.RemoteViewsService"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="onBind"
+ return="android.os.IBinder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="onGetViewFactory"
+ return="android.widget.RemoteViewsService.RemoteViewsFactory"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+</class>
+<interface name="RemoteViewsService.RemoteViewsFactory"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getCount"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getItemId"
+ return="long"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+<method name="getLoadingView"
+ return="android.widget.RemoteViews"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getViewAt"
+ return="android.widget.RemoteViews"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+<method name="getViewTypeCount"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasStableIds"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onCreate"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onDataSetChanged"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onDestroy"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
 <class name="ResourceCursorAdapter"
  extends="android.widget.CursorAdapter"
  abstract="true"
@@ -217463,7 +252712,7 @@
  type="android.widget.ResourceCursorAdapter"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="context" type="android.content.Context">
@@ -217489,6 +252738,22 @@
 <parameter name="autoRequery" type="boolean">
 </parameter>
 </constructor>
+<constructor name="ResourceCursorAdapter"
+ type="android.widget.ResourceCursorAdapter"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="layout" type="int">
+</parameter>
+<parameter name="c" type="android.database.Cursor">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</constructor>
 <method name="newView"
  return="android.view.View"
  abstract="false"
@@ -217876,6 +253141,20 @@
 <parameter name="interpolator" type="android.view.animation.Interpolator">
 </parameter>
 </constructor>
+<constructor name="Scroller"
+ type="android.widget.Scroller"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="interpolator" type="android.view.animation.Interpolator">
+</parameter>
+<parameter name="flywheel" type="boolean">
+</parameter>
+</constructor>
 <method name="abortAnimation"
  return="void"
  abstract="false"
@@ -218065,6 +253344,19 @@
 <parameter name="newY" type="int">
 </parameter>
 </method>
+<method name="setFriction"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="friction" type="float">
+</parameter>
+</method>
 <method name="startScroll"
  return="void"
  abstract="false"
@@ -218117,6 +253409,374 @@
 >
 </method>
 </class>
+<class name="SearchView"
+ extends="android.widget.LinearLayout"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SearchView"
+ type="android.widget.SearchView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="SearchView"
+ type="android.widget.SearchView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<method name="getQuery"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSuggestionsAdapter"
+ return="android.widget.CursorAdapter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isIconfiedByDefault"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isIconified"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isQueryRefinementEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isSubmitButtonEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setIconified"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="iconify" type="boolean">
+</parameter>
+</method>
+<method name="setIconifiedByDefault"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="iconified" type="boolean">
+</parameter>
+</method>
+<method name="setMaxWidth"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="maxpixels" type="int">
+</parameter>
+</method>
+<method name="setOnCloseListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.widget.SearchView.OnCloseListener">
+</parameter>
+</method>
+<method name="setOnQueryChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.widget.SearchView.OnQueryChangeListener">
+</parameter>
+</method>
+<method name="setOnQueryTextFocusChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.view.View.OnFocusChangeListener">
+</parameter>
+</method>
+<method name="setOnSearchClickListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.view.View.OnClickListener">
+</parameter>
+</method>
+<method name="setOnSuggestionSelectionListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.widget.SearchView.OnSuggestionSelectionListener">
+</parameter>
+</method>
+<method name="setQuery"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="query" type="java.lang.CharSequence">
+</parameter>
+<parameter name="submit" type="boolean">
+</parameter>
+</method>
+<method name="setQueryHint"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="hint" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setQueryRefinementEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+<method name="setSearchableInfo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="searchable" type="android.app.SearchableInfo">
+</parameter>
+</method>
+<method name="setSubmitButtonEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
+<method name="setSuggestionsAdapter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.widget.CursorAdapter">
+</parameter>
+</method>
+</class>
+<interface name="SearchView.OnCloseListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onClose"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="SearchView.OnQueryChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onQueryTextChanged"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="newText" type="java.lang.String">
+</parameter>
+</method>
+<method name="onSubmitQuery"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="query" type="java.lang.String">
+</parameter>
+</method>
+</interface>
+<interface name="SearchView.OnSuggestionSelectionListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onSuggestionClicked"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+<method name="onSuggestionSelected"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
+</interface>
 <interface name="SectionIndexer"
  abstract="true"
  static="false"
@@ -218484,6 +254144,24 @@
  type="android.widget.SimpleCursorAdapter"
  static="false"
  final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="layout" type="int">
+</parameter>
+<parameter name="c" type="android.database.Cursor">
+</parameter>
+<parameter name="from" type="java.lang.String[]">
+</parameter>
+<parameter name="to" type="int[]">
+</parameter>
+</constructor>
+<constructor name="SimpleCursorAdapter"
+ type="android.widget.SimpleCursorAdapter"
+ static="false"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -218497,6 +254175,8 @@
 </parameter>
 <parameter name="to" type="int[]">
 </parameter>
+<parameter name="flags" type="int">
+</parameter>
 </constructor>
 <method name="bindView"
  return="void"
@@ -219500,6 +255180,18 @@
 >
 <parameter name="context" type="android.content.Context">
 </parameter>
+<parameter name="mode" type="int">
+</parameter>
+</constructor>
+<constructor name="Spinner"
+ type="android.widget.Spinner"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
 <parameter name="attrs" type="android.util.AttributeSet">
 </parameter>
 </constructor>
@@ -219517,6 +255209,22 @@
 <parameter name="defStyle" type="int">
 </parameter>
 </constructor>
+<constructor name="Spinner"
+ type="android.widget.Spinner"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+<parameter name="mode" type="int">
+</parameter>
+</constructor>
 <method name="getPrompt"
  return="java.lang.CharSequence"
  abstract="false"
@@ -219543,6 +255251,19 @@
 <parameter name="which" type="int">
 </parameter>
 </method>
+<method name="setGravity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gravity" type="int">
+</parameter>
+</method>
 <method name="setPrompt"
  return="void"
  abstract="false"
@@ -219569,6 +255290,28 @@
 <parameter name="promptId" type="int">
 </parameter>
 </method>
+<field name="MODE_DIALOG"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MODE_DROPDOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <interface name="SpinnerAdapter"
  abstract="true"
@@ -219597,6 +255340,37 @@
 </parameter>
 </method>
 </interface>
+<class name="StackView"
+ extends="android.widget.AdapterViewAnimator"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="StackView"
+ type="android.widget.StackView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="StackView"
+ type="android.widget.StackView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+</class>
 <class name="TabHost"
  extends="android.widget.FrameLayout"
  abstract="false"
@@ -220096,19 +255870,6 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="drawable" type="android.graphics.drawable.Drawable">
-</parameter>
-</method>
-<method name="setDividerDrawable"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
 <parameter name="resId" type="int">
 </parameter>
 </method>
@@ -220906,6 +256667,17 @@
  visibility="public"
 >
 </method>
+<method name="getCustomSelectionActionModeCallback"
+ return="android.view.ActionMode.Callback"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getDefaultEditable"
  return="boolean"
  abstract="false"
@@ -221417,6 +257189,17 @@
  visibility="public"
 >
 </method>
+<method name="isTextSelectable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="length"
  return="int"
  abstract="false"
@@ -221463,6 +257246,19 @@
 <parameter name="text" type="android.view.inputmethod.CompletionInfo">
 </parameter>
 </method>
+<method name="onCommitCorrection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="info" type="android.view.inputmethod.CorrectionInfo">
+</parameter>
+</method>
 <method name="onEditorAction"
  return="void"
  abstract="false"
@@ -221693,6 +257489,19 @@
 <parameter name="visible" type="boolean">
 </parameter>
 </method>
+<method name="setCustomSelectionActionModeCallback"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="actionModeCallback" type="android.view.ActionMode.Callback">
+</parameter>
+</method>
 <method name="setEditableFactory"
  return="void"
  abstract="false"
@@ -222451,6 +258260,19 @@
 <parameter name="colors" type="android.content.res.ColorStateList">
 </parameter>
 </method>
+<method name="setTextIsSelectable"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="selectable" type="boolean">
+</parameter>
+</method>
 <method name="setTextKeepState"
  return="void"
  abstract="false"
@@ -224346,6 +260168,35 @@
 </package>
 <package name="dalvik.bytecode"
 >
+<class name="OpcodeInfo"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="MAXIMUM_PACKED_VALUE"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MAXIMUM_VALUE"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <interface name="Opcodes"
  abstract="true"
  static="false"
@@ -224701,7 +260552,7 @@
  value="236"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -224716,6 +260567,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_CHECK_CAST_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="511"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_CMPG_DOUBLE"
  type="int"
  transient="false"
@@ -224815,6 +260677,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_CONST_CLASS_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="255"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_CONST_HIGH16"
  type="int"
  transient="false"
@@ -225042,7 +260915,7 @@
  value="238"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225053,7 +260926,7 @@
  value="239"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225068,6 +260941,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_FILLED_NEW_ARRAY_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1535"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_FILLED_NEW_ARRAY_RANGE"
  type="int"
  transient="false"
@@ -225310,6 +261194,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_IGET_BOOLEAN_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2559"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_IGET_BYTE"
  type="int"
  transient="false"
@@ -225321,6 +261216,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_IGET_BYTE_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2815"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_IGET_CHAR"
  type="int"
  transient="false"
@@ -225332,6 +261238,28 @@
  visibility="public"
 >
 </field>
+<field name="OP_IGET_CHAR_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3071"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OP_IGET_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1791"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_IGET_OBJECT"
  type="int"
  transient="false"
@@ -225343,6 +261271,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_IGET_OBJECT_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2303"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_IGET_OBJECT_QUICK"
  type="int"
  transient="false"
@@ -225350,7 +261289,7 @@
  value="244"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225361,7 +261300,7 @@
  value="242"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225376,6 +261315,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_IGET_SHORT_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3327"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_IGET_WIDE"
  type="int"
  transient="false"
@@ -225387,6 +261337,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_IGET_WIDE_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2047"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_IGET_WIDE_QUICK"
  type="int"
  transient="false"
@@ -225394,7 +261355,7 @@
  value="243"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225405,7 +261366,7 @@
  value="232"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225420,6 +261381,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_INSTANCE_OF_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="767"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_INT_TO_BYTE"
  type="int"
  transient="false"
@@ -225504,6 +261476,17 @@
  value="240"
  static="true"
  final="true"
+ deprecated="deprecated"
+ visibility="public"
+>
+</field>
+<field name="OP_INVOKE_DIRECT_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9471"
+ static="true"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -225530,6 +261513,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_INVOKE_INTERFACE_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9983"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_INVOKE_INTERFACE_RANGE"
  type="int"
  transient="false"
@@ -225552,6 +261546,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_INVOKE_STATIC_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9727"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_INVOKE_STATIC_RANGE"
  type="int"
  transient="false"
@@ -225574,6 +261579,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_INVOKE_SUPER_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9215"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_INVOKE_SUPER_QUICK"
  type="int"
  transient="false"
@@ -225581,7 +261597,7 @@
  value="250"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225592,7 +261608,7 @@
  value="251"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225618,6 +261634,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_INVOKE_VIRTUAL_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8959"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_INVOKE_VIRTUAL_QUICK"
  type="int"
  transient="false"
@@ -225625,7 +261652,7 @@
  value="248"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225636,7 +261663,7 @@
  value="249"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225673,6 +261700,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_IPUT_BOOLEAN_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4351"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_IPUT_BYTE"
  type="int"
  transient="false"
@@ -225684,6 +261722,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_IPUT_BYTE_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4607"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_IPUT_CHAR"
  type="int"
  transient="false"
@@ -225695,6 +261744,28 @@
  visibility="public"
 >
 </field>
+<field name="OP_IPUT_CHAR_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4863"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OP_IPUT_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3583"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_IPUT_OBJECT"
  type="int"
  transient="false"
@@ -225706,6 +261777,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_IPUT_OBJECT_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4095"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_IPUT_OBJECT_QUICK"
  type="int"
  transient="false"
@@ -225713,7 +261795,7 @@
  value="247"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225724,7 +261806,7 @@
  value="245"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225739,6 +261821,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_IPUT_SHORT_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5119"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_IPUT_WIDE"
  type="int"
  transient="false"
@@ -225750,6 +261843,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_IPUT_WIDE_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3839"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_IPUT_WIDE_QUICK"
  type="int"
  transient="false"
@@ -225757,7 +261861,7 @@
  value="246"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -225768,7 +261872,7 @@
  value="233"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -226135,6 +262239,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_NEW_ARRAY_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1279"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_NEW_INSTANCE"
  type="int"
  transient="false"
@@ -226146,6 +262261,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_NEW_INSTANCE_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1023"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_NOP"
  type="int"
  transient="false"
@@ -226454,6 +262580,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_SGET_BOOLEAN_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6143"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_SGET_BYTE"
  type="int"
  transient="false"
@@ -226465,6 +262602,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_SGET_BYTE_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6399"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_SGET_CHAR"
  type="int"
  transient="false"
@@ -226476,6 +262624,28 @@
  visibility="public"
 >
 </field>
+<field name="OP_SGET_CHAR_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6655"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OP_SGET_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5375"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_SGET_OBJECT"
  type="int"
  transient="false"
@@ -226487,6 +262657,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_SGET_OBJECT_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5887"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_SGET_SHORT"
  type="int"
  transient="false"
@@ -226498,6 +262679,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_SGET_SHORT_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6911"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_SGET_WIDE"
  type="int"
  transient="false"
@@ -226509,6 +262701,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_SGET_WIDE_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5631"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_SGET_WIDE_VOLATILE"
  type="int"
  transient="false"
@@ -226516,7 +262719,7 @@
  value="234"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -226663,6 +262866,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_SPUT_BOOLEAN_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7935"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_SPUT_BYTE"
  type="int"
  transient="false"
@@ -226674,6 +262888,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_SPUT_BYTE_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8191"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_SPUT_CHAR"
  type="int"
  transient="false"
@@ -226685,6 +262910,28 @@
  visibility="public"
 >
 </field>
+<field name="OP_SPUT_CHAR_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8447"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OP_SPUT_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7167"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_SPUT_OBJECT"
  type="int"
  transient="false"
@@ -226696,6 +262943,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_SPUT_OBJECT_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7679"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_SPUT_SHORT"
  type="int"
  transient="false"
@@ -226707,6 +262965,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_SPUT_SHORT_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8703"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_SPUT_WIDE"
  type="int"
  transient="false"
@@ -226718,6 +262987,17 @@
  visibility="public"
 >
 </field>
+<field name="OP_SPUT_WIDE_JUMBO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7423"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="OP_SPUT_WIDE_VOLATILE"
  type="int"
  transient="false"
@@ -226725,7 +263005,7 @@
  value="235"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -226835,7 +263115,7 @@
  value="237"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -228315,7 +264595,7 @@
  return="void"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -228330,7 +264610,7 @@
  return="void"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -228464,7 +264744,7 @@
  return="java.beans.PropertyChangeListener[]"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -228477,7 +264757,7 @@
  return="java.beans.PropertyChangeListener[]"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -228488,7 +264768,7 @@
  return="boolean"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -228501,7 +264781,7 @@
  return="void"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -228516,7 +264796,7 @@
  return="void"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -229545,7 +265825,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="buffer" type="byte[]">
+<parameter name="dst" type="byte[]">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -229560,11 +265840,11 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="buffer" type="byte[]">
+<parameter name="dst" type="byte[]">
 </parameter>
 <parameter name="offset" type="int">
 </parameter>
-<parameter name="count" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -229805,7 +266085,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="buffer" type="byte[]">
+<parameter name="dst" type="byte[]">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -229820,11 +266100,11 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="buffer" type="byte[]">
+<parameter name="dst" type="byte[]">
 </parameter>
 <parameter name="offset" type="int">
 </parameter>
-<parameter name="length" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -231235,7 +267515,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="fileName" type="java.lang.String">
+<parameter name="path" type="java.lang.String">
 </parameter>
 <exception name="FileNotFoundException" type="java.io.FileNotFoundException">
 </exception>
@@ -231358,7 +267638,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="filename" type="java.lang.String">
+<parameter name="path" type="java.lang.String">
 </parameter>
 <exception name="FileNotFoundException" type="java.io.FileNotFoundException">
 </exception>
@@ -231370,7 +267650,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="filename" type="java.lang.String">
+<parameter name="path" type="java.lang.String">
 </parameter>
 <parameter name="append" type="boolean">
 </parameter>
@@ -232041,7 +268321,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="b" type="byte[]">
+<parameter name="buffer" type="byte[]">
 </parameter>
 <parameter name="offset" type="int">
 </parameter>
@@ -232535,7 +268815,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="toSkip" type="long">
+<parameter name="byteCount" type="long">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -232731,7 +269011,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="buffer" type="byte[]">
+<parameter name="dst" type="byte[]">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -232746,11 +269026,11 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="buffer" type="byte[]">
+<parameter name="dst" type="byte[]">
 </parameter>
 <parameter name="offset" type="int">
 </parameter>
-<parameter name="length" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -236551,7 +272831,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="buffer" type="byte[]">
+<parameter name="dst" type="byte[]">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -236566,11 +272846,11 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="buffer" type="byte[]">
+<parameter name="dst" type="byte[]">
 </parameter>
 <parameter name="offset" type="int">
 </parameter>
-<parameter name="count" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -237093,7 +273373,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="count" type="long">
+<parameter name="charCount" type="long">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -238106,9 +274386,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="beginIndex" type="int">
+<parameter name="start" type="int">
 </parameter>
-<parameter name="endIndex" type="int">
+<parameter name="end" type="int">
 </parameter>
 </method>
 <method name="ensureCapacity"
@@ -240806,7 +277086,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -249919,9 +286199,9 @@
 >
 <parameter name="data" type="byte[]">
 </parameter>
-<parameter name="start" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="length" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </constructor>
 <constructor name="String"
@@ -249935,9 +286215,9 @@
 </parameter>
 <parameter name="high" type="int">
 </parameter>
-<parameter name="start" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="length" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </constructor>
 <constructor name="String"
@@ -249949,9 +286229,9 @@
 >
 <parameter name="data" type="byte[]">
 </parameter>
-<parameter name="start" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="length" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 <parameter name="charsetName" type="java.lang.String">
 </parameter>
@@ -249981,9 +286261,9 @@
 >
 <parameter name="data" type="byte[]">
 </parameter>
-<parameter name="start" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="length" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 <parameter name="charset" type="java.nio.charset.Charset">
 </parameter>
@@ -250019,9 +286299,9 @@
 >
 <parameter name="data" type="char[]">
 </parameter>
-<parameter name="start" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="length" type="int">
+<parameter name="charCount" type="int">
 </parameter>
 </constructor>
 <constructor name="String"
@@ -250041,7 +286321,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="stringbuffer" type="java.lang.StringBuffer">
+<parameter name="stringBuffer" type="java.lang.StringBuffer">
 </parameter>
 </constructor>
 <constructor name="String"
@@ -250065,7 +286345,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="sb" type="java.lang.StringBuilder">
+<parameter name="stringBuilder" type="java.lang.StringBuilder">
 </parameter>
 </constructor>
 <method name="charAt"
@@ -250117,9 +286397,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="beginIndex" type="int">
+<parameter name="start" type="int">
 </parameter>
-<parameter name="endIndex" type="int">
+<parameter name="end" type="int">
 </parameter>
 </method>
 <method name="compareTo"
@@ -259290,11 +295570,11 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="buf" type="byte[]">
+<parameter name="data" type="byte[]">
 </parameter>
-<parameter name="anOffset" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="aLength" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </method>
 <method name="setData"
@@ -259320,7 +295600,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="len" type="int">
+<parameter name="length" type="int">
 </parameter>
 </method>
 <method name="setPort"
@@ -262723,9 +299003,9 @@
 >
 <parameter name="uri" type="java.net.URI">
 </parameter>
-<parameter name="sa" type="java.net.SocketAddress">
+<parameter name="address" type="java.net.SocketAddress">
 </parameter>
-<parameter name="ioe" type="java.io.IOException">
+<parameter name="failure" type="java.io.IOException">
 </parameter>
 </method>
 <method name="getDefault"
@@ -262824,7 +299104,7 @@
 >
 <parameter name="uri" type="java.net.URI">
 </parameter>
-<parameter name="conn" type="java.net.URLConnection">
+<parameter name="connection" type="java.net.URLConnection">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -267118,9 +303398,9 @@
 >
 <parameter name="dst" type="byte[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="dstOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </method>
 <method name="get"
@@ -267364,9 +303644,9 @@
 >
 <parameter name="src" type="byte[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="srcOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </method>
 <method name="put"
@@ -267603,7 +303883,7 @@
 </parameter>
 <parameter name="start" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </method>
 </class>
@@ -267836,9 +304116,9 @@
 >
 <parameter name="dst" type="char[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="dstOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="charCount" type="int">
 </parameter>
 </method>
 <method name="get"
@@ -267936,9 +304216,9 @@
 >
 <parameter name="src" type="char[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="srcOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="charCount" type="int">
 </parameter>
 </method>
 <method name="put"
@@ -268067,7 +304347,7 @@
 </parameter>
 <parameter name="start" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="charCount" type="int">
 </parameter>
 </method>
 <method name="wrap"
@@ -268093,7 +304373,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="chseq" type="java.lang.CharSequence">
+<parameter name="cs" type="java.lang.CharSequence">
 </parameter>
 <parameter name="start" type="int">
 </parameter>
@@ -268228,9 +304508,9 @@
 >
 <parameter name="dst" type="double[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="dstOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="doubleCount" type="int">
 </parameter>
 </method>
 <method name="get"
@@ -268317,9 +304597,9 @@
 >
 <parameter name="src" type="double[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="srcOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="doubleCount" type="int">
 </parameter>
 </method>
 <method name="put"
@@ -268388,7 +304668,7 @@
 </parameter>
 <parameter name="start" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="doubleCount" type="int">
 </parameter>
 </method>
 </class>
@@ -268519,9 +304799,9 @@
 >
 <parameter name="dst" type="float[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="dstOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="floatCount" type="int">
 </parameter>
 </method>
 <method name="get"
@@ -268608,9 +304888,9 @@
 >
 <parameter name="src" type="float[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="srcOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="floatCount" type="int">
 </parameter>
 </method>
 <method name="put"
@@ -268679,7 +304959,7 @@
 </parameter>
 <parameter name="start" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="floatCount" type="int">
 </parameter>
 </method>
 </class>
@@ -268810,9 +305090,9 @@
 >
 <parameter name="dst" type="int[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="dstOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="intCount" type="int">
 </parameter>
 </method>
 <method name="get"
@@ -268899,9 +305179,9 @@
 >
 <parameter name="src" type="int[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="srcOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="intCount" type="int">
 </parameter>
 </method>
 <method name="put"
@@ -268970,7 +305250,7 @@
 </parameter>
 <parameter name="start" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="intCount" type="int">
 </parameter>
 </method>
 </class>
@@ -269118,9 +305398,9 @@
 >
 <parameter name="dst" type="long[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="dstOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="longCount" type="int">
 </parameter>
 </method>
 <method name="get"
@@ -269207,9 +305487,9 @@
 >
 <parameter name="src" type="long[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="srcOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="longCount" type="int">
 </parameter>
 </method>
 <method name="put"
@@ -269278,7 +305558,7 @@
 </parameter>
 <parameter name="start" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="longCount" type="int">
 </parameter>
 </method>
 </class>
@@ -269468,9 +305748,9 @@
 >
 <parameter name="dst" type="short[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="dstOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="shortCount" type="int">
 </parameter>
 </method>
 <method name="get"
@@ -269557,9 +305837,9 @@
 >
 <parameter name="src" type="short[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="srcOffset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="shortCount" type="int">
 </parameter>
 </method>
 <method name="put"
@@ -269628,7 +305908,7 @@
 </parameter>
 <parameter name="start" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="shortCount" type="int">
 </parameter>
 </method>
 </class>
@@ -309562,7 +345842,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="minSize" type="int">
+<parameter name="numElements" type="int">
 </parameter>
 </constructor>
 <constructor name="ArrayDeque"
@@ -309828,7 +346108,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="obj" type="java.lang.Object">
+<parameter name="o" type="java.lang.Object">
 </parameter>
 </method>
 <method name="removeLast"
@@ -309852,7 +346132,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="obj" type="java.lang.Object">
+<parameter name="o" type="java.lang.Object">
 </parameter>
 </method>
 <method name="size"
@@ -314610,6 +350890,19 @@
 >
 <implements name="java.util.Queue">
 </implements>
+<method name="add"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="e" type="E">
+</parameter>
+</method>
 <method name="addFirst"
  return="void"
  abstract="true"
@@ -314636,6 +350929,19 @@
 <parameter name="e" type="E">
 </parameter>
 </method>
+<method name="contains"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
 <method name="descendingIterator"
  return="java.util.Iterator&lt;E&gt;"
  abstract="true"
@@ -314647,6 +350953,17 @@
  visibility="public"
 >
 </method>
+<method name="element"
+ return="E"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getFirst"
  return="E"
  abstract="true"
@@ -314669,6 +350986,30 @@
  visibility="public"
 >
 </method>
+<method name="iterator"
+ return="java.util.Iterator&lt;E&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="offer"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="e" type="E">
+</parameter>
+</method>
 <method name="offerFirst"
  return="boolean"
  abstract="true"
@@ -314695,6 +351036,17 @@
 <parameter name="e" type="E">
 </parameter>
 </method>
+<method name="peek"
+ return="E"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="peekFirst"
  return="E"
  abstract="true"
@@ -314717,6 +351069,17 @@
  visibility="public"
 >
 </method>
+<method name="poll"
+ return="E"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="pollFirst"
  return="E"
  abstract="true"
@@ -314763,6 +351126,30 @@
 <parameter name="e" type="E">
 </parameter>
 </method>
+<method name="remove"
+ return="E"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="remove"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
 <method name="removeFirst"
  return="E"
  abstract="true"
@@ -314811,6 +351198,17 @@
 <parameter name="o" type="java.lang.Object">
 </parameter>
 </method>
+<method name="size"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 </interface>
 <class name="Dictionary"
  extends="java.lang.Object"
@@ -317976,8 +354374,6 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<exception name="MissingResourceException" type="java.util.MissingResourceException">
-</exception>
 </method>
 <method name="getISO3Language"
  return="java.lang.String"
@@ -317989,8 +354385,6 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<exception name="MissingResourceException" type="java.util.MissingResourceException">
-</exception>
 </method>
 <method name="getISOCountries"
  return="java.lang.String[]"
@@ -318735,11 +355129,24 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="endKey" type="K">
+<parameter name="toKey" type="K">
 </parameter>
 <parameter name="inclusive" type="boolean">
 </parameter>
 </method>
+<method name="headMap"
+ return="java.util.SortedMap&lt;K, V&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="toKey" type="K">
+</parameter>
+</method>
 <method name="higherEntry"
  return="java.util.Map.Entry&lt;K, V&gt;"
  abstract="true"
@@ -318846,13 +355253,28 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="startKey" type="K">
+<parameter name="fromKey" type="K">
 </parameter>
-<parameter name="startInclusive" type="boolean">
+<parameter name="fromInclusive" type="boolean">
 </parameter>
-<parameter name="endKey" type="K">
+<parameter name="toKey" type="K">
 </parameter>
-<parameter name="endInclusive" type="boolean">
+<parameter name="toInclusive" type="boolean">
+</parameter>
+</method>
+<method name="subMap"
+ return="java.util.SortedMap&lt;K, V&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromKey" type="K">
+</parameter>
+<parameter name="toKey" type="K">
 </parameter>
 </method>
 <method name="tailMap"
@@ -318865,11 +355287,24 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="startKey" type="K">
+<parameter name="fromKey" type="K">
 </parameter>
 <parameter name="inclusive" type="boolean">
 </parameter>
 </method>
+<method name="tailMap"
+ return="java.util.SortedMap&lt;K, V&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromKey" type="K">
+</parameter>
+</method>
 </interface>
 <interface name="NavigableSet"
  abstract="true"
@@ -318938,9 +355373,22 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="end" type="E">
+<parameter name="toElement" type="E">
 </parameter>
-<parameter name="endInclusive" type="boolean">
+<parameter name="inclusive" type="boolean">
+</parameter>
+</method>
+<method name="headSet"
+ return="java.util.SortedSet&lt;E&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="toElement" type="E">
 </parameter>
 </method>
 <method name="higher"
@@ -318956,6 +355404,17 @@
 <parameter name="e" type="E">
 </parameter>
 </method>
+<method name="iterator"
+ return="java.util.Iterator&lt;E&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="lower"
  return="E"
  abstract="true"
@@ -319001,13 +355460,28 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="start" type="E">
+<parameter name="fromElement" type="E">
 </parameter>
-<parameter name="startInclusive" type="boolean">
+<parameter name="fromInclusive" type="boolean">
 </parameter>
-<parameter name="end" type="E">
+<parameter name="toElement" type="E">
 </parameter>
-<parameter name="endInclusive" type="boolean">
+<parameter name="toInclusive" type="boolean">
+</parameter>
+</method>
+<method name="subSet"
+ return="java.util.SortedSet&lt;E&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromElement" type="E">
+</parameter>
+<parameter name="toElement" type="E">
 </parameter>
 </method>
 <method name="tailSet"
@@ -319020,9 +355494,22 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="start" type="E">
+<parameter name="fromElement" type="E">
 </parameter>
-<parameter name="startInclusive" type="boolean">
+<parameter name="inclusive" type="boolean">
+</parameter>
+</method>
+<method name="tailSet"
+ return="java.util.SortedSet&lt;E&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromElement" type="E">
 </parameter>
 </method>
 </interface>
@@ -319684,6 +356171,19 @@
 >
 <implements name="java.util.Collection">
 </implements>
+<method name="add"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="e" type="E">
+</parameter>
+</method>
 <method name="element"
  return="E"
  abstract="true"
@@ -319705,7 +356205,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="o" type="E">
+<parameter name="e" type="E">
 </parameter>
 </method>
 <method name="peek"
@@ -319919,7 +356419,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -319930,7 +356430,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -319956,7 +356456,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -319971,7 +356471,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -320005,7 +356505,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -320020,7 +356520,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -320207,7 +356707,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -320248,7 +356748,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -326377,7 +362877,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="c" type="java.util.Collection&lt;? extends E&gt;">
+<parameter name="collection" type="java.util.Collection&lt;? extends E&gt;">
 </parameter>
 </constructor>
 <constructor name="CopyOnWriteArrayList"
@@ -326394,7 +362894,7 @@
  return="boolean"
  abstract="false"
  native="false"
- synchronized="false"
+ synchronized="true"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -326407,7 +362907,7 @@
  return="void"
  abstract="false"
  native="false"
- synchronized="false"
+ synchronized="true"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -326422,20 +362922,20 @@
  return="boolean"
  abstract="false"
  native="false"
- synchronized="false"
+ synchronized="true"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="c" type="java.util.Collection&lt;? extends E&gt;">
+<parameter name="collection" type="java.util.Collection&lt;? extends E&gt;">
 </parameter>
 </method>
 <method name="addAll"
  return="boolean"
  abstract="false"
  native="false"
- synchronized="false"
+ synchronized="true"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -326443,40 +362943,40 @@
 >
 <parameter name="index" type="int">
 </parameter>
-<parameter name="c" type="java.util.Collection&lt;? extends E&gt;">
+<parameter name="collection" type="java.util.Collection&lt;? extends E&gt;">
 </parameter>
 </method>
 <method name="addAllAbsent"
  return="int"
  abstract="false"
  native="false"
- synchronized="false"
+ synchronized="true"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="c" type="java.util.Collection&lt;? extends E&gt;">
+<parameter name="collection" type="java.util.Collection&lt;? extends E&gt;">
 </parameter>
 </method>
 <method name="addIfAbsent"
  return="boolean"
  abstract="false"
  native="false"
- synchronized="false"
+ synchronized="true"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="e" type="E">
+<parameter name="object" type="E">
 </parameter>
 </method>
 <method name="clear"
  return="void"
  abstract="false"
  native="false"
- synchronized="false"
+ synchronized="true"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -326517,7 +363017,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="c" type="java.util.Collection&lt;?&gt;">
+<parameter name="collection" type="java.util.Collection&lt;?&gt;">
 </parameter>
 </method>
 <method name="get"
@@ -326543,9 +363043,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="e" type="E">
+<parameter name="object" type="E">
 </parameter>
-<parameter name="index" type="int">
+<parameter name="from" type="int">
 </parameter>
 </method>
 <method name="indexOf"
@@ -326558,7 +363058,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="o" type="java.lang.Object">
+<parameter name="object" type="java.lang.Object">
 </parameter>
 </method>
 <method name="isEmpty"
@@ -326593,9 +363093,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="e" type="E">
+<parameter name="object" type="E">
 </parameter>
-<parameter name="index" type="int">
+<parameter name="to" type="int">
 </parameter>
 </method>
 <method name="lastIndexOf"
@@ -326608,7 +363108,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="o" type="java.lang.Object">
+<parameter name="object" type="java.lang.Object">
 </parameter>
 </method>
 <method name="listIterator"
@@ -326621,25 +363121,25 @@
  deprecated="not deprecated"
  visibility="public"
 >
-</method>
-<method name="listIterator"
- return="java.util.ListIterator&lt;E&gt;"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
 <parameter name="index" type="int">
 </parameter>
 </method>
+<method name="listIterator"
+ return="java.util.ListIterator&lt;E&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="remove"
  return="E"
  abstract="false"
  native="false"
- synchronized="false"
+ synchronized="true"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -326652,7 +363152,7 @@
  return="boolean"
  abstract="false"
  native="false"
- synchronized="false"
+ synchronized="true"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -326665,33 +363165,33 @@
  return="boolean"
  abstract="false"
  native="false"
- synchronized="false"
+ synchronized="true"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="c" type="java.util.Collection&lt;?&gt;">
+<parameter name="collection" type="java.util.Collection&lt;?&gt;">
 </parameter>
 </method>
 <method name="retainAll"
  return="boolean"
  abstract="false"
  native="false"
- synchronized="false"
+ synchronized="true"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="c" type="java.util.Collection&lt;?&gt;">
+<parameter name="collection" type="java.util.Collection&lt;?&gt;">
 </parameter>
 </method>
 <method name="set"
  return="E"
  abstract="false"
  native="false"
- synchronized="false"
+ synchronized="true"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -326723,9 +363223,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="fromIndex" type="int">
+<parameter name="from" type="int">
 </parameter>
-<parameter name="toIndex" type="int">
+<parameter name="to" type="int">
 </parameter>
 </method>
 <method name="toArray"
@@ -326749,7 +363249,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="a" type="T[]">
+<parameter name="contents" type="T[]">
 </parameter>
 </method>
 </class>
@@ -340835,9 +377335,9 @@
 >
 <parameter name="buf" type="byte[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="nbytes" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </method>
 </class>
@@ -340919,9 +377419,9 @@
 >
 <parameter name="buf" type="byte[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="nbytes" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </method>
 </class>
@@ -341139,9 +377639,9 @@
 >
 <parameter name="buf" type="byte[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="nbytes" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </method>
 <method name="end"
@@ -341264,7 +377764,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="buf" type="byte[]">
+<parameter name="dictionary" type="byte[]">
 </parameter>
 </method>
 <method name="setDictionary"
@@ -341279,9 +377779,9 @@
 >
 <parameter name="buf" type="byte[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="nbytes" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </method>
 <method name="setInput"
@@ -341309,9 +377809,9 @@
 >
 <parameter name="buf" type="byte[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="nbytes" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </method>
 <method name="setLevel"
@@ -341839,9 +378339,9 @@
 >
 <parameter name="buf" type="byte[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="nbytes" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 <exception name="DataFormatException" type="java.util.zip.DataFormatException">
 </exception>
@@ -341889,7 +378389,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="buf" type="byte[]">
+<parameter name="dictionary" type="byte[]">
 </parameter>
 </method>
 <method name="setDictionary"
@@ -341902,11 +378402,11 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="buf" type="byte[]">
+<parameter name="dictionary" type="byte[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="nbytes" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </method>
 <method name="setInput"
@@ -341934,9 +378434,9 @@
 >
 <parameter name="buf" type="byte[]">
 </parameter>
-<parameter name="off" type="int">
+<parameter name="offset" type="int">
 </parameter>
-<parameter name="nbytes" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </method>
 </class>
@@ -342258,7 +378758,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="string" type="java.lang.String">
+<parameter name="comment" type="java.lang.String">
 </parameter>
 </method>
 <method name="setCompressedSize"
@@ -346452,7 +382952,7 @@
 </parameter>
 <parameter name="offset" type="int">
 </parameter>
-<parameter name="len" type="int">
+<parameter name="byteCount" type="int">
 </parameter>
 </constructor>
 <method name="getIV"
diff --git a/api/current.xml b/api/current.xml
index 0cbfd76..b733d89 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1255,17 +1255,6 @@
  visibility="public"
 >
 </field>
-<field name="WRITE_MEDIA_STORAGE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.permission.WRITE_MEDIA_STORAGE&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="WRITE_SECURE_SETTINGS"
  type="java.lang.String"
  transient="false"
@@ -1482,17 +1471,6 @@
  visibility="public"
 >
 </constructor>
-<field name="accelerate_cubic_interpolator"
- type="int"
- transient="false"
- volatile="false"
- value="17432591"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="accelerate_decelerate_interpolator"
  type="int"
  transient="false"
@@ -1515,39 +1493,6 @@
  visibility="public"
 >
 </field>
-<field name="accelerate_quint_interpolator"
- type="int"
- transient="false"
- volatile="false"
- value="17432593"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="animator_fade_in"
- type="int"
- transient="false"
- volatile="false"
- value="17432589"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="animator_fade_out"
- type="int"
- transient="false"
- volatile="false"
- value="17432590"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="anticipate_interpolator"
  type="int"
  transient="false"
@@ -1592,17 +1537,6 @@
  visibility="public"
 >
 </field>
-<field name="decelerate_cubic_interpolator"
- type="int"
- transient="false"
- volatile="false"
- value="17432592"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="decelerate_interpolator"
  type="int"
  transient="false"
@@ -1614,17 +1548,6 @@
  visibility="public"
 >
 </field>
-<field name="decelerate_quint_interpolator"
- type="int"
- transient="false"
- volatile="false"
- value="17432594"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="fade_in"
  type="int"
  transient="false"
@@ -1692,6 +1615,45 @@
 >
 </field>
 </class>
+<class name="R.animator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="R.animator"
+ type="android.R.animator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="fade_in"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17498112"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fade_out"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17498113"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="R.array"
  extends="java.lang.Object"
  abstract="false"
@@ -1828,7 +1790,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843513"
+ value="16843501"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1839,7 +1801,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843482"
+ value="16843470"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1850,7 +1812,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843522"
+ value="16843510"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1861,7 +1823,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843521"
+ value="16843509"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1872,7 +1834,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843523"
+ value="16843511"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1883,7 +1845,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843492"
+ value="16843480"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1894,7 +1856,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843491"
+ value="16843479"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1905,7 +1867,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843529"
+ value="16843517"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1916,7 +1878,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843495"
+ value="16843483"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1927,7 +1889,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843525"
+ value="16843513"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1938,7 +1900,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843496"
+ value="16843484"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1949,7 +1911,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843552"
+ value="16843540"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1960,7 +1922,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843551"
+ value="16843539"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1971,7 +1933,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843553"
+ value="16843541"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1982,7 +1944,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843524"
+ value="16843512"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1993,7 +1955,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843530"
+ value="16843518"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2004,7 +1966,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843531"
+ value="16843519"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2055,17 +2017,6 @@
  visibility="public"
 >
 </field>
-<field name="adapter"
- type="int"
- transient="false"
- volatile="false"
- value="16843468"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="addStatesFromChildren"
  type="int"
  transient="false"
@@ -2088,6 +2039,17 @@
  visibility="public"
 >
 </field>
+<field name="alertDialogIcon"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843607"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="alertDialogStyle"
  type="int"
  transient="false"
@@ -2103,7 +2065,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843543"
+ value="16843531"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2114,7 +2076,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843480"
+ value="16843468"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2147,7 +2109,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843584"
+ value="16843572"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2180,7 +2142,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843565"
+ value="16843553"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2235,7 +2197,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843489"
+ value="16843477"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2246,7 +2208,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843520"
+ value="16843508"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2312,7 +2274,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843560"
+ value="16843548"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2352,17 +2314,6 @@
  visibility="public"
 >
 </field>
-<field name="as"
- type="int"
- transient="false"
- volatile="false"
- value="16843474"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="author"
  type="int"
  transient="false"
@@ -2389,7 +2340,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843549"
+ value="16843537"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2499,7 +2450,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843562"
+ value="16843550"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2543,7 +2494,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843577"
+ value="16843565"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2631,7 +2582,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843538"
+ value="16843526"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2642,7 +2593,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843537"
+ value="16843525"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2675,7 +2626,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843581"
+ value="16843569"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2686,7 +2637,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843580"
+ value="16843568"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2748,6 +2699,17 @@
  visibility="public"
 >
 </field>
+<field name="calendarViewShown"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843598"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="candidatesTextStyleSpans"
  type="int"
  transient="false"
@@ -3100,17 +3062,6 @@
  visibility="public"
 >
 </field>
-<field name="column"
- type="int"
- transient="false"
- volatile="false"
- value="16843477"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="columnDelay"
  type="int"
  transient="false"
@@ -3258,7 +3209,18 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843486"
+ value="16843474"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="customTokens"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843581"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -3309,6 +3271,17 @@
  visibility="public"
 >
 </field>
+<field name="dateTextAppearance"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843595"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="debuggable"
  type="int"
  transient="false"
@@ -3408,6 +3381,17 @@
  visibility="public"
 >
 </field>
+<field name="detailsElementBackground"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843600"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="dial"
  type="int"
  transient="false"
@@ -3467,7 +3451,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843542"
+ value="16843530"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -3544,7 +3528,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843484"
+ value="16843472"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -3588,7 +3572,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843578"
+ value="16843566"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -3599,7 +3583,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843576"
+ value="16843564"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -3610,7 +3594,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843544"
+ value="16843532"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -3786,7 +3770,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843490"
+ value="16843478"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -3837,6 +3821,28 @@
  visibility="public"
 >
 </field>
+<field name="editTextBackground"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843604"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="editTextColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843603"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="editTextPreferenceStyle"
  type="int"
  transient="false"
@@ -3940,7 +3946,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843546"
+ value="16843534"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -3995,7 +4001,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843547"
+ value="16843535"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4193,7 +4199,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843587"
+ value="16843575"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4215,7 +4221,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843592"
+ value="16843580"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4226,7 +4232,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843589"
+ value="16843577"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4237,7 +4243,18 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843590"
+ value="16843578"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fastScrollTextColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843611"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4248,7 +4265,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843588"
+ value="16843576"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4259,7 +4276,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843591"
+ value="16843579"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4354,6 +4371,17 @@
  visibility="public"
 >
 </field>
+<field name="firstDayOfWeek"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843583"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="fitsSystemWindows"
  type="int"
  transient="false"
@@ -4398,6 +4426,17 @@
  visibility="public"
 >
 </field>
+<field name="focusedMonthDateColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843589"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="footerDividersEnabled"
  type="int"
  transient="false"
@@ -4446,7 +4485,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843503"
+ value="16843491"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4457,7 +4496,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843507"
+ value="16843495"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4468,7 +4507,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843508"
+ value="16843496"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4479,7 +4518,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843509"
+ value="16843497"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4490,7 +4529,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843510"
+ value="16843498"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4501,7 +4540,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843505"
+ value="16843493"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4512,7 +4551,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843506"
+ value="16843494"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4523,7 +4562,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843511"
+ value="16843499"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4534,7 +4573,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843512"
+ value="16843500"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4552,17 +4591,6 @@
  visibility="public"
 >
 </field>
-<field name="from"
- type="int"
- transient="false"
- volatile="false"
- value="16843472"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="fromAlpha"
  type="int"
  transient="false"
@@ -4585,17 +4613,6 @@
  visibility="public"
 >
 </field>
-<field name="fromValue"
- type="int"
- transient="false"
- volatile="false"
- value="16843475"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="fromXDelta"
  type="int"
  transient="false"
@@ -4886,7 +4903,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843487"
+ value="16843475"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4952,7 +4969,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843545"
+ value="16843533"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4963,7 +4980,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843563"
+ value="16843551"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -4992,6 +5009,17 @@
  visibility="public"
 >
 </field>
+<field name="horizontalScrollViewStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843605"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="horizontalSpacing"
  type="int"
  transient="false"
@@ -5040,7 +5068,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843528"
+ value="16843516"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -5161,7 +5189,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843516"
+ value="16843504"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -5172,7 +5200,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843514"
+ value="16843502"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -5183,7 +5211,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843515"
+ value="16843503"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -5293,7 +5321,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843558"
+ value="16843546"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -5469,7 +5497,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843585"
+ value="16843573"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -5568,7 +5596,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843579"
+ value="16843567"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -5817,6 +5845,17 @@
  visibility="public"
 >
 </field>
+<field name="layerType"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843606"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="layout"
  type="int"
  transient="false"
@@ -6239,7 +6278,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843518"
+ value="16843506"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -6283,7 +6322,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843539"
+ value="16843527"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -6294,7 +6333,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843533"
+ value="16843521"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -6382,7 +6421,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843541"
+ value="16843529"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -6433,6 +6472,17 @@
  visibility="public"
 >
 </field>
+<field name="maxDate"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843586"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="maxEms"
  type="int"
  transient="false"
@@ -6547,7 +6597,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843488"
+ value="16843476"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -6576,6 +6626,17 @@
  visibility="public"
 >
 </field>
+<field name="minDate"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843585"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="minEms"
  type="int"
  transient="false"
@@ -6690,7 +6751,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843483"
+ value="16843471"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -6719,6 +6780,17 @@
  visibility="public"
 >
 </field>
+<field name="nextFocusForward"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843582"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="nextFocusLeft"
  type="int"
  transient="false"
@@ -6844,7 +6916,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843564"
+ value="16843552"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -6877,7 +6949,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843502"
+ value="16843490"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -7240,7 +7312,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843534"
+ value="16843522"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -7339,7 +7411,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843494"
+ value="16843482"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -7394,7 +7466,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843559"
+ value="16843547"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -7515,7 +7587,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843501"
+ value="16843489"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -7555,6 +7627,17 @@
  visibility="public"
 >
 </field>
+<field name="queryHint"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843610"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="quickContactBadgeStyleSmallWindowLarge"
  type="int"
  transient="false"
@@ -7867,7 +7950,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843572"
+ value="16843560"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -7878,7 +7961,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843573"
+ value="16843561"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -7889,7 +7972,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843574"
+ value="16843562"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -7988,7 +8071,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843570"
+ value="16843558"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -7999,7 +8082,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843571"
+ value="16843559"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -8351,7 +8434,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843582"
+ value="16843570"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -8384,18 +8467,29 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843548"
+ value="16843536"
  static="true"
  final="true"
  deprecated="not deprecated"
  visibility="public"
 >
 </field>
-<field name="selection"
+<field name="selectedDateVerticalBar"
  type="int"
  transient="false"
  volatile="false"
- value="16843469"
+ value="16843593"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="selectedWeekBackgroundColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843588"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -8516,7 +8610,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843493"
+ value="16843481"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -8538,7 +8632,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843575"
+ value="16843563"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -8556,6 +8650,28 @@
  visibility="public"
 >
 </field>
+<field name="showWeekNumber"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843584"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="shownWeekCount"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843587"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="shrinkColumns"
  type="int"
  transient="false"
@@ -8611,11 +8727,11 @@
  visibility="public"
 >
 </field>
-<field name="sortOrder"
+<field name="solidColor"
  type="int"
  transient="false"
  volatile="false"
- value="16843470"
+ value="16843596"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -8670,7 +8786,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843519"
+ value="16843507"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -8688,11 +8804,22 @@
  visibility="public"
 >
 </field>
+<field name="spinnersShown"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843597"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="splitMotionEvents"
  type="int"
  transient="false"
  volatile="false"
- value="16843517"
+ value="16843505"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -8791,7 +8918,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843561"
+ value="16843549"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -8802,7 +8929,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843532"
+ value="16843520"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -8930,6 +9057,17 @@
  visibility="public"
 >
 </field>
+<field name="state_multiline"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843599"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="state_pressed"
  type="int"
  transient="false"
@@ -8978,7 +9116,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843583"
+ value="16843571"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -9033,7 +9171,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843485"
+ value="16843473"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -9044,7 +9182,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843527"
+ value="16843515"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -9429,7 +9567,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843535"
+ value="16843523"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -9506,7 +9644,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843536"
+ value="16843524"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -9550,7 +9688,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843540"
+ value="16843528"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -9568,6 +9706,17 @@
  visibility="public"
 >
 </field>
+<field name="textColorHighlightInverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843601"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="textColorHint"
  type="int"
  transient="false"
@@ -9601,6 +9750,17 @@
  visibility="public"
 >
 </field>
+<field name="textColorLinkInverse"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843602"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="textColorPrimary"
  type="int"
  transient="false"
@@ -9737,7 +9897,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843555"
+ value="16843543"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -9748,7 +9908,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843554"
+ value="16843542"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -9770,7 +9930,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843556"
+ value="16843544"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10001,18 +10161,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843526"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="to"
- type="int"
- transient="false"
- volatile="false"
- value="16843473"
+ value="16843514"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10041,17 +10190,6 @@
  visibility="public"
 >
 </field>
-<field name="toValue"
- type="int"
- transient="false"
- volatile="false"
- value="16843476"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="toXDelta"
  type="int"
  transient="false"
@@ -10177,7 +10315,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843566"
+ value="16843554"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10188,7 +10326,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843567"
+ value="16843555"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10199,7 +10337,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843568"
+ value="16843556"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10210,7 +10348,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843569"
+ value="16843557"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10250,6 +10388,17 @@
  visibility="public"
 >
 </field>
+<field name="unfocusedMonthDateColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843590"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="unselectedAlpha"
  type="int"
  transient="false"
@@ -10272,22 +10421,11 @@
  visibility="public"
 >
 </field>
-<field name="uri"
- type="int"
- transient="false"
- volatile="false"
- value="16843471"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="useIntrinsicSizeAsMinimum"
  type="int"
  transient="false"
  volatile="false"
- value="16843550"
+ value="16843538"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10331,7 +10469,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843498"
+ value="16843486"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10342,7 +10480,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843499"
+ value="16843487"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10353,7 +10491,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843500"
+ value="16843488"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10430,7 +10568,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843586"
+ value="16843574"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10646,6 +10784,39 @@
  visibility="public"
 >
 </field>
+<field name="weekDayTextAppearance"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843594"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="weekNumberColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843591"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="weekSeparatorLineColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843592"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="weightSum"
  type="int"
  transient="false"
@@ -10683,7 +10854,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843481"
+ value="16843469"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10694,7 +10865,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843504"
+ value="16843492"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10705,7 +10876,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843497"
+ value="16843485"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10760,7 +10931,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843557"
+ value="16843545"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -10844,6 +11015,28 @@
  visibility="public"
 >
 </field>
+<field name="windowMinWidthMajor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843608"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="windowMinWidthMinor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843609"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="windowNoDisplay"
  type="int"
  transient="false"
@@ -10932,28 +11125,6 @@
  visibility="public"
 >
 </field>
-<field name="withClass"
- type="int"
- transient="false"
- volatile="false"
- value="16843479"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="withExpression"
- type="int"
- transient="false"
- volatile="false"
- value="16843478"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="writePermission"
  type="int"
  transient="false"
@@ -11280,6 +11451,28 @@
  visibility="public"
 >
 </field>
+<field name="dialog_min_width_major"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104899"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="dialog_min_width_minor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104900"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="thumbnail_height"
  type="int"
  transient="false"
@@ -13813,6 +14006,166 @@
 >
 </field>
 </class>
+<class name="R.interpolator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="R.interpolator"
+ type="android.R.interpolator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="accelerate_cubic"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563650"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="accelerate_decelerate"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563654"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="accelerate_quad"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563648"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="accelerate_quint"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563652"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="anticipate"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563655"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="anticipate_overshoot"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563657"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="bounce"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563658"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="cycle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563660"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="decelerate_cubic"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563651"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="decelerate_quad"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563649"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="decelerate_quint"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563653"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="linear"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563659"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="overshoot"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17563656"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="R.layout"
  extends="java.lang.Object"
  abstract="false"
@@ -14111,6 +14464,34 @@
 >
 </constructor>
 </class>
+<class name="R.mipmap"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="R.mipmap"
+ type="android.R.mipmap"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="sym_def_app_icon"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17629184"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="R.plurals"
  extends="java.lang.Object"
  abstract="false"
@@ -14501,7 +14882,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974050"
+ value="16974054"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14512,7 +14893,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974052"
+ value="16974056"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14523,7 +14904,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974051"
+ value="16974055"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14534,7 +14915,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974053"
+ value="16974057"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14545,7 +14926,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974055"
+ value="16974059"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14556,7 +14937,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974054"
+ value="16974058"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14875,7 +15256,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973949"
+ value="16973953"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14886,7 +15267,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973950"
+ value="16973954"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15003,22 +15384,11 @@
  visibility="public"
 >
 </field>
-<field name="Theme_Dialog_NoFrame"
- type="int"
- transient="false"
- volatile="false"
- value="16973930"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="Theme_Holo"
  type="int"
  transient="false"
  volatile="false"
- value="16973932"
+ value="16973931"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15029,7 +15399,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973937"
+ value="16973936"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15040,7 +15410,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973943"
+ value="16973944"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15051,18 +15421,18 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973944"
+ value="16973945"
  static="true"
  final="true"
  deprecated="not deprecated"
  visibility="public"
 >
 </field>
-<field name="Theme_Holo_Dialog_Alert"
+<field name="Theme_Holo_Dialog_MinWidth"
  type="int"
  transient="false"
  volatile="false"
- value="16973941"
+ value="16973937"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15080,18 +15450,7 @@
  visibility="public"
 >
 </field>
-<field name="Theme_Holo_Light"
- type="int"
- transient="false"
- volatile="false"
- value="16973936"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="Theme_Holo_Light_Dialog"
+<field name="Theme_Holo_Dialog_NoActionBar_MinWidth"
  type="int"
  transient="false"
  volatile="false"
@@ -15102,62 +15461,18 @@
  visibility="public"
 >
 </field>
-<field name="Theme_Holo_Light_DialogWhenLarge"
+<field name="Theme_Holo_InputMethod"
  type="int"
  transient="false"
  volatile="false"
- value="16973945"
+ value="16973952"
  static="true"
  final="true"
  deprecated="not deprecated"
  visibility="public"
 >
 </field>
-<field name="Theme_Holo_Light_DialogWhenLarge_NoActionBar"
- type="int"
- transient="false"
- volatile="false"
- value="16973946"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="Theme_Holo_Light_Dialog_Alert"
- type="int"
- transient="false"
- volatile="false"
- value="16973942"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="Theme_Holo_Light_Dialog_NoActionBar"
- type="int"
- transient="false"
- volatile="false"
- value="16973940"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="Theme_Holo_NoActionBar"
- type="int"
- transient="false"
- volatile="false"
- value="16973934"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="Theme_Holo_NoActionBar_Fullscreen"
+<field name="Theme_Holo_Light"
  type="int"
  transient="false"
  volatile="false"
@@ -15168,7 +15483,29 @@
  visibility="public"
 >
 </field>
-<field name="Theme_Holo_Wallpaper"
+<field name="Theme_Holo_Light_Dialog"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973940"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light_DialogWhenLarge"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973946"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light_DialogWhenLarge_NoActionBar"
  type="int"
  transient="false"
  volatile="false"
@@ -15179,7 +15516,73 @@
  visibility="public"
 >
 </field>
-<field name="Theme_Holo_Wallpaper_NoTitleBar"
+<field name="Theme_Holo_Light_Dialog_MinWidth"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973941"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light_Dialog_NoActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973942"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light_Dialog_NoActionBar_MinWidth"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973943"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Light_Panel"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973949"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_NoActionBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973933"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_NoActionBar_Fullscreen"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973934"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Panel"
  type="int"
  transient="false"
  volatile="false"
@@ -15190,6 +15593,28 @@
  visibility="public"
 >
 </field>
+<field name="Theme_Holo_Wallpaper"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973950"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Theme_Holo_Wallpaper_NoTitleBar"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973951"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Theme_InputMethod"
  type="int"
  transient="false"
@@ -15216,7 +15641,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973933"
+ value="16973932"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15304,7 +15729,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973931"
+ value="16973930"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15436,7 +15861,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973951"
+ value="16973955"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15447,7 +15872,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973953"
+ value="16973957"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15458,7 +15883,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973957"
+ value="16973961"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15469,7 +15894,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973956"
+ value="16973960"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15531,6 +15956,17 @@
  visibility="public"
 >
 </field>
+<field name="Widget_CalendarView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974069"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_CompoundButton"
  type="int"
  transient="false"
@@ -15608,6 +16044,17 @@
  visibility="public"
 >
 </field>
+<field name="Widget_EditText_NumberPickerInputText"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974061"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_ExpandableListView"
  type="int"
  transient="false"
@@ -15623,7 +16070,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973958"
+ value="16973962"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15656,7 +16103,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973959"
+ value="16973963"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15667,7 +16114,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974001"
+ value="16974005"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15678,7 +16125,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973996"
+ value="16974000"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15689,7 +16136,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974000"
+ value="16974004"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15700,7 +16147,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973997"
+ value="16974001"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15711,7 +16158,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973998"
+ value="16974002"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15722,7 +16169,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973999"
+ value="16974003"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15733,7 +16180,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973965"
+ value="16973969"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15744,7 +16191,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973960"
+ value="16973964"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15755,7 +16202,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974047"
+ value="16974051"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15766,7 +16213,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973962"
+ value="16973966"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15777,7 +16224,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973961"
+ value="16973965"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15788,7 +16235,18 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973963"
+ value="16973967"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_CalendarView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974070"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15799,7 +16257,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973966"
+ value="16973970"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15810,7 +16268,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973983"
+ value="16973987"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15821,7 +16279,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973987"
+ value="16973991"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15832,7 +16290,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973991"
+ value="16973995"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15843,7 +16301,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973992"
+ value="16973996"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15854,7 +16312,18 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973968"
+ value="16973972"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_EditText_NumberPickerInputText"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974064"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15865,7 +16334,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973969"
+ value="16973973"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15876,7 +16345,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973970"
+ value="16973974"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15887,7 +16356,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973985"
+ value="16973989"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15898,7 +16367,29 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973971"
+ value="16973975"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ImageButton_NumberPickerDownButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974065"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_ImageButton_NumberPickerUpButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974063"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15909,7 +16400,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974002"
+ value="16974006"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15920,7 +16411,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974046"
+ value="16974050"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15931,7 +16422,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974042"
+ value="16974046"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15942,7 +16433,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974045"
+ value="16974049"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15953,7 +16444,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974043"
+ value="16974047"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15964,7 +16455,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974044"
+ value="16974048"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15975,7 +16466,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974008"
+ value="16974012"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15986,7 +16477,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974003"
+ value="16974007"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15997,7 +16488,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974005"
+ value="16974009"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16008,7 +16499,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974004"
+ value="16974008"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16019,7 +16510,18 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974006"
+ value="16974010"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_CalendarView"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974071"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16030,7 +16532,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974009"
+ value="16974013"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16041,7 +16543,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974029"
+ value="16974033"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16052,7 +16554,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974033"
+ value="16974037"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16063,7 +16565,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974037"
+ value="16974041"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16074,7 +16576,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974038"
+ value="16974042"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16085,7 +16587,18 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974011"
+ value="16974015"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_EditText_NumberPickerInputText"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974067"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16096,7 +16609,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974012"
+ value="16974016"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16107,7 +16620,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974013"
+ value="16974017"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16118,7 +16631,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974031"
+ value="16974035"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16129,7 +16642,29 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974014"
+ value="16974018"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ImageButton_NumberPickerDownButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974068"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_Holo_Light_ImageButton_NumberPickerUpButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974066"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16140,7 +16675,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974040"
+ value="16974044"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16151,7 +16686,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974015"
+ value="16974019"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16162,7 +16697,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974010"
+ value="16974014"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16173,7 +16708,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974041"
+ value="16974045"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16184,7 +16719,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974016"
+ value="16974020"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16195,7 +16730,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974017"
+ value="16974021"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16206,7 +16741,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974018"
+ value="16974022"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16217,7 +16752,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974022"
+ value="16974026"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16228,7 +16763,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974021"
+ value="16974025"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16239,7 +16774,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974024"
+ value="16974028"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16250,7 +16785,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974019"
+ value="16974023"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16261,7 +16796,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974023"
+ value="16974027"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16272,7 +16807,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974020"
+ value="16974024"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16283,7 +16818,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974026"
+ value="16974030"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16294,7 +16829,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974027"
+ value="16974031"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16305,7 +16840,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974028"
+ value="16974032"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16316,7 +16851,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974030"
+ value="16974034"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16327,7 +16862,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974025"
+ value="16974029"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16338,7 +16873,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974032"
+ value="16974036"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16349,7 +16884,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974049"
+ value="16974053"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16360,7 +16895,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974034"
+ value="16974038"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16371,7 +16906,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974007"
+ value="16974011"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16382,7 +16917,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974039"
+ value="16974043"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16393,7 +16928,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974035"
+ value="16974039"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16404,7 +16939,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974036"
+ value="16974040"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16415,7 +16950,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973994"
+ value="16973998"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16426,7 +16961,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973972"
+ value="16973976"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16437,7 +16972,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973967"
+ value="16973971"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16448,7 +16983,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973995"
+ value="16973999"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16459,7 +16994,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973973"
+ value="16973977"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16470,7 +17005,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973974"
+ value="16973978"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16481,7 +17016,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973975"
+ value="16973979"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16492,7 +17027,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973978"
+ value="16973982"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16503,7 +17038,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973976"
+ value="16973980"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16514,7 +17049,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973977"
+ value="16973981"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16525,7 +17060,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973980"
+ value="16973984"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16536,7 +17071,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973981"
+ value="16973985"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16547,7 +17082,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973982"
+ value="16973986"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16558,7 +17093,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973984"
+ value="16973988"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16569,7 +17104,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973979"
+ value="16973983"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16580,7 +17115,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973986"
+ value="16973990"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16591,7 +17126,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974048"
+ value="16974052"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16602,7 +17137,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973988"
+ value="16973992"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16613,7 +17148,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973964"
+ value="16973968"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16624,7 +17159,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973993"
+ value="16973997"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16635,7 +17170,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973989"
+ value="16973993"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16646,7 +17181,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973990"
+ value="16973994"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16664,6 +17199,28 @@
  visibility="public"
 >
 </field>
+<field name="Widget_ImageButton_NumberPickerDownButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974062"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="Widget_ImageButton_NumberPickerUpButton"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16974060"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Widget_ImageWell"
  type="int"
  transient="false"
@@ -16690,7 +17247,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973954"
+ value="16973958"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16745,7 +17302,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973955"
+ value="16973959"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16888,7 +17445,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973952"
+ value="16973956"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -18308,6 +18865,28 @@
  visibility="public"
 >
 </field>
+<field name="KEY_CALLER_PID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;callerPid&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEY_CALLER_UID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;callerUid&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEY_ERROR_CODE"
  type="java.lang.String"
  transient="false"
@@ -18555,6 +19134,28 @@
 </parameter>
 <parameter name="prefId" type="int">
 </parameter>
+<parameter name="customTokens" type="boolean">
+</parameter>
+</constructor>
+<constructor name="AuthenticatorDescription"
+ type="android.accounts.AuthenticatorDescription"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.String">
+</parameter>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+<parameter name="labelId" type="int">
+</parameter>
+<parameter name="iconId" type="int">
+</parameter>
+<parameter name="smallIconId" type="int">
+</parameter>
+<parameter name="prefId" type="int">
+</parameter>
 </constructor>
 <method name="describeContents"
  return="int"
@@ -18615,6 +19216,16 @@
  visibility="public"
 >
 </field>
+<field name="customTokens"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="iconId"
  type="int"
  transient="false"
@@ -19446,6 +20057,42 @@
 </parameter>
 </method>
 </class>
+<class name="ArgbEvaluator"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.animation.TypeEvaluator">
+</implements>
+<constructor name="ArgbEvaluator"
+ type="android.animation.ArgbEvaluator"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="evaluate"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fraction" type="float">
+</parameter>
+<parameter name="startValue" type="java.lang.Object">
+</parameter>
+<parameter name="endValue" type="java.lang.Object">
+</parameter>
+</method>
+</class>
 <class name="DoubleEvaluator"
  extends="java.lang.Object"
  abstract="false"
@@ -19897,6 +20544,28 @@
 <parameter name="child" type="android.view.View">
 </parameter>
 </method>
+<method name="isChangingLayout"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isRunning"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="removeChild"
  return="void"
  abstract="false"
@@ -20412,42 +21081,6 @@
 </parameter>
 </method>
 </class>
-<class name="RGBEvaluator"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.animation.TypeEvaluator">
-</implements>
-<constructor name="RGBEvaluator"
- type="android.animation.RGBEvaluator"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="evaluate"
- return="java.lang.Object"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="fraction" type="float">
-</parameter>
-<parameter name="startValue" type="java.lang.Object">
-</parameter>
-<parameter name="endValue" type="java.lang.Object">
-</parameter>
-</method>
-</class>
 <interface name="TimeInterpolator"
  abstract="true"
  static="false"
@@ -21333,6 +21966,32 @@
 <parameter name="layoutParams" type="android.app.ActionBar.LayoutParams">
 </parameter>
 </method>
+<method name="setCustomView"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
+<method name="setDisplayHomeAsUpEnabled"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="showHomeAsUp" type="boolean">
+</parameter>
+</method>
 <method name="setDisplayOptions"
  return="void"
  abstract="true"
@@ -21361,6 +22020,58 @@
 <parameter name="mask" type="int">
 </parameter>
 </method>
+<method name="setDisplayShowCustomEnabled"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="showCustom" type="boolean">
+</parameter>
+</method>
+<method name="setDisplayShowHomeEnabled"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="showHome" type="boolean">
+</parameter>
+</method>
+<method name="setDisplayShowTitleEnabled"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="showTitle" type="boolean">
+</parameter>
+</method>
+<method name="setDisplayUseLogoEnabled"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="useLogo" type="boolean">
+</parameter>
+</method>
 <method name="setDropdownNavigationMode"
  return="void"
  abstract="true"
@@ -22118,6 +22829,19 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="dispatchKeyShortcutEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="dispatchPopulateAccessibilityEvent"
  return="boolean"
  abstract="false"
@@ -22176,32 +22900,6 @@
 <parameter name="args" type="java.lang.String[]">
 </parameter>
 </method>
-<method name="findFragmentById"
- return="android.app.Fragment"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="public"
->
-<parameter name="id" type="int">
-</parameter>
-</method>
-<method name="findFragmentByTag"
- return="android.app.Fragment"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="public"
->
-<parameter name="tag" type="java.lang.String">
-</parameter>
-</method>
 <method name="findViewById"
  return="android.view.View"
  abstract="false"
@@ -22995,6 +23693,21 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="onKeyShortcut"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="onKeyUp"
  return="boolean"
  abstract="false"
@@ -23409,17 +24122,6 @@
 <parameter name="view" type="android.view.View">
 </parameter>
 </method>
-<method name="openFragmentTransaction"
- return="android.app.FragmentTransaction"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="public"
->
-</method>
 <method name="openOptionsMenu"
  return="void"
  abstract="false"
@@ -24231,6 +24933,17 @@
  visibility="public"
 >
 </method>
+<method name="getLargeMemoryClass"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getMemoryClass"
  return="int"
  abstract="false"
@@ -24352,6 +25065,17 @@
 <exception name="SecurityException" type="java.lang.SecurityException">
 </exception>
 </method>
+<method name="isRunningInTestHarness"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isUserAMonkey"
  return="boolean"
  abstract="false"
@@ -25954,6 +26678,19 @@
 <parameter name="icon" type="android.graphics.drawable.Drawable">
 </parameter>
 </method>
+<method name="setIconAttribute"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="attrId" type="int">
+</parameter>
+</method>
 <method name="setInverseBackgroundForced"
  return="void"
  abstract="false"
@@ -26151,6 +26888,19 @@
 <parameter name="icon" type="android.graphics.drawable.Drawable">
 </parameter>
 </method>
+<method name="setIconAttribute"
+ return="android.app.AlertDialog.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="attrId" type="int">
+</parameter>
+</method>
 <method name="setInverseBackgroundForced"
  return="android.app.AlertDialog.Builder"
  abstract="false"
@@ -26655,6 +27405,17 @@
 <parameter name="dayOfMonth" type="int">
 </parameter>
 </constructor>
+<method name="getDatePicker"
+ return="android.widget.DatePicker"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="onClick"
  return="void"
  abstract="false"
@@ -26847,6 +27608,19 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="dispatchKeyShortcutEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="dispatchPopulateAccessibilityEvent"
  return="boolean"
  abstract="false"
@@ -27223,6 +27997,21 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="onKeyShortcut"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="onKeyUp"
  return="boolean"
  abstract="false"
@@ -27968,21 +28757,6 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="deprecated"
- visibility="public"
->
-<parameter name="activity" type="android.app.Activity">
-</parameter>
-<parameter name="tag" type="java.lang.String">
-</parameter>
-</method>
-<method name="show"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -29952,6 +30726,19 @@
 <parameter name="args" type="java.lang.String[]">
 </parameter>
 </method>
+<method name="enableDebugLogging"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
 <method name="executePendingTransactions"
  return="boolean"
  abstract="true"
@@ -32206,6 +32993,19 @@
  visibility="public"
 >
 </constructor>
+<method name="destroyLoader"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="int">
+</parameter>
+</method>
 <method name="dump"
  return="void"
  abstract="true"
@@ -32225,6 +33025,19 @@
 <parameter name="args" type="java.lang.String[]">
 </parameter>
 </method>
+<method name="enableDebugLogging"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
 <method name="getLoader"
  return="android.content.Loader&lt;D&gt;"
  abstract="true"
@@ -32274,12 +33087,12 @@
 </method>
 <method name="stopLoader"
  return="void"
- abstract="true"
+ abstract="false"
  native="false"
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="id" type="int">
@@ -32323,123 +33136,20 @@
 <parameter name="data" type="D">
 </parameter>
 </method>
+<method name="onLoaderReset"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="loader" type="android.content.Loader&lt;D&gt;">
+</parameter>
+</method>
 </interface>
-<class name="LoaderManagingFragment"
- extends="android.app.Fragment"
- abstract="true"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="public"
->
-<implements name="android.content.Loader.OnLoadCompleteListener">
-</implements>
-<constructor name="LoaderManagingFragment"
- type="android.app.LoaderManagingFragment"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="getLoader"
- return="android.content.Loader&lt;D&gt;"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="id" type="int">
-</parameter>
-</method>
-<method name="onCreateLoader"
- return="android.content.Loader&lt;D&gt;"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="id" type="int">
-</parameter>
-<parameter name="args" type="android.os.Bundle">
-</parameter>
-</method>
-<method name="onInitializeLoaders"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-</method>
-<method name="onLoadComplete"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="loader" type="android.content.Loader&lt;D&gt;">
-</parameter>
-<parameter name="data" type="D">
-</parameter>
-</method>
-<method name="onLoadFinished"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="loader" type="android.content.Loader&lt;D&gt;">
-</parameter>
-<parameter name="data" type="D">
-</parameter>
-</method>
-<method name="startLoading"
- return="android.content.Loader&lt;D&gt;"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="id" type="int">
-</parameter>
-<parameter name="args" type="android.os.Bundle">
-</parameter>
-</method>
-<method name="stopLoading"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="id" type="int">
-</parameter>
-</method>
-</class>
 <class name="LocalActivityManager"
  extends="java.lang.Object"
  abstract="false"
@@ -34159,6 +34869,32 @@
 <parameter name="d" type="android.graphics.drawable.Drawable">
 </parameter>
 </method>
+<method name="setProgressNumberFormat"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="format" type="java.lang.String">
+</parameter>
+</method>
+<method name="setProgressPercentFormat"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="format" type="java.text.NumberFormat">
+</parameter>
+</method>
 <method name="setProgressStyle"
  return="void"
  abstract="false"
@@ -36529,6 +37265,17 @@
  visibility="public"
 >
 </field>
+<field name="USES_ENCRYPTED_STORAGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="USES_POLICY_EXPIRE_PASSWORD"
  type="int"
  transient="false"
@@ -37092,6 +37839,19 @@
 <parameter name="admin" type="android.content.ComponentName">
 </parameter>
 </method>
+<method name="getStorageEncryption"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
 <method name="hasGrantedPolicy"
  return="boolean"
  abstract="false"
@@ -37367,6 +38127,21 @@
 <parameter name="quality" type="int">
 </parameter>
 </method>
+<method name="setStorageEncryption"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="encrypt" type="boolean">
+</parameter>
+</method>
 <method name="wipeData"
  return="void"
  abstract="false"
@@ -37402,6 +38177,72 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_START_ENCRYPTION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.app.action.START_ENCRYPTION&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_ACTIVATING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_ACTIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_INACTIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_REQUESTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_UNSUPPORTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_ADD_EXPLANATION"
  type="java.lang.String"
  transient="false"
@@ -38153,6 +38994,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"
@@ -39229,6 +40081,23 @@
  visibility="public"
 >
 </method>
+<method name="listenUsingInsecureRfcommWithServiceRecord"
+ return="android.bluetooth.BluetoothServerSocket"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="uuid" type="java.util.UUID">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
 <method name="listenUsingRfcommWithServiceRecord"
  return="android.bluetooth.BluetoothServerSocket"
  abstract="false"
@@ -41568,6 +42437,21 @@
 >
 <implements name="android.os.Parcelable">
 </implements>
+<method name="createInsecureRfcommSocketToServiceRecord"
+ return="android.bluetooth.BluetoothSocket"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uuid" type="java.util.UUID">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
 <method name="createRfcommSocketToServiceRecord"
  return="android.bluetooth.BluetoothSocket"
  abstract="false"
@@ -42899,17 +43783,6 @@
  visibility="public"
 >
 </method>
-<method name="forceLoad"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="loadInBackground"
  return="D"
  abstract="true"
@@ -42934,6 +43807,41 @@
 <parameter name="data" type="D">
 </parameter>
 </method>
+<method name="onLoadInBackground"
+ return="D"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="setUpdateThrottle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="delayMS" type="long">
+</parameter>
+</method>
+<method name="waitForLoader"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 </class>
 <class name="BroadcastReceiver"
  extends="java.lang.Object"
@@ -44261,6 +45169,23 @@
 <parameter name="values" type="android.content.ContentValues[]">
 </parameter>
 </method>
+<method name="call"
+ return="android.os.Bundle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="method" type="java.lang.String">
+</parameter>
+<parameter name="arg" type="java.lang.String">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+</method>
 <method name="delete"
  return="int"
  abstract="true"
@@ -45477,6 +46402,25 @@
 <parameter name="values" type="android.content.ContentValues[]">
 </parameter>
 </method>
+<method name="call"
+ return="android.os.Bundle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="method" type="java.lang.String">
+</parameter>
+<parameter name="arg" type="java.lang.String">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+</method>
 <method name="cancelSync"
  return="void"
  abstract="false"
@@ -49433,17 +50377,6 @@
 <parameter name="cursor" type="android.database.Cursor">
 </parameter>
 </method>
-<method name="destroy"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getProjection"
  return="java.lang.String[]"
  abstract="false"
@@ -49523,21 +50456,6 @@
 <parameter name="cursor" type="android.database.Cursor">
 </parameter>
 </method>
-<method name="registerContentObserver"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="cursor" type="android.database.Cursor">
-</parameter>
-<parameter name="observer" type="android.database.ContentObserver">
-</parameter>
-</method>
 <method name="setProjection"
  return="void"
  abstract="false"
@@ -49603,28 +50521,6 @@
 <parameter name="uri" type="android.net.Uri">
 </parameter>
 </method>
-<method name="startLoading"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="stopLoading"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 </class>
 <interface name="DialogInterface"
  abstract="true"
@@ -54719,7 +55615,7 @@
 </class>
 <class name="Loader"
  extends="java.lang.Object"
- abstract="true"
+ abstract="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -54735,6 +55631,19 @@
 <parameter name="context" type="android.content.Context">
 </parameter>
 </constructor>
+<method name="dataToString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="D">
+</parameter>
+</method>
 <method name="deliverResult"
  return="void"
  abstract="false"
@@ -54748,9 +55657,9 @@
 <parameter name="data" type="D">
 </parameter>
 </method>
-<method name="destroy"
+<method name="dump"
  return="void"
- abstract="true"
+ abstract="false"
  native="false"
  synchronized="false"
  static="false"
@@ -54758,10 +55667,18 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
 </method>
 <method name="forceLoad"
  return="void"
- abstract="true"
+ abstract="false"
  native="false"
  synchronized="false"
  static="false"
@@ -54792,6 +55709,28 @@
  visibility="public"
 >
 </method>
+<method name="isReset"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isStarted"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="onContentChanged"
  return="void"
  abstract="false"
@@ -54803,6 +55742,50 @@
  visibility="public"
 >
 </method>
+<method name="onForceLoad"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="onReset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="onStartLoading"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="onStopLoading"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
 <method name="registerListener"
  return="void"
  abstract="false"
@@ -54818,9 +55801,9 @@
 <parameter name="listener" type="android.content.Loader.OnLoadCompleteListener&lt;D&gt;">
 </parameter>
 </method>
-<method name="startLoading"
+<method name="reset"
  return="void"
- abstract="true"
+ abstract="false"
  native="false"
  synchronized="false"
  static="false"
@@ -54829,9 +55812,31 @@
  visibility="public"
 >
 </method>
+<method name="startLoading"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="stopLoading"
  return="void"
- abstract="true"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="takeContentChanged"
+ return="boolean"
+ abstract="false"
  native="false"
  synchronized="false"
  static="false"
@@ -57650,6 +58655,17 @@
  visibility="public"
 >
 </method>
+<method name="isEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <field name="applicationInfo"
  type="android.content.pm.ApplicationInfo"
  transient="false"
@@ -59262,6 +60278,19 @@
 <exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException">
 </exception>
 </method>
+<method name="getPackageObbPaths"
+ return="java.lang.String[]"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
 <method name="getPackagesForUid"
  return="java.lang.String[]"
  abstract="true"
@@ -59748,6 +60777,21 @@
 <parameter name="installerPackageName" type="java.lang.String">
 </parameter>
 </method>
+<method name="setPackageObbPaths"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+<parameter name="paths" type="java.lang.String[]">
+</parameter>
+</method>
 <field name="COMPONENT_ENABLED_STATE_DEFAULT"
  type="int"
  transient="false"
@@ -67241,6 +68285,21 @@
 <parameter name="selectionArgs" type="java.lang.String[]">
 </parameter>
 </method>
+<method name="concatenateWhere"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="a" type="java.lang.String">
+</parameter>
+<parameter name="b" type="java.lang.String">
+</parameter>
+</method>
 <method name="createDbFromSqlStatements"
  return="void"
  abstract="false"
@@ -70425,6 +71484,23 @@
 <parameter name="db" type="android.database.sqlite.SQLiteDatabase">
 </parameter>
 </method>
+<method name="onDowngrade"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="db" type="android.database.sqlite.SQLiteDatabase">
+</parameter>
+<parameter name="oldVersion" type="int">
+</parameter>
+<parameter name="newVersion" type="int">
+</parameter>
+</method>
 <method name="onOpen"
  return="void"
  abstract="false"
@@ -77464,17 +78540,6 @@
  visibility="public"
 >
 </method>
-<method name="getGL"
- return="javax.microedition.khronos.opengles.GL"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="deprecated"
- visibility="protected"
->
-</method>
 <method name="getHeight"
  return="int"
  abstract="false"
@@ -85198,6 +86263,110 @@
 </parameter>
 </constructor>
 </class>
+<class name="SurfaceTexture"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SurfaceTexture"
+ type="android.graphics.SurfaceTexture"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="texName" type="int">
+</parameter>
+</constructor>
+<method name="getTransformMatrix"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mtx" type="float[]">
+</parameter>
+</method>
+<method name="setOnFrameAvailableListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="l" type="android.graphics.SurfaceTexture.OnFrameAvailableListener">
+</parameter>
+</method>
+<method name="updateTexImage"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="SurfaceTexture.OnFrameAvailableListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onFrameAvailable"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="surfaceTexture" type="android.graphics.SurfaceTexture">
+</parameter>
+</method>
+</interface>
+<class name="SurfaceTexture.OutOfResourcesException"
+ extends="java.lang.Exception"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SurfaceTexture.OutOfResourcesException"
+ type="android.graphics.SurfaceTexture.OutOfResourcesException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SurfaceTexture.OutOfResourcesException"
+ type="android.graphics.SurfaceTexture.OutOfResourcesException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
 <class name="SweepGradient"
  extends="android.graphics.Shader"
  abstract="false"
@@ -89688,6 +90857,19 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="setPreviewTexture"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="surfaceTexture" type="android.graphics.SurfaceTexture">
+</parameter>
+</method>
 <method name="setZoomChangeListener"
  return="void"
  abstract="false"
@@ -102613,6 +103795,385 @@
 </parameter>
 </method>
 </interface>
+<class name="MediaMetadataRetriever"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="MediaMetadataRetriever"
+ type="android.media.MediaMetadataRetriever"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="extractMetadata"
+ return="java.lang.String"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+</method>
+<method name="getEmbeddedPicture"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFrameAtTime"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="timeUs" type="long">
+</parameter>
+<parameter name="option" type="int">
+</parameter>
+</method>
+<method name="getFrameAtTime"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="timeUs" type="long">
+</parameter>
+</method>
+<method name="getFrameAtTime"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="release"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setDataSource"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="setDataSource"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="offset" type="long">
+</parameter>
+<parameter name="length" type="long">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="setDataSource"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="setDataSource"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="SecurityException" type="java.lang.SecurityException">
+</exception>
+</method>
+<field name="METADATA_KEY_ALBUM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_ALBUMARTIST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="13"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_ARTIST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_AUTHOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_CD_TRACK_NUMBER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_COMPILATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="15"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_COMPOSER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_DATE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_DISC_NUMBER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="14"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_DURATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_GENRE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_MIMETYPE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="12"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_NUM_TRACKS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_TITLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_WRITER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="11"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="METADATA_KEY_YEAR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OPTION_CLOSEST"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OPTION_CLOSEST_SYNC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OPTION_NEXT_SYNC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OPTION_PREVIOUS_SYNC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="MediaPlayer"
  extends="java.lang.Object"
  abstract="false"
@@ -103921,6 +105482,17 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<field name="AAC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="AMR_NB"
  type="int"
  transient="false"
@@ -103932,6 +105504,17 @@
  visibility="public"
 >
 </field>
+<field name="AMR_WB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="DEFAULT"
  type="int"
  transient="false"
@@ -104099,6 +105682,28 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<field name="AMR_NB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AMR_WB"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="DEFAULT"
  type="int"
  transient="false"
@@ -116947,6 +118552,36 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="disableForegroundDispatch"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="activity" type="android.app.Activity">
+</parameter>
+</method>
+<method name="enableForegroundDispatch"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="activity" type="android.app.Activity">
+</parameter>
+<parameter name="intent" type="android.app.PendingIntent">
+</parameter>
+<parameter name="filters" type="android.content.IntentFilter...">
+</parameter>
+</method>
 <method name="getDefaultAdapter"
  return="android.nfc.NfcAdapter"
  abstract="false"
@@ -116982,6 +118617,17 @@
  visibility="public"
 >
 </method>
+<field name="ACTION_NDEF_DISCOVERED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.nfc.action.NDEF_DISCOVERED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_TAG_DISCOVERED"
  type="java.lang.String"
  transient="false"
@@ -116993,6 +118639,17 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_TECHNOLOGY_DISCOVERED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.nfc.action.TECH_DISCOVERED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_ID"
  type="java.lang.String"
  transient="false"
@@ -117015,6 +118672,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_TAG"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.nfc.extra.TAG&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="NfcManager"
  extends="java.lang.Object"
@@ -117036,6 +118704,1406 @@
 >
 </method>
 </class>
+<class name="Tag"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="createMockTag"
+ return="android.nfc.Tag"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="byte[]">
+</parameter>
+<parameter name="techList" type="int[]">
+</parameter>
+<parameter name="techListExtras" type="android.os.Bundle[]">
+</parameter>
+</method>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getId"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTechnology"
+ return="android.nfc.technology.TagTechnology"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.nfc.NfcAdapter">
+</parameter>
+<parameter name="tech" type="int">
+</parameter>
+</method>
+<method name="getTechnologyList"
+ return="int[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+</package>
+<package name="android.nfc.technology"
+>
+<class name="BasicTagTechnology"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility=""
+>
+<implements name="android.nfc.technology.TagTechnology">
+</implements>
+<method name="checkConnected"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="close"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="connect"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="getTag"
+ return="android.nfc.Tag"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTechnologyId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isConnected"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="reconnect"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="transceive"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="IsoDep"
+ extends="android.nfc.technology.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="IsoDep"
+ type="android.nfc.technology.IsoDep"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.nfc.NfcAdapter">
+</parameter>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</constructor>
+<method name="getHiLayerResponse"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHistoricalBytes"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="MifareClassic"
+ extends="android.nfc.technology.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="MifareClassic"
+ type="android.nfc.technology.MifareClassic"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.nfc.NfcAdapter">
+</parameter>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</constructor>
+<method name="authenticateBlock"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="block" type="int">
+</parameter>
+<parameter name="key" type="byte[]">
+</parameter>
+<parameter name="keyA" type="boolean">
+</parameter>
+</method>
+<method name="authenticateSector"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sector" type="int">
+</parameter>
+<parameter name="key" type="byte[]">
+</parameter>
+<parameter name="keyA" type="boolean">
+</parameter>
+</method>
+<method name="decrement"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="block" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="getBlockCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sector" type="int">
+</parameter>
+</method>
+<method name="getSectorCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSectorSize"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sector" type="int">
+</parameter>
+</method>
+<method name="getSize"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTotalBlockCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="increment"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="block" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="isEmulated"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="readBlock"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sector" type="int">
+</parameter>
+<parameter name="block" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="readBlock"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="block" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="restore"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="block" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="transfer"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="block" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="writeBlock"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="block" type="int">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="writeBlock"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sector" type="int">
+</parameter>
+<parameter name="block" type="int">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<field name="KEY_DEFAULT"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEY_MIFARE_APPLICATION_DIRECTORY"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEY_NFC_FORUM"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SIZE_1K"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1024"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SIZE_2K"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2048"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SIZE_4K"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4096"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SIZE_MINI"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="320"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SIZE_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_CLASSIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_DESFIRE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_PLUS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_PRO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_ULTRALIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="MifareUltralight"
+ extends="android.nfc.technology.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="MifareUltralight"
+ type="android.nfc.technology.MifareUltralight"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.nfc.NfcAdapter">
+</parameter>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</constructor>
+<method name="getType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="readBlock"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="block" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="readOTP"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="writeBlock"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="block" type="int">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="writePage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="block" type="int">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<field name="TYPE_ULTRALIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_ULTRALIGHT_C"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="10"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Ndef"
+ extends="android.nfc.technology.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="canMakeReadonly"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCachedNdefMessage"
+ return="android.nfc.NdefMessage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExtraNdefMessage"
+ return="android.nfc.NdefMessage[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="getMaxSize"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNdefMessage"
+ return="android.nfc.NdefMessage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="getType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isWritable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="makeReadonly"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="writeExtraNdefMessage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="msg" type="android.nfc.NdefMessage">
+</parameter>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="writeNdefMessage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="msg" type="android.nfc.NdefMessage">
+</parameter>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<field name="MIFARE_CLASSIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="105"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NFC_FORUM_TYPE_1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NFC_FORUM_TYPE_2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NFC_FORUM_TYPE_3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NFC_FORUM_TYPE_4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OTHER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="NdefFormatable"
+ extends="android.nfc.technology.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="format"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="firstMessage" type="android.nfc.NdefMessage">
+</parameter>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="NfcA"
+ extends="android.nfc.technology.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="NfcA"
+ type="android.nfc.technology.NfcA"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.nfc.NfcAdapter">
+</parameter>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</constructor>
+<method name="getAtqa"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSak"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="NfcB"
+ extends="android.nfc.technology.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="NfcB"
+ type="android.nfc.technology.NfcB"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.nfc.NfcAdapter">
+</parameter>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</constructor>
+<method name="getApplicationData"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProtocolInfo"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="NfcF"
+ extends="android.nfc.technology.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="NfcF"
+ type="android.nfc.technology.NfcF"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.nfc.NfcAdapter">
+</parameter>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</constructor>
+<method name="getManufacturer"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSystemCode"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="NfcV"
+ extends="android.nfc.technology.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="NfcV"
+ type="android.nfc.technology.NfcV"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.nfc.NfcAdapter">
+</parameter>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</constructor>
+<method name="getDsfId"
+ return="byte"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getResponseFlags"
+ return="byte"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="TagTechnology"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="close"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="connect"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="getTag"
+ return="android.nfc.Tag"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTechnologyId"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="reconnect"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<field name="ISO_DEP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MIFARE_CLASSIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MIFARE_ULTRALIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NDEF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NDEF_FORMATABLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NFC_A"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NFC_B"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NFC_F"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NFC_V"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</interface>
 </package>
 <package name="android.opengl"
 >
@@ -135995,6 +139063,19 @@
  deprecated="not deprecated"
  visibility="protected"
 >
+<parameter name="result" type="Result">
+</parameter>
+</method>
+<method name="onCancelled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
 </method>
 <method name="onPostExecute"
  return="void"
@@ -138586,7 +141667,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -138597,7 +141678,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -138608,7 +141689,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -138619,7 +141700,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -138742,7 +141823,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -138753,7 +141834,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -138854,7 +141935,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -138865,7 +141946,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -138876,7 +141957,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -138887,7 +141968,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -138953,7 +142034,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -138964,7 +142045,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -138986,7 +142067,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="limit" type="int">
@@ -138999,7 +142080,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="limit" type="int">
@@ -139887,6 +142968,17 @@
  visibility="public"
 >
 </method>
+<method name="isExternalStorageEmulated"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isExternalStorageRemovable"
  return="boolean"
  abstract="false"
@@ -143207,23 +146299,6 @@
  visibility="public"
 >
 </method>
-<method name="fromData"
- return="android.os.ParcelFileDescriptor"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="data" type="byte[]">
-</parameter>
-<parameter name="name" type="java.lang.String">
-</parameter>
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
 <method name="fromSocket"
  return="android.os.ParcelFileDescriptor"
  abstract="false"
@@ -149633,6 +152708,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_SKIP_UI"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.extra.alarm.SKIP_UI&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <interface name="BaseColumns"
  abstract="true"
@@ -165065,6 +168151,6877 @@
 </field>
 </class>
 </package>
+<package name="android.renderscript"
+>
+<class name="Allocation"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="copy1DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="int[]">
+</parameter>
+</method>
+<method name="copy1DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="short[]">
+</parameter>
+</method>
+<method name="copy1DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="byte[]">
+</parameter>
+</method>
+<method name="copy1DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="float[]">
+</parameter>
+</method>
+<method name="copy2DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+</method>
+<method name="copy2DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="data" type="short[]">
+</parameter>
+</method>
+<method name="copy2DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="data" type="int[]">
+</parameter>
+</method>
+<method name="copy2DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="data" type="float[]">
+</parameter>
+</method>
+<method name="copy2DRangeFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="data" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="copyFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="android.renderscript.BaseObj[]">
+</parameter>
+</method>
+<method name="copyFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="int[]">
+</parameter>
+</method>
+<method name="copyFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="short[]">
+</parameter>
+</method>
+<method name="copyFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="byte[]">
+</parameter>
+</method>
+<method name="copyFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="float[]">
+</parameter>
+</method>
+<method name="copyFrom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="copyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="copyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="byte[]">
+</parameter>
+</method>
+<method name="copyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="short[]">
+</parameter>
+</method>
+<method name="copyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="int[]">
+</parameter>
+</method>
+<method name="copyTo"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="float[]">
+</parameter>
+</method>
+<method name="createCubemapFromBitmap"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createCubemapFromBitmap"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="createCubemapFromCubeFaces"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="xpos" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="xneg" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="ypos" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="yneg" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="zpos" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="zneg" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createCubemapFromCubeFaces"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="xpos" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="xneg" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="ypos" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="yneg" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="zpos" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="zneg" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="createFromBitmap"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createFromBitmap"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+</method>
+<method name="createFromBitmapResource"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createFromBitmapResource"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="id" type="int">
+</parameter>
+</method>
+<method name="createFromString"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="str" type="java.lang.String">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createSized"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="e" type="android.renderscript.Element">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createSized"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="e" type="android.renderscript.Element">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+</method>
+<method name="createTyped"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="type" type="android.renderscript.Type">
+</parameter>
+<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createTyped"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="type" type="android.renderscript.Type">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</method>
+<method name="createTyped"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="type" type="android.renderscript.Type">
+</parameter>
+</method>
+<method name="generateMipmaps"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="android.renderscript.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="resize"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dimX" type="int">
+</parameter>
+</method>
+<method name="syncAll"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="srcLocation" type="int">
+</parameter>
+</method>
+<field name="USAGE_GRAPHICS_CONSTANTS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="USAGE_GRAPHICS_TEXTURE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="USAGE_GRAPHICS_VERTEX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="USAGE_SCRIPT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Allocation.MipmapControl"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Allocation.MipmapControl"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Allocation.MipmapControl[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="AllocationAdapter"
+ extends="android.renderscript.Allocation"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="create2D"
+ return="android.renderscript.AllocationAdapter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="a" type="android.renderscript.Allocation">
+</parameter>
+</method>
+<method name="readData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="int[]">
+</parameter>
+</method>
+<method name="readData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="d" type="float[]">
+</parameter>
+</method>
+<method name="setFace"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cf" type="android.renderscript.Type.CubemapFace">
+</parameter>
+</method>
+<method name="setLOD"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lod" type="int">
+</parameter>
+</method>
+<method name="setY"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="y" type="int">
+</parameter>
+</method>
+<method name="setZ"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="z" type="int">
+</parameter>
+</method>
+<method name="subData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="fp" type="android.renderscript.FieldPacker">
+</parameter>
+</method>
+<method name="subData1D"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="int[]">
+</parameter>
+</method>
+<method name="subData1D"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="short[]">
+</parameter>
+</method>
+<method name="subData1D"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="byte[]">
+</parameter>
+</method>
+<method name="subData1D"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="off" type="int">
+</parameter>
+<parameter name="count" type="int">
+</parameter>
+<parameter name="d" type="float[]">
+</parameter>
+</method>
+<method name="subData2D"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="d" type="int[]">
+</parameter>
+</method>
+<method name="subData2D"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="yoff" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="d" type="float[]">
+</parameter>
+</method>
+<method name="subElementData"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="component_number" type="int">
+</parameter>
+<parameter name="fp" type="android.renderscript.FieldPacker">
+</parameter>
+</method>
+</class>
+<class name="BaseObj"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility=""
+>
+<method name="destroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setName"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="Byte2"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Byte2"
+ type="android.renderscript.Byte2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Byte3"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Byte3"
+ type="android.renderscript.Byte3"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Byte4"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Byte4"
+ type="android.renderscript.Byte4"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="w"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="byte"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Element"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="ALLOCATION"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="A_8"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="BOOLEAN"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="ELEMENT"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="F32"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="F32_2"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="F32_3"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="F32_4"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="F64"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="I16"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="I32"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="I64"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="I8"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="MATRIX4X4"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="MATRIX_2X2"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="MATRIX_3X3"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="MATRIX_4X4"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="MESH"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="PROGRAM_FRAGMENT"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="PROGRAM_RASTER"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="PROGRAM_STORE"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="PROGRAM_VERTEX"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="RGBA_4444"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="RGBA_5551"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="RGBA_8888"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="RGB_565"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="RGB_888"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="SAMPLER"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="SCRIPT"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="TYPE"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="U16"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="U32"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="U64"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="U8"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="U8_4"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="createPixel"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="dt" type="android.renderscript.Element.DataType">
+</parameter>
+<parameter name="dk" type="android.renderscript.Element.DataKind">
+</parameter>
+</method>
+<method name="createVector"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="dt" type="android.renderscript.Element.DataType">
+</parameter>
+<parameter name="size" type="int">
+</parameter>
+</method>
+<method name="isComplex"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Element.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Element.Builder"
+ type="android.renderscript.Element.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="add"
+ return="android.renderscript.Element.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="element" type="android.renderscript.Element">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="arraySize" type="int">
+</parameter>
+</method>
+<method name="add"
+ return="android.renderscript.Element.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="element" type="android.renderscript.Element">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="create"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Element.DataKind"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Element.DataKind"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Element.DataKind[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Element.DataType"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Element.DataType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Element.DataType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="FieldPacker"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="FieldPacker"
+ type="android.renderscript.FieldPacker"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="len" type="int">
+</parameter>
+</constructor>
+<method name="addBoolean"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="boolean">
+</parameter>
+</method>
+<method name="addF32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="float">
+</parameter>
+</method>
+<method name="addF32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Float2">
+</parameter>
+</method>
+<method name="addF32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Float3">
+</parameter>
+</method>
+<method name="addF32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Float4">
+</parameter>
+</method>
+<method name="addF64"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="double">
+</parameter>
+</method>
+<method name="addI16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="short">
+</parameter>
+</method>
+<method name="addI16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Short2">
+</parameter>
+</method>
+<method name="addI16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Short3">
+</parameter>
+</method>
+<method name="addI16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Short4">
+</parameter>
+</method>
+<method name="addI32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="int">
+</parameter>
+</method>
+<method name="addI32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int2">
+</parameter>
+</method>
+<method name="addI32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int3">
+</parameter>
+</method>
+<method name="addI32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int4">
+</parameter>
+</method>
+<method name="addI64"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="long">
+</parameter>
+</method>
+<method name="addI8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="byte">
+</parameter>
+</method>
+<method name="addI8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Byte2">
+</parameter>
+</method>
+<method name="addI8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Byte3">
+</parameter>
+</method>
+<method name="addI8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Byte4">
+</parameter>
+</method>
+<method name="addMatrix"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+<method name="addMatrix"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Matrix3f">
+</parameter>
+</method>
+<method name="addMatrix"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Matrix2f">
+</parameter>
+</method>
+<method name="addObj"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="obj" type="android.renderscript.BaseObj">
+</parameter>
+</method>
+<method name="addU16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="int">
+</parameter>
+</method>
+<method name="addU16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int2">
+</parameter>
+</method>
+<method name="addU16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int3">
+</parameter>
+</method>
+<method name="addU16"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int4">
+</parameter>
+</method>
+<method name="addU32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="long">
+</parameter>
+</method>
+<method name="addU32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int2">
+</parameter>
+</method>
+<method name="addU32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int3">
+</parameter>
+</method>
+<method name="addU32"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Int4">
+</parameter>
+</method>
+<method name="addU64"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="long">
+</parameter>
+</method>
+<method name="addU8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="short">
+</parameter>
+</method>
+<method name="addU8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Short2">
+</parameter>
+</method>
+<method name="addU8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Short3">
+</parameter>
+</method>
+<method name="addU8"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Short4">
+</parameter>
+</method>
+<method name="align"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="int">
+</parameter>
+</method>
+<method name="getData"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="reset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="reset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+</method>
+<method name="skip"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+</method>
+</class>
+<class name="FileA3D"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="createFromAsset"
+ return="android.renderscript.FileA3D"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="mgr" type="android.content.res.AssetManager">
+</parameter>
+<parameter name="path" type="java.lang.String">
+</parameter>
+</method>
+<method name="createFromFile"
+ return="android.renderscript.FileA3D"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="path" type="java.lang.String">
+</parameter>
+</method>
+<method name="createFromFile"
+ return="android.renderscript.FileA3D"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="path" type="java.io.File">
+</parameter>
+</method>
+<method name="createFromResource"
+ return="android.renderscript.FileA3D"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="id" type="int">
+</parameter>
+</method>
+<method name="getIndexEntry"
+ return="android.renderscript.FileA3D.IndexEntry"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+</method>
+<method name="getIndexEntryCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="FileA3D.EntryType"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.FileA3D.EntryType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.FileA3D.EntryType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="FileA3D.IndexEntry"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getEntryType"
+ return="android.renderscript.FileA3D.EntryType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMesh"
+ return="android.renderscript.Mesh"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getObject"
+ return="android.renderscript.BaseObj"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Float2"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Float2"
+ type="android.renderscript.Float2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Float2"
+ type="android.renderscript.Float2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="initX" type="float">
+</parameter>
+<parameter name="initY" type="float">
+</parameter>
+</constructor>
+<field name="x"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Float3"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Float3"
+ type="android.renderscript.Float3"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Float3"
+ type="android.renderscript.Float3"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="initX" type="float">
+</parameter>
+<parameter name="initY" type="float">
+</parameter>
+<parameter name="initZ" type="float">
+</parameter>
+</constructor>
+<field name="x"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Float4"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Float4"
+ type="android.renderscript.Float4"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Float4"
+ type="android.renderscript.Float4"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="initX" type="float">
+</parameter>
+<parameter name="initY" type="float">
+</parameter>
+<parameter name="initZ" type="float">
+</parameter>
+<parameter name="initW" type="float">
+</parameter>
+</constructor>
+<field name="w"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Font"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="create"
+ return="android.renderscript.Font"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="familyName" type="java.lang.String">
+</parameter>
+<parameter name="fontStyle" type="android.renderscript.Font.Style">
+</parameter>
+<parameter name="pointSize" type="float">
+</parameter>
+</method>
+<method name="createFromAsset"
+ return="android.renderscript.Font"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="pointSize" type="float">
+</parameter>
+</method>
+<method name="createFromFile"
+ return="android.renderscript.Font"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="pointSize" type="float">
+</parameter>
+</method>
+<method name="createFromFile"
+ return="android.renderscript.Font"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="path" type="java.io.File">
+</parameter>
+<parameter name="pointSize" type="float">
+</parameter>
+</method>
+<method name="createFromResource"
+ return="android.renderscript.Font"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="pointSize" type="float">
+</parameter>
+</method>
+</class>
+<class name="Font.Style"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Font.Style"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Font.Style[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Int2"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Int2"
+ type="android.renderscript.Int2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Int3"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Int3"
+ type="android.renderscript.Int3"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Int4"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Int4"
+ type="android.renderscript.Int4"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="w"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Long2"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Long2"
+ type="android.renderscript.Long2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Long3"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Long3"
+ type="android.renderscript.Long3"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Long4"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Long4"
+ type="android.renderscript.Long4"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="w"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Matrix2f"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Matrix2f"
+ type="android.renderscript.Matrix2f"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Matrix2f"
+ type="android.renderscript.Matrix2f"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dataArray" type="float[]">
+</parameter>
+</constructor>
+<method name="get"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="j" type="int">
+</parameter>
+</method>
+<method name="getArray"
+ return="float[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="load"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="src" type="android.renderscript.Matrix2f">
+</parameter>
+</method>
+<method name="loadIdentity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="loadMultiply"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lhs" type="android.renderscript.Matrix2f">
+</parameter>
+<parameter name="rhs" type="android.renderscript.Matrix2f">
+</parameter>
+</method>
+<method name="loadRotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+</method>
+<method name="loadScale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="multiply"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rhs" type="android.renderscript.Matrix2f">
+</parameter>
+</method>
+<method name="rotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+</method>
+<method name="scale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="set"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="j" type="int">
+</parameter>
+<parameter name="v" type="float">
+</parameter>
+</method>
+<method name="transpose"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Matrix3f"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Matrix3f"
+ type="android.renderscript.Matrix3f"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Matrix3f"
+ type="android.renderscript.Matrix3f"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dataArray" type="float[]">
+</parameter>
+</constructor>
+<method name="get"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="j" type="int">
+</parameter>
+</method>
+<method name="getArray"
+ return="float[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="load"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="src" type="android.renderscript.Matrix3f">
+</parameter>
+</method>
+<method name="loadIdentity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="loadMultiply"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lhs" type="android.renderscript.Matrix3f">
+</parameter>
+<parameter name="rhs" type="android.renderscript.Matrix3f">
+</parameter>
+</method>
+<method name="loadRotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="loadRotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+</method>
+<method name="loadScale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="loadScale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="loadTranslate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="multiply"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rhs" type="android.renderscript.Matrix3f">
+</parameter>
+</method>
+<method name="rotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="rotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+</method>
+<method name="scale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="scale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="set"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="j" type="int">
+</parameter>
+<parameter name="v" type="float">
+</parameter>
+</method>
+<method name="translate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="transpose"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Matrix4f"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Matrix4f"
+ type="android.renderscript.Matrix4f"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Matrix4f"
+ type="android.renderscript.Matrix4f"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dataArray" type="float[]">
+</parameter>
+</constructor>
+<method name="get"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="j" type="int">
+</parameter>
+</method>
+<method name="getArray"
+ return="float[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="inverse"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="inverseTranspose"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="load"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="src" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+<method name="loadFrustum"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="l" type="float">
+</parameter>
+<parameter name="r" type="float">
+</parameter>
+<parameter name="b" type="float">
+</parameter>
+<parameter name="t" type="float">
+</parameter>
+<parameter name="n" type="float">
+</parameter>
+<parameter name="f" type="float">
+</parameter>
+</method>
+<method name="loadIdentity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="loadMultiply"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lhs" type="android.renderscript.Matrix4f">
+</parameter>
+<parameter name="rhs" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+<method name="loadOrtho"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="l" type="float">
+</parameter>
+<parameter name="r" type="float">
+</parameter>
+<parameter name="b" type="float">
+</parameter>
+<parameter name="t" type="float">
+</parameter>
+<parameter name="n" type="float">
+</parameter>
+<parameter name="f" type="float">
+</parameter>
+</method>
+<method name="loadOrthoWindow"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+</method>
+<method name="loadPerspective"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fovy" type="float">
+</parameter>
+<parameter name="aspect" type="float">
+</parameter>
+<parameter name="near" type="float">
+</parameter>
+<parameter name="far" type="float">
+</parameter>
+</method>
+<method name="loadProjectionNormalized"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+</method>
+<method name="loadRotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="loadScale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="loadTranslate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="multiply"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rhs" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+<method name="rotate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rot" type="float">
+</parameter>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="scale"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="set"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="i" type="int">
+</parameter>
+<parameter name="j" type="int">
+</parameter>
+<parameter name="v" type="float">
+</parameter>
+</method>
+<method name="translate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="transpose"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Mesh"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getIndexSetAllocation"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="slot" type="int">
+</parameter>
+</method>
+<method name="getPrimitive"
+ return="android.renderscript.Mesh.Primitive"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="slot" type="int">
+</parameter>
+</method>
+<method name="getPrimitiveCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getVertexAllocation"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="slot" type="int">
+</parameter>
+</method>
+<method name="getVertexAllocationCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Mesh.AllocationBuilder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Mesh.AllocationBuilder"
+ type="android.renderscript.Mesh.AllocationBuilder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="addIndexSetAllocation"
+ return="android.renderscript.Mesh.AllocationBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="a" type="android.renderscript.Allocation">
+</parameter>
+<parameter name="p" type="android.renderscript.Mesh.Primitive">
+</parameter>
+</method>
+<method name="addIndexSetType"
+ return="android.renderscript.Mesh.AllocationBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.Mesh.Primitive">
+</parameter>
+</method>
+<method name="addVertexAllocation"
+ return="android.renderscript.Mesh.AllocationBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="a" type="android.renderscript.Allocation">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="create"
+ return="android.renderscript.Mesh"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentIndexSetIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentVertexTypeIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Mesh.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Mesh.Builder"
+ type="android.renderscript.Mesh.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="usage" type="int">
+</parameter>
+</constructor>
+<method name="addIndexSetType"
+ return="android.renderscript.Mesh.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="android.renderscript.Type">
+</parameter>
+<parameter name="p" type="android.renderscript.Mesh.Primitive">
+</parameter>
+</method>
+<method name="addIndexSetType"
+ return="android.renderscript.Mesh.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.Mesh.Primitive">
+</parameter>
+</method>
+<method name="addIndexSetType"
+ return="android.renderscript.Mesh.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="e" type="android.renderscript.Element">
+</parameter>
+<parameter name="size" type="int">
+</parameter>
+<parameter name="p" type="android.renderscript.Mesh.Primitive">
+</parameter>
+</method>
+<method name="addVertexType"
+ return="android.renderscript.Mesh.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="android.renderscript.Type">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="addVertexType"
+ return="android.renderscript.Mesh.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="e" type="android.renderscript.Element">
+</parameter>
+<parameter name="size" type="int">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="create"
+ return="android.renderscript.Mesh"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentIndexSetIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentVertexTypeIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Mesh.Primitive"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Mesh.Primitive"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Mesh.Primitive[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Mesh.TriangleMeshBuilder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Mesh.TriangleMeshBuilder"
+ type="android.renderscript.Mesh.TriangleMeshBuilder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="vtxSize" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</constructor>
+<method name="addTriangle"
+ return="android.renderscript.Mesh.TriangleMeshBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="idx1" type="int">
+</parameter>
+<parameter name="idx2" type="int">
+</parameter>
+<parameter name="idx3" type="int">
+</parameter>
+</method>
+<method name="addVertex"
+ return="android.renderscript.Mesh.TriangleMeshBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+</method>
+<method name="addVertex"
+ return="android.renderscript.Mesh.TriangleMeshBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="create"
+ return="android.renderscript.Mesh"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uploadToBufferObject" type="boolean">
+</parameter>
+</method>
+<method name="setColor"
+ return="android.renderscript.Mesh.TriangleMeshBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="r" type="float">
+</parameter>
+<parameter name="g" type="float">
+</parameter>
+<parameter name="b" type="float">
+</parameter>
+<parameter name="a" type="float">
+</parameter>
+</method>
+<method name="setNormal"
+ return="android.renderscript.Mesh.TriangleMeshBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="z" type="float">
+</parameter>
+</method>
+<method name="setTexture"
+ return="android.renderscript.Mesh.TriangleMeshBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="s" type="float">
+</parameter>
+<parameter name="t" type="float">
+</parameter>
+</method>
+<field name="COLOR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TEXTURE_0"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="256"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Program"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bindConstants"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="a" type="android.renderscript.Allocation">
+</parameter>
+<parameter name="slot" type="int">
+</parameter>
+</method>
+<method name="bindSampler"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="vs" type="android.renderscript.Sampler">
+</parameter>
+<parameter name="slot" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="bindTexture"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="va" type="android.renderscript.Allocation">
+</parameter>
+<parameter name="slot" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+</class>
+<class name="Program.BaseProgramBuilder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Program.BaseProgramBuilder"
+ type="android.renderscript.Program.BaseProgramBuilder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="addConstant"
+ return="android.renderscript.Program.BaseProgramBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="t" type="android.renderscript.Type">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="addTexture"
+ return="android.renderscript.Program.BaseProgramBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="texType" type="android.renderscript.Program.TextureType">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="getCurrentConstantIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getCurrentTextureIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="initProgram"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="p" type="android.renderscript.Program">
+</parameter>
+</method>
+<method name="setShader"
+ return="android.renderscript.Program.BaseProgramBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="s" type="java.lang.String">
+</parameter>
+</method>
+<method name="setShader"
+ return="android.renderscript.Program.BaseProgramBuilder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resources" type="android.content.res.Resources">
+</parameter>
+<parameter name="resourceID" type="int">
+</parameter>
+</method>
+</class>
+<class name="Program.TextureType"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Program.TextureType"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Program.TextureType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramFragment"
+ extends="android.renderscript.Program"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="ProgramFragment.Builder"
+ extends="android.renderscript.Program.BaseProgramBuilder"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramFragment.Builder"
+ type="android.renderscript.ProgramFragment.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.ProgramFragment"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramFragmentFixedFunction"
+ extends="android.renderscript.ProgramFragment"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="ProgramFragmentFixedFunction.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramFragmentFixedFunction.Builder"
+ type="android.renderscript.ProgramFragmentFixedFunction.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.ProgramFragmentFixedFunction"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setPointSpriteTexCoordinateReplacement"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+<method name="setTexture"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="env" type="android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode">
+</parameter>
+<parameter name="fmt" type="android.renderscript.ProgramFragmentFixedFunction.Builder.Format">
+</parameter>
+<parameter name="slot" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
+<method name="setVaryingColor"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+<field name="MAX_TEXTURE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="ProgramFragmentFixedFunction.Builder.EnvMode"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder.EnvMode[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramFragmentFixedFunction.Builder.Format"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder.Format"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.ProgramFragmentFixedFunction.Builder.Format[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramRaster"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="CULL_BACK"
+ return="android.renderscript.ProgramRaster"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="CULL_FRONT"
+ return="android.renderscript.ProgramRaster"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="CULL_NONE"
+ return="android.renderscript.ProgramRaster"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+</class>
+<class name="ProgramRaster.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramRaster.Builder"
+ type="android.renderscript.ProgramRaster.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.ProgramRaster"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setCullMode"
+ return="android.renderscript.ProgramRaster.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="android.renderscript.ProgramRaster.CullMode">
+</parameter>
+</method>
+<method name="setPointSpriteEnabled"
+ return="android.renderscript.ProgramRaster.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+</class>
+<class name="ProgramRaster.CullMode"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.ProgramRaster.CullMode"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.ProgramRaster.CullMode[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramStore"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="BLEND_ALPHA_DEPTH_NONE"
+ return="android.renderscript.ProgramStore"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="BLEND_ALPHA_DEPTH_TEST"
+ return="android.renderscript.ProgramStore"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="BLEND_NONE_DEPTH_NONE"
+ return="android.renderscript.ProgramStore"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="BLEND_NONE_DEPTH_TEST"
+ return="android.renderscript.ProgramStore"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+</class>
+<class name="ProgramStore.BlendDstFunc"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.ProgramStore.BlendDstFunc"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.ProgramStore.BlendDstFunc[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramStore.BlendSrcFunc"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.ProgramStore.BlendSrcFunc"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.ProgramStore.BlendSrcFunc[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramStore.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramStore.Builder"
+ type="android.renderscript.ProgramStore.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.ProgramStore"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setBlendFunc"
+ return="android.renderscript.ProgramStore.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="src" type="android.renderscript.ProgramStore.BlendSrcFunc">
+</parameter>
+<parameter name="dst" type="android.renderscript.ProgramStore.BlendDstFunc">
+</parameter>
+</method>
+<method name="setColorMaskEnabled"
+ return="android.renderscript.ProgramStore.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="r" type="boolean">
+</parameter>
+<parameter name="g" type="boolean">
+</parameter>
+<parameter name="b" type="boolean">
+</parameter>
+<parameter name="a" type="boolean">
+</parameter>
+</method>
+<method name="setDepthFunc"
+ return="android.renderscript.ProgramStore.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="func" type="android.renderscript.ProgramStore.DepthFunc">
+</parameter>
+</method>
+<method name="setDepthMaskEnabled"
+ return="android.renderscript.ProgramStore.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+<method name="setDitherEnabled"
+ return="android.renderscript.ProgramStore.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+</class>
+<class name="ProgramStore.DepthFunc"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.ProgramStore.DepthFunc"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.ProgramStore.DepthFunc[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramVertex"
+ extends="android.renderscript.Program"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="ProgramVertex.Builder"
+ extends="android.renderscript.Program.BaseProgramBuilder"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramVertex.Builder"
+ type="android.renderscript.ProgramVertex.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="addInput"
+ return="android.renderscript.ProgramVertex.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="e" type="android.renderscript.Element">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="create"
+ return="android.renderscript.ProgramVertex"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="ProgramVertexFixedFunction"
+ extends="android.renderscript.ProgramVertex"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bindConstants"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="va" type="android.renderscript.ProgramVertexFixedFunction.Constants">
+</parameter>
+</method>
+</class>
+<class name="ProgramVertexFixedFunction.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramVertexFixedFunction.Builder"
+ type="android.renderscript.ProgramVertexFixedFunction.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.ProgramVertexFixedFunction"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setTextureMatrixEnable"
+ return="android.renderscript.ProgramVertexFixedFunction.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enable" type="boolean">
+</parameter>
+</method>
+</class>
+<class name="ProgramVertexFixedFunction.Constants"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ProgramVertexFixedFunction.Constants"
+ type="android.renderscript.ProgramVertexFixedFunction.Constants"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="destroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setModelview"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+<method name="setProjection"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+<method name="setTexture"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="m" type="android.renderscript.Matrix4f">
+</parameter>
+</method>
+</class>
+<class name="RSDriverException"
+ extends="android.renderscript.RSRuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RSDriverException"
+ type="android.renderscript.RSDriverException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="string" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="RSIllegalArgumentException"
+ extends="android.renderscript.RSRuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RSIllegalArgumentException"
+ type="android.renderscript.RSIllegalArgumentException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="string" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="RSInvalidStateException"
+ extends="android.renderscript.RSRuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RSInvalidStateException"
+ type="android.renderscript.RSInvalidStateException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="string" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="RSRuntimeException"
+ extends="java.lang.RuntimeException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RSRuntimeException"
+ type="android.renderscript.RSRuntimeException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="string" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+<class name="RSSurfaceView"
+ extends="android.view.SurfaceView"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.SurfaceHolder.Callback">
+</implements>
+<constructor name="RSSurfaceView"
+ type="android.renderscript.RSSurfaceView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="RSSurfaceView"
+ type="android.renderscript.RSSurfaceView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<method name="createRenderScriptGL"
+ return="android.renderscript.RenderScriptGL"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sc" type="android.renderscript.RenderScriptGL.SurfaceConfig">
+</parameter>
+</method>
+<method name="destroyRenderScriptGL"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRenderScriptGL"
+ return="android.renderscript.RenderScriptGL"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="pause"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="resume"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setRenderScriptGL"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScriptGL">
+</parameter>
+</method>
+<method name="surfaceChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="holder" type="android.view.SurfaceHolder">
+</parameter>
+<parameter name="format" type="int">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+</method>
+<method name="surfaceCreated"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="holder" type="android.view.SurfaceHolder">
+</parameter>
+</method>
+<method name="surfaceDestroyed"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="holder" type="android.view.SurfaceHolder">
+</parameter>
+</method>
+</class>
+<class name="RenderScript"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="contextDump"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="create"
+ return="android.renderscript.RenderScript"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ctx" type="android.content.Context">
+</parameter>
+</method>
+<method name="destroy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="finish"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getApplicationContext"
+ return="android.content.Context"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getErrorHandler"
+ return="android.renderscript.RenderScript.RSErrorHandler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMessageHandler"
+ return="android.renderscript.RenderScript.RSMessageHandler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setErrorHandler"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="msg" type="android.renderscript.RenderScript.RSErrorHandler">
+</parameter>
+</method>
+<method name="setMessageHandler"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="msg" type="android.renderscript.RenderScript.RSMessageHandler">
+</parameter>
+</method>
+<method name="setPriority"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.RenderScript.Priority">
+</parameter>
+</method>
+</class>
+<class name="RenderScript.Priority"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.RenderScript.Priority"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.RenderScript.Priority[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="RenderScript.RSErrorHandler"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.Runnable">
+</implements>
+<constructor name="RenderScript.RSErrorHandler"
+ type="android.renderscript.RenderScript.RSErrorHandler"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="run"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="mErrorMessage"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+<field name="mErrorNum"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+</class>
+<class name="RenderScript.RSMessageHandler"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.lang.Runnable">
+</implements>
+<constructor name="RenderScript.RSMessageHandler"
+ type="android.renderscript.RenderScript.RSMessageHandler"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="run"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="mData"
+ type="int[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+<field name="mID"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+<field name="mLength"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+</class>
+<class name="RenderScriptGL"
+ extends="android.renderscript.RenderScript"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RenderScriptGL"
+ type="android.renderscript.RenderScriptGL"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ctx" type="android.content.Context">
+</parameter>
+<parameter name="sc" type="android.renderscript.RenderScriptGL.SurfaceConfig">
+</parameter>
+</constructor>
+<method name="bindProgramFragment"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.ProgramFragment">
+</parameter>
+</method>
+<method name="bindProgramRaster"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.ProgramRaster">
+</parameter>
+</method>
+<method name="bindProgramStore"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.ProgramStore">
+</parameter>
+</method>
+<method name="bindProgramVertex"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="p" type="android.renderscript.ProgramVertex">
+</parameter>
+</method>
+<method name="bindRootScript"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="s" type="android.renderscript.Script">
+</parameter>
+</method>
+<method name="getHeight"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getWidth"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="pause"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="resume"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setSurface"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sur" type="android.view.SurfaceHolder">
+</parameter>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+</method>
+</class>
+<class name="RenderScriptGL.SurfaceConfig"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="RenderScriptGL.SurfaceConfig"
+ type="android.renderscript.RenderScriptGL.SurfaceConfig"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="RenderScriptGL.SurfaceConfig"
+ type="android.renderscript.RenderScriptGL.SurfaceConfig"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sc" type="android.renderscript.RenderScriptGL.SurfaceConfig">
+</parameter>
+</constructor>
+<method name="setAlpha"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minimum" type="int">
+</parameter>
+<parameter name="preferred" type="int">
+</parameter>
+</method>
+<method name="setColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minimum" type="int">
+</parameter>
+<parameter name="preferred" type="int">
+</parameter>
+</method>
+<method name="setDepth"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minimum" type="int">
+</parameter>
+<parameter name="preferred" type="int">
+</parameter>
+</method>
+<method name="setSamples"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minimum" type="int">
+</parameter>
+<parameter name="preferred" type="int">
+</parameter>
+<parameter name="Q" type="float">
+</parameter>
+</method>
+</class>
+<class name="Sampler"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="CLAMP_LINEAR"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="CLAMP_LINEAR_MIP_LINEAR"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="CLAMP_NEAREST"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="WRAP_LINEAR"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="WRAP_LINEAR_MIP_LINEAR"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+<method name="WRAP_NEAREST"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</method>
+</class>
+<class name="Sampler.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Sampler.Builder"
+ type="android.renderscript.Sampler.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.Sampler"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setAnisotropy"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="float">
+</parameter>
+</method>
+<method name="setMagnification"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Sampler.Value">
+</parameter>
+</method>
+<method name="setMinification"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Sampler.Value">
+</parameter>
+</method>
+<method name="setWrapS"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Sampler.Value">
+</parameter>
+</method>
+<method name="setWrapT"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="v" type="android.renderscript.Sampler.Value">
+</parameter>
+</method>
+</class>
+<class name="Sampler.Value"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Sampler.Value"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Sampler.Value[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Script"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="setTimeZone"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="timeZone" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="Script.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="Script.FieldBase"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Script.FieldBase"
+ type="android.renderscript.Script.FieldBase"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</constructor>
+<method name="getAllocation"
+ return="android.renderscript.Allocation"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getElement"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="android.renderscript.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="init"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="dimx" type="int">
+</parameter>
+</method>
+<method name="init"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="dimx" type="int">
+</parameter>
+<parameter name="usages" type="int">
+</parameter>
+</method>
+<method name="updateAllocation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="mAllocation"
+ type="android.renderscript.Allocation"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+<field name="mElement"
+ type="android.renderscript.Element"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</field>
+</class>
+<class name="ScriptC"
+ extends="android.renderscript.Script"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</class>
+<class name="Short2"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Short2"
+ type="android.renderscript.Short2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Short3"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Short3"
+ type="android.renderscript.Short3"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="x"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Short4"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Short4"
+ type="android.renderscript.Short4"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="w"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="z"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Type"
+ extends="android.renderscript.BaseObj"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getElement"
+ return="android.renderscript.Element"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getX"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getY"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getZ"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasFaces"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasMipmaps"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="Type.Builder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Type.Builder"
+ type="android.renderscript.Type.Builder"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="e" type="android.renderscript.Element">
+</parameter>
+</constructor>
+<method name="create"
+ return="android.renderscript.Type"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setFaces"
+ return="android.renderscript.Type.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="boolean">
+</parameter>
+</method>
+<method name="setMipmaps"
+ return="android.renderscript.Type.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="boolean">
+</parameter>
+</method>
+<method name="setX"
+ return="android.renderscript.Type.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+<method name="setY"
+ return="android.renderscript.Type.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="int">
+</parameter>
+</method>
+</class>
+<class name="Type.CubemapFace"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.renderscript.Type.CubemapFace"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.renderscript.Type.CubemapFace[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+</package>
 <package name="android.sax"
 >
 <class name="Element"
@@ -166218,6 +176175,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_WEB_SEARCH_ONLY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extra.WEB_SEARCH_ONLY&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="LANGUAGE_MODEL_FREE_FORM"
  type="java.lang.String"
  transient="false"
@@ -166296,6 +176264,92 @@
 >
 </field>
 </class>
+<class name="RecognizerResultsIntent"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="ACTION_VOICE_SEARCH_RESULTS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.action.VOICE_SEARCH_RESULTS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VOICE_SEARCH_RESULT_HTML"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extras.VOICE_SEARCH_RESULT_HTML&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VOICE_SEARCH_RESULT_HTML_BASE_URLS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extras.VOICE_SEARCH_RESULT_HTML_BASE_URLS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VOICE_SEARCH_RESULT_HTTP_HEADERS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extras.EXTRA_VOICE_SEARCH_RESULT_HTTP_HEADERS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VOICE_SEARCH_RESULT_STRINGS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extras.VOICE_SEARCH_RESULT_STRINGS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_VOICE_SEARCH_RESULT_URLS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extras.VOICE_SEARCH_RESULT_URLS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="URI_SCHEME_INLINE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;inline&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="SpeechRecognizer"
  extends="java.lang.Object"
  abstract="false"
@@ -176666,6 +186720,19 @@
 <exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException">
 </exception>
 </method>
+<method name="getPackageObbPaths"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
 <method name="getPackagesForUid"
  return="java.lang.String[]"
  abstract="false"
@@ -177165,6 +187232,21 @@
 <parameter name="path" type="java.lang.String">
 </parameter>
 </method>
+<method name="setPackageObbPaths"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+<parameter name="paths" type="java.lang.String[]">
+</parameter>
+</method>
 </class>
 <class name="MockResources"
  extends="android.content.res.Resources"
@@ -179188,6 +189270,28 @@
  visibility="public"
 >
 </field>
+<field name="TYPE_NUMBER_VARIATION_NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_NUMBER_VARIATION_PASSWORD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TYPE_TEXT_FLAG_AUTO_COMPLETE"
  type="int"
  transient="false"
@@ -184122,10 +194226,10 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
-<parameter name="addr" type="int">
+<parameter name="ipv4Address" type="int">
 </parameter>
 </method>
 <method name="formatShortFileSize"
@@ -184851,7 +194955,7 @@
 <package name="android.text.method"
 >
 <class name="ArrowKeyMovementMethod"
- extends="java.lang.Object"
+ extends="android.text.method.BaseMovementMethod"
  abstract="false"
  static="false"
  final="false"
@@ -184868,17 +194972,6 @@
  visibility="public"
 >
 </constructor>
-<method name="canSelectArbitrarily"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getInstance"
  return="android.text.method.MovementMethod"
  abstract="false"
@@ -184890,127 +194983,6 @@
  visibility="public"
 >
 </method>
-<method name="initialize"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-</method>
-<method name="onKeyDown"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-<parameter name="keyCode" type="int">
-</parameter>
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="onKeyOther"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="view" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="onKeyUp"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-<parameter name="keyCode" type="int">
-</parameter>
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="onTakeFocus"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="view" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-<parameter name="dir" type="int">
-</parameter>
-</method>
-<method name="onTouchEvent"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-<parameter name="event" type="android.view.MotionEvent">
-</parameter>
-</method>
-<method name="onTrackballEvent"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-<parameter name="event" type="android.view.MotionEvent">
-</parameter>
-</method>
 </class>
 <class name="BaseKeyListener"
  extends="android.text.method.MetaKeyKeyListener"
@@ -185049,6 +195021,25 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="forwardDelete"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+<parameter name="content" type="android.text.Editable">
+</parameter>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="onKeyOther"
  return="boolean"
  abstract="false"
@@ -185067,6 +195058,373 @@
 </parameter>
 </method>
 </class>
+<class name="BaseMovementMethod"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.text.method.MovementMethod">
+</implements>
+<constructor name="BaseMovementMethod"
+ type="android.text.method.BaseMovementMethod"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="bottom"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="canSelectArbitrarily"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="down"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="end"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="getMovementMetaState"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="handleMovementKey"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="movementMetaState" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="home"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="initialize"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="left"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="lineEnd"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="lineStart"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="onKeyDown"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="onKeyOther"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="onKeyUp"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="onTakeFocus"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="direction" type="int">
+</parameter>
+</method>
+<method name="onTouchEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="onTrackballEvent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="text" type="android.text.Spannable">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="pageDown"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="pageUp"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="right"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="top"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+<method name="up"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="widget" type="android.widget.TextView">
+</parameter>
+<parameter name="buffer" type="android.text.Spannable">
+</parameter>
+</method>
+</class>
 <class name="CharacterPickerDialog"
  extends="android.app.Dialog"
  abstract="false"
@@ -186532,7 +196890,7 @@
 </method>
 </class>
 <class name="ScrollingMovementMethod"
- extends="java.lang.Object"
+ extends="android.text.method.BaseMovementMethod"
  abstract="false"
  static="false"
  final="false"
@@ -186549,32 +196907,6 @@
  visibility="public"
 >
 </constructor>
-<method name="canSelectArbitrarily"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="down"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-</method>
 <method name="getInstance"
  return="android.text.method.MovementMethod"
  abstract="false"
@@ -186586,172 +196918,6 @@
  visibility="public"
 >
 </method>
-<method name="initialize"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-</method>
-<method name="left"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-</method>
-<method name="onKeyDown"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-<parameter name="keyCode" type="int">
-</parameter>
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="onKeyOther"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="view" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="onKeyUp"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-<parameter name="keyCode" type="int">
-</parameter>
-<parameter name="event" type="android.view.KeyEvent">
-</parameter>
-</method>
-<method name="onTakeFocus"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-<parameter name="dir" type="int">
-</parameter>
-</method>
-<method name="onTouchEvent"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-<parameter name="event" type="android.view.MotionEvent">
-</parameter>
-</method>
-<method name="onTrackballEvent"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="text" type="android.text.Spannable">
-</parameter>
-<parameter name="event" type="android.view.MotionEvent">
-</parameter>
-</method>
-<method name="right"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-</method>
-<method name="up"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="widget" type="android.widget.TextView">
-</parameter>
-<parameter name="buffer" type="android.text.Spannable">
-</parameter>
-</method>
 </class>
 <class name="SingleLineTransformationMethod"
  extends="android.text.method.ReplacementTransformationMethod"
@@ -192027,6 +202193,17 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="isLenient"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="nextBoolean"
  return="boolean"
  abstract="false"
@@ -192157,21 +202334,6 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
-<method name="syntaxError"
- return="java.io.IOException"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="message" type="java.lang.String">
-</parameter>
-<exception name="IOException" type="java.io.IOException">
-</exception>
-</method>
 </class>
 <class name="JsonToken"
  extends="java.lang.Enum"
@@ -192304,6 +202466,17 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="isLenient"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="name"
  return="android.util.JsonWriter"
  abstract="false"
@@ -192345,6 +202518,19 @@
 <parameter name="indent" type="java.lang.String">
 </parameter>
 </method>
+<method name="setLenient"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lenient" type="boolean">
+</parameter>
+</method>
 <method name="value"
  return="android.util.JsonWriter"
  abstract="false"
@@ -192405,6 +202591,21 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="value"
+ return="android.util.JsonWriter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.Number">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
 </class>
 <class name="Log"
  extends="java.lang.Object"
@@ -192784,6 +202985,25 @@
 </parameter>
 </method>
 </class>
+<class name="MalformedJsonException"
+ extends="java.io.IOException"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="MalformedJsonException"
+ type="android.util.MalformedJsonException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
 <class name="MonthDisplayHelper"
  extends="java.lang.Object"
  abstract="false"
@@ -200694,6 +210914,17 @@
  visibility="public"
 >
 </field>
+<field name="META_ALT_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="50"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="META_ALT_ON"
  type="int"
  transient="false"
@@ -200738,6 +210969,17 @@
  visibility="public"
 >
 </field>
+<field name="META_CTRL_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="28672"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="META_CTRL_ON"
  type="int"
  transient="false"
@@ -200782,6 +211024,17 @@
  visibility="public"
 >
 </field>
+<field name="META_META_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="458752"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="META_META_ON"
  type="int"
  transient="false"
@@ -200837,6 +211090,17 @@
  visibility="public"
 >
 </field>
+<field name="META_SHIFT_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="193"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="META_SHIFT_ON"
  type="int"
  transient="false"
@@ -202078,6 +212342,19 @@
 <parameter name="view" type="android.view.View">
 </parameter>
 </method>
+<method name="setActionView"
+ return="android.view.MenuItem"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
 <method name="setAlphabeticShortcut"
  return="android.view.MenuItem"
  abstract="true"
@@ -206586,6 +216863,17 @@
  visibility="public"
 >
 </method>
+<method name="getLayerType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getLayoutParams"
  return="android.view.ViewGroup.LayoutParams"
  abstract="false"
@@ -206746,6 +217034,17 @@
  visibility="public"
 >
 </method>
+<method name="getNextFocusForwardId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getNextFocusLeftId"
  return="int"
  abstract="false"
@@ -207454,6 +217753,17 @@
  visibility="public"
 >
 </method>
+<method name="isDirty"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isDrawingCacheEnabled"
  return="boolean"
  abstract="false"
@@ -207746,7 +218056,7 @@
  native="false"
  synchronized="false"
  static="false"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -209066,6 +219376,21 @@
 <parameter name="keepScreenOn" type="boolean">
 </parameter>
 </method>
+<method name="setLayerType"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="layerType" type="int">
+</parameter>
+<parameter name="paint" type="android.graphics.Paint">
+</parameter>
+</method>
 <method name="setLayoutParams"
  return="void"
  abstract="false"
@@ -209159,6 +219484,19 @@
 <parameter name="nextFocusDownId" type="int">
 </parameter>
 </method>
+<method name="setNextFocusForwardId"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="nextFocusForwardId" type="int">
+</parameter>
+</method>
 <method name="setNextFocusLeftId"
  return="void"
  abstract="false"
@@ -209762,12 +220100,12 @@
 >
 <parameter name="data" type="android.content.ClipData">
 </parameter>
-<parameter name="thumbBuilder" type="android.view.View.DragThumbnailBuilder">
-</parameter>
-<parameter name="myWindowOnly" type="boolean">
+<parameter name="shadowBuilder" type="android.view.View.DragShadowBuilder">
 </parameter>
 <parameter name="myLocalState" type="java.lang.Object">
 </parameter>
+<parameter name="flags" type="int">
+</parameter>
 </method>
 <method name="unscheduleDrawable"
  return="void"
@@ -210140,6 +220478,39 @@
  visibility="public"
 >
 </field>
+<field name="LAYER_TYPE_HARDWARE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LAYER_TYPE_NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LAYER_TYPE_SOFTWARE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MEASURED_HEIGHT_STATE_SHIFT"
  type="int"
  transient="false"
@@ -210576,7 +220947,7 @@
 >
 </field>
 </class>
-<class name="View.DragThumbnailBuilder"
+<class name="View.DragShadowBuilder"
  extends="java.lang.Object"
  abstract="false"
  static="true"
@@ -210584,8 +220955,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<constructor name="View.DragThumbnailBuilder"
- type="android.view.View.DragThumbnailBuilder"
+<constructor name="View.DragShadowBuilder"
+ type="android.view.View.DragShadowBuilder"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -210605,7 +220976,7 @@
  visibility="public"
 >
 </method>
-<method name="onDrawThumbnail"
+<method name="onDrawShadow"
  return="void"
  abstract="false"
  native="false"
@@ -210618,7 +220989,7 @@
 <parameter name="canvas" type="android.graphics.Canvas">
 </parameter>
 </method>
-<method name="onProvideThumbnailMetrics"
+<method name="onProvideShadowMetrics"
  return="void"
  abstract="false"
  native="false"
@@ -210628,9 +220999,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="thumbnailSize" type="android.graphics.Point">
+<parameter name="shadowSize" type="android.graphics.Point">
 </parameter>
-<parameter name="thumbnailTouchPoint" type="android.graphics.Point">
+<parameter name="shadowTouchPoint" type="android.graphics.Point">
 </parameter>
 </method>
 </class>
@@ -212316,6 +222687,25 @@
  visibility="public"
 >
 </method>
+<method name="layout"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="l" type="int">
+</parameter>
+<parameter name="t" type="int">
+</parameter>
+<parameter name="r" type="int">
+</parameter>
+<parameter name="b" type="int">
+</parameter>
+</method>
 <method name="measureChild"
  return="void"
  abstract="false"
@@ -214896,6 +225286,19 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="superDispatchKeyShortcutEvent"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="superDispatchTouchEvent"
  return="boolean"
  abstract="true"
@@ -215228,6 +225631,19 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="dispatchKeyShortcutEvent"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="dispatchPopulateAccessibilityEvent"
  return="boolean"
  abstract="true"
@@ -222521,6 +232937,8 @@
 >
 <parameter name="imi" type="android.view.inputmethod.InputMethodInfo">
 </parameter>
+<parameter name="allowsImplicitlySelectedSubtypes" type="boolean">
+</parameter>
 </method>
 <method name="getInputMethodList"
  return="java.util.List&lt;android.view.inputmethod.InputMethodInfo&gt;"
@@ -223299,7 +233717,7 @@
  abstract="false"
  static="false"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="CacheManager"
@@ -223317,7 +233735,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -223339,7 +233757,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="url" type="java.lang.String">
@@ -223354,7 +233772,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -223365,7 +233783,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="url" type="java.lang.String">
@@ -223390,7 +233808,7 @@
  abstract="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="CacheManager.CacheResult"
@@ -225778,6 +236196,17 @@
  visibility="public"
 >
 </method>
+<method name="getAllowContentAccess"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getAllowFileAccess"
  return="boolean"
  abstract="false"
@@ -226196,6 +236625,19 @@
  visibility="public"
 >
 </method>
+<method name="setAllowContentAccess"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="allow" type="boolean">
+</parameter>
+</method>
 <method name="setAllowFileAccess"
  return="void"
  abstract="false"
@@ -228422,7 +238864,7 @@
 </parameter>
 </method>
 <method name="showFindDialog"
- return="void"
+ return="boolean"
  abstract="false"
  native="false"
  synchronized="false"
@@ -228433,6 +238875,8 @@
 >
 <parameter name="text" type="java.lang.String">
 </parameter>
+<parameter name="showIme" type="boolean">
+</parameter>
 </method>
 <method name="stopLoading"
  return="void"
@@ -229217,6 +239661,34 @@
 >
 </field>
 </class>
+<class name="WebViewFragment"
+ extends="android.app.Fragment"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="WebViewFragment"
+ type="android.webkit.WebViewFragment"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getWebView"
+ return="android.webkit.WebView"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
 </package>
 <package name="android.widget"
 >
@@ -231907,195 +242379,6 @@
 >
 </method>
 </class>
-<class name="Adapters"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="Adapters"
- type="android.widget.Adapters"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="loadAdapter"
- return="android.widget.BaseAdapter"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="id" type="int">
-</parameter>
-<parameter name="parameters" type="java.lang.Object...">
-</parameter>
-</method>
-<method name="loadCursorAdapter"
- return="android.widget.CursorAdapter"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="id" type="int">
-</parameter>
-<parameter name="uri" type="java.lang.String">
-</parameter>
-<parameter name="parameters" type="java.lang.Object...">
-</parameter>
-</method>
-<method name="loadCursorAdapter"
- return="android.widget.CursorAdapter"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="id" type="int">
-</parameter>
-<parameter name="cursor" type="android.database.Cursor">
-</parameter>
-<parameter name="parameters" type="java.lang.Object...">
-</parameter>
-</method>
-</class>
-<class name="Adapters.CursorBinder"
- extends="java.lang.Object"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="Adapters.CursorBinder"
- type="android.widget.Adapters.CursorBinder"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="transformation" type="android.widget.Adapters.CursorTransformation">
-</parameter>
-</constructor>
-<method name="bind"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="view" type="android.view.View">
-</parameter>
-<parameter name="cursor" type="android.database.Cursor">
-</parameter>
-<parameter name="columnIndex" type="int">
-</parameter>
-</method>
-<field name="mContext"
- type="android.content.Context"
- transient="false"
- volatile="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="protected"
->
-</field>
-<field name="mTransformation"
- type="android.widget.Adapters.CursorTransformation"
- transient="false"
- volatile="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="protected"
->
-</field>
-</class>
-<class name="Adapters.CursorTransformation"
- extends="java.lang.Object"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="Adapters.CursorTransformation"
- type="android.widget.Adapters.CursorTransformation"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-</constructor>
-<method name="transform"
- return="java.lang.String"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="cursor" type="android.database.Cursor">
-</parameter>
-<parameter name="columnIndex" type="int">
-</parameter>
-</method>
-<method name="transformToResource"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="cursor" type="android.database.Cursor">
-</parameter>
-<parameter name="columnIndex" type="int">
-</parameter>
-</method>
-<field name="mContext"
- type="android.content.Context"
- transient="false"
- volatile="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="protected"
->
-</field>
-</class>
 <class name="AlphabetIndexer"
  extends="android.database.DataSetObserver"
  abstract="false"
@@ -233547,6 +243830,228 @@
 </parameter>
 </constructor>
 </class>
+<class name="CalendarView"
+ extends="android.widget.FrameLayout"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="CalendarView"
+ type="android.widget.CalendarView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="CalendarView"
+ type="android.widget.CalendarView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="CalendarView"
+ type="android.widget.CalendarView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
+<method name="getDate"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getFirstDayOfWeek"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMaxDate"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMinDate"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getShowWeekNumber"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setDate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="date" type="long">
+</parameter>
+</method>
+<method name="setDate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="date" type="long">
+</parameter>
+<parameter name="animate" type="boolean">
+</parameter>
+<parameter name="center" type="boolean">
+</parameter>
+</method>
+<method name="setFirstDayOfWeek"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="firstDayOfWeek" type="int">
+</parameter>
+</method>
+<method name="setMaxDate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="maxDate" type="long">
+</parameter>
+</method>
+<method name="setMinDate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minDate" type="long">
+</parameter>
+</method>
+<method name="setOnDateChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.widget.CalendarView.OnDateChangeListener">
+</parameter>
+</method>
+<method name="setShowWeekNumber"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="showWeekNumber" type="boolean">
+</parameter>
+</method>
+</class>
+<interface name="CalendarView.OnDateChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onSelectedDayChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.widget.CalendarView">
+</parameter>
+<parameter name="year" type="int">
+</parameter>
+<parameter name="month" type="int">
+</parameter>
+<parameter name="dayOfMonth" type="int">
+</parameter>
+</method>
+</interface>
 <class name="CheckBox"
  extends="android.widget.CompoundButton"
  abstract="false"
@@ -234061,7 +244566,7 @@
  type="android.widget.CursorAdapter"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="context" type="android.content.Context">
@@ -234234,7 +244739,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="protected"
 >
 <parameter name="context" type="android.content.Context">
@@ -234244,23 +244749,6 @@
 <parameter name="autoRequery" type="boolean">
 </parameter>
 </method>
-<method name="init"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="c" type="android.database.Cursor">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-</method>
 <method name="newDropDownView"
  return="android.view.View"
  abstract="false"
@@ -234332,6 +244820,19 @@
 <parameter name="filterQueryProvider" type="android.widget.FilterQueryProvider">
 </parameter>
 </method>
+<method name="swapCursor"
+ return="android.database.Cursor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="newCursor" type="android.database.Cursor">
+</parameter>
+</method>
 <field name="FLAG_AUTO_REQUERY"
  type="int"
  transient="false"
@@ -234339,7 +244840,7 @@
  value="1"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -234797,6 +245298,17 @@
 <parameter name="defStyle" type="int">
 </parameter>
 </constructor>
+<method name="getCalendarViewShown"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getDayOfMonth"
  return="int"
  abstract="false"
@@ -234808,6 +245320,28 @@
  visibility="public"
 >
 </method>
+<method name="getMaxDate"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMinDate"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getMonth"
  return="int"
  abstract="false"
@@ -234819,6 +245353,17 @@
  visibility="public"
 >
 </method>
+<method name="getSpinnersShown"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getYear"
  return="int"
  abstract="false"
@@ -234849,6 +245394,58 @@
 <parameter name="onDateChangedListener" type="android.widget.DatePicker.OnDateChangedListener">
 </parameter>
 </method>
+<method name="setCalendarViewShown"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="shown" type="boolean">
+</parameter>
+</method>
+<method name="setMaxDate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="maxDate" type="long">
+</parameter>
+</method>
+<method name="setMinDate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minDate" type="long">
+</parameter>
+</method>
+<method name="setSpinnersShown"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="shown" type="boolean">
+</parameter>
+</method>
 <method name="updateDate"
  return="void"
  abstract="false"
@@ -234894,172 +245491,6 @@
 </parameter>
 </method>
 </interface>
-<class name="DayPicker"
- extends="android.widget.FrameLayout"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="DayPicker"
- type="android.widget.DayPicker"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-</constructor>
-<constructor name="DayPicker"
- type="android.widget.DayPicker"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="attrs" type="android.util.AttributeSet">
-</parameter>
-</constructor>
-<constructor name="DayPicker"
- type="android.widget.DayPicker"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="attrs" type="android.util.AttributeSet">
-</parameter>
-<parameter name="defStyle" type="int">
-</parameter>
-</constructor>
-<method name="getSelectedDay"
- return="java.util.Calendar"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="goTo"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="year" type="int">
-</parameter>
-<parameter name="month" type="int">
-</parameter>
-<parameter name="dayOfMonth" type="int">
-</parameter>
-<parameter name="animate" type="boolean">
-</parameter>
-<parameter name="setSelected" type="boolean">
-</parameter>
-<parameter name="forceScroll" type="boolean">
-</parameter>
-</method>
-<method name="goTo"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="date" type="java.util.Calendar">
-</parameter>
-<parameter name="animate" type="boolean">
-</parameter>
-<parameter name="setSelected" type="boolean">
-</parameter>
-<parameter name="forceScroll" type="boolean">
-</parameter>
-</method>
-<method name="setOnDateChangeListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="listener" type="android.widget.DayPicker.OnSelectedDayChangeListener">
-</parameter>
-</method>
-<method name="setRange"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="startRangeDate" type="java.util.Calendar">
-</parameter>
-<parameter name="endRangeDate" type="java.util.Calendar">
-</parameter>
-</method>
-<method name="setSelectedDay"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="selectedDay" type="java.util.Calendar">
-</parameter>
-</method>
-</class>
-<interface name="DayPicker.OnSelectedDayChangeListener"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="onSelectedDayChange"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="view" type="android.widget.DayPicker">
-</parameter>
-<parameter name="year" type="int">
-</parameter>
-<parameter name="month" type="int">
-</parameter>
-<parameter name="dayOfMonth" type="int">
-</parameter>
-</method>
-</interface>
 <class name="DialerFilter"
  extends="android.widget.RelativeLayout"
  abstract="false"
@@ -240262,7 +250693,18 @@
 <parameter name="defStyle" type="int">
 </parameter>
 </constructor>
-<method name="getCurrent"
+<method name="getDisplayedValues"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMaxValue"
  return="int"
  abstract="false"
  native="false"
@@ -240273,7 +250715,7 @@
  visibility="public"
 >
 </method>
-<method name="getRangeEnd"
+<method name="getMinValue"
  return="int"
  abstract="false"
  native="false"
@@ -240284,7 +250726,7 @@
  visibility="public"
 >
 </method>
-<method name="getRangeStart"
+<method name="getValue"
  return="int"
  abstract="false"
  native="false"
@@ -240295,7 +250737,18 @@
  visibility="public"
 >
 </method>
-<method name="setCurrent"
+<method name="getWrapSelectorWheel"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setDisplayedValues"
  return="void"
  abstract="false"
  native="false"
@@ -240305,7 +250758,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="current" type="int">
+<parameter name="displayedValues" type="java.lang.String[]">
 </parameter>
 </method>
 <method name="setFormatter"
@@ -240321,7 +250774,7 @@
 <parameter name="formatter" type="android.widget.NumberPicker.Formatter">
 </parameter>
 </method>
-<method name="setOnChangeListener"
+<method name="setMaxValue"
  return="void"
  abstract="false"
  native="false"
@@ -240331,7 +250784,20 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="onChangeListener" type="android.widget.NumberPicker.OnChangeListener">
+<parameter name="maxValue" type="int">
+</parameter>
+</method>
+<method name="setMinValue"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="minValue" type="int">
 </parameter>
 </method>
 <method name="setOnLongPressUpdateInterval"
@@ -240360,7 +250826,7 @@
 <parameter name="onScrollListener" type="android.widget.NumberPicker.OnScrollListener">
 </parameter>
 </method>
-<method name="setRange"
+<method name="setOnValueChangedListener"
  return="void"
  abstract="false"
  native="false"
@@ -240370,12 +250836,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="start" type="int">
-</parameter>
-<parameter name="end" type="int">
+<parameter name="onValueChangedListener" type="android.widget.NumberPicker.OnValueChangedListener">
 </parameter>
 </method>
-<method name="setRange"
+<method name="setValue"
  return="void"
  abstract="false"
  native="false"
@@ -240385,30 +250849,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="start" type="int">
-</parameter>
-<parameter name="end" type="int">
-</parameter>
-<parameter name="displayedValues" type="java.lang.String[]">
-</parameter>
-</method>
-<method name="setRange"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="start" type="int">
-</parameter>
-<parameter name="end" type="int">
-</parameter>
-<parameter name="displayedValues" type="java.lang.String[]">
-</parameter>
-<parameter name="wrapSelectorWheel" type="boolean">
+<parameter name="value" type="int">
 </parameter>
 </method>
 <method name="setWrapSelectorWheel"
@@ -240424,16 +250865,6 @@
 <parameter name="wrapSelector" type="boolean">
 </parameter>
 </method>
-<field name="TWO_DIGIT_FORMATTER"
- type="android.widget.NumberPicker.Formatter"
- transient="false"
- volatile="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 </class>
 <interface name="NumberPicker.Formatter"
  abstract="true"
@@ -240442,7 +250873,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<method name="toString"
+<method name="format"
  return="java.lang.String"
  abstract="true"
  native="false"
@@ -240456,31 +250887,6 @@
 </parameter>
 </method>
 </interface>
-<interface name="NumberPicker.OnChangeListener"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="onChange"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="picker" type="android.widget.NumberPicker">
-</parameter>
-<parameter name="oldVal" type="int">
-</parameter>
-<parameter name="newVal" type="int">
-</parameter>
-</method>
-</interface>
 <interface name="NumberPicker.OnScrollListener"
  abstract="true"
  static="true"
@@ -240537,6 +250943,31 @@
 >
 </field>
 </interface>
+<interface name="NumberPicker.OnValueChangedListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onValueChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="picker" type="android.widget.NumberPicker">
+</parameter>
+<parameter name="oldVal" type="int">
+</parameter>
+<parameter name="newVal" type="int">
+</parameter>
+</method>
+</interface>
 <class name="OverScroller"
  extends="java.lang.Object"
  abstract="false"
@@ -243850,7 +254281,7 @@
  type="android.widget.ResourceCursorAdapter"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="context" type="android.content.Context">
@@ -245282,6 +255713,24 @@
  type="android.widget.SimpleCursorAdapter"
  static="false"
  final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="layout" type="int">
+</parameter>
+<parameter name="c" type="android.database.Cursor">
+</parameter>
+<parameter name="from" type="java.lang.String[]">
+</parameter>
+<parameter name="to" type="int[]">
+</parameter>
+</constructor>
+<constructor name="SimpleCursorAdapter"
+ type="android.widget.SimpleCursorAdapter"
+ static="false"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -245295,6 +255744,8 @@
 </parameter>
 <parameter name="to" type="int[]">
 </parameter>
+<parameter name="flags" type="int">
+</parameter>
 </constructor>
 <method name="bindView"
  return="void"
@@ -246369,6 +256820,19 @@
 <parameter name="which" type="int">
 </parameter>
 </method>
+<method name="setGravity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gravity" type="int">
+</parameter>
+</method>
 <method name="setPrompt"
  return="void"
  abstract="false"
@@ -255700,7 +266164,7 @@
  return="void"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -255715,7 +266179,7 @@
  return="void"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -255849,7 +266313,7 @@
  return="java.beans.PropertyChangeListener[]"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -255862,7 +266326,7 @@
  return="java.beans.PropertyChangeListener[]"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -255873,7 +266337,7 @@
  return="boolean"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -255886,7 +266350,7 @@
  return="void"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -255901,7 +266365,7 @@
  return="void"
  abstract="false"
  native="false"
- synchronized="true"
+ synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
@@ -335145,7 +345609,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -335213,7 +345677,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -335237,7 +345701,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -340880,7 +351344,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -340891,7 +351355,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -340902,7 +351366,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -343272,7 +353736,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -345479,8 +355943,6 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<exception name="MissingResourceException" type="java.util.MissingResourceException">
-</exception>
 </method>
 <method name="getISO3Language"
  return="java.lang.String"
@@ -345492,8 +355954,6 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<exception name="MissingResourceException" type="java.util.MissingResourceException">
-</exception>
 </method>
 <method name="getISOCountries"
  return="java.lang.String[]"
@@ -358346,7 +368806,7 @@
  native="false"
  synchronized="false"
  static="true"
- final="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
diff --git a/build/phone-hdpi-512-dalvik-heap.mk b/build/phone-hdpi-512-dalvik-heap.mk
new file mode 100644
index 0000000..afc45ee
--- /dev/null
+++ b/build/phone-hdpi-512-dalvik-heap.mk
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Provides overrides to configure the Dalvik heap for a standard high density
+# phone with around 512MB total RAM.
+
+PRODUCT_PROPERTY_OVERRIDES += \
+    dalvik.vm.heapstartsize=5m \
+    dalvik.vm.smallheapsize=32m \
+    dalvik.vm.heapsize=32m
diff --git a/build/phone-hdpi-dalvik-heap.mk b/build/phone-hdpi-dalvik-heap.mk
new file mode 100644
index 0000000..ee30b92
--- /dev/null
+++ b/build/phone-hdpi-dalvik-heap.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Provides overrides to configure the Dalvik heap for a standard high density phone.
+
+PRODUCT_PROPERTY_OVERRIDES += \
+    dalvik.vm.heapstartsize=5m \
+    dalvik.vm.smallheapsize=32m \
+    dalvik.vm.heapsize=32m
diff --git a/build/tablet-dalvik-heap.mk b/build/tablet-dalvik-heap.mk
new file mode 100644
index 0000000..9cb2f6b
--- /dev/null
+++ b/build/tablet-dalvik-heap.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Provides overrides to configure the Dalvik heap for a standard tablet device.
+
+PRODUCT_PROPERTY_OVERRIDES += \
+    dalvik.vm.heapstartsize=5m \
+    dalvik.vm.smallheapsize=48m \
+    dalvik.vm.heapsize=48m
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index a236a3c..cc6e739 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -18,9 +18,11 @@
 
 import com.android.internal.content.PackageHelper;
 
+import android.app.ActivityManagerNative;
 import android.content.ComponentName;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.FeatureInfo;
+import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.IPackageInstallObserver;
 import android.content.pm.IPackageManager;
@@ -100,6 +102,11 @@
             return;
         }
 
+        if ("clear".equals(op)) {
+            runClear();
+            return;
+        }
+
         if ("enable".equals(op)) {
             runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
             return;
@@ -811,6 +818,55 @@
         return obs.result;
     }
 
+    class ClearDataObserver extends IPackageDataObserver.Stub {
+        boolean finished;
+        boolean result;
+
+        @Override
+        public void onRemoveCompleted(String packageName, boolean succeeded) throws RemoteException {
+            synchronized (this) {
+                finished = true;
+                result = succeeded;
+                notifyAll();
+            }
+        }
+
+    }
+
+    private void runClear() {
+        String pkg = nextArg();
+        if (pkg == null) {
+            System.err.println("Error: no package specified");
+            showUsage();
+            return;
+        }
+
+        ClearDataObserver obs = new ClearDataObserver();
+        try {
+            if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs)) {
+                System.err.println("Failed");
+            }
+
+            synchronized (obs) {
+                while (!obs.finished) {
+                    try {
+                        obs.wait();
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+
+            if (obs.result) {
+                System.err.println("Success");
+            } else {
+                System.err.println("Failed");
+            }
+        } catch (RemoteException e) {
+            System.err.println(e.toString());
+            System.err.println(PM_NOT_RUNNING_ERR);
+        }
+    }
+
     private static String enabledSettingToString(int state) {
         switch (state) {
             case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
@@ -946,6 +1002,7 @@
         System.err.println("       pm path PACKAGE");
         System.err.println("       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH");
         System.err.println("       pm uninstall [-k] PACKAGE");
+        System.err.println("       pm clear PACKAGE");
         System.err.println("       pm enable PACKAGE_OR_COMPONENT");
         System.err.println("       pm disable PACKAGE_OR_COMPONENT");
         System.err.println("       pm setInstallLocation [0/auto] [1/internal] [2/external]");
@@ -991,6 +1048,8 @@
         System.err.println("  -k: keep the data and cache directories around.");
         System.err.println("after the package removal.");
         System.err.println("");
+        System.err.println("The clear command deletes all data associated with a package.");
+        System.err.println("");
         System.err.println("The enable and disable commands change the enabled state of");
         System.err.println("a given package or component (written as \"package/class\").");
         System.err.println("");
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 7ba5291c..a43b190 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -678,10 +678,6 @@
             const char *filename = argv[k];
 
             CHECK_EQ(retriever->setDataSource(filename), (status_t)OK);
-            CHECK_EQ(retriever->setMode(
-                        METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL),
-                     (status_t)OK);
-
             sp<IMemory> mem =
                     retriever->getFrameAtTime(-1,
                                     MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index ccae92eb..9246a00 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -40,7 +40,7 @@
 MyStreamSource::MyStreamSource(int fd)
     : mFd(fd),
       mFileSize(0),
-      mNextSeekTimeUs(ALooper::GetNowUs() + 5000000ll) {
+      mNextSeekTimeUs(-1) {  // ALooper::GetNowUs() + 5000000ll) {
     CHECK_GE(fd, 0);
 
     mFileSize = lseek64(fd, 0, SEEK_END);
diff --git a/cmds/system_server/library/Android.mk b/cmds/system_server/library/Android.mk
index 457cbd4..e8afce3 100644
--- a/cmds/system_server/library/Android.mk
+++ b/cmds/system_server/library/Android.mk
@@ -21,6 +21,7 @@
 	libaudioflinger \
     libcameraservice \
     libmediaplayerservice \
+    libinput \
 	libutils \
 	libbinder \
 	libcutils
diff --git a/core/java/android/accounts/AccountAuthenticatorCache.java b/core/java/android/accounts/AccountAuthenticatorCache.java
index 524d3f4..7214c50 100644
--- a/core/java/android/accounts/AccountAuthenticatorCache.java
+++ b/core/java/android/accounts/AccountAuthenticatorCache.java
@@ -38,7 +38,7 @@
  * @hide
  */
 /* package private */ class AccountAuthenticatorCache
-        extends RegisteredServicesCache<AuthenticatorDescription> 
+        extends RegisteredServicesCache<AuthenticatorDescription>
         implements IAccountAuthenticatorCache {
     private static final String TAG = "Account";
     private static final MySerializer sSerializer = new MySerializer();
@@ -64,11 +64,13 @@
                     com.android.internal.R.styleable.AccountAuthenticator_smallIcon, 0);
             final int prefId = sa.getResourceId(
                     com.android.internal.R.styleable.AccountAuthenticator_accountPreferences, 0);
+            final boolean customTokens = sa.getBoolean(
+                    com.android.internal.R.styleable.AccountAuthenticator_customTokens, false);
             if (TextUtils.isEmpty(accountType)) {
                 return null;
             }
-            return new AuthenticatorDescription(accountType, packageName, labelId, iconId, 
-                    smallIconId, prefId);
+            return new AuthenticatorDescription(accountType, packageName, labelId, iconId,
+                    smallIconId, prefId, customTokens);
         } finally {
             sa.recycle();
         }
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index fd3a0d0..6388dc5 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -188,6 +188,12 @@
     public static final String KEY_ERROR_CODE = "errorCode";
     public static final String KEY_ERROR_MESSAGE = "errorMessage";
     public static final String KEY_USERDATA = "userdata";
+    /**
+     * Authenticators using 'customTokens' option will also get the UID of the
+     * caller
+     */
+    public static final String KEY_CALLER_UID = "callerUid";
+    public static final String KEY_CALLER_PID = "callerPid";
 
     public static final String ACTION_AUTHENTICATOR_INTENT =
             "android.accounts.AccountAuthenticator";
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index a815b3a..9cbc7be 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -21,6 +21,7 @@
 import com.android.internal.telephony.TelephonyIntents;
 
 import android.Manifest;
+import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -82,8 +83,6 @@
         implements RegisteredServicesCacheListener<AuthenticatorDescription> {
     private static final String GOOGLE_ACCOUNT_TYPE = "com.google";
 
-    private static final String NO_BROADCAST_FLAG = "nobroadcast";
-
     private static final String TAG = "AccountManagerService";
 
     private static final int TIMEOUT_DELAY_MS = 1000 * 60;
@@ -164,8 +163,6 @@
     private static AtomicReference<AccountManagerService> sThis =
             new AtomicReference<AccountManagerService>();
 
-    private static final boolean isDebuggableMonkeyBuild =
-            SystemProperties.getBoolean("ro.monkey", false);
     private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[]{};
 
     static {
@@ -375,14 +372,6 @@
         if (account == null) {
             return false;
         }
-        final boolean noBroadcast = account.type.equals(GOOGLE_ACCOUNT_TYPE)
-                && extras != null && extras.getBoolean(NO_BROADCAST_FLAG, false);
-        // Remove the 'nobroadcast' flag since we don't want it to persist in the db. It is instead
-        // used as a control signal to indicate whether or not this insertion should result in
-        // an accounts changed broadcast being sent.
-        if (extras != null) {
-            extras.remove(NO_BROADCAST_FLAG);
-        }
         db.beginTransaction();
         try {
             long numMatches = DatabaseUtils.longForQuery(db,
@@ -419,9 +408,7 @@
         } finally {
             db.endTransaction();
         }
-        if (!noBroadcast) {
-            sendAccountsChangedBroadcast();
-        }
+        sendAccountsChangedBroadcast();
         return true;
     }
 
@@ -776,10 +763,6 @@
         if (account == null) throw new IllegalArgumentException("account is null");
         checkAuthenticateAccountsPermission(account);
         long identityToken = clearCallingIdentity();
-        if (account.type.equals(GOOGLE_ACCOUNT_TYPE) && key.equals("broadcast")) {
-            sendAccountsChangedBroadcast();
-            return;
-        }
         try {
             writeUserdataIntoDatabase(account, key, value);
         } finally {
@@ -878,7 +861,7 @@
 
     public void getAuthToken(IAccountManagerResponse response, final Account account,
             final String authTokenType, final boolean notifyOnAuthFailure,
-            final boolean expectActivityLaunch, final Bundle loginOptions) {
+            final boolean expectActivityLaunch, Bundle loginOptionsIn) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "getAuthToken: " + account
                     + ", response " + response
@@ -893,13 +876,31 @@
         if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
         checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
         final int callerUid = Binder.getCallingUid();
-        final boolean permissionGranted = permissionIsGranted(account, authTokenType, callerUid);
+        final int callerPid = Binder.getCallingPid();
+
+        AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo =
+            mAuthenticatorCache.getServiceInfo(
+                    AuthenticatorDescription.newKey(account.type));
+        final boolean customTokens =
+            authenticatorInfo != null && authenticatorInfo.type.customTokens;
+
+        // skip the check if customTokens
+        final boolean permissionGranted = customTokens ||
+            permissionIsGranted(account, authTokenType, callerUid);
+
+        final Bundle loginOptions = (loginOptionsIn == null) ? new Bundle() :
+            loginOptionsIn;
+        if (customTokens) {
+            // let authenticator know the identity of the caller
+            loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
+            loginOptions.putInt(AccountManager.KEY_CALLER_PID, callerPid);
+        }
 
         long identityToken = clearCallingIdentity();
         try {
             // if the caller has permission, do the peek. otherwise go the more expensive
             // route of starting a Session
-            if (permissionGranted) {
+            if (!customTokens && permissionGranted) {
                 String authToken = readAuthTokenFromCache(account, authTokenType);
                 if (authToken != null) {
                     Bundle result = new Bundle();
@@ -953,8 +954,10 @@
                                         "the type and name should not be empty");
                                 return;
                             }
-                            saveAuthTokenToDatabase(new Account(name, type),
-                                    authTokenType, authToken);
+                            if (!customTokens) {
+                                saveAuthTokenToDatabase(new Account(name, type),
+                                        authTokenType, authToken);
+                            }
                         }
 
                         Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
@@ -1990,12 +1993,12 @@
                 account.name, account.type};
         final boolean permissionGranted =
                 DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS, args) != 0;
-        if (!permissionGranted && isDebuggableMonkeyBuild) {
+        if (!permissionGranted && ActivityManager.isRunningInTestHarness()) {
             // TODO: Skip this check when running automated tests. Replace this
             // with a more general solution.
             Log.d(TAG, "no credentials permission for usage of " + account + ", "
                     + authTokenType + " by uid " + Binder.getCallingUid()
-                    + " but ignoring since this is a monkey build");
+                    + " but ignoring since device is in test harness.");
             return true;
         }
         return permissionGranted;
diff --git a/core/java/android/accounts/AuthenticatorDescription.java b/core/java/android/accounts/AuthenticatorDescription.java
index c6515672..5d9abb0 100644
--- a/core/java/android/accounts/AuthenticatorDescription.java
+++ b/core/java/android/accounts/AuthenticatorDescription.java
@@ -44,9 +44,12 @@
     /** The package name that can be used to lookup the resources from above. */
     final public String packageName;
 
+    /** Authenticator handles its own token caching and permission screen */
+    final public boolean customTokens;
+
     /** A constructor for a full AuthenticatorDescription */
     public AuthenticatorDescription(String type, String packageName, int labelId, int iconId,
-            int smallIconId, int prefId) {
+            int smallIconId, int prefId, boolean customTokens) {
         if (type == null) throw new IllegalArgumentException("type cannot be null");
         if (packageName == null) throw new IllegalArgumentException("packageName cannot be null");
         this.type = type;
@@ -55,6 +58,12 @@
         this.iconId = iconId;
         this.smallIconId = smallIconId;
         this.accountPreferencesId = prefId;
+        this.customTokens = customTokens;
+    }
+
+    public AuthenticatorDescription(String type, String packageName, int labelId, int iconId,
+            int smallIconId, int prefId) {
+        this(type, packageName, labelId, iconId, smallIconId, prefId, false);
     }
 
     /**
@@ -74,6 +83,7 @@
         this.iconId = 0;
         this.smallIconId = 0;
         this.accountPreferencesId = 0;
+        this.customTokens = false;
     }
 
     private AuthenticatorDescription(Parcel source) {
@@ -83,6 +93,7 @@
         this.iconId = source.readInt();
         this.smallIconId = source.readInt();
         this.accountPreferencesId = source.readInt();
+        this.customTokens = source.readByte() == 1;
     }
 
     /** @inheritDoc */
@@ -115,6 +126,7 @@
         dest.writeInt(iconId);
         dest.writeInt(smallIconId);
         dest.writeInt(accountPreferencesId);
+        dest.writeByte((byte) (customTokens ? 1 : 0));
     }
 
     /** Used to create the object from a parcel. */
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 6e589e4..bcab66e 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -215,7 +215,7 @@
                 (toType <= TypedValue.TYPE_LAST_COLOR_INT))) {
             // special case for colors: ignore valueType and get ints
             getFloats = false;
-            anim.setEvaluator(new RGBEvaluator());
+            anim.setEvaluator(new ArgbEvaluator());
         }
 
         if (getFloats) {
diff --git a/core/java/android/animation/ArgbEvaluator.java b/core/java/android/animation/ArgbEvaluator.java
new file mode 100644
index 0000000..c3875be
--- /dev/null
+++ b/core/java/android/animation/ArgbEvaluator.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.animation;
+
+/**
+ * This evaluator can be used to perform type interpolation between integer
+ * values that represent ARGB colors.
+ */
+public class ArgbEvaluator implements TypeEvaluator {
+
+    /**
+     * This function returns the calculated in-between value for a color
+     * given integers that represent the start and end values in the four
+     * bytes of the 32-bit int. Each channel is separately linearly interpolated
+     * and the resulting calculated values are recombined into the return value.
+     *
+     * @param fraction The fraction from the starting to the ending values
+     * @param startValue A 32-bit int value representing colors in the
+     * separate bytes of the parameter
+     * @param endValue A 32-bit int value representing colors in the
+     * separate bytes of the parameter
+     * @return A value that is calculated to be the linearly interpolated
+     * result, derived by separating the start and end values into separate
+     * color channels and interpolating each one separately, recombining the
+     * resulting values in the same way.
+     */
+    public Object evaluate(float fraction, Object startValue, Object endValue) {
+        int startInt = (Integer) startValue;
+        int startA = (startInt >> 24);
+        int startR = (startInt >> 16) & 0xff;
+        int startG = (startInt >> 8) & 0xff;
+        int startB = startInt & 0xff;
+
+        int endInt = (Integer) endValue;
+        int endA = (endInt >> 24);
+        int endR = (endInt >> 16) & 0xff;
+        int endG = (endInt >> 8) & 0xff;
+        int endB = endInt & 0xff;
+
+        return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
+                (int)((startR + (int)(fraction * (endR - startR))) << 16) |
+                (int)((startG + (int)(fraction * (endG - startG))) << 8) |
+                (int)((startB + (int)(fraction * (endB - startB))));
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index cb06c89..e405df5 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -73,19 +73,19 @@
 
     /**
      * A flag indicating the animation that runs on those items that are changing
-     * due to a new item disappearing from the container.
+     * due to an item disappearing from the container.
      */
     public static final int CHANGE_DISAPPEARING = 1;
 
     /**
-     * A flag indicating the animation that runs on those items that are changing
-     * due to a new item appearing in the container.
+     * A flag indicating the animation that runs on those items that are appearing
+     * in the container.
      */
     public static final int APPEARING = 2;
 
     /**
-     * A flag indicating the animation that runs on those items that are changing
-     * due to a new item appearing in the container.
+     * A flag indicating the animation that runs on those items that are disappearing
+     * from the container.
      */
     public static final int DISAPPEARING = 3;
 
@@ -153,8 +153,9 @@
      * we cache all of the current animations in this map for possible cancellation on
      * another layout event.
      */
-    private HashMap<View, Animator> currentChangingAnimations = new HashMap<View, Animator>();
-    private HashMap<View, Animator> currentVisibilityAnimations = new HashMap<View, Animator>();
+    private final HashMap<View, Animator> currentChangingAnimations = new HashMap<View, Animator>();
+    private final HashMap<View, Animator> currentVisibilityAnimations =
+            new HashMap<View, Animator>();
 
     /**
      * This hashmap is used to track the listeners that have been added to the children of
@@ -165,7 +166,7 @@
      * the process of setting up and running all appropriate animations is done, we need to
      * remove these listeners and clear out the map.
      */
-    private HashMap<View, View.OnLayoutChangeListener> layoutChangeListenerMap =
+    private final HashMap<View, View.OnLayoutChangeListener> layoutChangeListenerMap =
             new HashMap<View, View.OnLayoutChangeListener>();
 
     /**
@@ -552,9 +553,6 @@
                 // Make a copy of the appropriate animation
                 final Animator anim = baseAnimator.clone();
 
-                // Cache the animation in case we need to cancel it later
-                currentChangingAnimations.put(child, anim);
-
                 // Set the target object for the animation
                 anim.setTarget(child);
 
@@ -585,6 +583,9 @@
                         anim.setStartDelay(startDelay);
                         anim.setDuration(duration);
 
+                        // Cache the animation in case we need to cancel it later
+                        currentChangingAnimations.put(child, anim);
+
                         if (anim instanceof ObjectAnimator) {
                             ((ObjectAnimator) anim).setCurrentPlayTime(0);
                         }
@@ -599,16 +600,38 @@
                 // Remove the animation from the cache when it ends
                 anim.addListener(new AnimatorListenerAdapter() {
                     private boolean canceled = false;
+
+                    @Override
+                    public void onAnimationStart(Animator animator) {
+                        if (mListeners != null) {
+                            for (TransitionListener listener : mListeners) {
+                                listener.startTransition(LayoutTransition.this, parent, child,
+                                        changeReason == APPEARING ?
+                                                CHANGE_APPEARING : CHANGE_DISAPPEARING);
+                            }
+                        }
+                    }
+
+                    @Override
                     public void onAnimationCancel(Animator animator) {
                         // we remove canceled animations immediately, not here
                         canceled = true;
                         child.removeOnLayoutChangeListener(listener);
                         layoutChangeListenerMap.remove(child);
                     }
+
+                    @Override
                     public void onAnimationEnd(Animator animator) {
                         if (!canceled) {
                             currentChangingAnimations.remove(child);
                         }
+                        if (mListeners != null) {
+                            for (TransitionListener listener : mListeners) {
+                                listener.endTransition(LayoutTransition.this, parent, child,
+                                        changeReason == APPEARING ?
+                                                CHANGE_APPEARING : CHANGE_DISAPPEARING);
+                            }
+                        }
                     }
                 });
 
@@ -635,6 +658,27 @@
     }
 
     /**
+     * Returns true if animations are running which animate layout-related properties. This
+     * essentially means that either CHANGE_APPEARING or CHANGE_DISAPPEARING animations
+     * are running, since these animations operate on layout-related properties.
+     *
+     * @return true if CHANGE_APPEARING or CHANGE_DISAPPEARING animations are currently
+     * running.
+     */
+    public boolean isChangingLayout() {
+        return (currentChangingAnimations.size() > 0);
+    }
+
+    /**
+     * Returns true if any of the animations in this transition are currently running.
+     *
+     * @return true if any animations in the transition are running.
+     */
+    public boolean isRunning() {
+        return (currentChangingAnimations.size() > 0 || currentVisibilityAnimations.size() > 0);
+    }
+
+    /**
      * This method runs the animation that makes an added item appear.
      *
      * @param parent The ViewGroup to which the View is being added.
@@ -662,7 +706,8 @@
         }
         if (mListeners != null) {
             anim.addListener(new AnimatorListenerAdapter() {
-                public void onAnimationEnd() {
+                @Override
+                public void onAnimationEnd(Animator anim) {
                     currentVisibilityAnimations.remove(child);
                     for (TransitionListener listener : mListeners) {
                         listener.endTransition(LayoutTransition.this, parent, child, APPEARING);
@@ -818,28 +863,31 @@
     public interface TransitionListener {
 
         /**
-         * This event is sent to listeners when an APPEARING or DISAPPEARING transition
-         * begins.
+         * This event is sent to listeners when any type of transition animation begins.
          *
          * @param transition The LayoutTransition sending out the event.
          * @param container The ViewGroup on which the transition is playing.
-         * @param view The View object being added or removed from its parent.
-         * @param transitionType The type of transition that is beginning, either
-         * {@link android.animation.LayoutTransition#APPEARING} or
-         * {@link android.animation.LayoutTransition#DISAPPEARING}.
+         * @param view The View object being affected by the transition animation.
+         * @param transitionType The type of transition that is beginning,
+         * {@link android.animation.LayoutTransition#APPEARING},
+         * {@link android.animation.LayoutTransition#DISAPPEARING},
+         * {@link android.animation.LayoutTransition#CHANGE_APPEARING}, or
+         * {@link android.animation.LayoutTransition#CHANGE_DISAPPEARING}.
          */
         public void startTransition(LayoutTransition transition, ViewGroup container,
                 View view, int transitionType);
 
         /**
-         * This event is sent to listeners when an APPEARING or DISAPPEARING transition ends.
+         * This event is sent to listeners when any type of transition animation ends.
          *
          * @param transition The LayoutTransition sending out the event.
          * @param container The ViewGroup on which the transition is playing.
-         * @param view The View object being added or removed from its parent.
-         * @param transitionType The type of transition that is ending, either
-         * {@link android.animation.LayoutTransition#APPEARING} or
-         * {@link android.animation.LayoutTransition#DISAPPEARING}.
+         * @param view The View object being affected by the transition animation.
+         * @param transitionType The type of transition that is ending,
+         * {@link android.animation.LayoutTransition#APPEARING},
+         * {@link android.animation.LayoutTransition#DISAPPEARING},
+         * {@link android.animation.LayoutTransition#CHANGE_APPEARING}, or
+         * {@link android.animation.LayoutTransition#CHANGE_DISAPPEARING}.
          */
         public void endTransition(LayoutTransition transition, ViewGroup container,
                 View view, int transitionType);
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 7f11871..3212cba 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -18,6 +18,7 @@
 
 import android.util.Log;
 
+import java.lang.ref.WeakReference;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 
@@ -28,6 +29,8 @@
  * 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 @@
     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 @@
      * @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 @@
             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 @@
      * 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 @@
      * 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 @@
      * 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 @@
      * 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 @@
      * 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 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 @@
     @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 @@
     @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 @@
     /**
      * 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 @@
 
     @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 @@
     @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/animation/RGBEvaluator.java b/core/java/android/animation/RGBEvaluator.java
deleted file mode 100644
index bae0af0..0000000
--- a/core/java/android/animation/RGBEvaluator.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.animation;
-
-/**
- * This evaluator can be used to perform type interpolation between integer
- * values that represent ARGB colors.
- */
-public class RGBEvaluator implements TypeEvaluator {
-
-    /**
-     * This function returns the calculated in-between value for a color
-     * given integers that represent the start and end values in the four
-     * bytes of the 32-bit int. Each channel is separately linearly interpolated
-     * and the resulting calculated values are recombined into the return value.
-     *
-     * @param fraction The fraction from the starting to the ending values
-     * @param startValue A 32-bit int value representing colors in the
-     * separate bytes of the parameter
-     * @param endValue A 32-bit int value representing colors in the
-     * separate bytes of the parameter
-     * @return A value that is calculated to be the linearly interpolated
-     * result, derived by separating the start and end values into separate
-     * color channels and interpolating each one separately, recombining the
-     * resulting values in the same way.
-     */
-    public Object evaluate(float fraction, Object startValue, Object endValue) {
-        int startInt = (Integer) startValue;
-        int startA = (startInt >> 24);
-        int startR = (startInt >> 16) & 0xff;
-        int startG = (startInt >> 8) & 0xff;
-        int startB = startInt & 0xff;
-
-        int endInt = (Integer) endValue;
-        int endA = (endInt >> 24);
-        int endR = (endInt >> 16) & 0xff;
-        int endG = (endInt >> 8) & 0xff;
-        int endB = endInt & 0xff;
-
-        return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
-                (int)((startR + (int)(fraction * (endR - startR))) << 16) |
-                (int)((startG + (int)(fraction * (endG - startG))) << 8) |
-                (int)((startB + (int)(fraction * (endB - startB))));
-    }
-}
\ No newline at end of file
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 50082f9..f884473 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -22,6 +22,7 @@
 import android.util.AndroidRuntimeException;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.AnimationUtils;
+import android.view.animation.LinearInterpolator;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -478,12 +479,17 @@
     /**
      * Sets the length of the animation. The default duration is 300 milliseconds.
      *
-     * @param duration The length of the animation, in milliseconds.
+     * @param duration The length of the animation, in milliseconds. This value cannot
+     * be negative.
      * @return ValueAnimator The object called with setDuration(). This return
      * value makes it easier to compose statements together that construct and then set the
      * duration, as in <code>ValueAnimator.ofInt(0, 10).setDuration(500).start()</code>.
      */
     public ValueAnimator setDuration(long duration) {
+        if (duration < 0) {
+            throw new IllegalArgumentException("Animators cannot have negative duration: " +
+                    duration);
+        }
         mDuration = duration;
         return this;
     }
@@ -829,12 +835,15 @@
      * such as acceleration and deceleration. The default value is
      * {@link android.view.animation.AccelerateDecelerateInterpolator}
      *
-     * @param value the interpolator to be used by this animation
+     * @param value the interpolator to be used by this animation. A value of <code>null</code>
+     * will result in linear interpolation.
      */
     @Override
     public void setInterpolator(TimeInterpolator value) {
         if (value != null) {
             mInterpolator = value;
+        } else {
+            mInterpolator = new LinearInterpolator();
         }
     }
 
@@ -853,7 +862,7 @@
      * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
      * are not one of these primitive types, or if different evaluation is desired (such as is
      * necessary with int values that represent colors), a custom evaluator needs to be assigned.
-     * For example, when running an animation on color values, the {@link RGBEvaluator}
+     * For example, when running an animation on color values, the {@link ArgbEvaluator}
      * should be used to get correct RGB color interpolation.
      *
      * <p>If this ValueAnimator has only one set of values being animated between, this evaluator
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 67eb02d..8d5a6da 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -154,6 +154,25 @@
     public abstract void setCustomView(View view, LayoutParams layoutParams);
 
     /**
+     * Set the action bar into custom navigation mode, supplying a view
+     * for custom navigation.
+     *
+     * <p>Custom navigation views appear between the application icon and
+     * any action buttons and may use any space available there. Common
+     * use cases for custom navigation views might include an auto-suggesting
+     * address bar for a browser or other navigation mechanisms that do not
+     * translate well to provided navigation modes.</p>
+     *
+     * <p>The display option {@link #DISPLAY_SHOW_CUSTOM} must be set for
+     * the custom view to be displayed.</p>
+     *
+     * @param resId Resource ID of a layout to inflate into the ActionBar.
+     *
+     * @see #setDisplayOptions(int, int)
+     */
+    public abstract void setCustomView(int resId);
+
+    /**
      * @param view
      * @deprecated Use {@link #setCustomView(View)} and {@link #setDisplayOptions(int)} instead.
      */
@@ -319,7 +338,72 @@
      * @param mask A bit mask declaring which display options should be changed.
      */
     public abstract void setDisplayOptions(int options, int mask);
-    
+
+    /**
+     * Set whether to display the activity logo rather than the activity icon.
+     * A logo is often a wider, more detailed image.
+     *
+     * <p>To set several display options at once, see the setDisplayOptions methods.
+     *
+     * @param useLogo true to use the activity logo, false to use the activity icon.
+     *
+     * @see #setDisplayOptions(int)
+     * @see #setDisplayOptions(int, int)
+     */
+    public abstract void setDisplayUseLogoEnabled(boolean useLogo);
+
+    /**
+     * Set whether to include the application home affordance in the action bar.
+     * Home is presented as either an activity icon or logo.
+     *
+     * <p>To set several display options at once, see the setDisplayOptions methods.
+     *
+     * @param showHome true to show home, false otherwise.
+     *
+     * @see #setDisplayOptions(int)
+     * @see #setDisplayOptions(int, int)
+     */
+    public abstract void setDisplayShowHomeEnabled(boolean showHome);
+
+    /**
+     * Set whether home should be displayed as an "up" affordance.
+     * Set this to true if selecting "home" returns up by a single level in your UI
+     * rather than back to the top level or front page.
+     *
+     * <p>To set several display options at once, see the setDisplayOptions methods.
+     *
+     * @param showHomeAsUp true to show the user that selecting home will return one
+     *                     level up rather than to the top level of the app.
+     *
+     * @see #setDisplayOptions(int)
+     * @see #setDisplayOptions(int, int)
+     */
+    public abstract void setDisplayHomeAsUpEnabled(boolean showHomeAsUp);
+
+    /**
+     * Set whether an activity title/subtitle should be displayed.
+     *
+     * <p>To set several display options at once, see the setDisplayOptions methods.
+     *
+     * @param showTitle true to display a title/subtitle if present.
+     *
+     * @see #setDisplayOptions(int)
+     * @see #setDisplayOptions(int, int)
+     */
+    public abstract void setDisplayShowTitleEnabled(boolean showTitle);
+
+    /**
+     * Set whether a custom view should be displayed, if set.
+     *
+     * <p>To set several display options at once, see the setDisplayOptions methods.
+     *
+     * @param showCustom true if the currently set custom view should be displayed, false otherwise.
+     *
+     * @see #setDisplayOptions(int)
+     * @see #setDisplayOptions(int, int)
+     */
+    public abstract void setDisplayShowCustomEnabled(boolean showCustom);
+
     /**
      * Set the ActionBar's background.
      * 
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 77cbe0a..6f0cb45 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -73,13 +73,11 @@
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView;
-import android.widget.FrameLayout;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 
 /**
  * An activity is a single, focused thing that the user can do.  Almost all
@@ -656,7 +654,7 @@
     boolean mCalled;
     boolean mCheckedForLoaderManager;
     boolean mLoadersStarted;
-    private boolean mResumed;
+    /*package*/ boolean mResumed;
     private boolean mStopped;
     boolean mFinished;
     boolean mStartedActivity;
@@ -1579,16 +1577,6 @@
         return mFragments;
     }
 
-    /**
-     * Start a series of edit operations on the Fragments associated with
-     * this activity.
-     * @deprecated use {@link #getFragmentManager}.
-     */
-    @Deprecated
-    public FragmentTransaction openFragmentTransaction() {
-        return mFragments.openTransaction();
-    }
-    
     void invalidateFragmentIndex(int index) {
         //Log.v(TAG, "invalidateFragmentIndex: index=" + index);
         if (mAllLoaderManagers != null) {
@@ -1770,30 +1758,6 @@
     }
     
     /**
-     * Finds a fragment that was identified by the given id either when inflated
-     * from XML or as the container ID when added in a transaction.  This only
-     * returns fragments that are currently added to the activity's content.
-     * @return The fragment if found or null otherwise.
-     * @deprecated use {@link #getFragmentManager}.
-     */
-    @Deprecated
-    public Fragment findFragmentById(int id) {
-        return mFragments.findFragmentById(id);
-    }
-    
-    /**
-     * Finds a fragment that was identified by the given tag either when inflated
-     * from XML or as supplied when added in a transaction.  This only
-     * returns fragments that are currently added to the activity's content.
-     * @return The fragment if found or null otherwise.
-     * @deprecated use {@link #getFragmentManager}.
-     */
-    @Deprecated
-    public Fragment findFragmentByTag(String tag) {
-        return mFragments.findFragmentByTag(tag);
-    }
-    
-    /**
      * Set the activity content from a layout resource.  The resource will be
      * inflated, adding all top-level views to the activity.
      * 
@@ -2071,7 +2035,21 @@
             finish();
         }
     }
-    
+
+    /**
+     * Called when a key shortcut event is not handled by any of the views in the Activity.
+     * Override this method to implement global key shortcuts for the Activity.
+     * Key shortcuts can also be implemented by setting the
+     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
+     *
+     * @param keyCode The value in event.getKeyCode().
+     * @param event Description of the key event.
+     * @return True if the key shortcut was handled.
+     */
+    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
+        return false;
+    }
+
     /**
      * Called when a touch screen event was not handled by any of the views
      * under it.  This is most useful to process touch events that happen
@@ -2232,6 +2210,23 @@
     }
 
     /**
+     * Called to process a key shortcut event.
+     * You can override this to intercept all key shortcut events before they are
+     * dispatched to the window.  Be sure to call this implementation for key shortcut
+     * events that should be handled normally.
+     *
+     * @param event The key shortcut event.
+     * @return True if this event was consumed.
+     */
+    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+        onUserInteraction();
+        if (getWindow().superDispatchKeyShortcutEvent(event)) {
+            return true;
+        }
+        return onKeyShortcut(event.getKeyCode(), event);
+    }
+
+    /**
      * Called to process touch screen events.  You can override this to
      * intercept all touch screen events before they are dispatched to the
      * window.  Be sure to call this implementation for touch screen events
@@ -4340,9 +4335,8 @@
         
         mLastNonConfigurationInstances = null;
         
-        // First call onResume() -before- setting mResumed, so we don't
-        // send out any status bar / menu notifications the client makes.
         mCalled = false;
+        // mResumed is set by the instrumentation
         mInstrumentation.callActivityOnResume(this);
         if (!mCalled) {
             throw new SuperNotCalledException(
@@ -4351,7 +4345,6 @@
         }
 
         // Now really resume, and install the current status bar and menu.
-        mResumed = true;
         mCalled = false;
         
         mFragments.dispatchResume();
@@ -4375,6 +4368,7 @@
                     "Activity " + mComponent.toShortString() +
                     " did not call through to super.onPause()");
         }
+        mResumed = false;
     }
     
     final void performUserLeaving() {
@@ -4422,7 +4416,6 @@
     
             mStopped = true;
         }
-        mResumed = false;
     }
 
     final void performDestroy() {
@@ -4434,7 +4427,10 @@
         }
     }
     
-    final boolean isResumed() {
+    /**
+     * @hide
+     */
+    public final boolean isResumed() {
         return mResumed;
     }
 
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index ebdc7fd..44db50f 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -64,6 +64,28 @@
     static public int staticGetMemoryClass() {
         // Really brain dead right now -- just take this from the configured
         // vm heap size, and assume it is in megabytes and thus ends with "m".
+        String vmHeapSize = SystemProperties.get("dalvik.vm.smallheapsize", "16m");
+        return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1));
+    }
+    
+    /**
+     * Return the approximate per-application memory class of the current
+     * device when an application is running with a large heap.  This is the
+     * space available for memory-intensive applications; most applications
+     * should not need this amount of memory, and should instead stay with the
+     * {@link #getMemoryClass()} limit.  The returned value is in megabytes.
+     * This may be the same size as {@link #getMemoryClass()} on memory
+     * constrained devices, or it may be significantly larger on devices with
+     * a large amount of available RAM.
+     */
+    public int getLargeMemoryClass() {
+        return staticGetLargeMemoryClass();
+    }
+    
+    /** @hide */
+    static public int staticGetLargeMemoryClass() {
+        // Really brain dead right now -- just take this from the configured
+        // vm heap size, and assume it is in megabytes and thus ends with "m".
         String vmHeapSize = SystemProperties.get("dalvik.vm.heapsize", "16m");
         return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1));
     }
@@ -1127,4 +1149,11 @@
         }
         return false;
     }
+
+    /**
+     * Returns "true" if device is running in a test harness.
+     */
+    public static boolean isRunningInTestHarness() {
+        return SystemProperties.getBoolean("ro.test_harness", false);
+    }
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index cc94aa0..0d3afae 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -194,6 +194,9 @@
     final HashMap<IBinder, ProviderClientRecord> mLocalProviders
         = new HashMap<IBinder, ProviderClientRecord>();
 
+    final HashMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
+        = new HashMap<Activity, ArrayList<OnActivityPausedListener>>();
+
     final GcIdler mGcIdler = new GcIdler();
     boolean mGcIdlerScheduled = false;
 
@@ -1506,6 +1509,18 @@
         }
     }
 
+    public void registerOnActivityPausedListener(Activity activity,
+            OnActivityPausedListener listener) {
+        synchronized (mOnPauseListeners) {
+            ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
+            if (list == null) {
+                list = new ArrayList<OnActivityPausedListener>();
+                mOnPauseListeners.put(activity, list);
+            }
+            list.add(listener);
+        }
+    }
+
     public final ActivityInfo resolveActivityInfo(Intent intent) {
         ActivityInfo aInfo = intent.resolveActivityInfo(
                 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
@@ -2443,6 +2458,17 @@
             }
         }
         r.paused = true;
+
+        // Notify any outstanding on paused listeners
+        ArrayList<OnActivityPausedListener> listeners;
+        synchronized (mOnPauseListeners) {
+            listeners = mOnPauseListeners.remove(r.activity);
+        }
+        int size = (listeners != null ? listeners.size() : 0);
+        for (int i = 0; i < size; i++) {
+            listeners.get(i).onPaused(r.activity);
+        }
+
         return state;
     }
 
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index 5dc29a9..70e3616 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -24,7 +24,6 @@
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Message;
-import android.util.Log;
 import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
 import android.view.KeyEvent;
@@ -271,6 +270,17 @@
         mAlert.setIcon(icon);
     }
 
+    /**
+     * Set an icon as supplied by a theme attribute. e.g. android.R.attr.alertDialogIcon
+     *
+     * @param attrId ID of a theme attribute that points to a drawable resource.
+     */
+    public void setIconAttribute(int attrId) {
+        TypedValue out = new TypedValue();
+        mContext.getTheme().resolveAttribute(attrId, out, true);
+        mAlert.setIcon(out.resourceId);
+    }
+
     public void setInverseBackgroundForced(boolean forceInverseBackground) {
         mAlert.setInverseBackgroundForced(forceInverseBackground);
     }
@@ -400,7 +410,19 @@
             P.mIcon = icon;
             return this;
         }
-        
+
+        /**
+         * Set an icon as supplied by a theme attribute. e.g. android.R.attr.alertDialogIcon
+         *
+         * @param attrId ID of a theme attribute that points to a drawable resource.
+         */
+        public Builder setIconAttribute(int attrId) {
+            TypedValue out = new TypedValue();
+            P.mContext.getTheme().resolveAttribute(attrId, out, true);
+            P.mIconId = out.resourceId;
+            return this;
+        }
+
         /**
          * Set a listener to be invoked when the positive button of the dialog is pressed.
          * @param textId The resource id of the text to display in the positive button
@@ -480,7 +502,7 @@
         }
         
         /**
-         * Sets whether the dialog is cancelable or not default is true.
+         * Sets whether the dialog is cancelable or not.  Default is true.
          *
          * @return This Builder object to allow for chaining of calls to set methods
          */
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 4018703..b64069d 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1104,14 +1104,24 @@
     }
 
     @Override
-    public void setPackageObbPath(String packageName, String path) {
+    public void setPackageObbPaths(String packageName, String[] paths) {
         try {
-            mPM.setPackageObbPath(packageName, path);
+            mPM.setPackageObbPaths(packageName, paths);
         } catch (RemoteException e) {
             // Should never happen!
         }
     }
 
+    @Override
+    public String[] getPackageObbPaths(String packageName) {
+        try {
+            return mPM.getPackageObbPaths(packageName);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+        return null;
+    }
+
     private final ContextImpl mContext;
     private final IPackageManager mPM;
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 72f7286..e133ea0 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -17,9 +17,6 @@
 package android.app;
 
 import com.android.internal.policy.PolicyManager;
-import com.android.internal.util.XmlUtils;
-
-import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -35,14 +32,7 @@
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.ComponentInfo;
-import android.content.pm.FeatureInfo;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageInstallObserver;
-import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageManager;
-import android.content.pm.IPackageStatsObserver;
 import android.content.pm.PackageManager;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
@@ -80,14 +70,12 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.Vibrator;
-import android.os.FileUtils.FileStatus;
 import android.os.storage.StorageManager;
 import android.telephony.TelephonyManager;
 import android.content.ClipboardManager;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
-import android.view.LayoutInflater;
 import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.InputMethodManager;
@@ -104,9 +92,6 @@
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 class ReceiverRestrictedContext extends ContextWrapper {
     ReceiverRestrictedContext(Context base) {
@@ -354,10 +339,10 @@
                     final Context outerContext = ctx.getOuterContext();
                     return new NotificationManager(
                         new ContextThemeWrapper(outerContext,
-                                outerContext.getApplicationInfo().targetSdkVersion >=
-                                    Build.VERSION_CODES.HONEYCOMB
-                                ? com.android.internal.R.style.Theme_Holo_Dialog
-                                : com.android.internal.R.style.Theme_Dialog),
+                                Resources.selectSystemTheme(0,
+                                        outerContext.getApplicationInfo().targetSdkVersion,
+                                        com.android.internal.R.style.Theme_Dialog,
+                                        com.android.internal.R.style.Theme_Holo_Dialog)),
                         ctx.mMainThread.getHandler());
                 }});
 
@@ -485,15 +470,15 @@
     }
 
     @Override
+    public int getThemeResId() {
+        return mThemeResource;
+    }
+
+    @Override
     public Resources.Theme getTheme() {
         if (mTheme == null) {
-            if (mThemeResource == 0) {
-                final Context outerContext = getOuterContext();
-                mThemeResource = (outerContext.getApplicationInfo().targetSdkVersion
-                        >= Build.VERSION_CODES.HONEYCOMB)
-                                ? com.android.internal.R.style.Theme_Holo
-                                : com.android.internal.R.style.Theme;
-            }
+            mThemeResource = Resources.selectDefaultTheme(mThemeResource,
+                    getOuterContext().getApplicationInfo().targetSdkVersion);
             mTheme = mResources.newTheme();
             mTheme.applyStyle(mThemeResource, true);
         }
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index efe527f..8b70370 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
-import android.os.Build;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -71,10 +70,7 @@
             int year,
             int monthOfYear,
             int dayOfMonth) {
-        this(context, context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB
-                        ? com.android.internal.R.style.Theme_Holo_Dialog_Alert
-                        : com.android.internal.R.style.Theme_Dialog_Alert,
-                callBack, year, monthOfYear, dayOfMonth);
+        this(context, 0, callBack, year, monthOfYear, dayOfMonth);
     }
 
     /**
@@ -121,6 +117,22 @@
         mDatePicker.init(year, month, day, null);
     }
 
+    /**
+     * Gets the {@link DatePicker} contained in this dialog.
+     *
+     * @return The calendar view.
+     */
+    public DatePicker getDatePicker() {
+        return mDatePicker;
+    }
+
+    /**
+     * Sets the current date.
+     *
+     * @param year The date year.
+     * @param monthOfYear The date month.
+     * @param dayOfMonth The date day of month.
+     */
     public void updateDate(int year, int monthOfYear, int dayOfMonth) {
         mDatePicker.updateDate(year, monthOfYear, dayOfMonth);
     }
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index c398e98..6791400 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -25,7 +25,6 @@
 import android.content.DialogInterface;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -101,6 +100,7 @@
 
     private boolean mCreated = false;
     private boolean mShowing = false;
+    private boolean mCanceled = false;
 
     private final Thread mUiThread;
     private final Handler mHandler = new Handler();
@@ -244,6 +244,8 @@
             return;
         }
 
+        mCanceled = false;
+        
         if (!mCreated) {
             dispatchOnCreate(null);
         }
@@ -569,7 +571,21 @@
             cancel();
         }
     }
-    
+
+    /**
+     * Called when an key shortcut event is not handled by any of the views in the Dialog.
+     * Override this method to implement global key shortcuts for the Dialog.
+     * Key shortcuts can also be implemented by setting the
+     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
+     *
+     * @param keyCode The value in event.getKeyCode().
+     * @param event Description of the key event.
+     * @return True if the key shortcut was handled.
+     */
+    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
+        return false;
+    }
+
     /**
      * Called when a touch screen event was not handled by any of the views
      * under it. This is most useful to process touch events that happen outside
@@ -657,6 +673,22 @@
     }
 
     /**
+     * Called to process a key shortcut event.
+     * You can override this to intercept all key shortcut events before they are
+     * dispatched to the window.  Be sure to call this implementation for key shortcut
+     * events that should be handled normally.
+     *
+     * @param event The key shortcut event.
+     * @return True if this event was consumed.
+     */
+    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+        if (mWindow.superDispatchKeyShortcutEvent(event)) {
+            return true;
+        }
+        return onKeyShortcut(event.getKeyCode(), event);
+    }
+
+    /**
      * Called to process touch screen events.  You can override this to
      * intercept all touch screen events before they are dispatched to the
      * window.  Be sure to call this implementation for touch screen events
@@ -997,7 +1029,8 @@
      * also call your {@link DialogInterface.OnCancelListener} (if registered).
      */
     public void cancel() {
-        if (mCancelMessage != null) {
+        if (!mCanceled && mCancelMessage != null) {
+            mCanceled = true;
             // Obtain a new message so this dialog can be re-used
             Message.obtain(mCancelMessage).sendToTarget();
         }
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java
index bcd46d9..6194240 100644
--- a/core/java/android/app/DialogFragment.java
+++ b/core/java/android/app/DialogFragment.java
@@ -207,16 +207,6 @@
     }
 
     /**
-     * @deprecated Please use {@link #show(FragmentManager, String)}.
-     */
-    @Deprecated
-    public void show(Activity activity, String tag) {
-        FragmentTransaction ft = activity.openFragmentTransaction();
-        ft.add(this, tag);
-        ft.commit();
-    }
-
-    /**
      * Display the dialog, adding the fragment to the given FragmentManager.  This
      * is a convenience for explicitly creating a transaction, adding the
      * fragment to it with the given tag, and committing it.  This does
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index a24375e..12f4a18 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -453,7 +453,19 @@
          * @return this object
          */
         public Request setDestinationInExternalPublicDir(String dirType, String subPath) {
-            setDestinationFromBase(Environment.getExternalStoragePublicDirectory(dirType), subPath);
+            File file = Environment.getExternalStoragePublicDirectory(dirType);
+            if (file.exists()) {
+                if (!file.isDirectory()) {
+                    throw new IllegalStateException(file.getAbsolutePath() +
+                            " already exists and is not a directory");
+                }
+            } else {
+                if (!file.mkdir()) {
+                    throw new IllegalStateException("Unable to create directory: "+
+                            file.getAbsolutePath());
+                }
+            }
+            setDestinationFromBase(file, subPath);
             return this;
         }
 
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 348149e..316e513 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -27,6 +27,7 @@
 import android.os.Parcelable;
 import android.util.AndroidRuntimeException;
 import android.util.AttributeSet;
+import android.util.DebugUtils;
 import android.util.SparseArray;
 import android.view.ContextMenu;
 import android.view.LayoutInflater;
@@ -97,6 +98,7 @@
         }
         mInstance.setIndex(mIndex);
         mInstance.mFromLayout = mFromLayout;
+        mInstance.mRestored = true;
         mInstance.mFragmentId = mFragmentId;
         mInstance.mContainerId = mContainerId;
         mInstance.mTag = mTag;
@@ -223,12 +225,11 @@
  * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
  *      main}
  *
- * <p>The titles fragment, showing a list of titles, is very simple, relying
+ * <p>The titles fragment, showing a list of titles, is fairly simple, relying
  * on {@link ListFragment} for most of its work.  Note the implementation of
- * clicking an item, which can either update
- * the content of the details fragment or start a new activity show the
- * details depending on whether the current activity's layout can show the
- * details.</p>
+ * clicking an item: depending on the current activity's layout, it can either
+ * create and display a new fragment to show the details in-place (more about
+ * this later), or start a new activity show the details.</p>
  *
  * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
  *      titles}
@@ -241,7 +242,7 @@
  *      details}
  *
  * <p>In this case when the user clicks on a title, there is no details
- * fragment in the current activity, so the title title fragment's click code will
+ * container in the current activity, so the title title fragment's click code will
  * launch a new activity to display the details fragment:</p>
  *
  * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
@@ -253,22 +254,25 @@
  *
  * {@sample development/samples/ApiDemos/res/layout-land/fragment_layout.xml layout}
  *
- * <p>Note how the prior code will adjust to this alternative UI flow: the
- * titles fragment will now show its text inside of its activity, and the
- * details activity will finish of it finds itself running in a configuration
- * where the details can be shown inline.
+ * <p>Note how the prior code will adjust to this alternative UI flow: the titles
+ * fragment will now embed the details fragment inside of this activity, and the
+ * details activity will finish itself if it is running in a configuration
+ * where the details can be shown in-place.
  *
  * <p>When a configuration change causes the activity hosting these fragments
  * to restart, its new instance may use a different layout that doesn't
  * include the same fragments as the previous layout.  In this case all of
  * the previous fragments will still be instantiated and running in the new
- * instance; however, any that are no longer associated with a &lt;fragment&gt;
- * tag in the view hierarchy will not have their content view created and will
- * return false from {@link #isInLayout}.
+ * instance.  However, any that are no longer associated with a &lt;fragment&gt;
+ * tag in the view hierarchy will not have their content view created
+ * and will return false from {@link #isInLayout}.  (The code here also shows
+ * how you can determine if a fragment placed in a container is no longer
+ * running in a layout with that container and avoid creating its view hierarchy
+ * in that case.)
  * 
  * <p>The attributes of the &lt;fragment&gt; tag are used to control the
- * LayoutParams provider when attaching the fragment's view to the parent
- * container.  They can alse be parsed by the fragment in {@link #onInflate}
+ * LayoutParams provided when attaching the fragment's view to the parent
+ * container.  They can also be parsed by the fragment in {@link #onInflate}
  * as parameters.
  * 
  * <p>The fragment being instantiated must have some kind of unique identifier
@@ -322,6 +326,15 @@
     
     int mState = INITIALIZING;
     
+    // Non-null if the fragment's view hierarchy is currently animating away,
+    // meaning we need to wait a bit on completely destroying it.  This is the
+    // animation that is running.
+    Animator mAnimatingAway;
+
+    // If mAnimatingAway != null, this is the state we should move to once the
+    // animation is done.
+    int mStateAfterAnimating;
+
     // When instantiated from saved state, this is the saved state.
     Bundle mSavedFragmentState;
     SparseArray<Parcelable> mSavedViewState;
@@ -353,6 +366,9 @@
     // Set to true when the view has actually been inflated in its layout.
     boolean mInLayout;
 
+    // True if this fragment has been restored from previously saved state.
+    boolean mRestored;
+    
     // Number of active back stack entries this fragment is in.
     int mBackStackNesting;
     
@@ -526,17 +542,7 @@
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder(128);
-        String simpleName = getClass().getSimpleName();
-        if (simpleName == null || simpleName.isEmpty()) {
-            simpleName = getClass().getName();
-            int end = simpleName.lastIndexOf('.');
-            if (end > 0) {
-                simpleName = simpleName.substring(end+1);
-            }
-        }
-        sb.append(simpleName);
-        sb.append("{");
-        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        DebugUtils.buildShortClassTag(this, sb);
         if (mIndex >= 0) {
             sb.append(" #");
             sb.append(mIndex);
@@ -1249,6 +1255,11 @@
         if (mView != null) {
             writer.print(prefix); writer.print("mView="); writer.println(mView);
         }
+        if (mAnimatingAway != null) {
+            writer.print(prefix); writer.print("mAnimatingAway="); writer.println(mAnimatingAway);
+            writer.print(prefix); writer.print("mStateAfterAnimating=");
+                    writer.println(mStateAfterAnimating);
+        }
         if (mLoaderManager != null) {
             writer.print(prefix); writer.println("Loader Manager:");
             mLoaderManager.dump(prefix + "  ", fd, writer, args);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 488b673..eb9b8a3 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -26,6 +26,7 @@
 import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.DebugUtils;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.Menu;
@@ -37,6 +38,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 
 /**
  * Interface for interacting with {@link Fragment} objects inside of an
@@ -251,6 +253,15 @@
      * @param args Additional arguments to the dump request.
      */
     public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
+
+    /**
+     * Control whether the framework's internal fragment manager debugging
+     * logs are turned on.  If enabled, you will see output in logcat as
+     * the framework performs fragment operations.
+     */
+    public static void enableDebugLogging(boolean enabled) {
+        FragmentManagerImpl.DEBUG = enabled;
+    }
 }
 
 final class FragmentManagerState implements Parcelable {
@@ -293,7 +304,7 @@
  * Container for fragments associated with an activity.
  */
 final class FragmentManagerImpl extends FragmentManager {
-    static final boolean DEBUG = false;
+    static boolean DEBUG = true;
     static final String TAG = "FragmentManager";
     
     static final String TARGET_REQUEST_CODE_STATE_TAG = "android:target_req_state";
@@ -321,6 +332,7 @@
     
     boolean mNeedMenuInvalidate;
     boolean mStateSaved;
+    boolean mDestroyed;
     String mNoTransactionsBecause;
     
     // Temporary vars for state save and restore.
@@ -451,24 +463,35 @@
     }
 
     @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("FragmentManager{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(" in ");
+        DebugUtils.buildShortClassTag(mActivity, sb);
+        sb.append("}}");
+        return sb.toString();
+    }
+
+    @Override
     public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
-        if (mActive == null || mActive.size() <= 0) {
-            return;
-        }
-
-        writer.print(prefix); writer.print("Active Fragments in ");
-                writer.print(Integer.toHexString(System.identityHashCode(this)));
-                writer.println(":");
-
         String innerPrefix = prefix + "    ";
 
-        int N = mActive.size();
-        for (int i=0; i<N; i++) {
-            Fragment f = mActive.get(i);
-            if (f != null) {
-                writer.print(prefix); writer.print("  #"); writer.print(i);
-                        writer.print(": "); writer.println(f.toString());
-                f.dump(innerPrefix, fd, writer, args);
+        int N;
+        if (mActive != null) {
+            N = mActive.size();
+            if (N > 0) {
+                writer.print(prefix); writer.print("Active Fragments in ");
+                        writer.print(Integer.toHexString(System.identityHashCode(this)));
+                        writer.println(":");
+                for (int i=0; i<N; i++) {
+                    Fragment f = mActive.get(i);
+                    writer.print(prefix); writer.print("  #"); writer.print(i);
+                            writer.print(": "); writer.println(f);
+                    if (f != null) {
+                        f.dump(innerPrefix, fd, writer, args);
+                    }
+                }
             }
         }
 
@@ -484,6 +507,18 @@
             }
         }
 
+        if (mCreatedMenus != null) {
+            N = mCreatedMenus.size();
+            if (N > 0) {
+                writer.print(prefix); writer.println("Fragments Created Menus:");
+                for (int i=0; i<N; i++) {
+                    Fragment f = mCreatedMenus.get(i);
+                    writer.print(prefix); writer.print("  #"); writer.print(i);
+                            writer.print(": "); writer.println(f.toString());
+                }
+            }
+        }
+
         if (mBackStack != null) {
             N = mBackStack.size();
             if (N > 0) {
@@ -496,6 +531,54 @@
                 }
             }
         }
+
+        synchronized (this) {
+            if (mBackStackIndices != null) {
+                N = mBackStackIndices.size();
+                if (N > 0) {
+                    writer.print(prefix); writer.println("Back Stack Indices:");
+                    for (int i=0; i<N; i++) {
+                        BackStackRecord bs = mBackStackIndices.get(i);
+                        writer.print(prefix); writer.print("  #"); writer.print(i);
+                                writer.print(": "); writer.println(bs);
+                    }
+                }
+            }
+
+            if (mAvailBackStackIndices != null && mAvailBackStackIndices.size() > 0) {
+                writer.print(prefix); writer.print("mAvailBackStackIndices: ");
+                        writer.println(Arrays.toString(mAvailBackStackIndices.toArray()));
+            }
+        }
+
+        if (mPendingActions != null) {
+            N = mPendingActions.size();
+            if (N > 0) {
+                writer.print(prefix); writer.println("Pending Actions:");
+                for (int i=0; i<N; i++) {
+                    Runnable r = mPendingActions.get(i);
+                    writer.print(prefix); writer.print("  #"); writer.print(i);
+                            writer.print(": "); writer.println(r);
+                }
+            }
+        }
+
+        writer.print(prefix); writer.println("FragmentManager misc state:");
+        writer.print(prefix); writer.print("  mCurState="); writer.print(mCurState);
+                writer.print(" mStateSaved="); writer.print(mStateSaved);
+                writer.print(" mDestroyed="); writer.println(mDestroyed);
+        if (mNeedMenuInvalidate) {
+            writer.print(prefix); writer.print("  mNeedMenuInvalidate=");
+                    writer.println(mNeedMenuInvalidate);
+        }
+        if (mNoTransactionsBecause != null) {
+            writer.print(prefix); writer.print("  mNoTransactionsBecause=");
+                    writer.println(mNoTransactionsBecause);
+        }
+        if (mAvailIndices != null && mAvailIndices.size() > 0) {
+            writer.print(prefix); writer.print("  mAvailIndices: ");
+                    writer.println(Arrays.toString(mAvailIndices.toArray()));
+        }
     }
 
     Animator loadAnimator(Fragment fragment, int transit, boolean enter,
@@ -548,6 +631,14 @@
         }
         
         if (f.mState < newState) {
+            if (f.mAnimatingAway != null) {
+                // The fragment is currently being animated...  but!  Now we
+                // want to move our state back up.  Give up on waiting for the
+                // animation, move to whatever the final state should be once
+                // the animation is done, and then we can proceed from there.
+                f.mAnimatingAway = null;
+                moveToState(f, f.mStateAfterAnimating, 0, 0);
+            }
             switch (f.mState) {
                 case Fragment.INITIALIZING:
                     if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
@@ -599,7 +690,7 @@
                             ViewGroup container = null;
                             if (f.mContainerId != 0) {
                                 container = (ViewGroup)mActivity.findViewById(f.mContainerId);
-                                if (container == null) {
+                                if (container == null && !f.mRestored) {
                                     throw new IllegalArgumentException("No view found for id 0x"
                                             + Integer.toHexString(f.mContainerId)
                                             + " for fragment " + f);
@@ -695,18 +786,26 @@
                         }
                         if (f.mView != null && f.mContainer != null) {
                             Animator anim = null;
-                            if (mCurState > Fragment.INITIALIZING) {
+                            if (mCurState > Fragment.INITIALIZING && !mDestroyed) {
                                 anim = loadAnimator(f, transit, false,
                                         transitionStyle);
                             }
                             if (anim != null) {
                                 final ViewGroup container = f.mContainer;
                                 final View view = f.mView;
+                                final Fragment fragment = f;
                                 container.startViewTransition(view);
+                                f.mAnimatingAway = anim;
+                                f.mStateAfterAnimating = newState;
                                 anim.addListener(new AnimatorListenerAdapter() {
                                     @Override
                                     public void onAnimationEnd(Animator anim) {
                                         container.endViewTransition(view);
+                                        if (fragment.mAnimatingAway != null) {
+                                            fragment.mAnimatingAway = null;
+                                            moveToState(fragment, fragment.mStateAfterAnimating,
+                                                    0, 0);
+                                        }
                                     }
                                 });
                                 anim.setTarget(f.mView);
@@ -720,25 +819,46 @@
                     }
                 case Fragment.CREATED:
                     if (newState < Fragment.CREATED) {
-                        if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
-                        if (!f.mRetaining) {
-                            f.mCalled = false;
-                            f.onDestroy();
-                            if (!f.mCalled) {
-                                throw new SuperNotCalledException("Fragment " + f
-                                        + " did not call through to super.onDestroy()");
+                        if (mDestroyed) {
+                            if (f.mAnimatingAway != null) {
+                                // The fragment's containing activity is
+                                // being destroyed, but this fragment is
+                                // currently animating away.  Stop the
+                                // animation right now -- it is not needed,
+                                // and we can't wait any more on destroying
+                                // the fragment.
+                                Animator anim = f.mAnimatingAway;
+                                f.mAnimatingAway = null;
+                                anim.cancel();
                             }
                         }
-                        
-                        f.mCalled = false;
-                        f.onDetach();
-                        if (!f.mCalled) {
-                            throw new SuperNotCalledException("Fragment " + f
-                                    + " did not call through to super.onDetach()");
+                        if (f.mAnimatingAway != null) {
+                            // We are waiting for the fragment's view to finish
+                            // animating away.  Just make a note of the state
+                            // the fragment now should move to once the animation
+                            // is done.
+                            f.mStateAfterAnimating = newState;
+                        } else {
+                            if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
+                            if (!f.mRetaining) {
+                                f.mCalled = false;
+                                f.onDestroy();
+                                if (!f.mCalled) {
+                                    throw new SuperNotCalledException("Fragment " + f
+                                            + " did not call through to super.onDestroy()");
+                                }
+                            }
+
+                            f.mCalled = false;
+                            f.onDetach();
+                            if (!f.mCalled) {
+                                throw new SuperNotCalledException("Fragment " + f
+                                        + " did not call through to super.onDetach()");
+                            }
+                            f.mImmediateActivity = null;
+                            f.mActivity = null;
+                            f.mFragmentManager = null;
                         }
-                        f.mImmediateActivity = null;
-                        f.mActivity = null;
-                        f.mFragmentManager = null;
                     }
             }
         }
@@ -852,9 +972,21 @@
                         transitionStyle);
                 if (anim != null) {
                     anim.setTarget(fragment.mView);
+                    // Delay the actual hide operation until the animation finishes, otherwise
+                    // the fragment will just immediately disappear
+                    final Fragment finalFragment = fragment;
+                    anim.addListener(new AnimatorListenerAdapter() {
+                        @Override
+                        public void onAnimationEnd(Animator animation) {
+                            if (finalFragment.mView != null) {
+                                finalFragment.mView.setVisibility(View.GONE);
+                            }
+                        }
+                    });
                     anim.start();
+                } else {
+                    fragment.mView.setVisibility(View.GONE);
                 }
-                fragment.mView.setVisibility(View.GONE);
             }
             if (fragment.mAdded && fragment.mHasMenu) {
                 mNeedMenuInvalidate = true;
@@ -1421,6 +1553,7 @@
     }
     
     public void dispatchDestroy() {
+        mDestroyed = true;
         moveToState(Fragment.INITIALIZING, false);
         mActivity = null;
     }
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index 5aec348..1b8debc 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -24,8 +24,8 @@
      * @param fragment The fragment to be added.  This fragment must not already
      * be added to the activity.
      * @param tag Optional tag name for the fragment, to later retrieve the
-     * fragment with {@link Activity#findFragmentByTag(String)
-     * Activity.findFragmentByTag(String)}.
+     * fragment with {@link FragmentManager#findFragmentByTag(String)
+     * FragmentManager.findFragmentByTag(String)}.
      * 
      * @return Returns the same FragmentTransaction instance.
      */
@@ -47,8 +47,8 @@
      * to be replaced.
      * @param fragment The new fragment to place in the container.
      * @param tag Optional tag name for the fragment, to later retrieve the
-     * fragment with {@link Activity#findFragmentByTag(String)
-     * Activity.findFragmentByTag(String)}.
+     * fragment with {@link FragmentManager#findFragmentByTag(String)
+     * FragmentManager.findFragmentByTag(String)}.
      * 
      * @return Returns the same FragmentTransaction instance.
      */
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index ad811d8..cd278be 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1149,6 +1149,7 @@
      * @param activity The activity being resumed.
      */
     public void callActivityOnResume(Activity activity) {
+        activity.mResumed = true;
         activity.onResume();
         
         if (mActivityMonitors != null) {
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 7c2d3a0..57a2695 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -113,6 +113,12 @@
         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 @@
         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 @@
      * 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/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index 0ab987a..5f8c098 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -18,15 +18,29 @@
 
 import android.content.Loader;
 import android.os.Bundle;
+import android.util.DebugUtils;
 import android.util.Log;
 import android.util.SparseArray;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.lang.reflect.Modifier;
 
 /**
  * Interface associated with an {@link Activity} or {@link Fragment} for managing
- * one or more {@link android.content.Loader} instances associated with it.
+ * one or more {@link android.content.Loader} instances associated with it.  This
+ * helps an application manage longer-running operations in conjunction with the
+ * Activity or Fragment lifecycle; the most common use of this is with a
+ * {@link android.content.CursorLoader}, however applications are free to write
+ * their own loaders for loading other types of data.
+ *
+ * <p>As an example, here is the full implementation of a {@link Fragment}
+ * that displays a {@link android.widget.ListView} containing the results of
+ * a query against the contacts content provider.  It uses a
+ * {@link android.content.CursorLoader} to manage the query on the provider.
+ *
+ * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentListCursorLoader.java
+ *      fragment_cursor}
  */
 public abstract class LoaderManager {
     /**
@@ -49,10 +63,48 @@
          * activity's state is saved.  See {@link FragmentManager#openTransaction()
          * FragmentManager.openTransaction()} for further discussion on this.
          * 
+         * <p>This function is guaranteed to be called prior to the release of
+         * the last data that was supplied for this Loader.  At this point
+         * you should remove all use of the old data (since it will be released
+         * soon), but should not do your own release of the data since its Loader
+         * owns it and will take care of that.  The Loader will take care of
+         * management of its data so you don't have to.  In particular:
+         *
+         * <ul>
+         * <li> <p>The Loader will monitor for changes to the data, and report
+         * them to you through new calls here.  You should not monitor the
+         * data yourself.  For example, if the data is a {@link android.database.Cursor}
+         * and you place it in a {@link android.widget.CursorAdapter}, use
+         * the {@link android.widget.CursorAdapter#CursorAdapter(android.content.Context,
+         * android.database.Cursor, int)} constructor <em>without</em> passing
+         * in either {@link android.widget.CursorAdapter#FLAG_AUTO_REQUERY}
+         * or {@link android.widget.CursorAdapter#FLAG_REGISTER_CONTENT_OBSERVER}
+         * (that is, use 0 for the flags argument).  This prevents the CursorAdapter
+         * from doing its own observing of the Cursor, which is not needed since
+         * when a change happens you will get a new Cursor throw another call
+         * here.
+         * <li> The Loader will release the data once it knows the application
+         * is no longer using it.  For example, if the data is
+         * a {@link android.database.Cursor} from a {@link android.content.CursorLoader},
+         * you should not call close() on it yourself.  If the Cursor is being placed in a
+         * {@link android.widget.CursorAdapter}, you should use the
+         * {@link android.widget.CursorAdapter#swapCursor(android.database.Cursor)}
+         * method so that the old Cursor is not closed.
+         * </ul>
+         *
          * @param loader The Loader that has finished.
          * @param data The data generated by the Loader.
          */
         public void onLoadFinished(Loader<D> loader, D data);
+
+        /**
+         * Called when a previously created loader is being reset, and thus
+         * making its data unavailable.  The application should at this point
+         * remove any references it has to the Loader's data.
+         *
+         * @param loader The Loader that is being reset.
+         */
+        public void onLoaderReset(Loader<D> loader);
     }
     
     /**
@@ -65,28 +117,54 @@
      * will be called as the loader state changes.  If at the point of call
      * the caller is in its started state, and the requested loader
      * already exists and has generated its data, then
-     * callback. {@link LoaderCallbacks#onLoadFinished} will
+     * callback {@link LoaderCallbacks#onLoadFinished} will
      * be called immediately (inside of this function), so you must be prepared
      * for this to happen.
+     *
+     * @param id A unique identifier for this loader.  Can be whatever you want.
+     * Identifiers are scoped to a particular LoaderManager instance.
+     * @param args Optional arguments to supply to the loader at construction.
+     * If a loader already exists (a new one does not need to be created), this
+     * parameter will be ignored and the last arguments continue to be used.
+     * @param callback Interface the LoaderManager will call to report about
+     * changes in the state of the loader.  Required.
      */
     public abstract <D> Loader<D> initLoader(int id, Bundle args,
             LoaderManager.LoaderCallbacks<D> callback);
 
     /**
-     * Creates a new loader in this manager, registers the callbacks to it,
+     * Starts a new or restarts an existing {@link android.content.Loader} in
+     * this manager, registers the callbacks to it,
      * and (if the activity/fragment is currently started) starts loading it.
      * If a loader with the same id has previously been
      * started it will automatically be destroyed when the new loader completes
      * its work. The callback will be delivered before the old loader
      * is destroyed.
+     *
+     * @param id A unique identifier for this loader.  Can be whatever you want.
+     * Identifiers are scoped to a particular LoaderManager instance.
+     * @param args Optional arguments to supply to the loader at construction.
+     * @param callback Interface the LoaderManager will call to report about
+     * changes in the state of the loader.  Required.
      */
     public abstract <D> Loader<D> restartLoader(int id, Bundle args,
             LoaderManager.LoaderCallbacks<D> callback);
 
     /**
-     * Stops and removes the loader with the given ID.
+     * Stops and removes the loader with the given ID.  If this loader
+     * had previously reported data to the client through
+     * {@link LoaderCallbacks#onLoadFinished(Loader, Object)}, a call
+     * will be made to {@link LoaderCallbacks#onLoaderReset(Loader)}.
      */
-    public abstract void stopLoader(int id);
+    public abstract void destroyLoader(int id);
+
+    /**
+     * @deprecated Renamed to {@link #destroyLoader}.
+     */
+    @Deprecated
+    public void stopLoader(int id) {
+        destroyLoader(id);
+    }
 
     /**
      * Return the Loader with the given id or null if no matching Loader
@@ -103,11 +181,20 @@
      * @param args Additional arguments to the dump request.
      */
     public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
+
+    /**
+     * Control whether the framework's internal loader manager debugging
+     * logs are turned on.  If enabled, you will see output in logcat as
+     * the framework performs loader operations.
+     */
+    public static void enableDebugLogging(boolean enabled) {
+        LoaderManagerImpl.DEBUG = enabled;
+    }
 }
 
 class LoaderManagerImpl extends LoaderManager {
-    static final String TAG = "LoaderManagerImpl";
-    static final boolean DEBUG = true;
+    static final String TAG = "LoaderManager";
+    static boolean DEBUG = true;
 
     // These are the currently active loaders.  A loader is here
     // from the time its load is started until it has been explicitly
@@ -131,6 +218,7 @@
         LoaderManager.LoaderCallbacks<Object> mCallbacks;
         Loader<Object> mLoader;
         Object mData;
+        Object mDeliveredData;
         boolean mStarted;
         boolean mRetaining;
         boolean mRetainingStarted;
@@ -157,17 +245,24 @@
                 return;
             }
 
+            mStarted = true;
+            
             if (DEBUG) Log.v(TAG, "  Starting: " + this);
             if (mLoader == null && mCallbacks != null) {
                mLoader = mCallbacks.onCreateLoader(mId, mArgs);
             }
             if (mLoader != null) {
+                if (mLoader.getClass().isMemberClass()
+                        && !Modifier.isStatic(mLoader.getClass().getModifiers())) {
+                    throw new IllegalArgumentException(
+                            "Object returned from onCreateLoader must not be a non-static inner member class: "
+                            + mLoader);
+                }
                 if (!mListenerRegistered) {
                     mLoader.registerListener(mId, this);
                     mListenerRegistered = true;
                 }
                 mLoader.startLoading();
-                mStarted = true;
             }
         }
         
@@ -191,13 +286,16 @@
                         stop();
                     }
                 }
-                if (mStarted && mData != null) {
-                    // This loader was retained, and now at the point of
-                    // finishing the retain we find we remain started, have
-                    // our data, and the owner has a new callback...  so
-                    // let's deliver the data now.
-                    callOnLoadFinished(mLoader, mData);
-                }
+            }
+
+            if (mStarted && mData != null) {
+                // This loader has retained its data, either completely across
+                // a configuration change or just whatever the last data set
+                // was after being restarted from a stop, and now at the point of
+                // finishing the retain we find we remain started, have
+                // our data, and the owner has a new callback...  so
+                // let's deliver the data now.
+                callOnLoadFinished(mLoader, mData);
             }
         }
         
@@ -211,36 +309,58 @@
                     mLoader.unregisterListener(this);
                     mLoader.stopLoading();
                 }
-                mData = null;
             }
         }
         
         void destroy() {
             if (DEBUG) Log.v(TAG, "  Destroying: " + this);
             mDestroyed = true;
+            boolean needReset = mDeliveredData != null;
+            mDeliveredData = null;
+            if (mCallbacks != null && mLoader != null && mData != null && needReset) {
+                if (DEBUG) Log.v(TAG, "  Reseting: " + this);
+                String lastBecause = null;
+                if (mActivity != null) {
+                    lastBecause = mActivity.mFragments.mNoTransactionsBecause;
+                    mActivity.mFragments.mNoTransactionsBecause = "onLoaderReset";
+                }
+                try {
+                    mCallbacks.onLoaderReset(mLoader);
+                } finally {
+                    if (mActivity != null) {
+                        mActivity.mFragments.mNoTransactionsBecause = lastBecause;
+                    }
+                }
+            }
             mCallbacks = null;
+            mData = null;
             if (mLoader != null) {
                 if (mListenerRegistered) {
                     mListenerRegistered = false;
                     mLoader.unregisterListener(this);
                 }
-                mLoader.destroy();
+                mLoader.reset();
             }
         }
         
         @Override public void onLoadComplete(Loader<Object> loader, Object data) {
-            if (DEBUG) Log.v(TAG, "onLoadComplete: " + this + " mDestroyed=" + mDestroyed);
+            if (DEBUG) Log.v(TAG, "onLoadComplete: " + this);
 
             if (mDestroyed) {
+                if (DEBUG) Log.v(TAG, "  Ignoring load complete -- destroyed");
                 return;
             }
             
             // Notify of the new data so the app can switch out the old data before
             // we try to destroy it.
-            mData = data;
-            callOnLoadFinished(loader, data);
+            if (mData != data) {
+                mData = data;
+                if (mStarted) {
+                    callOnLoadFinished(loader, data);
+                }
+            }
 
-            if (DEBUG) Log.v(TAG, "onLoadFinished returned: " + this);
+            //if (DEBUG) Log.v(TAG, "  onLoadFinished returned: " + this);
 
             // We have now given the application the new loader with its
             // loaded data, so it should have stopped using the previous
@@ -248,6 +368,7 @@
             // clean it up.
             LoaderInfo info = mInactiveLoaders.get(mId);
             if (info != null && info != this) {
+                info.mDeliveredData = null;
                 info.destroy();
                 mInactiveLoaders.remove(mId);
             }
@@ -261,12 +382,15 @@
                     mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished";
                 }
                 try {
+                    if (DEBUG) Log.v(TAG, "  onLoadFinished in " + loader + ": "
+                            + loader.dataToString(data));
                     mCallbacks.onLoadFinished(loader, data);
                 } finally {
                     if (mActivity != null) {
                         mActivity.mFragments.mNoTransactionsBecause = lastBecause;
                     }
                 }
+                mDeliveredData = data;
             }
         }
         
@@ -277,21 +401,9 @@
             sb.append(Integer.toHexString(System.identityHashCode(this)));
             sb.append(" #");
             sb.append(mId);
-            if (mArgs != null) {
-                sb.append(" ");
-                sb.append(mArgs.toString());
-            }
-            sb.append("}");
-            return sb.toString();
-        }
-
-        public String toBasicString() {
-            StringBuilder sb = new StringBuilder(64);
-            sb.append("LoaderInfo{");
-            sb.append(Integer.toHexString(System.identityHashCode(this)));
-            sb.append(" #");
-            sb.append(mId);
-            sb.append("}");
+            sb.append(" : ");
+            DebugUtils.buildShortClassTag(mLoader, sb);
+            sb.append("}}");
             return sb.toString();
         }
 
@@ -300,11 +412,16 @@
                     writer.print(" mArgs="); writer.println(mArgs);
             writer.print(prefix); writer.print("mCallbacks="); writer.println(mCallbacks);
             writer.print(prefix); writer.print("mLoader="); writer.println(mLoader);
+            if (mLoader != null) {
+                mLoader.dump(prefix + "  ", fd, writer, args);
+            }
             writer.print(prefix); writer.print("mData="); writer.println(mData);
+            writer.print(prefix); writer.print("mDeliveredData="); writer.println(mDeliveredData);
             writer.print(prefix); writer.print("mStarted="); writer.print(mStarted);
                     writer.print(" mRetaining="); writer.print(mRetaining);
-                    writer.print(" mDestroyed="); writer.print(mDestroyed);
-                    writer.print(" mListenerRegistered="); writer.println(mListenerRegistered);
+                    writer.print(" mDestroyed="); writer.println(mDestroyed);
+            writer.print(prefix); writer.print("mListenerRegistered=");
+                    writer.println(mListenerRegistered);
         }
     }
     
@@ -336,12 +453,14 @@
     public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
         LoaderInfo info = mLoaders.get(id);
         
-        if (DEBUG) Log.v(TAG, "initLoader in " + this + ": cur=" + info);
+        if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args);
 
         if (info == null) {
             // Loader doesn't already exist; create.
             info = createLoader(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);
+            if (DEBUG) Log.v(TAG, "  Created new loader " + info);
         } else {
+            if (DEBUG) Log.v(TAG, "  Re-using existing loader " + info);
             info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
         }
         
@@ -356,7 +475,7 @@
     @SuppressWarnings("unchecked")
     public <D> Loader<D> restartLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
         LoaderInfo info = mLoaders.get(id);
-        if (DEBUG) Log.v(TAG, "restartLoader in " + this + ": cur=" + info);
+        if (DEBUG) Log.v(TAG, "restartLoader in " + this + ": args=" + args);
         if (info != null) {
             LoaderInfo inactive = mInactiveLoaders.get(id);
             if (inactive != null) {
@@ -365,7 +484,8 @@
                     // called from within onLoadComplete, where we haven't
                     // yet destroyed the last inactive loader.  So just do
                     // that now.
-                    if (DEBUG) Log.v(TAG, "  Removing last inactive loader in " + this);
+                    if (DEBUG) Log.v(TAG, "  Removing last inactive loader: " + info);
+                    inactive.mDeliveredData = null;
                     inactive.destroy();
                     mInactiveLoaders.put(id, info);
                 } else {
@@ -373,13 +493,13 @@
                     // waiting for!  Now we have three active loaders... let's just
                     // drop the one in the middle, since we are still waiting for
                     // its result but that result is already out of date.
-                    if (DEBUG) Log.v(TAG, "  Removing intermediate loader in " + this);
+                    if (DEBUG) Log.v(TAG, "  Removing intermediate loader: " + info);
                     info.destroy();
                 }
             } else {
                 // Keep track of the previous instance of this loader so we can destroy
                 // it when the new one completes.
-                if (DEBUG) Log.v(TAG, "  Making inactive: " + info);
+                if (DEBUG) Log.v(TAG, "  Making last loader inactive: " + info);
                 mInactiveLoaders.put(id, info);
             }
         }
@@ -388,14 +508,20 @@
         return (Loader<D>)info.mLoader;
     }
     
-    public void stopLoader(int id) {
-        if (DEBUG) Log.v(TAG, "stopLoader in " + this + " of " + id);
+    public void destroyLoader(int id) {
+        if (DEBUG) Log.v(TAG, "destroyLoader in " + this + " of " + id);
         int idx = mLoaders.indexOfKey(id);
         if (idx >= 0) {
             LoaderInfo info = mLoaders.valueAt(idx);
             mLoaders.removeAt(idx);
             info.destroy();
         }
+        idx = mInactiveLoaders.indexOfKey(id);
+        if (idx >= 0) {
+            LoaderInfo info = mInactiveLoaders.valueAt(idx);
+            mInactiveLoaders.removeAt(idx);
+            info.destroy();
+        }
     }
 
     @SuppressWarnings("unchecked")
@@ -408,7 +534,7 @@
     }
  
     void doStart() {
-        if (DEBUG) Log.v(TAG, "Starting: " + this);
+        if (DEBUG) Log.v(TAG, "Starting in " + this);
         if (mStarted) {
             RuntimeException e = new RuntimeException("here");
             e.fillInStackTrace();
@@ -416,16 +542,17 @@
             return;
         }
         
+        mStarted = true;
+
         // Call out to sub classes so they can start their loaders
         // Let the existing loaders know that we want to be notified when a load is complete
         for (int i = mLoaders.size()-1; i >= 0; i--) {
             mLoaders.valueAt(i).start();
         }
-        mStarted = true;
     }
     
     void doStop() {
-        if (DEBUG) Log.v(TAG, "Stopping: " + this);
+        if (DEBUG) Log.v(TAG, "Stopping in " + this);
         if (!mStarted) {
             RuntimeException e = new RuntimeException("here");
             e.fillInStackTrace();
@@ -440,7 +567,7 @@
     }
     
     void doRetain() {
-        if (DEBUG) Log.v(TAG, "Retaining: " + this);
+        if (DEBUG) Log.v(TAG, "Retaining in " + this);
         if (!mStarted) {
             RuntimeException e = new RuntimeException("here");
             e.fillInStackTrace();
@@ -456,23 +583,25 @@
     }
     
     void finishRetain() {
-        if (DEBUG) Log.v(TAG, "Finished Retaining: " + this);
+        if (mRetaining) {
+            if (DEBUG) Log.v(TAG, "Finished Retaining in " + this);
 
-        mRetaining = false;
-        for (int i = mLoaders.size()-1; i >= 0; i--) {
-            mLoaders.valueAt(i).finishRetain();
+            mRetaining = false;
+            for (int i = mLoaders.size()-1; i >= 0; i--) {
+                mLoaders.valueAt(i).finishRetain();
+            }
         }
     }
     
     void doDestroy() {
         if (!mRetaining) {
-            if (DEBUG) Log.v(TAG, "Destroying Active: " + this);
+            if (DEBUG) Log.v(TAG, "Destroying Active in " + this);
             for (int i = mLoaders.size()-1; i >= 0; i--) {
                 mLoaders.valueAt(i).destroy();
             }
         }
         
-        if (DEBUG) Log.v(TAG, "Destroying Inactive: " + this);
+        if (DEBUG) Log.v(TAG, "Destroying Inactive in " + this);
         for (int i = mInactiveLoaders.size()-1; i >= 0; i--) {
             mInactiveLoaders.valueAt(i).destroy();
         }
@@ -480,6 +609,17 @@
     }
 
     @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("LoaderManager{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(" in ");
+        DebugUtils.buildShortClassTag(mActivity, sb);
+        sb.append("}}");
+        return sb.toString();
+    }
+
+    @Override
     public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
         if (mLoaders.size() > 0) {
             writer.print(prefix); writer.println("Active Loaders:");
@@ -487,7 +627,7 @@
             for (int i=0; i < mLoaders.size(); i++) {
                 LoaderInfo li = mLoaders.valueAt(i);
                 writer.print(prefix); writer.print("  #"); writer.print(mLoaders.keyAt(i));
-                        writer.print(": "); writer.println(li.toBasicString());
+                        writer.print(": "); writer.println(li.toString());
                 li.dump(innerPrefix, fd, writer, args);
             }
         }
@@ -497,7 +637,7 @@
             for (int i=0; i < mInactiveLoaders.size(); i++) {
                 LoaderInfo li = mInactiveLoaders.valueAt(i);
                 writer.print(prefix); writer.print("  #"); writer.print(mInactiveLoaders.keyAt(i));
-                        writer.print(": "); writer.println(li.toBasicString());
+                        writer.print(": "); writer.println(li.toString());
                 li.dump(innerPrefix, fd, writer, args);
             }
         }
diff --git a/core/java/android/app/LoaderManagingFragment.java b/core/java/android/app/LoaderManagingFragment.java
deleted file mode 100644
index f0f5856..0000000
--- a/core/java/android/app/LoaderManagingFragment.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.content.Loader;
-import android.os.Bundle;
-
-import java.util.HashMap;
-
-/**
- * A Fragment that has utility methods for managing {@link Loader}s.
- *
- * @param <D> The type of data returned by the Loader. If you're using multiple Loaders with
- * different return types use Object and case the results.
- * 
- * @deprecated This was an old design, it will be removed before Honeycomb ships.
- */
-@Deprecated
-public abstract class LoaderManagingFragment<D> extends Fragment
-        implements Loader.OnLoadCompleteListener<D> {
-    private boolean mStarted = false;
-
-    static final class LoaderInfo<D> {
-        public Bundle args;
-        public Loader<D> loader;
-    }
-    private HashMap<Integer, LoaderInfo<D>> mLoaders;
-    private HashMap<Integer, LoaderInfo<D>> mInactiveLoaders;
-
-    /**
-     * Registers a loader with this activity, registers the callbacks on it, and starts it loading.
-     * If a loader with the same id has previously been started it will automatically be destroyed
-     * when the new loader completes it's work. The callback will be delivered before the old loader
-     * is destroyed.
-     */
-    public Loader<D> startLoading(int id, Bundle args) {
-        LoaderInfo<D> info = mLoaders.get(id);
-        if (info != null) {
-            // Keep track of the previous instance of this loader so we can destroy
-            // it when the new one completes.
-            mInactiveLoaders.put(id, info);
-        }
-        info = new LoaderInfo<D>();
-        info.args = args;
-        mLoaders.put(id, info);
-        Loader<D> loader = onCreateLoader(id, args);
-        info.loader = loader;
-        if (mStarted) {
-            // The activity will start all existing loaders in it's onStart(), so only start them
-            // here if we're past that point of the activitiy's life cycle
-            loader.registerListener(id, this);
-            loader.startLoading();
-        }
-        return loader;
-    }
-
-    protected abstract Loader<D> onCreateLoader(int id, Bundle args);
-    protected abstract void onInitializeLoaders();
-    protected abstract void onLoadFinished(Loader<D> loader, D data);
-
-    public final void onLoadComplete(Loader<D> loader, D data) {
-        // Notify of the new data so the app can switch out the old data before
-        // we try to destroy it.
-        onLoadFinished(loader, data);
-
-        // Look for an inactive loader and destroy it if found
-        int id = loader.getId();
-        LoaderInfo<D> info = mInactiveLoaders.get(id);
-        if (info != null) {
-            Loader<D> oldLoader = info.loader;
-            if (oldLoader != null) {
-                oldLoader.destroy();
-            }
-            mInactiveLoaders.remove(id);
-        }
-    }
-
-    @Override
-    public void onCreate(Bundle savedState) {
-        super.onCreate(savedState);
-
-        if (mLoaders == null) {
-            // Look for a passed along loader and create a new one if it's not there
-// TODO: uncomment once getLastNonConfigurationInstance method is available
-//            mLoaders = (HashMap<Integer, LoaderInfo>) getLastNonConfigurationInstance();
-            if (mLoaders == null) {
-                mLoaders = new HashMap<Integer, LoaderInfo<D>>();
-                onInitializeLoaders();
-            }
-        }
-        if (mInactiveLoaders == null) {
-            mInactiveLoaders = new HashMap<Integer, LoaderInfo<D>>();
-        }
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-
-        // Call out to sub classes so they can start their loaders
-        // Let the existing loaders know that we want to be notified when a load is complete
-        for (HashMap.Entry<Integer, LoaderInfo<D>> entry : mLoaders.entrySet()) {
-            LoaderInfo<D> info = entry.getValue();
-            Loader<D> loader = info.loader;
-            int id = entry.getKey();
-            if (loader == null) {
-               loader = onCreateLoader(id, info.args);
-               info.loader = loader;
-            }
-            loader.registerListener(id, this);
-            loader.startLoading();
-        }
-
-        mStarted = true;
-    }
-
-    @Override
-    public void onStop() {
-        super.onStop();
-
-        for (HashMap.Entry<Integer, LoaderInfo<D>> entry : mLoaders.entrySet()) {
-            LoaderInfo<D> info = entry.getValue();
-            Loader<D> loader = info.loader;
-            if (loader == null) {
-                continue;
-            }
-
-            // Let the loader know we're done with it
-            loader.unregisterListener(this);
-
-            // The loader isn't getting passed along to the next instance so ask it to stop loading
-            if (!getActivity().isChangingConfigurations()) {
-                loader.stopLoading();
-            }
-        }
-
-        mStarted = false;
-    }
-
-    /* TO DO: This needs to be turned into a retained fragment.
-    @Override
-    public Object onRetainNonConfigurationInstance() {
-        // Pass the loader along to the next guy
-        Object result = mLoaders;
-        mLoaders = null;
-        return result;
-    }
-    **/
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-
-        if (mLoaders != null) {
-            for (HashMap.Entry<Integer, LoaderInfo<D>> entry : mLoaders.entrySet()) {
-                LoaderInfo<D> info = entry.getValue();
-                Loader<D> loader = info.loader;
-                if (loader == null) {
-                    continue;
-                }
-                loader.destroy();
-            }
-        }
-    }
-
-    /**
-     * Stops and removes the loader with the given ID.
-     */
-    public void stopLoading(int id) {
-        if (mLoaders != null) {
-            LoaderInfo<D> info = mLoaders.remove(id);
-            if (info != null) {
-                Loader<D> loader = info.loader;
-                if (loader != null) {
-                    loader.unregisterListener(this);
-                    loader.destroy();
-                }
-            }
-        }
-    }
-
-    /**
-     * @return the Loader with the given id or null if no matching Loader
-     * is found.
-     */
-    public Loader<D> getLoader(int id) {
-        LoaderInfo<D> loaderInfo = mLoaders.get(id);
-        if (loaderInfo != null) {
-            return mLoaders.get(id).loader;
-        }
-        return null;
-    }
-}
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 5da04f1..c958e1b 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -493,7 +493,7 @@
                 // We need to save the state now, if we don't currently
                 // already have it or the activity is currently resumed.
                 final Bundle childState = new Bundle();
-                r.activity.onSaveInstanceState(childState);
+                r.activity.performSaveInstanceState(childState);
                 r.instanceState = childState;
             }
             if (r.instanceState != null) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index a196792..0243b02 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -574,7 +574,15 @@
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("Notification(vibrate=");
+        sb.append("Notification(contentView=");
+        if (contentView != null) {
+            sb.append(contentView.getPackage());
+            sb.append("/0x");
+            sb.append(Integer.toHexString(contentView.getLayoutId()));
+        } else {
+            sb.append("null");
+        }
+        sb.append(" vibrate=");
         if (this.vibrate != null) {
             int N = this.vibrate.length-1;
             sb.append("[");
@@ -752,7 +760,7 @@
         }
 
         public Builder setAutoCancel(boolean autoCancel) {
-            setFlag(FLAG_ONLY_ALERT_ONCE, autoCancel);
+            setFlag(FLAG_AUTO_CANCEL, autoCancel);
             return this;
         }
 
@@ -783,8 +791,13 @@
             if (mContentInfo != null) {
                 contentView.setTextViewText(R.id.info, mContentInfo);
             } else if (mNumber > 0) {
-                NumberFormat f = NumberFormat.getIntegerInstance();
-                contentView.setTextViewText(R.id.info, f.format(mNumber));
+                if (mNumber > 100) {
+                    contentView.setTextViewText(R.id.info, mContext.getString(
+                                R.string.status_bar_notification_info_overflow));
+                } else {
+                    NumberFormat f = NumberFormat.getIntegerInstance();
+                    contentView.setTextViewText(R.id.info, f.format(mNumber));
+                }
                 contentView.setFloat(R.id.info, "setTextSize",
                         mContext.getResources().getDimensionPixelSize(
                             R.dimen.status_bar_content_number_size));
diff --git a/core/java/android/app/OnActivityPausedListener.java b/core/java/android/app/OnActivityPausedListener.java
new file mode 100644
index 0000000..379f133
--- /dev/null
+++ b/core/java/android/app/OnActivityPausedListener.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *	    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app;
+
+/**
+ * A listener that is called when an Activity is paused. Since this is tracked client side
+ * it should not be trusted to represent the exact current state, but can be used as a hint
+ * for cleanup.
+ *
+ * @hide
+ */
+public interface OnActivityPausedListener {
+    /**
+     * Called when the given activity is paused.
+     */
+    public void onPaused(Activity activity);
+}
diff --git a/core/java/android/app/ProgressDialog.java b/core/java/android/app/ProgressDialog.java
index af1b294..d421173 100644
--- a/core/java/android/app/ProgressDialog.java
+++ b/core/java/android/app/ProgressDialog.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -75,12 +74,20 @@
     
     public ProgressDialog(Context context) {
         super(context);
+        initFormats();
     }
 
     public ProgressDialog(Context context, int theme) {
         super(context, theme);
+        initFormats();
     }
 
+    private void initFormats() {
+        mProgressNumberFormat = "%1d/%2d";
+        mProgressPercentFormat = NumberFormat.getPercentInstance();
+        mProgressPercentFormat.setMaximumFractionDigits(0);
+    }
+    
     public static ProgressDialog show(Context context, CharSequence title,
             CharSequence message) {
         return show(context, title, message, false);
@@ -125,22 +132,27 @@
                     /* Update the number and percent */
                     int progress = mProgress.getProgress();
                     int max = mProgress.getMax();
-                    double percent = (double) progress / (double) max;
-                    String format = mProgressNumberFormat;
-                    mProgressNumber.setText(String.format(format, progress, max));
-                    SpannableString tmp = new SpannableString(mProgressPercentFormat.format(percent));
-                    tmp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
-                            0, tmp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-                    mProgressPercent.setText(tmp);
+                    if (mProgressNumberFormat != null) {
+                        String format = mProgressNumberFormat;
+                        mProgressNumber.setText(String.format(format, progress, max));
+                    } else {
+                        mProgressNumber.setText("");
+                    }
+                    if (mProgressPercentFormat != null) {
+                        double percent = (double) progress / (double) max;
+                        SpannableString tmp = new SpannableString(mProgressPercentFormat.format(percent));
+                        tmp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
+                                0, tmp.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                        mProgressPercent.setText(tmp);
+                    } else {
+                        mProgressPercent.setText("");
+                    }
                 }
             };
             View view = inflater.inflate(R.layout.alert_dialog_progress, null);
             mProgress = (ProgressBar) view.findViewById(R.id.progress);
             mProgressNumber = (TextView) view.findViewById(R.id.progress_number);
-            mProgressNumberFormat = "%d/%d";
             mProgressPercent = (TextView) view.findViewById(R.id.progress_percent);
-            mProgressPercentFormat = NumberFormat.getPercentInstance();
-            mProgressPercentFormat.setMaximumFractionDigits(0);
             setView(view);
         } else {
             View view = inflater.inflate(R.layout.progress_dialog, null);
@@ -304,19 +316,36 @@
     }
 
     /**
-     * Change the format of Progress Number. The default is "current/max".
+     * Change the format of the small text showing current and maximum units
+     * of progress.  The default is "%1d/%2d".
      * Should not be called during the number is progressing.
-     * @param format Should contain two "%d". The first is used for current number
-     * and the second is used for the maximum.
-     * @hide
+     * @param format A string passed to {@link String#format String.format()};
+     * use "%1d" for the current number and "%2d" for the maximum.  If null,
+     * nothing will be shown.
      */
     public void setProgressNumberFormat(String format) {
         mProgressNumberFormat = format;
+        onProgressChanged();
+    }
+
+    /**
+     * Change the format of the small text showing the percentage of progress.
+     * The default is
+     * {@link NumberFormat#getPercentInstance() NumberFormat.getPercentageInstnace().}
+     * Should not be called during the number is progressing.
+     * @param format An instance of a {@link NumberFormat} to generate the
+     * percentage text.  If null, nothing will be shown.
+     */
+    public void setProgressPercentFormat(NumberFormat format) {
+        mProgressPercentFormat = format;
+        onProgressChanged();
     }
     
     private void onProgressChanged() {
         if (mProgressStyle == STYLE_HORIZONTAL) {
-            mViewUpdateHandler.sendEmptyMessage(0);
+            if (!mViewUpdateHandler.hasMessages(0)) {
+                mViewUpdateHandler.sendEmptyMessage(0);
+            }
         }
     }
 }
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index 26af4eb..f9920c7 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
-import android.os.Build;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -72,11 +71,7 @@
     public TimePickerDialog(Context context,
             OnTimeSetListener callBack,
             int hourOfDay, int minute, boolean is24HourView) {
-        this(context,
-                context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB
-                        ? com.android.internal.R.style.Theme_Holo_Dialog_Alert
-                        : com.android.internal.R.style.Theme_Dialog_Alert,
-                callBack, hourOfDay, minute, is24HourView);
+        this(context, 0, callBack, hourOfDay, minute, is24HourView);
     }
 
     /**
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 2bb0e33..ec4ec89 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -121,6 +121,14 @@
      */
     public static final int USES_POLICY_EXPIRE_PASSWORD = 6;
 
+    /**
+     * A type of policy that this device admin can use: require encryption of stored data.
+     *
+     * <p>To control this policy, the device admin must have a "encrypted-storage"
+     * tag in the "uses-policies" section of its meta-data.
+     */
+    public static final int USES_ENCRYPTED_STORAGE = 7;
+
     /** @hide */
     public static class PolicyInfo {
         public final int ident;
@@ -162,6 +170,9 @@
         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_EXPIRE_PASSWORD, "expire-password",
                 com.android.internal.R.string.policylab_expirePassword,
                 com.android.internal.R.string.policydesc_expirePassword));
+        sPoliciesDisplayOrder.add(new PolicyInfo(USES_ENCRYPTED_STORAGE, "encrypted-storage",
+                com.android.internal.R.string.policylab_encryptedStorage,
+                com.android.internal.R.string.policydesc_encryptedStorage));
 
         for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
             PolicyInfo pi = sPoliciesDisplayOrder.get(i);
@@ -352,7 +363,8 @@
      * the given policy control.  The possible policy identifier inputs are:
      * {@link #USES_POLICY_LIMIT_PASSWORD}, {@link #USES_POLICY_WATCH_LOGIN},
      * {@link #USES_POLICY_RESET_PASSWORD}, {@link #USES_POLICY_FORCE_LOCK},
-     * {@link #USES_POLICY_WIPE_DATA}, {@link #USES_POLICY_SETS_GLOBAL_PROXY}.
+     * {@link #USES_POLICY_WIPE_DATA}, {@link #USES_POLICY_SETS_GLOBAL_PROXY},
+     * {@link #USES_POLICY_EXPIRE_PASSWORD}, {@link #USES_ENCRYPTED_STORAGE}.
      */
     public boolean usesPolicy(int policyIdent) {
         return (mUsesPolicies & (1<<policyIdent)) != 0;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 1edbdb8..4186fec 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1093,6 +1093,112 @@
     }
 
     /**
+     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryption}:
+     * indicating that encryption is not supported.
+     */
+    public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0;
+
+    /**
+     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryption}:
+     * indicating that encryption is supported, but is not currently active.
+     */
+    public static final int ENCRYPTION_STATUS_INACTIVE = 1;
+
+    /**
+     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryption}:
+     * indicating that encryption is not currently active, but has been requested.
+     */
+    public static final int ENCRYPTION_STATUS_REQUESTED = 2;
+
+    /**
+     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryption}:
+     * indicating that encryption is not currently active, but is currently
+     * being activated.  This is only reported by devices that support
+     * encryption of data and only when the storage is currently
+     * undergoing a process of becoming encrypted.  A device that must reboot and/or wipe data
+     * to become encrypted will never return this value.
+     */
+    public static final int ENCRYPTION_STATUS_ACTIVATING = 3;
+
+    /**
+     * Result code for {@link #setStorageEncryption} and {@link #getStorageEncryption}:
+     * indicating that encryption is active.
+     */
+    public static final int ENCRYPTION_STATUS_ACTIVE = 4;
+
+    /**
+     * Activity action: begin the process of encrypting data on the device.  This activity should
+     * be launched after using {@link #setStorageEncryption} to request encryption be activated.
+     * After resuming from this activity, use {@link #getStorageEncryption}
+     * to check encryption status.  However, on some devices this activity may never return, as
+     * it may trigger a reboot and in some cases a complete data wipe of the device.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_START_ENCRYPTION
+            = "android.app.action.START_ENCRYPTION";
+
+    /**
+     * Called by an application that is administering the device to
+     * request that the storage system be encrypted.  Depending
+     * on the returned status code, the caller may proceed in different
+     * ways.  If the result is {@link #ENCRYPTION_STATUS_UNSUPPORTED}, the
+     * storage system does not support encryption.  If the
+     * result is {@link #ENCRYPTION_STATUS_REQUESTED}, use {@link
+     * #ACTION_START_ENCRYPTION} to begin the process of encrypting or decrypting the
+     * storage.  If the result is {@link #ENCRYPTION_STATUS_ACTIVATING} or
+     * {@link #ENCRYPTION_STATUS_ACTIVE}, no further action is required.
+     *
+     * <p>When multiple device administrators attempt to control device
+     * encryption, the most secure, supported setting will always be
+     * used.  If any device administrator requests device encryption,
+     * it will be enabled;  Conversely, if a device administrator
+     * attempts to disable device encryption while another
+     * device administrator has enabled it, the call to disable will
+     * fail (most commonly returning {@link #ENCRYPTION_STATUS_ACTIVE}).
+     *
+     * <p>This policy controls encryption of the secure (application data) storage area.  Data
+     * written to other areas (e.g. the directory returned by
+     * {@link android.os.Environment#getExternalStorageDirectory()} may or may not be encrypted.
+     *
+     * <p>Important Note:  On some devices, it is possible to encrypt storage without requiring
+     * the user to create a device PIN or Password.  In this case, the storage is encrypted, but
+     * the encryption key may not be fully secured.  For maximum security, the administrator should
+     * also require (and check for) a pattern, PIN, or password.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param encrypt true to request encryption, false to release any previous request
+     * @return current status of encryption
+     */
+    public int setStorageEncryption(ComponentName admin, boolean encrypt) {
+        if (mService != null) {
+            try {
+                return mService.setStorageEncryption(admin, encrypt);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return ENCRYPTION_STATUS_UNSUPPORTED;
+    }
+
+    /**
+     * Called by an application that is administering the device to
+     * determine the encryption status of a specific storage system.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @return current status of encryption
+     */
+    public int getStorageEncryption(ComponentName admin) {
+        if (mService != null) {
+            try {
+                return mService.getStorageEncryption(admin);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return ENCRYPTION_STATUS_UNSUPPORTED;
+    }
+
+    /**
      * @hide
      */
     public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7504f5b..d3b5cf3 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -74,7 +74,10 @@
 
     ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList);
     ComponentName getGlobalProxyAdmin();
-    
+
+    int setStorageEncryption(in ComponentName who, boolean encrypt);
+    int getStorageEncryption(in ComponentName who);
+
     void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing);
     boolean isAdminActive(in ComponentName policyReceiver);
     List<ComponentName> getActiveAdmins();
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 7730942..9835484 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -214,6 +214,10 @@
         }
     }
 
+    /**
+     * 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 @@
             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/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 32df4e8..b2185ad 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -868,6 +868,42 @@
      */
     public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
             throws IOException {
+        return createNewRfcommSocketAndRecord(name, uuid, true, true);
+    }
+
+    /**
+     * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
+     * <p>The link key will be unauthenticated i.e the communication is
+     * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices,
+     * the link key will be encrypted, as encryption is mandartory.
+     * For legacy devices (pre Bluetooth 2.1 devices) the link key will not
+     * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
+     * encrypted and authenticated communication channel is desired.
+     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
+     * connections from a listening {@link BluetoothServerSocket}.
+     * <p>The system will assign an unused RFCOMM channel to listen on.
+     * <p>The system will also register a Service Discovery
+     * Protocol (SDP) record with the local SDP server containing the specified
+     * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
+     * can use the same UUID to query our SDP server and discover which channel
+     * to connect to. This SDP record will be removed when this socket is
+     * closed, or if this application closes unexpectedly.
+     * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
+     * connect to this socket from another device using the same {@link UUID}.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
+     * @param name service name for SDP record
+     * @param uuid uuid for SDP record
+     * @return a listening RFCOMM BluetoothServerSocket
+     * @throws IOException on error, for example Bluetooth not available, or
+     *                     insufficient permissions, or channel in use.
+     */
+    public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
+            throws IOException {
+        return createNewRfcommSocketAndRecord(name, uuid, false, false);
+    }
+
+    private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
+            boolean auth, boolean encrypt) throws IOException {
         RfcommChannelPicker picker = new RfcommChannelPicker(uuid);
 
         BluetoothServerSocket socket;
@@ -881,7 +917,7 @@
             }
 
             socket = new BluetoothServerSocket(
-                    BluetoothSocket.TYPE_RFCOMM, true, true, channel);
+                    BluetoothSocket.TYPE_RFCOMM, auth, encrypt, channel);
             errno = socket.mSocket.bindListen();
             if (errno == 0) {
                 if (DBG) Log.d(TAG, "listening on RFCOMM channel " + channel);
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
index e604e6b..54bf4af 100644
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ b/core/java/android/bluetooth/BluetoothClass.java
@@ -226,6 +226,24 @@
         public static final int HEALTH_PULSE_OXIMETER               = 0x0914;
         public static final int HEALTH_PULSE_RATE                   = 0x0918;
         public static final int HEALTH_DATA_DISPLAY                 = 0x091C;
+
+        // Devices in PERIPHERAL major class
+        /**
+         * @hide
+         */
+        public static final int PERIPHERAL_NON_KEYBOARD_NON_POINTING = 0x0500;
+        /**
+         * @hide
+         */
+        public static final int PERIPHERAL_KEYBOARD                  = 0x0540;
+        /**
+         * @hide
+         */
+        public static final int PERIPHERAL_POINTING                  = 0x0580;
+        /**
+         * @hide
+         */
+        public static final int PERIPHERAL_KEYBOARD_POINTING         = 0x05C0;
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index ada3c24..24217d7 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -239,7 +239,7 @@
     public static final String EXTRA_PAIRING_VARIANT =
             "android.bluetooth.device.extra.PAIRING_VARIANT";
     /** @hide */
-    public static final String EXTRA_PASSKEY = "android.bluetooth.device.extra.PASSKEY";
+    public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY";
 
     /**
      * Broadcast Action: This intent is used to broadcast the {@link UUID}
@@ -276,58 +276,113 @@
     public static final String ACTION_PAIRING_CANCEL =
             "android.bluetooth.device.action.PAIRING_CANCEL";
 
-    /** A bond attempt succeeded
-     * @hide */
+    /**
+     * A bond attempt succeeded
+     * @hide
+     */
     public static final int BOND_SUCCESS = 0;
-    /** A bond attempt failed because pins did not match, or remote device did
+
+    /**
+     * A bond attempt failed because pins did not match, or remote device did
      * not respond to pin request in time
-     * @hide */
+     * @hide
+     */
     public static final int UNBOND_REASON_AUTH_FAILED = 1;
-    /** A bond attempt failed because the other side explicitly rejected
+
+    /**
+     * A bond attempt failed because the other side explicitly rejected
      * bonding
-     * @hide */
+     * @hide
+     */
     public static final int UNBOND_REASON_AUTH_REJECTED = 2;
-    /** A bond attempt failed because we canceled the bonding process
-     * @hide */
+
+    /**
+     * A bond attempt failed because we canceled the bonding process
+     * @hide
+     */
     public static final int UNBOND_REASON_AUTH_CANCELED = 3;
-    /** A bond attempt failed because we could not contact the remote device
-     * @hide */
+
+    /**
+     * A bond attempt failed because we could not contact the remote device
+     * @hide
+     */
     public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4;
-    /** A bond attempt failed because a discovery is in progress
-     * @hide */
+
+    /**
+     * A bond attempt failed because a discovery is in progress
+     * @hide
+     */
     public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5;
-    /** A bond attempt failed because of authentication timeout
-     * @hide */
+
+    /**
+     * A bond attempt failed because of authentication timeout
+     * @hide
+     */
     public static final int UNBOND_REASON_AUTH_TIMEOUT = 6;
-    /** A bond attempt failed because of repeated attempts
-     * @hide */
+
+    /**
+     * A bond attempt failed because of repeated attempts
+     * @hide
+     */
     public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7;
-    /** A bond attempt failed because we received an Authentication Cancel
-     *  by remote end
-     * @hide */
+
+    /**
+     * A bond attempt failed because we received an Authentication Cancel
+     * by remote end
+     * @hide
+     */
     public static final int UNBOND_REASON_REMOTE_AUTH_CANCELED = 8;
-    /** An existing bond was explicitly revoked
-     * @hide */
+
+    /**
+     * An existing bond was explicitly revoked
+     * @hide
+     */
     public static final int UNBOND_REASON_REMOVED = 9;
 
-    /** The user will be prompted to enter a pin
-     * @hide */
+    /**
+     * The user will be prompted to enter a pin
+     * @hide
+     */
     public static final int PAIRING_VARIANT_PIN = 0;
-    /** The user will be prompted to enter a passkey
-     * @hide */
+
+    /**
+     * The user will be prompted to enter a passkey
+     * @hide
+     */
     public static final int PAIRING_VARIANT_PASSKEY = 1;
-    /** The user will be prompted to confirm the passkey displayed on the screen
-     * @hide */
+
+    /**
+     * The user will be prompted to confirm the passkey displayed on the screen
+     * @hide
+     */
     public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2;
-    /** The user will be prompted to accept or deny the incoming pairing request
-     * @hide */
+
+    /**
+     * The user will be prompted to accept or deny the incoming pairing request
+     * @hide
+     */
     public static final int PAIRING_VARIANT_CONSENT = 3;
-    /** The user will be prompted to enter the passkey displayed on remote device
-     * @hide */
+
+    /**
+     * The user will be prompted to enter the passkey displayed on remote device
+     * This is used for Bluetooth 2.1 pairing.
+     * @hide
+     */
     public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4;
-    /** The user will be prompted to accept or deny the OOB pairing request
-     * @hide */
-    public static final int PAIRING_VARIANT_OOB_CONSENT = 5;
+
+    /**
+     * The user will be prompted to enter the PIN displayed on remote device.
+     * This is used for Bluetooth 2.0 pairing.
+     * @hide
+     */
+    public static final int PAIRING_VARIANT_DISPLAY_PIN = 5;
+
+    /**
+     * The user will be prompted to accept or deny the OOB pairing request
+     * @hide
+     */
+    public static final int PAIRING_VARIANT_OOB_CONSENT = 6;
+
     /**
      * Used as an extra field in {@link #ACTION_UUID} intents,
      * Contains the {@link android.os.ParcelUuid}s of the remote device which
@@ -737,6 +792,39 @@
     }
 
     /**
+     * Create an RFCOMM {@link BluetoothSocket} socket ready to start an insecure
+     * outgoing connection to this remote device using SDP lookup of uuid.
+     * <p> The communication channel will not have an authenticated link key
+     * i.e it will be subject to man-in-the-middle attacks. For Bluetooth 2.1
+     * devices, the link key will be encrypted, as encryption is mandatory.
+     * For legacy devices (pre Bluetooth 2.1 devices) the link key will
+     * be not be encrypted. Use {@link #createRfcommSocketToServiceRecord} if an
+     * encrypted and authenticated communication channel is desired.
+     * <p>This is designed to be used with {@link
+     * BluetoothAdapter#listenUsingInsecureRfcommWithServiceRecord} for peer-peer
+     * Bluetooth applications.
+     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
+     * connection. This will also perform an SDP lookup of the given uuid to
+     * determine which channel to connect to.
+     * <p>The remote device will be authenticated and communication on this
+     * socket will be encrypted.
+     * <p>Hint: If you are connecting to a Bluetooth serial board then try
+     * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB.
+     * However if you are connecting to an Android peer then please generate
+     * your own unique UUID.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
+     *
+     * @param uuid service record uuid to lookup RFCOMM channel
+     * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
+     * @throws IOException on error, for example Bluetooth not available, or
+     *                     insufficient permissions
+     */
+    public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException {
+        return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, -1,
+                new ParcelUuid(uuid));
+    }
+
+    /**
      * Construct an insecure RFCOMM socket ready to start an outgoing
      * connection.
      * Call #connect on the returned #BluetoothSocket to begin the connection.
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index 80a80bd..3280d39 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -102,7 +102,6 @@
     private BluetoothDevice mDevice;
     private int mHeadsetState = BluetoothProfile.STATE_DISCONNECTED;
     private int mA2dpState = BluetoothProfile.STATE_DISCONNECTED;
-    private int mHidState = BluetoothProfile.STATE_DISCONNECTED;
 
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -140,7 +139,7 @@
                 int newState = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, 0);
                 int oldState =
                     intent.getIntExtra(BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, 0);
-                mHidState = newState;
+
                 if (oldState == BluetoothInputDevice.STATE_CONNECTED &&
                     newState == BluetoothInputDevice.STATE_DISCONNECTED) {
                     sendMessage(DISCONNECT_HID_INCOMING);
@@ -149,10 +148,6 @@
                     newState == BluetoothInputDevice.STATE_DISCONNECTED) {
                     sendMessage(TRANSITION_TO_STABLE);
                 }
-            } else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
-                Message msg = new Message();
-                msg.what = AUTO_CONNECT_PROFILES;
-                sendMessage(msg);
             } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
                 // This is technically not needed, but we can get stuck sometimes.
                 // For example, if incoming A2DP fails, we are not informed by Bluez
@@ -290,7 +285,8 @@
                         sendMessage(DISCONNECT_A2DP_OUTGOING);
                         deferMessage(message);
                         break;
-                    } else if (mHidState != BluetoothInputDevice.STATE_DISCONNECTED) {
+                    } else if (mService.getInputDeviceState(mDevice) !=
+                            BluetoothInputDevice.STATE_DISCONNECTED) {
                         sendMessage(DISCONNECT_HID_OUTGOING);
                         deferMessage(message);
                         break;
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index f55e96a..7dee25e 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -34,21 +34,31 @@
     private static final String TAG = "BluetoothPan";
     private static final boolean DBG = false;
 
+    //TODO: This needs to inherit from BluetoothProfile like other profiles.
+
     /** int extra for ACTION_PAN_STATE_CHANGED */
-    public static final String EXTRA_PAN_STATE =
-        "android.bluetooth.pan.extra.STATE";
+    public static final String EXTRA_PAN_STATE = "android.bluetooth.pan.extra.STATE";
+
     /** int extra for ACTION_PAN_STATE_CHANGED */
     public static final String EXTRA_PREVIOUS_PAN_STATE =
         "android.bluetooth.pan.extra.PREVIOUS_STATE";
 
-    /** Indicates the state of an PAN device has changed.
+    /** int extra for ACTION_PAN_STATE_CHANGED */
+    public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
+
+    public static final int LOCAL_NAP_ROLE = 1;
+    public static final int LOCAL_PANU_ROLE = 2;
+
+    /**
+     * Indicates the state of an PAN device has changed.
      * This intent will always contain EXTRA_DEVICE_STATE,
-     * EXTRA_PREVIOUS_DEVICE_STATE and BluetoothDevice.EXTRA_DEVICE
+     * EXTRA_PREVIOUS_DEVICE_STATE, BluetoothDevice.EXTRA_DEVICE
+     * and EXTRA_LOCAL_ROLE.
      * extras.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PAN_STATE_CHANGED =
-        "android.bluetooth.pan.action.STATE_CHANGED";
+      "android.bluetooth.pan.action.STATE_CHANGED";
 
     public static final String NAP_ROLE = "nap";
     public static final String NAP_BRIDGE = "pan1";
@@ -130,40 +140,42 @@
         }
     }
 
-    /** Get the state of a PAN Device.
-    *
-    * This function returns an int representing the state of the PAN connection
-    *
-    *  @param device Remote BT device.
-    *  @return The current state of the PAN Device
-    *  @hide
-    */
-   public int getPanDeviceState(BluetoothDevice device) {
-       if (DBG) log("getPanDeviceState(" + device + ")");
+    /**
+     * Get the state of a PAN Device.
+     *
+     * This function returns an int representing the state of the PAN connection
+     *
+     *  @param device Remote BT device.
+     *  @return The current state of the PAN Device
+     *  @hide
+     */
+    public int getPanDeviceState(BluetoothDevice device) {
+        if (DBG) log("getPanDeviceState(" + device + ")");
+        try {
+            return mService.getPanDeviceState(device);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+            return STATE_DISCONNECTED;
+        }
+    }
+
+    /**
+     * Returns a set of all the connected PAN Devices
+     *
+     * Does not include devices that are currently connecting or disconnecting
+     *
+     *  @return List of PAN devices or empty on Error
+     * @hide
+     */
+    public List<BluetoothDevice> getConnectedDevices() {
+       if (DBG) log("getConnectedDevices");
        try {
-           return mService.getPanDeviceState(device);
+           return mService.getConnectedPanDevices();
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
-           return STATE_DISCONNECTED;
+           return new ArrayList<BluetoothDevice>();
        }
-   }
-
-   /** Returns a set of all the connected PAN Devices
-   *
-   * Does not include devices that are currently connecting or disconnecting
-   *
-   * @return List of PAN devices or empty on Error
-   * @hide
-   */
-   public List<BluetoothDevice> getConnectedDevices() {
-      if (DBG) log("getConnectedDevices");
-      try {
-          return mService.getConnectedPanDevices();
-      } catch (RemoteException e) {
-          Log.e(TAG, "", e);
-          return new ArrayList<BluetoothDevice>();
-      }
-   }
+    }
 
     private static void log(String msg) {
         Log.d(TAG, msg);
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
new file mode 100644
index 0000000..7b083f1
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.DhcpInfo;
+import android.net.LinkAddress;
+import android.net.LinkCapabilities;
+import android.net.LinkProperties;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkStateTracker;
+import android.net.NetworkUtils;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import java.net.InetAddress;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class tracks the data connection associated with Bluetooth
+ * reverse tethering. This is a singleton class and an instance will be
+ * created by ConnectivityService. BluetoothService will call into this
+ * when a reverse tethered connection needs to be activated.
+ *
+ * @hide
+ */
+public class BluetoothTetheringDataTracker implements NetworkStateTracker {
+    private static final String NETWORKTYPE = "BLUETOOTH_TETHER";
+    private static final String TAG = "BluetoothTethering";
+
+    private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
+    private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
+    private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
+    private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
+
+    private LinkProperties mLinkProperties;
+    private LinkCapabilities mLinkCapabilities;
+    private NetworkInfo mNetworkInfo;
+
+    private BluetoothPan mBluetoothPan;
+    private BluetoothDevice mDevice;
+    private static String mIface;
+
+    /* For sending events to connectivity service handler */
+    private Handler mCsHandler;
+    private Context mContext;
+    public static BluetoothTetheringDataTracker sInstance;
+
+    private BluetoothTetheringDataTracker() {
+        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORKTYPE, "");
+        mLinkProperties = new LinkProperties();
+        mLinkCapabilities = new LinkCapabilities();
+
+        mNetworkInfo.setIsAvailable(false);
+        setTeardownRequested(false);
+    }
+
+    public static synchronized BluetoothTetheringDataTracker getInstance() {
+        if (sInstance == null) sInstance = new BluetoothTetheringDataTracker();
+        return sInstance;
+    }
+
+    public Object Clone() throws CloneNotSupportedException {
+        throw new CloneNotSupportedException();
+    }
+
+    public void setTeardownRequested(boolean isRequested) {
+        mTeardownRequested.set(isRequested);
+    }
+
+    public boolean isTeardownRequested() {
+        return mTeardownRequested.get();
+    }
+
+    /**
+     * Begin monitoring connectivity
+     */
+    public void startMonitoring(Context context, Handler target) {
+        mContext = context;
+        mCsHandler = target;
+        mBluetoothPan = new BluetoothPan(mContext);
+    }
+
+    /**
+     * Disable connectivity to a network
+     * TODO: do away with return value after making MobileDataStateTracker async
+     */
+    public boolean teardown() {
+        mTeardownRequested.set(true);
+        for (BluetoothDevice device: mBluetoothPan.getConnectedDevices()) {
+            mBluetoothPan.disconnect(device);
+        }
+        return true;
+    }
+
+    /**
+     * Re-enable connectivity to a network after a {@link #teardown()}.
+     */
+    public boolean reconnect() {
+        mTeardownRequested.set(false);
+        //Ignore
+        return true;
+    }
+
+    /**
+     * Turn the wireless radio off for a network.
+     * @param turnOn {@code true} to turn the radio on, {@code false}
+     */
+    public boolean setRadio(boolean turnOn) {
+        return true;
+    }
+
+    /**
+     * @return true - If are we currently tethered with another device.
+     */
+    public synchronized boolean isAvailable() {
+        return mNetworkInfo.isAvailable();
+    }
+
+    /**
+     * Tells the underlying networking system that the caller wants to
+     * begin using the named feature. The interpretation of {@code feature}
+     * is completely up to each networking implementation.
+     * @param feature the name of the feature to be used
+     * @param callingPid the process ID of the process that is issuing this request
+     * @param callingUid the user ID of the process that is issuing this request
+     * @return an integer value representing the outcome of the request.
+     * The interpretation of this value is specific to each networking
+     * implementation+feature combination, except that the value {@code -1}
+     * always indicates failure.
+     * TODO: needs to go away
+     */
+    public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
+        return -1;
+    }
+
+    /**
+     * Tells the underlying networking system that the caller is finished
+     * using the named feature. The interpretation of {@code feature}
+     * is completely up to each networking implementation.
+     * @param feature the name of the feature that is no longer needed.
+     * @param callingPid the process ID of the process that is issuing this request
+     * @param callingUid the user ID of the process that is issuing this request
+     * @return an integer value representing the outcome of the request.
+     * The interpretation of this value is specific to each networking
+     * implementation+feature combination, except that the value {@code -1}
+     * always indicates failure.
+     * TODO: needs to go away
+     */
+    public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
+        return -1;
+    }
+
+    /**
+     * @param enabled
+     */
+    public void setDataEnable(boolean enabled) {
+        android.util.Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled);
+    }
+
+    /**
+     * Check if private DNS route is set for the network
+     */
+    public boolean isPrivateDnsRouteSet() {
+        return mPrivateDnsRouteSet.get();
+    }
+
+    /**
+     * Set a flag indicating private DNS route is set
+     */
+    public void privateDnsRouteSet(boolean enabled) {
+        mPrivateDnsRouteSet.set(enabled);
+    }
+
+    /**
+     * Fetch NetworkInfo for the network
+     */
+    public synchronized NetworkInfo getNetworkInfo() {
+        return mNetworkInfo;
+    }
+
+    /**
+     * Fetch LinkProperties for the network
+     */
+    public synchronized LinkProperties getLinkProperties() {
+        return new LinkProperties(mLinkProperties);
+    }
+
+   /**
+     * A capability is an Integer/String pair, the capabilities
+     * are defined in the class LinkSocket#Key.
+     *
+     * @return a copy of this connections capabilities, may be empty but never null.
+     */
+    public LinkCapabilities getLinkCapabilities() {
+        return new LinkCapabilities(mLinkCapabilities);
+    }
+
+    /**
+     * Fetch default gateway address for the network
+     */
+    public int getDefaultGatewayAddr() {
+        return mDefaultGatewayAddr.get();
+    }
+
+    /**
+     * Check if default route is set
+     */
+    public boolean isDefaultRouteSet() {
+        return mDefaultRouteSet.get();
+    }
+
+    /**
+     * Set a flag indicating default route is set for the network
+     */
+    public void defaultRouteSet(boolean enabled) {
+        mDefaultRouteSet.set(enabled);
+    }
+
+    /**
+     * Return the system properties name associated with the tcp buffer sizes
+     * for this network.
+     */
+    public String getTcpBufferSizesPropName() {
+        return "net.tcp.buffersize.wifi";
+    }
+
+
+    public synchronized void startReverseTether(String iface, BluetoothDevice device) {
+        mIface = iface;
+        mDevice = device;
+        Thread dhcpThread = new Thread(new Runnable() {
+            public void run() {
+                //TODO(): Add callbacks for failure and success case.
+                //Currently this thread runs independently.
+                DhcpInfo dhcpInfo = new DhcpInfo();
+                if (!NetworkUtils.runDhcp(mIface, dhcpInfo)) {
+                    Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
+                    return;
+                }
+                mLinkProperties.addLinkAddress(new LinkAddress(
+                    NetworkUtils.intToInetAddress(dhcpInfo.ipAddress),
+                    NetworkUtils.intToInetAddress(dhcpInfo.netmask)));
+                mLinkProperties.setGateway(NetworkUtils.intToInetAddress(dhcpInfo.gateway));
+                InetAddress dns1Addr = NetworkUtils.intToInetAddress(dhcpInfo.dns1);
+                if (dns1Addr == null || dns1Addr.equals("0.0.0.0")) {
+                    mLinkProperties.addDns(dns1Addr);
+                }
+                InetAddress dns2Addr = NetworkUtils.intToInetAddress(dhcpInfo.dns2);
+                if (dns2Addr == null || dns2Addr.equals("0.0.0.0")) {
+                    mLinkProperties.addDns(dns2Addr);
+                }
+                mLinkProperties.setInterfaceName(mIface);
+
+                mNetworkInfo.setIsAvailable(true);
+                mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+
+                Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
+                msg.sendToTarget();
+
+                msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+                msg.sendToTarget();
+            }
+        });
+        dhcpThread.start();
+    }
+
+    public synchronized void stopReverseTether(String iface) {
+        NetworkUtils.stopDhcp(iface);
+
+        mLinkProperties.clear();
+        mNetworkInfo.setIsAvailable(false);
+        mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
+
+        Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
+        msg.sendToTarget();
+
+        msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+        msg.sendToTarget();
+    }
+}
diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java
index b19c072..c6b9e80 100644
--- a/core/java/android/content/AsyncTaskLoader.java
+++ b/core/java/android/content/AsyncTaskLoader.java
@@ -17,6 +17,14 @@
 package android.content;
 
 import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.TimeUtils;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.concurrent.CountDownLatch;
 
 /**
  * Abstract Loader that provides an {@link AsyncTask} to do the work.
@@ -24,60 +32,134 @@
  * @param <D> the data type to be loaded.
  */
 public abstract class AsyncTaskLoader<D> extends Loader<D> {
-    final class LoadTask extends AsyncTask<Void, Void, D> {
+    static final String TAG = "AsyncTaskLoader";
+    static final boolean DEBUG = false;
 
-        private D result;
+    final class LoadTask extends AsyncTask<Void, Void, D> implements Runnable {
+
+        D result;
+        boolean waiting;
+
+        private CountDownLatch done = new CountDownLatch(1);
 
         /* Runs on a worker thread */
         @Override
         protected D doInBackground(Void... params) {
-            result = AsyncTaskLoader.this.loadInBackground();
+            if (DEBUG) Slog.v(TAG, this + " >>> doInBackground");
+            result = AsyncTaskLoader.this.onLoadInBackground();
+            if (DEBUG) Slog.v(TAG, this + "  <<< doInBackground");
             return result;
         }
 
         /* Runs on the UI thread */
         @Override
         protected void onPostExecute(D data) {
-            AsyncTaskLoader.this.dispatchOnLoadComplete(data);
+            if (DEBUG) Slog.v(TAG, this + " onPostExecute");
+            try {
+                AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
+            } finally {
+                done.countDown();
+            }
         }
 
         @Override
         protected void onCancelled() {
-            AsyncTaskLoader.this.onCancelled(result);
+            if (DEBUG) Slog.v(TAG, this + " onCancelled");
+            try {
+                AsyncTaskLoader.this.dispatchOnCancelled(this, result);
+            } finally {
+                done.countDown();
+            }
+        }
+
+        @Override
+        public void run() {
+            waiting = false;
+            AsyncTaskLoader.this.executePendingTask();
         }
     }
 
-    LoadTask mTask;
+    volatile LoadTask mTask;
+    volatile LoadTask mCancellingTask;
+
+    long mUpdateThrottle;
+    long mLastLoadCompleteTime = -10000;
+    Handler mHandler;
 
     public AsyncTaskLoader(Context context) {
         super(context);
     }
 
     /**
-     * Force an asynchronous load. Unlike {@link #startLoading()} this will ignore a previously
-     * loaded data set and load a new one.
+     * Set amount to throttle updates by.  This is the minimum time from
+     * when the last {@link #onLoadInBackground()} call has completed until
+     * a new load is scheduled.
+     *
+     * @param delayMS Amount of delay, in milliseconds.
      */
+    public void setUpdateThrottle(long delayMS) {
+        mUpdateThrottle = delayMS;
+        if (delayMS != 0) {
+            mHandler = new Handler();
+        }
+    }
+
     @Override
-    public void forceLoad() {
+    protected void onForceLoad() {
+        super.onForceLoad();
         cancelLoad();
         mTask = new LoadTask();
-        mTask.execute((Void[]) null);
+        if (DEBUG) Slog.v(TAG, "Preparing load: mTask=" + mTask);
+        executePendingTask();
     }
 
     /**
      * Attempt to cancel the current load task. See {@link AsyncTask#cancel(boolean)}
-     * for more info.
+     * for more info.  Must be called on the main thread of the process.
      *
-     * @return <tt>false</tt> if the task could not be canceled,
+     * <p>Cancelling is not an immediate operation, since the load is performed
+     * in a background thread.  If there is currently a load in progress, this
+     * method requests that the load be cancelled, and notes this is the case;
+     * once the background thread has completed its work its remaining state
+     * will be cleared.  If another load request comes in during this time,
+     * it will be held until the cancelled load is complete.
+     *
+     * @return Returns <tt>false</tt> if the task could not be cancelled,
      *         typically because it has already completed normally, or
-     *         because {@link #startLoading()} hasn't been called, and
-     *         <tt>true</tt> otherwise
+     *         because {@link #startLoading()} hasn't been called; returns
+     *         <tt>true</tt> otherwise.
      */
     public boolean cancelLoad() {
+        if (DEBUG) Slog.v(TAG, "cancelLoad: mTask=" + mTask);
         if (mTask != null) {
-            boolean cancelled = mTask.cancel(false);
-            mTask = null;
-            return cancelled;
+            if (mCancellingTask != null) {
+                // There was a pending task already waiting for a previous
+                // one being canceled; just drop it.
+                if (DEBUG) Slog.v(TAG,
+                        "cancelLoad: still waiting for cancelled task; dropping next");
+                if (mTask.waiting) {
+                    mTask.waiting = false;
+                    mHandler.removeCallbacks(mTask);
+                }
+                mTask = null;
+                return false;
+            } else if (mTask.waiting) {
+                // There is a task, but it is waiting for the time it should
+                // execute.  We can just toss it.
+                if (DEBUG) Slog.v(TAG, "cancelLoad: task is waiting, dropping it");
+                mTask.waiting = false;
+                mHandler.removeCallbacks(mTask);
+                mTask = null;
+                return false;
+            } else {
+                boolean cancelled = mTask.cancel(false);
+                if (DEBUG) Slog.v(TAG, "cancelLoad: cancelled=" + cancelled);
+                if (cancelled) {
+                    mCancellingTask = mTask;
+                }
+                mTask = null;
+                return cancelled;
+            }
         }
         return false;
     }
@@ -89,19 +171,105 @@
     public void onCancelled(D data) {
     }
 
-    void dispatchOnLoadComplete(D data) {
-        mTask = null;
-        deliverResult(data);
+    void executePendingTask() {
+        if (mCancellingTask == null && mTask != null) {
+            if (mTask.waiting) {
+                mTask.waiting = false;
+                mHandler.removeCallbacks(mTask);
+            }
+            if (mUpdateThrottle > 0) {
+                long now = SystemClock.uptimeMillis();
+                if (now < (mLastLoadCompleteTime+mUpdateThrottle)) {
+                    // Not yet time to do another load.
+                    if (DEBUG) Slog.v(TAG, "Waiting until "
+                            + (mLastLoadCompleteTime+mUpdateThrottle)
+                            + " to execute: " + mTask);
+                    mTask.waiting = true;
+                    mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle);
+                    return;
+                }
+            }
+            if (DEBUG) Slog.v(TAG, "Executing: " + mTask);
+            mTask.execute((Void[]) null);
+        }
+    }
+
+    void dispatchOnCancelled(LoadTask task, D data) {
+        onCancelled(data);
+        if (mCancellingTask == task) {
+            if (DEBUG) Slog.v(TAG, "Cancelled task is now canceled!");
+            mLastLoadCompleteTime = SystemClock.uptimeMillis();
+            mCancellingTask = null;
+            executePendingTask();
+        }
+    }
+
+    void dispatchOnLoadComplete(LoadTask task, D data) {
+        if (mTask != task) {
+            if (DEBUG) Slog.v(TAG, "Load complete of old task, trying to cancel");
+            dispatchOnCancelled(task, data);
+        } else {
+            mLastLoadCompleteTime = SystemClock.uptimeMillis();
+            mTask = null;
+            if (DEBUG) Slog.v(TAG, "Delivering result");
+            deliverResult(data);
+        }
     }
 
     /**
-     * Called on a worker thread to perform the actual load. Implementations should not deliver the
-     * results directly, but should return them from this method, which will eventually end up
-     * calling deliverResult on the UI thread. If implementations need to process
-     * the results on the UI thread they may override deliverResult and do so
-     * there.
-     *
-     * @return the result of the load
      */
     public abstract D loadInBackground();
+
+    /**
+     * Called on a worker thread to perform the actual load. Implementations should not deliver the
+     * result directly, but should return them from this method, which will eventually end up
+     * calling {@link #deliverResult} on the UI thread. If implementations need to process
+     * the results on the UI thread they may override {@link #deliverResult} and do so
+     * there.
+     *
+     * @return Implementations must return the result of their load operation.
+     */
+    protected D onLoadInBackground() {
+        return loadInBackground();
+    }
+
+    /**
+     * Locks the current thread until the loader completes the current load
+     * operation. Returns immediately if there is no load operation running.
+     * Should not be called from the UI thread: calling it from the UI
+     * thread would cause a deadlock.
+     * <p>
+     * Use for testing only.  <b>Never</b> call this from a UI thread.
+     */
+    public void waitForLoader() {
+        LoadTask task = mTask;
+        if (task != null) {
+            try {
+                task.done.await();
+            } catch (InterruptedException e) {
+                // Ignore
+            }
+        }
+    }
+
+    @Override
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        super.dump(prefix, fd, writer, args);
+        if (mTask != null) {
+            writer.print(prefix); writer.print("mTask="); writer.print(mTask);
+                    writer.print(" waiting="); writer.println(mTask.waiting);
+        }
+        if (mCancellingTask != null) {
+            writer.print(prefix); writer.print("mCancellingTask="); writer.print(mCancellingTask);
+                    writer.print(" waiting="); writer.println(mCancellingTask.waiting);
+        }
+        if (mUpdateThrottle != 0) {
+            writer.print(prefix); writer.print("mUpdateThrottle=");
+                    TimeUtils.formatDuration(mUpdateThrottle, writer);
+                    writer.print(" mLastLoadCompleteTime=");
+                    TimeUtils.formatDuration(mLastLoadCompleteTime,
+                            SystemClock.uptimeMillis(), writer);
+                    writer.println();
+        }
+    }
 }
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 6bb32c1..5467a30 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -247,11 +247,8 @@
             return ContentProvider.this.openAssetFile(uri, mode);
         }
 
-        /**
-         * @hide
-         */
-        public Bundle call(String method, String request, Bundle args) {
-            return ContentProvider.this.call(method, request, args);
+        public Bundle call(String method, String arg, Bundle extras) {
+            return ContentProvider.this.call(method, arg, extras);
         }
 
         @Override
@@ -987,16 +984,17 @@
     }
 
     /**
-     * @hide -- until interface has proven itself
-     *
      * Call a provider-defined method.  This can be used to implement
-     * interfaces that are cheaper than using a Cursor.
+     * interfaces that are cheaper and/or unnatural for a table-like
+     * model.
      *
-     * @param method Method name to call.  Opaque to framework.
-     * @param request Nullable String argument passed to method.
-     * @param args Nullable Bundle argument passed to method.
+     * @param method method name to call.  Opaque to framework, but should not be null.
+     * @param arg provider-defined String argument.  May be null.
+     * @param extras provider-defined Bundle argument.  May be null.
+     * @return provider-defined return value.  May be null.  Null is also
+     *   the default for providers which don't implement any call methods.
      */
-    public Bundle call(String method, String request, Bundle args) {
+    public Bundle call(String method, String arg, Bundle extras) {
         return null;
     }
 
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index da1aac4..2d03e7c 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -201,6 +201,7 @@
             } catch (RemoteException e) {
                 return null;
             } catch (java.lang.Exception e) {
+                Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
                 return null;
             } finally {
                 releaseProvider(provider);
@@ -215,6 +216,11 @@
             String type = ActivityManagerNative.getDefault().getProviderMimeType(url);
             return type;
         } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
+            return null;
+        } catch (java.lang.Exception e) {
+            Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
             return null;
         }
     }
@@ -245,10 +251,12 @@
         try {
             return provider.getStreamTypes(url, mimeTypeFilter);
         } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return null;
         } finally {
-			releaseProvider(provider);
-		}
+            releaseProvider(provider);
+        }
     }
 
     /**
@@ -304,8 +312,11 @@
             return new CursorWrapperInner(qCursor, provider);
         } catch (RemoteException e) {
             releaseProvider(provider);
+
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return null;
-        } catch(RuntimeException e) {
+        } catch (RuntimeException e) {
             releaseProvider(provider);
             throw e;
         }
@@ -535,6 +546,8 @@
                     return new AssetFileDescriptor(pfd, fd.getStartOffset(),
                             fd.getDeclaredLength());
                 } catch (RemoteException e) {
+                    // Somewhat pointless, as Activity Manager will kill this
+                    // process shortly anyway if the depdendent ContentProvider dies.
                     throw new FileNotFoundException("Dead content provider: " + uri);
                 } catch (FileNotFoundException e) {
                     throw e;
@@ -710,6 +723,8 @@
             maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
             return createdRow;
         } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return null;
         } finally {
             releaseProvider(provider);
@@ -769,6 +784,8 @@
             maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
             return rowsCreated;
         } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return 0;
         } finally {
             releaseProvider(provider);
@@ -798,6 +815,8 @@
             maybeLogUpdateToEventLog(durationMillis, url, "delete", where);
             return rowsDeleted;
         } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return -1;
         } finally {
             releaseProvider(provider);
@@ -814,7 +833,7 @@
                      A null value will remove an existing field value.
      * @param where A filter to apply to rows before updating, formatted as an SQL WHERE clause
                     (excluding the WHERE itself).
-     * @return The number of rows updated.
+     * @return the number of rows updated.
      * @throws NullPointerException if uri or values are null
      */
     public final int update(Uri uri, ContentValues values, String where,
@@ -830,6 +849,8 @@
             maybeLogUpdateToEventLog(durationMillis, uri, "update", where);
             return rowsUpdated;
         } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
             return -1;
         } finally {
             releaseProvider(provider);
@@ -837,6 +858,42 @@
     }
 
     /**
+     * Call an provider-defined method.  This can be used to implement
+     * read or write interfaces which are cheaper than using a Cursor and/or
+     * do not fit into the traditional table model.
+     *
+     * @param method provider-defined method name to call.  Opaque to
+     *   framework, but must be non-null.
+     * @param arg provider-defined String argument.  May be null.
+     * @param extras provider-defined Bundle argument.  May be null.
+     * @return a result Bundle, possibly null.  Will be null if the ContentProvider
+     *   does not implement call.
+     * @throws NullPointerException if uri or method is null
+     * @throws IllegalArgumentException if uri is not known
+     */
+    public final Bundle call(Uri uri, String method, String arg, Bundle extras) {
+        if (uri == null) {
+            throw new NullPointerException("uri == null");
+        }
+        if (method == null) {
+            throw new NullPointerException("method == null");
+        }
+        IContentProvider provider = acquireProvider(uri);
+        if (provider == null) {
+            throw new IllegalArgumentException("Unknown URI " + uri);
+        }
+        try {
+            return provider.call(method, arg, extras);
+        } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
+            return null;
+        } finally {
+            releaseProvider(provider);
+        }
+    }
+
+    /**
      * Returns the content provider for the given content URI.
      *
      * @param uri The URI to a content provider
@@ -1522,9 +1579,11 @@
 
         @Override
         protected void finalize() throws Throwable {
+            // TODO: integrate CloseGuard support.
             try {
                 if(!mCloseFlag) {
-                    ContentResolver.this.releaseProvider(mContentProvider);
+                    Log.w(TAG, "Cursor finalized without prior close()");
+                    close();
                 }
             } finally {
                 super.finalize();
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index b128d31..227df21 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -227,6 +227,12 @@
      */
     public abstract void setTheme(int resid);
 
+    /** @hide Needed for some internal implementation...  not public because
+     * you can't assume this actually means anything. */
+    public int getThemeResId() {
+        return 0;
+    }
+
     /**
      * Return the Theme object associated with this Context.
      */
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index f8928e4..545144e 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -106,6 +106,12 @@
         mBase.setTheme(resid);
     }
 
+    /** @hide */
+    @Override
+    public int getThemeResId() {
+        return mBase.getThemeResId();
+    }
+
     @Override
     public Resources.Theme getTheme() {
         return mBase.getTheme();
diff --git a/core/java/android/content/CursorLoader.java b/core/java/android/content/CursorLoader.java
index 7776874..38ebaf2 100644
--- a/core/java/android/content/CursorLoader.java
+++ b/core/java/android/content/CursorLoader.java
@@ -20,19 +20,24 @@
 import android.database.Cursor;
 import android.net.Uri;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
+
 /**
  * A loader that queries the {@link ContentResolver} and returns a {@link Cursor}.
  */
 public class CursorLoader extends AsyncTaskLoader<Cursor> {
-    Cursor mCursor;
-    ForceLoadContentObserver mObserver;
-    boolean mStopped;
+    final ForceLoadContentObserver mObserver;
+
     Uri mUri;
     String[] mProjection;
     String mSelection;
     String[] mSelectionArgs;
     String mSortOrder;
 
+    Cursor mCursor;
+
     /* Runs on a worker thread */
     @Override
     public Cursor loadInBackground() {
@@ -50,14 +55,14 @@
      * Registers an observer to get notifications from the content provider
      * when the cursor needs to be refreshed.
      */
-    public void registerContentObserver(Cursor cursor, ContentObserver observer) {
+    void registerContentObserver(Cursor cursor, ContentObserver observer) {
         cursor.registerContentObserver(mObserver);
     }
 
     /* Runs on the UI thread */
     @Override
     public void deliverResult(Cursor cursor) {
-        if (mStopped) {
+        if (isReset()) {
             // An async query came in while the loader is stopped
             if (cursor != null) {
                 cursor.close();
@@ -66,9 +71,12 @@
         }
         Cursor oldCursor = mCursor;
         mCursor = cursor;
-        super.deliverResult(cursor);
 
-        if (oldCursor != null && !oldCursor.isClosed()) {
+        if (isStarted()) {
+            super.deliverResult(cursor);
+        }
+
+        if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
             oldCursor.close();
         }
     }
@@ -92,12 +100,11 @@
      * Must be called from the UI thread
      */
     @Override
-    public void startLoading() {
-        mStopped = false;
-
+    protected void onStartLoading() {
         if (mCursor != null) {
             deliverResult(mCursor);
-        } else {
+        }
+        if (takeContentChanged() || mCursor == null) {
             forceLoad();
         }
     }
@@ -106,17 +113,9 @@
      * Must be called from the UI thread
      */
     @Override
-    public void stopLoading() {
-        if (mCursor != null && !mCursor.isClosed()) {
-            mCursor.close();
-        }
-        mCursor = null;
-
+    protected void onStopLoading() {
         // Attempt to cancel the current load task if possible.
         cancelLoad();
-
-        // Make sure that any outstanding loads clean themselves up properly
-        mStopped = true;
     }
 
     @Override
@@ -127,9 +126,16 @@
     }
 
     @Override
-    public void destroy() {
+    protected void onReset() {
+        super.onReset();
+        
         // Ensure the loader is stopped
-        stopLoading();
+        onStopLoading();
+
+        if (mCursor != null && !mCursor.isClosed()) {
+            mCursor.close();
+        }
+        mCursor = null;
     }
 
     public Uri getUri() {
@@ -171,4 +177,18 @@
     public void setSortOrder(String sortOrder) {
         mSortOrder = sortOrder;
     }
+
+    @Override
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        super.dump(prefix, fd, writer, args);
+        writer.print(prefix); writer.print("mUri="); writer.println(mUri);
+        writer.print(prefix); writer.print("mProjection=");
+                writer.println(Arrays.toString(mProjection));
+        writer.print(prefix); writer.print("mSelection="); writer.println(mSelection);
+        writer.print(prefix); writer.print("mSelectionArgs=");
+                writer.println(Arrays.toString(mSelectionArgs));
+        writer.print(prefix); writer.print("mSortOrder="); writer.println(mSortOrder);
+        writer.print(prefix); writer.print("mCursor="); writer.println(mCursor);
+        writer.print(prefix); writer.print("mContentChanged="); writer.println(mContentChanged);
+    }
 }
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 8f122ce..72bc9c2 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -59,18 +59,7 @@
             throws RemoteException, FileNotFoundException;
     public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
             throws RemoteException, OperationApplicationException;
-
-    /**
-     * @hide -- until interface has proven itself
-     *
-     * Call an provider-defined method.  This can be used to implement
-     * interfaces that are cheaper than using a Cursor.
-     *
-     * @param method Method name to call.  Opaque to framework.
-     * @param request Nullable String argument passed to method.
-     * @param args Nullable Bundle argument passed to method.
-     */
-    public Bundle call(String method, String request, Bundle args) throws RemoteException;
+    public Bundle call(String method, String arg, Bundle extras) throws RemoteException;
 
     // Data interchange.
     public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 22befa8..ca5ff24 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1845,7 +1845,7 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_USB_ANLG_HEADSET_PLUG =
-            "android.intent.action.DOCK_HEADSET_PLUG";
+            "android.intent.action.USB_ANLG_HEADSET_PLUG";
 
     /**
      * Broadcast Action: An analog audio speaker/headset plugged in or unplugged.
@@ -1860,7 +1860,7 @@
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_USB_DGTL_HEADSET_PLUG =
-            "android.intent.action.HDMI_AUDIO_PLUG";
+            "android.intent.action.USB_DGTL_HEADSET_PLUG";
 
     /**
      * Broadcast Action: A HMDI cable was plugged or unplugged
diff --git a/core/java/android/content/Loader.java b/core/java/android/content/Loader.java
index 234096a..d63fe69 100644
--- a/core/java/android/content/Loader.java
+++ b/core/java/android/content/Loader.java
@@ -18,18 +18,35 @@
 
 import android.database.ContentObserver;
 import android.os.Handler;
+import android.util.DebugUtils;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 
 /**
  * An abstract class that performs asynchronous loading of data. While Loaders are active
  * they should monitor the source of their data and deliver new results when the contents
  * change.
  *
+ * <p><b>Note on threading:</b> Clients of loaders should as a rule perform
+ * any calls on to a Loader from the main thread of their process (that is,
+ * the thread the Activity callbacks and other things occur on).  Subclasses
+ * of Loader (such as {@link AsyncTaskLoader}) will often perform their work
+ * in a separate thread, but when delivering their results this too should
+ * be done on the main thread.</p>
+ *
+ * <p>Subclasses generally must implement at least {@link #onStartLoading()},
+ * {@link #onStopLoading()}, {@link #onForceLoad()}, and {@link #onReset()}.
+ *
  * @param <D> The result returned when the load is complete
  */
-public abstract class Loader<D> {
+public class Loader<D> {
     int mId;
     OnLoadCompleteListener<D> mListener;
     Context mContext;
+    boolean mStarted = false;
+    boolean mReset = true;
+    boolean mContentChanged = false;
 
     public final class ForceLoadContentObserver extends ContentObserver {
         public ForceLoadContentObserver() {
@@ -70,7 +87,7 @@
     /**
      * Sends the result of the load to the registered listener. Should only be called by subclasses.
      *
-     * Must be called from the UI thread.
+     * Must be called from the process's main thread.
      *
      * @param data the result of the load
      */
@@ -95,10 +112,11 @@
     }
 
     /**
-     * Registers a class that will receive callbacks when a load is complete. The callbacks will
-     * be called on the UI thread so it's safe to pass the results to widgets.
+     * Registers a class that will receive callbacks when a load is complete.
+     * The callback will be called on the process's main thread so it's safe to
+     * pass the results to widgets.
      *
-     * Must be called from the UI thread
+     * <p>Must be called from the process's main thread.
      */
     public void registerListener(int id, OnLoadCompleteListener<D> listener) {
         if (mListener != null) {
@@ -109,7 +127,9 @@
     }
 
     /**
-     * Must be called from the UI thread
+     * Remove a listener that was previously added with {@link #registerListener}.
+     *
+     * Must be called from the process's main thread.
      */
     public void unregisterListener(OnLoadCompleteListener<D> listener) {
         if (mListener == null) {
@@ -122,43 +142,191 @@
     }
 
     /**
-     * Starts an asynchronous load of the contacts list data. When the result is ready the callbacks
-     * will be called on the UI thread. If a previous load has been completed and is still valid
-     * the result may be passed to the callbacks immediately. The loader will monitor the source of
-     * the data set and may deliver future callbacks if the source changes. Calling
-     * {@link #stopLoading} will stop the delivery of callbacks.
-     *
-     * Must be called from the UI thread
+     * Return whether this load has been started.  That is, its {@link #startLoading()}
+     * has been called and no calls to {@link #stopLoading()} or
+     * {@link #reset()} have yet been made.
      */
-    public abstract void startLoading();
+    public boolean isStarted() {
+        return mStarted;
+    }
+
+    /**
+     * Return whether this load has been reset.  That is, either the loader
+     * has not yet been started for the first time, or its {@link #reset()}
+     * has been called.
+     */
+    public boolean isReset() {
+        return mReset;
+    }
+
+    /**
+     * Starts an asynchronous load of the Loader's data. When the result
+     * is ready the callbacks will be called on the process's main thread.
+     * If a previous load has been completed and is still valid
+     * the result may be passed to the callbacks immediately.
+     * The loader will monitor the source of
+     * the data set and may deliver future callbacks if the source changes.
+     * Calling {@link #stopLoading} will stop the delivery of callbacks.
+     *
+     * <p>This updates the Loader's internal state so that
+     * {@link #isStarted()} and {@link #isReset()} will return the correct
+     * values, and then calls the implementation's {@link #onStartLoading()}.
+     *
+     * <p>Must be called from the process's main thread.
+     */
+    public final void startLoading() {
+        mStarted = true;
+        mReset = false;
+        onStartLoading();
+    }
+
+    /**
+     * Subclasses must implement this to take care of loading their data,
+     * as per {@link #startLoading()}.  This is not called by clients directly,
+     * but as a result of a call to {@link #startLoading()}.
+     */
+    protected void onStartLoading() {
+    }
 
     /**
      * Force an asynchronous load. Unlike {@link #startLoading()} this will ignore a previously
-     * loaded data set and load a new one.
+     * loaded data set and load a new one.  This simply calls through to the
+     * implementation's {@link #onForceLoad()}.  You generally should only call this
+     * when the loader is started -- that is, {@link #isStarted()} returns true.
+     *
+     * <p>Must be called from the process's main thread.
      */
-    public abstract void forceLoad();
+    public void forceLoad() {
+        onForceLoad();
+    }
 
     /**
-     * Stops delivery of updates until the next time {@link #startLoading()} is called
-     *
-     * Must be called from the UI thread
+     * Subclasses must implement this to take care of requests to {@link #forceLoad()}.
+     * This will always be called from the process's main thread.
      */
-    public abstract void stopLoading();
+    protected void onForceLoad() {
+    }
 
     /**
-     * Destroys the loader and frees its resources, making it unusable.
+     * Stops delivery of updates until the next time {@link #startLoading()} is called.
+     * Implementations should <em>not</em> invalidate their data at this point --
+     * clients are still free to use the last data the loader reported.  They will,
+     * however, typically stop reporting new data if the data changes; they can
+     * still monitor for changes, but must not report them to the client until and
+     * if {@link #startLoading()} is later called.
      *
-     * Must be called from the UI thread
+     * <p>This updates the Loader's internal state so that
+     * {@link #isStarted()} will return the correct
+     * value, and then calls the implementation's {@link #onStopLoading()}.
+     *
+     * <p>Must be called from the process's main thread.
      */
-    public abstract void destroy();
+    public void stopLoading() {
+        mStarted = false;
+        onStopLoading();
+    }
 
     /**
-     * Called when {@link ForceLoadContentObserver} detects a change.  Calls {@link #forceLoad()}
-     * by default.
+     * Subclasses must implement this to take care of stopping their loader,
+     * as per {@link #stopLoading()}.  This is not called by clients directly,
+     * but as a result of a call to {@link #stopLoading()}.
+     * This will always be called from the process's main thread.
+     */
+    protected void onStopLoading() {
+    }
+
+    /**
+     * Resets the state of the Loader.  The Loader should at this point free
+     * all of its resources, since it may never be called again; however, its
+     * {@link #startLoading()} may later be called at which point it must be
+     * able to start running again.
      *
-     * Must be called from the UI thread
+     * <p>This updates the Loader's internal state so that
+     * {@link #isStarted()} and {@link #isReset()} will return the correct
+     * values, and then calls the implementation's {@link #onReset()}.
+     *
+     * <p>Must be called from the process's main thread.
+     */
+    public void reset() {
+        onReset();
+        mReset = true;
+        mStarted = false;
+        mContentChanged = false;
+    }
+
+    /**
+     * Subclasses must implement this to take care of resetting their loader,
+     * as per {@link #reset()}.  This is not called by clients directly,
+     * but as a result of a call to {@link #reset()}.
+     * This will always be called from the process's main thread.
+     */
+    protected void onReset() {
+    }
+
+    /**
+     * Take the current flag indicating whether the loader's content had
+     * changed while it was stopped.  If it had, true is returned and the
+     * flag is cleared.
+     */
+    public boolean takeContentChanged() {
+        boolean res = mContentChanged;
+        mContentChanged = false;
+        return res;
+    }
+    
+    /**
+     * Called when {@link ForceLoadContentObserver} detects a change.  The
+     * default implementation checks to see if the loader is currently started;
+     * if so, it simply calls {@link #forceLoad()}; otherwise, it sets a flag
+     * so that {@link #takeContentChanged()} returns true.
+     *
+     * <p>Must be called from the process's main thread.
      */
     public void onContentChanged() {
-        forceLoad();
+        if (mStarted) {
+            forceLoad();
+        } else {
+            // This loader has been stopped, so we don't want to load
+            // new data right now...  but keep track of it changing to
+            // refresh later if we start again.
+            mContentChanged = true;
+        }
+    }
+
+    /**
+     * For debugging, converts an instance of the Loader's data class to
+     * a string that can be printed.  Must handle a null data.
+     */
+    public String dataToString(D data) {
+        StringBuilder sb = new StringBuilder(64);
+        DebugUtils.buildShortClassTag(data, sb);
+        sb.append("}");
+        return sb.toString();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(64);
+        DebugUtils.buildShortClassTag(this, sb);
+        sb.append(" id=");
+        sb.append(mId);
+        sb.append("}");
+        return sb.toString();
+    }
+
+    /**
+     * Print the Loader's state into the given stream.
+     *
+     * @param prefix Text to print at the front of each line.
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param writer A PrintWriter to which the dump is to be set.
+     * @param args Additional arguments to the dump request.
+     */
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        writer.print(prefix); writer.print("mId="); writer.print(mId);
+                writer.print(" mListener="); writer.println(mListener);
+        writer.print(prefix); writer.print("mStarted="); writer.print(mStarted);
+                writer.print(" mContentChanged="); writer.print(mContentChanged);
+                writer.print(" mReset="); writer.println(mReset);
     }
 }
\ No newline at end of file
diff --git a/core/java/android/content/SyncActivityTooManyDeletes.java b/core/java/android/content/SyncActivityTooManyDeletes.java
new file mode 100644
index 0000000..350f35e
--- /dev/null
+++ b/core/java/android/content/SyncActivityTooManyDeletes.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+import com.android.internal.R;
+import android.accounts.Account;
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+/**
+ * Presents multiple options for handling the case where a sync was aborted because there
+ * were too many pending deletes. One option is to force the delete, another is to rollback
+ * the deletes, the third is to do nothing.
+ * @hide
+ */
+public class SyncActivityTooManyDeletes extends Activity
+        implements AdapterView.OnItemClickListener {
+
+    private long mNumDeletes;
+    private Account mAccount;
+    private String mAuthority;
+    private String mProvider;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Bundle extras = getIntent().getExtras();
+        if (extras == null) {
+            finish();
+            return;
+        }
+
+        mNumDeletes = extras.getLong("numDeletes");
+        mAccount = (Account) extras.getParcelable("account");
+        mAuthority = extras.getString("authority");
+        mProvider = extras.getString("provider");
+
+        // the order of these must match up with the constants for position used in onItemClick
+        CharSequence[] options = new CharSequence[]{
+                getResources().getText(R.string.sync_really_delete),
+                getResources().getText(R.string.sync_undo_deletes),
+                getResources().getText(R.string.sync_do_nothing)
+        };
+
+        ListAdapter adapter = new ArrayAdapter<CharSequence>(this,
+                android.R.layout.simple_list_item_1,
+                android.R.id.text1,
+                options);
+
+        ListView listView = new ListView(this);
+        listView.setAdapter(adapter);
+        listView.setItemsCanFocus(true);
+        listView.setOnItemClickListener(this);
+
+        TextView textView = new TextView(this);
+        CharSequence tooManyDeletesDescFormat =
+                getResources().getText(R.string.sync_too_many_deletes_desc);
+        textView.setText(String.format(tooManyDeletesDescFormat.toString(),
+                mNumDeletes, mProvider, mAccount.name));
+
+        final LinearLayout ll = new LinearLayout(this);
+        ll.setOrientation(LinearLayout.VERTICAL);
+        final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0);
+        ll.addView(textView, lp);
+        ll.addView(listView, lp);
+
+        // TODO: consider displaying the icon of the account type
+//        AuthenticatorDescription[] descs = AccountManager.get(this).getAuthenticatorTypes();
+//        for (AuthenticatorDescription desc : descs) {
+//            if (desc.type.equals(mAccount.type)) {
+//                try {
+//                    final Context authContext = createPackageContext(desc.packageName, 0);
+//                    ImageView imageView = new ImageView(this);
+//                    imageView.setImageDrawable(authContext.getResources().getDrawable(desc.iconId));
+//                    ll.addView(imageView, lp);
+//                } catch (PackageManager.NameNotFoundException e) {
+//                }
+//                break;
+//            }
+//        }
+
+        setContentView(ll);
+    }
+
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        // the constants for position correspond to the items options array in onCreate()
+        if (position == 0) startSyncReallyDelete();
+        else if (position == 1) startSyncUndoDeletes();
+        finish();
+    }
+
+    private void startSyncReallyDelete() {
+        Bundle extras = new Bundle();
+        extras.putBoolean(ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS, true);
+        extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
+        extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
+        extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
+        ContentResolver.requestSync(mAccount, mAuthority, extras);
+    }
+
+    private void startSyncUndoDeletes() {
+        Bundle extras = new Bundle();
+        extras.putBoolean(ContentResolver.SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS, true);
+        extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
+        extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
+        extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
+        ContentResolver.requestSync(mAccount, mAuthority, extras);
+    }
+}
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 599429b..f45cf2a 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -237,43 +237,7 @@
     private BroadcastReceiver mConnectivityIntentReceiver =
             new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
-            NetworkInfo networkInfo =
-                    intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
-            NetworkInfo.State state = (networkInfo == null ? NetworkInfo.State.UNKNOWN :
-                    networkInfo.getState());
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "received connectivity action.  network info: " + networkInfo);
-            }
-
-            final boolean wasConnected = mDataConnectionIsConnected;
-            // only pay attention to the CONNECTED and DISCONNECTED states.
-            // if connected, we are connected.
-            // if disconnected, we may not be connected.  in some cases, we may be connected on
-            // a different network.
-            // e.g., if switching from GPRS to WiFi, we may receive the CONNECTED to WiFi and
-            // DISCONNECTED for GPRS in any order.  if we receive the CONNECTED first, and then
-            // a DISCONNECTED, we want to make sure we set mDataConnectionIsConnected to true
-            // since we still have a WiFi connection.
-            switch (state) {
-                case CONNECTED:
-                    mDataConnectionIsConnected = true;
-                    break;
-                case DISCONNECTED:
-                    mDataConnectionIsConnected = !intent.getBooleanExtra(
-                            ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
-                    break;
-                default:
-                    // ignore the rest of the states -- leave our boolean alone.
-            }
-            if (mDataConnectionIsConnected) {
-                if (!wasConnected) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.v(TAG, "Reconnection detected: clearing all backoffs");
-                    }
-                    mSyncStorageEngine.clearAllBackoffs();
-                }
-                sendCheckAlarmsMessage();
-            }
+            sendCheckAlarmsMessage();
         }
     };
 
@@ -1409,8 +1373,13 @@
         public void handleMessage(Message msg) {
             long earliestFuturePollTime = Long.MAX_VALUE;
             long nextPendingSyncTime = Long.MAX_VALUE;
+
+            // Setting the value here instead of a method because we want the dumpsys logs
+            // to have the most recent value used.
             try {
                 waitUntilReadyToRun();
+                NetworkInfo networkInfo = getConnectivityManager().getActiveNetworkInfo();
+                mDataConnectionIsConnected = (networkInfo != null) && networkInfo.isConnected();
                 mSyncManagerWakeLock.acquire();
                 // Always do this first so that we be sure that any periodic syncs that
                 // are ready to run have been converted into pending syncs. This allows the
@@ -2157,9 +2126,7 @@
             }
             CharSequence authorityName = providerInfo.loadLabel(mContext.getPackageManager());
 
-            Intent clickIntent = new Intent();
-            clickIntent.setClassName("com.android.providers.subscribedfeeds",
-                    "com.android.settings.SyncActivityTooManyDeletes");
+            Intent clickIntent = new Intent(mContext, SyncActivityTooManyDeletes.class);
             clickIntent.putExtra("account", account);
             clickIntent.putExtra("authority", authority);
             clickIntent.putExtra("provider", authorityName.toString());
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index f16c4ef..2812477 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -98,6 +98,13 @@
         }
         return name;
     }
+
+    /**
+     * Return whether this component and its enclosing application are enabled.
+     */
+    public boolean isEnabled() {
+        return enabled && applicationInfo.enabled;
+    }
     
     /**
      * Return the icon resource identifier to use for this component.  If
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index d01a68a..28e1a63 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -324,5 +324,6 @@
     boolean setInstallLocation(int loc);
     int getInstallLocation();
 
-    void setPackageObbPath(String packageName, String path);
+    void setPackageObbPaths(in String packageName, in String[] paths);
+    String[] getPackageObbPaths(in String packageName);
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ac7a95a..47418aa 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2291,15 +2291,30 @@
             String packageName, IPackageMoveObserver observer, int flags);
 
     /**
-     * Sets the Opaque Binary Blob (OBB) file location.
+     * Sets the Opaque Binary Blob (OBB) file path associated with a package
+     * name. The caller must have the
+     * {@link android.Manifest.permission#INSTALL_PACKAGES} permission.
      * <p>
      * NOTE: The existence or format of this file is not currently checked, but
      * it may be in the future.
      * 
      * @param packageName Name of the package with which to associate the .obb
-     *            file
-     * @param path Path on the filesystem to the .obb file
-     * @hide
+     *            file.
+     * @param paths Arrays of paths on the filesystem to the .obb files
+     *            associated with the package.
+     * @see #getPackageObbPaths(String)
      */
-    public abstract void setPackageObbPath(String packageName, String path);
+    public abstract void setPackageObbPaths(String packageName, String[] paths);
+
+    /**
+     * Gets the Opaque Binary Blob (OBB) file path associated with the package.
+     * The caller must be the owner of the package queried or have the
+     * {@link android.Manifest.permission#INSTALL_PACKAGES} permission.
+     * 
+     * @param packageName Name of the package with which to associate the .obb
+     *            file.
+     * @return array of paths to .obb files associated with the package
+     * @see #setPackageObbPaths(String, String[])
+     */
+    public abstract String[] getPackageObbPaths(String packageName);
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 9cfe2db..20a22e5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1508,18 +1508,12 @@
             ai.nonLocalizedLabel = v.coerceToString();
         }
 
-        int defaultTheme = 0;
-        if (owner.applicationInfo.targetSdkVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {
-            // As of honeycomb, the default application theme is holographic.
-            defaultTheme = android.R.style.Theme_Holo;
-        }
-
         ai.icon = sa.getResourceId(
                 com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
         ai.logo = sa.getResourceId(
                 com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
         ai.theme = sa.getResourceId(
-                com.android.internal.R.styleable.AndroidManifestApplication_theme, defaultTheme);
+                com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
         ai.descriptionRes = sa.getResourceId(
                 com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
 
@@ -2636,14 +2630,8 @@
 
         int priority = sa.getInt(
                 com.android.internal.R.styleable.AndroidManifestIntentFilter_priority, 0);
-        if (priority > 0 && isActivity && (flags&PARSE_IS_SYSTEM) == 0) {
-            Log.w(TAG, "Activity with priority > 0, forcing to 0 at "
-                    + mArchiveSourcePath + " "
-                    + parser.getPositionDescription());
-            priority = 0;
-        }
         outInfo.setPriority(priority);
-        
+
         TypedValue v = sa.peekValue(
                 com.android.internal.R.styleable.AndroidManifestIntentFilter_label);
         if (v != null && (outInfo.labelRes=v.resourceId) == 0) {
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index e6fd039..b40a226 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -115,6 +115,23 @@
         return (LongSparseArray<T>) EMPTY_ARRAY;
     }
 
+    /** @hide */
+    public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
+        return selectSystemTheme(curTheme, targetSdkVersion,
+                com.android.internal.R.style.Theme, com.android.internal.R.style.Theme_Holo);
+    }
+    
+    /** @hide */
+    public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo) {
+        if (curTheme != 0) {
+            return curTheme;
+        }
+        if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) {
+            return orig;
+        }
+        return holo;
+    }
+    
     /**
      * This exception is thrown by the resource APIs when a requested resource
      * can not be found.
@@ -1459,7 +1476,6 @@
                 }
             }
         }
-        cache.clear();
     }
 
     /**
diff --git a/core/java/android/database/BulkCursorToCursorAdaptor.java b/core/java/android/database/BulkCursorToCursorAdaptor.java
index 2cb2aec..16becf5 100644
--- a/core/java/android/database/BulkCursorToCursorAdaptor.java
+++ b/core/java/android/database/BulkCursorToCursorAdaptor.java
@@ -154,7 +154,10 @@
                     false /* the window will be accessed across processes */));
             if (mCount != -1) {
                 mPos = -1;
-                mWindow = null;
+                if (mWindow != null) {
+                    mWindow.close();
+                    mWindow = null;
+                }
 
                 // super.requery() will call onChanged. Do it here instead of relying on the
                 // observer from the far side so that observers can see a correct value for mCount
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index a026eca..bd78063 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -16,20 +16,38 @@
 
 package android.database;
 
+import android.content.res.Resources;
+import android.database.sqlite.DatabaseObjectNotClosedException;
 import android.database.sqlite.SQLiteClosable;
+import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Process;
+import android.os.StrictMode;
+import android.util.Log;
+import android.util.SparseIntArray;
 
 /**
  * A buffer containing multiple cursor rows.
  */
 public class CursorWindow extends SQLiteClosable implements Parcelable {
-    /** The pointer to the native window class */
-    @SuppressWarnings("unused")
+    private static final String STATS_TAG = "CursorWindowStats";
+
+    /** The cursor window size. resource xml file specifies the value in kB.
+     * convert it to bytes here by multiplying with 1024.
+     */
+    private static final int sCursorWindowSize =
+        Resources.getSystem().getInteger(
+                com.android.internal.R.integer.config_cursorWindowSize) * 1024;
+
+    /** The pointer to the native window class. set by the native methods in
+     * android_database_CursorWindow.cpp
+     */
     private int nWindow;
 
     private int mStartPos;
+    private final Throwable mStackTrace;
 
     /**
      * Creates a new empty window.
@@ -38,7 +56,19 @@
      */
     public CursorWindow(boolean localWindow) {
         mStartPos = 0;
-        native_init(localWindow);
+        int rslt = native_init(sCursorWindowSize, localWindow);
+        printDebugMsgIfError(rslt);
+        recordNewWindow(Binder.getCallingPid(), nWindow);
+        mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
+    }
+
+    private void printDebugMsgIfError(int rslt) {
+        if (rslt > 0) {
+            // cursor window allocation failed. either low memory or too many cursors being open.
+            // print info to help in debugging this.
+            throw new CursorWindowAllocationException("Cursor Window allocation of " +
+                    sCursorWindowSize/1024 + " kb failed. " + printStats());
+        }
     }
 
     /**
@@ -535,7 +565,16 @@
 
     @Override
     protected void finalize() {
-        // Just in case someone forgot to call close...
+        if (nWindow == 0) {
+            return;
+        }
+        if (StrictMode.vmSqliteObjectLeaksEnabled()) {
+            StrictMode.onSqliteObjectLeaked(
+                    "Releasing cursor in a finalizer. Please ensure " +
+                    "that you explicitly call close() on your cursor: ",
+                    mStackTrace);
+        }
+        recordClosingOfWindow(nWindow);
         close_native();
     }
     
@@ -566,21 +605,78 @@
     private CursorWindow(Parcel source) {
         IBinder nativeBinder = source.readStrongBinder();
         mStartPos = source.readInt();
-
-        native_init(nativeBinder);
+        int rslt = native_init(nativeBinder);
+        mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
+        printDebugMsgIfError(rslt);
     }
 
     /** Get the binder for the native side of the window */
     private native IBinder native_getBinder();
 
     /** Does the native side initialization for an empty window */
-    private native void native_init(boolean localOnly);
+    private native int native_init(int cursorWindowSize, boolean localOnly);
 
     /** Does the native side initialization with an existing binder from another process */
-    private native void native_init(IBinder nativeBinder);
+    private native int native_init(IBinder nativeBinder);
 
     @Override
     protected void onAllReferencesReleased() {
-        close_native();        
+        recordClosingOfWindow(nWindow);
+        close_native();
+    }
+
+    private static final SparseIntArray sWindowToPidMap = new SparseIntArray();
+
+    private void recordNewWindow(int pid, int window) {
+        synchronized (sWindowToPidMap) {
+            sWindowToPidMap.put(window, pid);
+            if (Log.isLoggable(STATS_TAG, Log.VERBOSE)) {
+                Log.i(STATS_TAG, "Created a new Cursor. " + printStats());
+            }
+        }
+    }
+
+    private void recordClosingOfWindow(int window) {
+        synchronized (sWindowToPidMap) {
+            if (sWindowToPidMap.size() == 0) {
+                // this means we are not in the ContentProvider.
+                return;
+            }
+            sWindowToPidMap.delete(window);
+        }
+    }
+    private String printStats() {
+        StringBuilder buff = new StringBuilder();
+        int myPid = Process.myPid();
+        int total = 0;
+        SparseIntArray pidCounts = new SparseIntArray();
+        synchronized (sWindowToPidMap) {
+            int size = sWindowToPidMap.size();
+            if (size == 0) {
+                // this means we are not in the ContentProvider.
+                return "";
+            }
+            for (int indx = 0; indx < size; indx++) {
+                int pid = sWindowToPidMap.valueAt(indx);
+                int value = pidCounts.get(pid);
+                pidCounts.put(pid, ++value);
+            }
+        }
+        int numPids = pidCounts.size();
+        for (int i = 0; i < numPids;i++) {
+            buff.append(" (# cursors opened by ");
+            int pid = pidCounts.keyAt(i);
+            if (pid == myPid) {
+                buff.append("this proc=");
+            } else {
+                buff.append("pid " + pid + "=");
+            }
+            int num = pidCounts.get(pid);
+            buff.append(num + ")");
+            total += num;
+        }
+        // limit the returned string size to 1000
+        String s = (buff.length() > 980) ? buff.substring(0, 980) : buff.toString();
+        return "# Open Cursors=" + total + s;
     }
 }
diff --git a/core/java/android/database/CursorWindowAllocationException.java b/core/java/android/database/CursorWindowAllocationException.java
new file mode 100644
index 0000000..ba7df68
--- /dev/null
+++ b/core/java/android/database/CursorWindowAllocationException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database;
+
+/**
+ * This exception is thrown when a CursorWindow couldn't be allocated,
+ * most probably due to memory not being available
+ */
+class CursorWindowAllocationException extends java.lang.RuntimeException
+{
+    public CursorWindowAllocationException()
+    {
+        super();
+    }
+
+    public CursorWindowAllocationException(String description)
+    {
+        super(description);
+    }
+}
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 70a7fb6..f428aad 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -311,7 +311,6 @@
 
     /**
      * Concatenates two SQL WHERE clauses, handling empty or null values.
-     * @hide
      */
     public static String concatenateWhere(String a, String b) {
         if (TextUtils.isEmpty(a)) {
diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java
index 93f9a71e..01e9fb3 100644
--- a/core/java/android/database/sqlite/SQLiteClosable.java
+++ b/core/java/android/database/sqlite/SQLiteClosable.java
@@ -38,20 +38,22 @@
     }
 
     public void releaseReference() {
+        boolean refCountIsZero = false;
         synchronized(this) {
-            mReferenceCount--;
-            if (mReferenceCount == 0) {
-                onAllReferencesReleased();
-            }
+            refCountIsZero = --mReferenceCount == 0;
+        }
+        if (refCountIsZero) {
+            onAllReferencesReleased();
         }
     }
 
     public void releaseReferenceFromContainer() {
+        boolean refCountIsZero = false;
         synchronized(this) {
-            mReferenceCount--;
-            if (mReferenceCount == 0) {
-                onAllReferencesReleasedFromContainer();
-            }
+            refCountIsZero = --mReferenceCount == 0;
+        }
+        if (refCountIsZero) {
+            onAllReferencesReleasedFromContainer();
         }
     }
 
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index 5a6c667..4c2d123 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -407,15 +407,32 @@
                 mWindow.clear();
             }
             mPos = -1;
-            SQLiteDatabase db = mQuery.mDatabase.getDatabaseHandle(mQuery.mSql);
+            SQLiteDatabase db = null;
+            try {
+                db = mQuery.mDatabase.getDatabaseHandle(mQuery.mSql);
+            } catch (IllegalStateException e) {
+                // for backwards compatibility, just return false
+                Log.w(TAG, "requery() failed " + e.getMessage(), e);
+                return false;
+            }
             if (!db.equals(mQuery.mDatabase)) {
                 // since we need to use a different database connection handle,
                 // re-compile the query
-                db.lock();
+                try {
+                    db.lock();
+                } catch (IllegalStateException e) {
+                    // for backwards compatibility, just return false
+                    Log.w(TAG, "requery() failed " + e.getMessage(), e);
+                    return false;
+                }
                 try {
                     // close the old mQuery object and open a new one
                     mQuery.close();
                     mQuery = new SQLiteQuery(db, mQuery);
+                } catch (IllegalStateException e) {
+                    // for backwards compatibility, just return false
+                    Log.w(TAG, "requery() failed " + e.getMessage(), e);
+                    return false;
                 } finally {
                     db.unlock();
                 }
@@ -427,6 +444,10 @@
             queryThreadLock();
             try {
                 mQuery.requery();
+            } catch (IllegalStateException e) {
+                // for backwards compatibility, just return false
+                Log.w(TAG, "requery() failed " + e.getMessage(), e);
+                return false;
             } finally {
                 queryThreadUnlock();
             }
@@ -437,7 +458,13 @@
             Log.v(TAG, "--- Requery()ed cursor " + this + ": " + mQuery);
         }
 
-        boolean result = super.requery();
+        boolean result = false;
+        try {
+            result = super.requery();
+        } catch (IllegalStateException e) {
+            // for backwards compatibility, just return false
+            Log.w(TAG, "requery() failed " + e.getMessage(), e);
+        }
         if (Config.LOGV) {
             long timeEnd = System.currentTimeMillis();
             Log.v(TAG, "requery (" + (timeEnd - timeStart) + " ms): " + mDriver.toString());
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 184988b..b1c84a1 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -18,6 +18,7 @@
 
 import android.app.AppGlobals;
 import android.content.ContentValues;
+import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.DatabaseErrorHandler;
 import android.database.DatabaseUtils;
@@ -957,13 +958,7 @@
             sBlockSize = new StatFs("/data").getBlockSize();
         }
         sqliteDatabase.setPageSize(sBlockSize);
-        //STOPSHIP - uncomment the following line
-        //sqliteDatabase.setJournalMode(path, "TRUNCATE");
-        // STOPSHIP remove the following lines
-        if (!path.equalsIgnoreCase(MEMORY_DB_PATH)) {
-            sqliteDatabase.enableWriteAheadLogging();
-        }
-        // END STOPSHIP
+        sqliteDatabase.setJournalMode(path, "TRUNCATE");
 
         // add this database to the list of databases opened in this process
         synchronized(mActiveDatabases) {
@@ -1593,9 +1588,13 @@
      * Convenience method for inserting a row into the database.
      *
      * @param table the table to insert the row into
-     * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
-     *            so if initialValues is empty this column will explicitly be
-     *            assigned a NULL value
+     * @param nullColumnHack optional; may be <code>null</code>.
+     *            SQL doesn't allow inserting a completely empty row without
+     *            naming at least one column name.  If your provided <code>values</code> is
+     *            empty, no column names are known and an empty row can't be inserted.
+     *            If not set to null, the <code>nullColumnHack</code> parameter
+     *            provides the name of nullable column name to explicitly insert a NULL into
+     *            in the case where your <code>values</code> is empty.
      * @param values this map contains the initial column values for the
      *            row. The keys should be the column names and the values the
      *            column values
@@ -1614,9 +1613,13 @@
      * Convenience method for inserting a row into the database.
      *
      * @param table the table to insert the row into
-     * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
-     *            so if initialValues is empty this column will explicitly be
-     *            assigned a NULL value
+     * @param nullColumnHack optional; may be <code>null</code>.
+     *            SQL doesn't allow inserting a completely empty row without
+     *            naming at least one column name.  If your provided <code>values</code> is
+     *            empty, no column names are known and an empty row can't be inserted.
+     *            If not set to null, the <code>nullColumnHack</code> parameter
+     *            provides the name of nullable column name to explicitly insert a NULL into
+     *            in the case where your <code>values</code> is empty.
      * @param values this map contains the initial column values for the
      *            row. The keys should be the column names and the values the
      *            column values
@@ -1632,11 +1635,15 @@
      * Convenience method for replacing a row in the database.
      *
      * @param table the table in which to replace the row
-     * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
-     *            so if initialValues is empty this row will explicitly be
-     *            assigned a NULL value
+     * @param nullColumnHack optional; may be <code>null</code>.
+     *            SQL doesn't allow inserting a completely empty row without
+     *            naming at least one column name.  If your provided <code>initialValues</code> is
+     *            empty, no column names are known and an empty row can't be inserted.
+     *            If not set to null, the <code>nullColumnHack</code> parameter
+     *            provides the name of nullable column name to explicitly insert a NULL into
+     *            in the case where your <code>initialValues</code> is empty.
      * @param initialValues this map contains the initial column values for
-     *   the row. The key
+     *   the row.
      * @return the row ID of the newly inserted row, or -1 if an error occurred
      */
     public long replace(String table, String nullColumnHack, ContentValues initialValues) {
@@ -1653,9 +1660,13 @@
      * Convenience method for replacing a row in the database.
      *
      * @param table the table in which to replace the row
-     * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
-     *            so if initialValues is empty this row will explicitly be
-     *            assigned a NULL value
+     * @param nullColumnHack optional; may be <code>null</code>.
+     *            SQL doesn't allow inserting a completely empty row without
+     *            naming at least one column name.  If your provided <code>initialValues</code> is
+     *            empty, no column names are known and an empty row can't be inserted.
+     *            If not set to null, the <code>nullColumnHack</code> parameter
+     *            provides the name of nullable column name to explicitly insert a NULL into
+     *            in the case where your <code>initialValues</code> is empty.
      * @param initialValues this map contains the initial column values for
      *   the row. The key
      * @throws SQLException
@@ -1671,9 +1682,13 @@
      * General method for inserting a row into the database.
      *
      * @param table the table to insert the row into
-     * @param nullColumnHack SQL doesn't allow inserting a completely empty row,
-     *            so if initialValues is empty this column will explicitly be
-     *            assigned a NULL value
+     * @param nullColumnHack optional; may be <code>null</code>.
+     *            SQL doesn't allow inserting a completely empty row without
+     *            naming at least one column name.  If your provided <code>initialValues</code> is
+     *            empty, no column names are known and an empty row can't be inserted.
+     *            If not set to null, the <code>nullColumnHack</code> parameter
+     *            provides the name of nullable column name to explicitly insert a NULL into
+     *            in the case where your <code>initialValues</code> is empty.
      * @param initialValues this map contains the initial column values for the
      *            row. The keys should be the column names and the values the
      *            column values
@@ -1832,7 +1847,7 @@
      *
      * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
      * not supported.
-     * @throws SQLException If the SQL string is invalid for some reason
+     * @throws SQLException if the SQL string is invalid
      */
     public void execSQL(String sql) throws SQLException {
         int stmtType = DatabaseUtils.getSqlStatementType(sql);
@@ -1896,7 +1911,7 @@
      * @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
      * not supported.
      * @param bindArgs only byte[], String, Long and Double are supported in bindArgs.
-     * @throws SQLException If the SQL string is invalid for some reason
+     * @throws SQLException if the SQL string is invalid
      */
     public void execSQL(String sql, Object[] bindArgs) throws SQLException {
         if (bindArgs == null) {
@@ -1963,6 +1978,15 @@
         // If the caller sets errorHandler = null, then use default errorhandler.
         mErrorHandler = (errorHandler == null) ? new DefaultDatabaseErrorHandler() : errorHandler;
         mConnectionNum = connectionNum;
+        /* sqlite soft heap limit http://www.sqlite.org/c3ref/soft_heap_limit64.html
+         * set it to 4 times the default cursor window size.
+         * TODO what is an appropriate value, considring the WAL feature which could burn
+         * a lot of memory with many connections to the database. needs testing to figure out
+         * optimal value for this.
+         */
+        int limit = Resources.getSystem().getInteger(
+                com.android.internal.R.integer.config_cursorWindowSize) * 1024 * 4;
+        native_setSqliteSoftHeapLimit(limit);
     }
 
     /**
@@ -2670,4 +2694,10 @@
      * @param statementId statement to be finzlied by sqlite
      */
     private final native void native_finalize(int statementId);
+
+    /**
+     * set sqlite soft heap limit
+     * http://www.sqlite.org/c3ref/soft_heap_limit64.html
+     */
+    private native void native_setSqliteSoftHeapLimit(int softHeapLimit);
 }
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index ccf8d68..e2befca 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -38,10 +38,7 @@
  * in the <em>samples/</em> directory of the SDK.</p>
  *
  * <p class="note"><strong>Note:</strong> this class assumes
- * monotonically increasing version numbers for upgrades.  Also, there
- * is no concept of a database downgrade; installing a new version of
- * your app which uses a lower version number than a
- * previously-installed version will result in undefined behavior.</p>
+ * monotonically increasing version numbers for upgrades.</p>
  */
 public abstract class SQLiteOpenHelper {
     private static final String TAG = SQLiteOpenHelper.class.getSimpleName();
@@ -65,7 +62,8 @@
      * @param name of the database file, or null for an in-memory database
      * @param factory to use for creating cursor objects, or null for the default
      * @param version number of the database (starting at 1); if the database is older,
-     *     {@link #onUpgrade} will be used to upgrade the database
+     *     {@link #onUpgrade} will be used to upgrade the database; if the database is
+     *     newer, {@link #onDowngrade} will be used to downgrade the database
      */
     public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {
         this(context, name, factory, version, new DefaultDatabaseErrorHandler());
@@ -152,10 +150,6 @@
             }
 
             int version = db.getVersion();
-            if (version > mNewVersion) {
-                throw new IllegalStateException("Database " + mName +
-                        " cannot be downgraded. instead, please uninstall new version first.");
-            }
             if (version != mNewVersion) {
                 db.beginTransaction();
                 try {
@@ -163,10 +157,10 @@
                         onCreate(db);
                     } else {
                         if (version > mNewVersion) {
-                            Log.wtf(TAG, "Can't downgrade read-only database from version " +
-                                    version + " to " + mNewVersion + ": " + db.getPath());
+                            onDowngrade(db, version, mNewVersion);
+                        } else {
+                            onUpgrade(db, version, mNewVersion);
                         }
-                        onUpgrade(db, version, mNewVersion);
                     }
                     db.setVersion(mNewVersion);
                     db.setTransactionSuccessful();
@@ -291,6 +285,22 @@
     public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
 
     /**
+     * Called when the database needs to be downgraded. This is stricly similar to
+     * onUpgrade() method, but is called whenever current version is newer than requested one.
+     * However, this method is not abstract, so it is not mandatory for a customer to
+     * implement it. If not overridden, default implementation will reject downgrade and
+     * throws SQLiteException
+     *
+     * @param db The database.
+     * @param oldVersion The old database version.
+     * @param newVersion The new database version.
+     */
+    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+        throw new SQLiteException("Can't downgrade database from version " +
+                oldVersion + " to " + newVersion);
+    }
+
+    /**
      * Called when the database has been opened.  The implementation
      * should check {@link SQLiteDatabase#isReadOnly} before updating the
      * database.
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index 5e96928..c76cc6c 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -131,6 +131,10 @@
             long retValue = native_1x1_long();
             mDatabase.logTimeStat(mSql, timeStart);
             return retValue;
+        } catch (SQLiteDoneException e) {
+            throw new SQLiteDoneException(
+                    "expected 1 row from this query but query returned no data. check the query: " +
+                    mSql);
         } finally {
             releaseAndUnlock();
         }
@@ -150,6 +154,10 @@
             String retValue = native_1x1_string();
             mDatabase.logTimeStat(mSql, timeStart);
             return retValue;
+        } catch (SQLiteDoneException e) {
+            throw new SQLiteDoneException(
+                    "expected 1 row from this query but query returned no data. check the query: " +
+                    mSql);
         } finally {
             releaseAndUnlock();
         }
@@ -172,6 +180,10 @@
         } catch (IOException ex) {
             Log.e(TAG, "simpleQueryForBlobFileDescriptor() failed", ex);
             return null;
+        } catch (SQLiteDoneException e) {
+            throw new SQLiteDoneException(
+                    "expected 1 row from this query but query returned no data. check the query: " +
+                    mSql);
         } finally {
             releaseAndUnlock();
         }
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index fe4b900..207785c 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -27,6 +27,7 @@
 import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.graphics.ImageFormat;
+import android.graphics.SurfaceTexture;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -183,10 +184,10 @@
          * the right of the screen, the value should be 270.
          *
          * @see #setDisplayOrientation(int)
-         * @see #setRotation(int)
-         * @see #setPreviewSize(int, int)
-         * @see #setPictureSize(int, int)
-         * @see #setJpegThumbnailSize(int, int)
+         * @see Parameters#setRotation(int)
+         * @see Parameters#setPreviewSize(int, int)
+         * @see Parameters#setPictureSize(int, int)
+         * @see Parameters#setJpegThumbnailSize(int, int)
          */
         public int orientation;
     };
@@ -324,8 +325,10 @@
 
     /**
      * Sets the {@link Surface} to be used for live preview.
-     * A surface is necessary for preview, and preview is necessary to take
-     * pictures.  The same surface can be re-set without harm.
+     * Either a surface or surface texture is necessary for preview, and
+     * preview is necessary to take pictures.  The same surface can be re-set
+     * without harm.  Setting a preview surface will un-set any preview surface
+     * texture that was set via {@link #setPreviewTexture}.
      *
      * <p>The {@link SurfaceHolder} must already contain a surface when this
      * method is called.  If you are using {@link android.view.SurfaceView},
@@ -357,6 +360,29 @@
     private native final void setPreviewDisplay(Surface surface);
 
     /**
+     * Sets the {@link SurfaceTexture} to be used for live preview.
+     * Either a surface or surface texture is necessary for preview, and
+     * preview is necessary to take pictures.  The same surface texture can be
+     * re-set without harm.  Setting a preview surface texture will un-set any
+     * preview surface that was set via {@link #setPreviewDisplay}.
+     *
+     * <p>This method must be called before {@link #startPreview()}.  The
+     * one exception is that if the preview surface texture is not set (or set
+     * to null) before startPreview() is called, then this method may be called
+     * once with a non-null parameter to set the preview surface.  (This allows
+     * camera setup and surface creation to happen in parallel, saving time.)
+     * The preview surface texture may not otherwise change while preview is
+     * running.
+     *
+     * @param surfaceTexture the {@link SurfaceTexture} to which the preview
+     *     images are to be sent or null to remove the current preview surface
+     *     texture
+     * @throws IOException if the method fails (for example, if the surface
+     *     texture is unavailable or unsuitable).
+     */
+    public native final void setPreviewTexture(SurfaceTexture surfaceTexture);
+
+    /**
      * Callback interface used to deliver copies of preview frames as
      * they are displayed.
      *
@@ -609,9 +635,10 @@
     public interface AutoFocusCallback
     {
         /**
-         * Called when the camera auto focus completes.  If the camera does not
-         * support auto-focus and autoFocus is called, onAutoFocus will be
-         * called immediately with success.
+         * Called when the camera auto focus completes.  If the camera
+         * does not support auto-focus and autoFocus is called,
+         * onAutoFocus will be called immediately with a fake value of
+         * <code>success</code> set to <code>true</code>.
          *
          * @param success true if focus was successful, false if otherwise
          * @param camera  the Camera service object
@@ -785,12 +812,12 @@
      * is, the image is reflected along the central vertical axis of the camera
      * sensor. So the users can see themselves as looking into a mirror.
      *
-     * This does not affect the order of byte array passed in {@link
+     * <p>This does not affect the order of byte array passed in {@link
      * PreviewCallback#onPreviewFrame}, JPEG pictures, or recorded videos. This
      * method is not allowed to be called during preview.
      *
-     * If you want to make the camera image show in the same orientation as
-     * the display, you can use the following code.<p>
+     * <p>If you want to make the camera image show in the same orientation as
+     * the display, you can use the following code.
      * <pre>
      * public static void setCameraDisplayOrientation(Activity activity,
      *         int cameraId, android.hardware.Camera camera) {
@@ -1810,26 +1837,27 @@
          * the orientation in the EXIF header will be missing or 1 (row #0 is
          * top and column #0 is left side).
          *
-         * If applications want to rotate the picture to match the orientation
+         * <p>If applications want to rotate the picture to match the orientation
          * of what users see, apps should use {@link
          * android.view.OrientationEventListener} and {@link CameraInfo}.
          * The value from OrientationEventListener is relative to the natural
          * orientation of the device. CameraInfo.orientation is the angle
-         * between camera orientation and natural device orientation. The sum or
+         * between camera orientation and natural device orientation. The sum
          * of the two is the rotation angle for back-facing camera. The
          * difference of the two is the rotation angle for front-facing camera.
          * Note that the JPEG pictures of front-facing cameras are not mirrored
          * as in preview display.
          *
-         * For example, suppose the natural orientation of the device is
+         * <p>For example, suppose the natural orientation of the device is
          * portrait. The device is rotated 270 degrees clockwise, so the device
          * orientation is 270. Suppose a back-facing camera sensor is mounted in
          * landscape and the top side of the camera sensor is aligned with the
          * right edge of the display in natural orientation. So the camera
          * orientation is 90. The rotation should be set to 0 (270 + 90).
          *
-         * The reference code is as follows.
+         * <p>The reference code is as follows.
          *
+	 * <pre>
          * public void public void onOrientationChanged(int orientation) {
          *     if (orientation == ORIENTATION_UNKNOWN) return;
          *     android.hardware.Camera.CameraInfo info =
@@ -1844,6 +1872,7 @@
          *     }
          *     mParameters.setRotation(rotation);
          * }
+	 * </pre>
          *
          * @param rotation The rotation angle in degrees relative to the
          *                 orientation of the camera. Rotation can only be 0,
diff --git a/core/java/android/hardware/UsbManager.java b/core/java/android/hardware/UsbManager.java
index 1003bf9..18790d2 100644
--- a/core/java/android/hardware/UsbManager.java
+++ b/core/java/android/hardware/UsbManager.java
@@ -39,24 +39,6 @@
     public static final String ACTION_USB_STATE =
             "android.hardware.action.USB_STATE";
 
-   /**
-     * Broadcast Action:  A broadcast for USB camera attached event.
-     *
-     * This intent is sent when a USB device supporting PTP is attached to the host USB bus.
-     * The intent's data contains a Uri for the device in the MTP provider.
-     */
-    public static final String ACTION_USB_CAMERA_ATTACHED =
-            "android.hardware.action.USB_CAMERA_ATTACHED";
-
-   /**
-     * Broadcast Action:  A broadcast for USB camera detached event.
-     *
-     * This intent is sent when a USB device supporting PTP is detached from the host USB bus.
-     * The intent's data contains a Uri for the device in the MTP provider.
-     */
-    public static final String ACTION_USB_CAMERA_DETACHED =
-            "android.hardware.action.USB_CAMERA_DETACHED";
-
     /**
      * Boolean extra indicating whether USB is connected or disconnected.
      * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 8150493..23b9ad5 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -22,6 +22,7 @@
 import android.app.Dialog;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.os.Bundle;
@@ -220,7 +221,7 @@
     
     InputMethodManager mImm;
     
-    int mTheme = android.R.style.Theme_InputMethod;
+    int mTheme = 0;
     
     LayoutInflater mInflater;
     TypedArray mThemeAttrs;
@@ -556,6 +557,9 @@
     }
     
     @Override public void onCreate() {
+        mTheme = Resources.selectSystemTheme(mTheme,
+                getApplicationInfo().targetSdkVersion,
+                android.R.style.Theme_InputMethod, android.R.style.Theme_Holo_InputMethod);
         super.setTheme(mTheme);
         super.onCreate();
         mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3d685cb..7e809f5 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -213,10 +213,16 @@
      */
     public static final int TYPE_WIMAX       = 6;
 
+    /**
+     * Bluetooth data connection. This is used for Bluetooth reverse tethering.
+     * @hide
+     */
+    public static final int TYPE_BLUETOOTH   = 7;
+
     /** {@hide} */
-    public static final int TYPE_DUMMY       = 7;
+    public static final int TYPE_DUMMY       = 8;
     /** {@hide} TODO: Need to adjust this for WiMAX. */
-    public static final int MAX_RADIO_TYPE   = TYPE_WIFI;
+    public static final int MAX_RADIO_TYPE   = TYPE_DUMMY;
     /** {@hide} TODO: Need to adjust this for WiMAX. */
     public static final int MAX_NETWORK_TYPE = TYPE_DUMMY;
 
diff --git a/core/java/android/net/Downloads.java b/core/java/android/net/Downloads.java
index ddde5c1..ed6d103 100644
--- a/core/java/android/net/Downloads.java
+++ b/core/java/android/net/Downloads.java
@@ -196,7 +196,7 @@
          * @return a boolean whether the download is successful.
          */
         public boolean isSuccessful() {
-            return android.provider.Downloads.Impl.isStatusCompleted(statusCode);
+            return android.provider.Downloads.Impl.isStatusSuccess(statusCode);
         }
     }
 
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index b3a354f..9ecd68c 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -221,6 +221,8 @@
                 if (!TextUtils.equals(apnType, mApnType)) {
                     return;
                 }
+                mNetworkInfo.setSubtype(TelephonyManager.getDefault().getNetworkType(),
+                        TelephonyManager.getDefault().getNetworkTypeName());
                 Phone.DataState state = Enum.valueOf(Phone.DataState.class,
                         intent.getStringExtra(Phone.STATE_KEY));
                 String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 8a653dd..f1bf852 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -125,24 +125,19 @@
 
     /**
      * Convert a IPv4 address from an integer to an InetAddress.
-     * @param hostAddr is an Int corresponding to the IPv4 address in network byte order
-     * @return the IP address as an {@code InetAddress}, returns null if
-     * unable to convert or if the int is an invalid address.
+     * @param hostAddress an int corresponding to the IPv4 address in network byte order
      */
     public static InetAddress intToInetAddress(int hostAddress) {
-        InetAddress inetAddress;
         byte[] addressBytes = { (byte)(0xff & hostAddress),
                                 (byte)(0xff & (hostAddress >> 8)),
                                 (byte)(0xff & (hostAddress >> 16)),
                                 (byte)(0xff & (hostAddress >> 24)) };
 
         try {
-           inetAddress = InetAddress.getByAddress(addressBytes);
-        } catch(UnknownHostException e) {
-           return null;
+           return InetAddress.getByAddress(addressBytes);
+        } catch (UnknownHostException e) {
+           throw new AssertionError();
         }
-
-        return inetAddress;
     }
 
     /**
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index 0ad80dd..f750122 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -65,7 +65,9 @@
      * that either the default connection or its proxy has changed.
      * The intent will have the following extra value:</p>
      * <ul>
-     *   <li><em>EXTRA_PROXY_INFO</em> - The ProxyProperties for the proxy
+     *   <li><em>EXTRA_PROXY_INFO</em> - The ProxyProperties for the proxy.  Non-null,
+     *                                   though if the proxy is undefined the host string
+     *                                   will be empty.
      * </ul>
      *
      * <p class="note">This is a protected intent that can only be sent by the system
diff --git a/core/java/android/net/http/RequestHandle.java b/core/java/android/net/http/RequestHandle.java
index 103fd94..2c48a04 100644
--- a/core/java/android/net/http/RequestHandle.java
+++ b/core/java/android/net/http/RequestHandle.java
@@ -308,7 +308,7 @@
         String A2 = mMethod  + ":" + mUrl;
 
         // because we do not preemptively send authorization headers, nc is always 1
-        String nc = "000001";
+        String nc = "00000001";
         String cnonce = computeCnonce();
         String digest = computeDigest(A1, A2, nonce, QOP, nc, cnonce);
 
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index a663fb8..cb9fc9d 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -16,6 +16,9 @@
 
 package android.nfc;
 
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.IntentFilter;
 import android.nfc.NdefMessage;
 import android.nfc.Tag;
 import android.nfc.ILlcpSocket;
@@ -44,6 +47,9 @@
     NdefMessage localGet();
     void localSet(in NdefMessage message);
     void openTagConnection(in Tag tag);
+    void enableForegroundDispatch(in ComponentName activity, in PendingIntent intent,
+        in IntentFilter[] filters);
+    void disableForegroundDispatch(in ComponentName activity);
 
     // Non-public methods
     // TODO: check and complete
diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl
index 0f96d6b..5d222d9 100644
--- a/core/java/android/nfc/INfcTag.aidl
+++ b/core/java/android/nfc/INfcTag.aidl
@@ -24,7 +24,7 @@
 interface INfcTag
 {
     int close(int nativeHandle);
-    int connect(int nativeHandle);
+    int connect(int nativeHandle, int technology);
     int reconnect(int nativeHandle);
     int[] getTechList(int nativeHandle);
     byte[] getUid(int nativeHandle);
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 758c8a0..62b75d0 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -18,8 +18,12 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.app.Activity;
 import android.app.ActivityThread;
+import android.app.OnActivityPausedListener;
+import android.app.PendingIntent;
 import android.content.Context;
+import android.content.IntentFilter;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.os.IBinder;
@@ -43,7 +47,6 @@
      *
      * If any activities respond to this intent neither
      * {@link #ACTION_TECHNOLOGY_DISCOVERED} or {@link #ACTION_TAG_DISCOVERED} will be started.
-     * @hide
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
@@ -57,7 +60,6 @@
      * {@link #ACTION_TAG_DISCOVERED}
      *
      * If any activities respond to this intent {@link #ACTION_TAG_DISCOVERED} will not be started.
-     * @hide
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_TECHNOLOGY_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
@@ -76,7 +78,6 @@
 
     /**
      * Mandatory Tag extra for the ACTION_TAG intents.
-     * @hide
      */
     public static final String EXTRA_TAG = "android.nfc.extra.TAG";
 
@@ -102,6 +103,20 @@
             "android.nfc.action.TRANSACTION_DETECTED";
 
     /**
+     * Broadcast Action: an RF field ON has been detected.
+     * @hide
+     */
+    public static final String ACTION_RF_FIELD_ON_DETECTED =
+            "android.nfc.action.RF_FIELD_ON_DETECTED";
+
+    /**
+     * Broadcast Action: an RF Field OFF has been detected.
+     * @hide
+     */
+    public static final String ACTION_RF_FIELD_OFF_DETECTED =
+            "android.nfc.action.RF_FIELD_OFF_DETECTED";
+
+    /**
      * Broadcast Action: an adapter's state changed between enabled and disabled.
      *
      * The new value is stored in the extra EXTRA_NEW_BOOLEAN_STATE and just contains
@@ -197,8 +212,7 @@
     // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
     // recovery
     private static INfcAdapter sService;
-
-    private final Context mContext;
+    private static INfcTag sTagService;
 
     /**
      * Helper to check if this device has FEATURE_NFC, but without using
@@ -235,6 +249,12 @@
                 Log.e(TAG, "could not retrieve NFC service");
                 return null;
             }
+            try {
+                sTagService = sService.getNfcTagInterface();
+            } catch (RemoteException e) {
+                Log.e(TAG, "could not retrieve NFC Tag service");
+                return null;
+            }
         }
         return sService;
     }
@@ -289,7 +309,6 @@
         if (setupService() == null) {
             throw new UnsupportedOperationException();
         }
-        mContext = context;
     }
 
     /**
@@ -297,10 +316,20 @@
      * @hide
      */
     public INfcAdapter getService() {
+        isEnabled();  // NOP call to recover sService if it is stale
         return sService;
     }
 
     /**
+     * Returns the binder interface to the tag service.
+     * @hide
+     */
+    public INfcTag getTagService() {
+        isEnabled();  // NOP call to recover sTagService if it is stale
+        return sTagService;
+    }
+
+    /**
      * NFC service dead - attempt best effort recovery
      * @hide
      */
@@ -309,11 +338,21 @@
         INfcAdapter service = getServiceInterface();
         if (service == null) {
             Log.e(TAG, "could not retrieve NFC service during service recovery");
+            // nothing more can be done now, sService is still stale, we'll hit
+            // this recovery path again later
             return;
         }
-        /* assigning to sService is not thread-safe, but this is best-effort code
-         * and on a well-behaved system should never happen */
+        // assigning to sService is not thread-safe, but this is best-effort code
+        // and on a well-behaved system should never happen
         sService = service;
+        try {
+            sTagService = service.getNfcTagInterface();
+        } catch (RemoteException ee) {
+            Log.e(TAG, "could not retrieve NFC tag service during service recovery");
+            // nothing more can be done now, sService is still stale, we'll hit
+            // this recovery path again later
+        }
+
         return;
     }
 
@@ -373,6 +412,66 @@
         }
     }
 
+    class ForegroundDispatchPausedListener implements OnActivityPausedListener {
+        @Override
+        public void onPaused(Activity activity) {
+            disableForegroundDispatchInternal(activity, true);
+        }
+    }
+
+    /**
+     * Enables foreground dispatching to the given Activity. This will force all NFC Intents that
+     * match the given filters to be delivered to the activity bypassing the standard dispatch
+     * mechanism.
+     *
+     * This method must be called from the main thread.
+     *
+     * @param activity the Activity to dispatch to
+     * @param intent the PendingIntent to start for the dispatch
+     * @param filters the IntentFilters to override dispatching for
+     * @throws IllegalStateException
+     */
+    public void enableForegroundDispatch(Activity activity, PendingIntent intent,
+            IntentFilter... filters) {
+        if (activity == null || intent == null || filters == null) {
+            throw new NullPointerException();
+        }
+        if (!activity.isResumed()) {
+            throw new IllegalStateException("Foregorund dispatching can onlly be enabled " +
+                    "when your activity is resumed");
+        }
+        try {
+            ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
+                    new ForegroundDispatchPausedListener());
+            sService.enableForegroundDispatch(activity.getComponentName(), intent, filters);
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+        }
+    }
+
+    /**
+     * Disables foreground activity dispatching setup with
+     * {@link #enableForegroundDispatch}. This must be called before the Activity returns from
+     * it's <code>onPause()</code> or this method will throw an IllegalStateException.
+     *
+     * This method must be called from the main thread.
+     */
+    public void disableForegroundDispatch(Activity activity) {
+        disableForegroundDispatchInternal(activity, false);
+    }
+
+    void disableForegroundDispatchInternal(Activity activity, boolean force) {
+        try {
+            sService.disableForegroundDispatch(activity.getComponentName());
+            if (!force && !activity.isResumed()) {
+                throw new IllegalStateException("You must disable forgeground dispatching " +
+                        "while your activity is still resumed");
+            }
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+        }
+    }
+
     /**
      * Set the NDEF Message that this NFC adapter should appear as to Tag
      * readers.
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index d042634..6cdd9f1 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -45,7 +45,7 @@
  * in {@link NfcAdapter#ACTION_TAG_DISCOVERED} intents. A {@link Tag} object is immutable
  * and represents the state of the tag at the time of discovery. It can be
  * directly queried for its UID and Type, or used to create a {@link TagTechnology}
- * (with {@link Tag#getTechnology(int)}).
+ * (with {@link Tag#getTechnology}).
  * <p>
  * A {@link Tag} can  be used to create a {@link TagTechnology} only while the tag is in
  * range. If it is removed and then returned to range, then the most recent
@@ -55,7 +55,6 @@
  * time and calls on this class will retrieve those read-only properties, and
  * not cause any further RF activity or block. Note however that arrays passed to and
  * returned by this class are *not* cloned, so be careful not to modify them.
- * @hide
  */
 public class Tag implements Parcelable {
     /*package*/ final byte[] mId;
@@ -63,6 +62,8 @@
     /*package*/ final Bundle[] mTechExtras;
     /*package*/ final int mServiceHandle;  // for use by NFC service, 0 indicates a mock
 
+    /*package*/ int mConnectedTechnology;
+
     /**
      * Hidden constructor to be used by NFC service and internal classes.
      * @hide
@@ -76,6 +77,8 @@
         // Ensure mTechExtras is as long as mTechList
         mTechExtras = Arrays.copyOf(techListExtras, techList.length);
         mServiceHandle = serviceHandle;
+
+        mConnectedTechnology = -1;
     }
 
     /**
@@ -244,4 +247,35 @@
             return new Tag[size];
         }
     };
+
+    /**
+     * For internal use only.
+     *
+     * @hide
+     */
+    public synchronized void setConnectedTechnology(int technology) {
+        if (mConnectedTechnology == -1) {
+            mConnectedTechnology = technology;
+        } else {
+            throw new IllegalStateException("Close other technology first!");
+        }
+    }
+
+    /**
+     * For internal use only.
+     *
+     * @hide
+     */
+    public int getConnectedTechnology() {
+        return mConnectedTechnology;
+    }
+
+    /**
+     * For internal use only.
+     *
+     * @hide
+     */
+    public void setTechnologyDisconnected() {
+        mConnectedTechnology = -1;
+    }
 }
diff --git a/core/java/android/nfc/technology/BasicTagTechnology.java b/core/java/android/nfc/technology/BasicTagTechnology.java
index a50c10b..f529ee5 100644
--- a/core/java/android/nfc/technology/BasicTagTechnology.java
+++ b/core/java/android/nfc/technology/BasicTagTechnology.java
@@ -22,6 +22,7 @@
 import android.nfc.INfcTag;
 import android.nfc.NfcAdapter;
 import android.nfc.Tag;
+import android.nfc.ErrorCodes;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -29,19 +30,14 @@
  * A base class for tag technologies that are built on top of transceive().
  */
 /* package */ abstract class BasicTagTechnology implements TagTechnology {
+    private static final String TAG = "NFC";
 
     /*package*/ final Tag mTag;
     /*package*/ boolean mIsConnected;
     /*package*/ int mSelectedTechnology;
     private final NfcAdapter mAdapter;
-
-    // Following fields are final after construction, except for
-    // during attemptDeadServiceRecovery() when NFC crashes.
-    // Not locked - we accept a best effort attempt when NFC crashes.
-    /*package*/ INfcAdapter mService;
-    /*package*/ INfcTag mTagService;
-
-    private static final String TAG = "NFC";
+    /*package*/ final INfcAdapter mService;
+    /*package*/ final INfcTag mTagService;
 
     /**
      * @hide
@@ -63,11 +59,7 @@
 
         mAdapter = adapter;
         mService = mAdapter.getService();
-        try {
-          mTagService = mService.getNfcTagInterface();
-        } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
-        }
+        mTagService = mAdapter.getTagService();
         mTag = tag;
         mSelectedTechnology = tech;
     }
@@ -79,19 +71,6 @@
         this(adapter, tag, tag.getTechnologyList()[0]);
     }
 
-    /** NFC service dead - attempt best effort recovery */
-    /*package*/ void attemptDeadServiceRecovery(Exception e) {
-        mAdapter.attemptDeadServiceRecovery(e);
-        /* assigning to mService is not thread-safe, but this is best-effort code
-         * and on a well-behaved system should never happen */
-        mService = mAdapter.getService();
-        try {
-            mTagService = mService.getNfcTagInterface();
-        } catch (RemoteException e2) {
-            Log.e(TAG, "second RemoteException trying to recover from dead NFC service", e2);
-        }
-    }
-
     /**
      * Get the {@link Tag} this connection is associated with.
      * <p>Requires {@link android.Manifest.permission#NFC} permission.
@@ -101,6 +80,13 @@
         return mTag;
     }
 
+    public void checkConnected() {
+       if ((mTag.getConnectedTechnology() != getTechnologyId()) ||
+               (mTag.getConnectedTechnology() == -1)) {
+           throw new IllegalStateException("Call connect() first!");
+       }
+    }
+
     /**
      * <p>Requires {@link android.Manifest.permission#NFC} permission.
      */
@@ -127,7 +113,7 @@
         try {
             return mTagService.isPresent(mTag.getServiceHandle());
         } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
+            Log.e(TAG, "NFC service dead", e);
             return false;
         }
     }
@@ -144,8 +130,53 @@
      */
     @Override
     public void connect() throws IOException {
-        //TODO(nxp): enforce exclusivity
-        mIsConnected = true;
+        try {
+            int errorCode = mTagService.connect(mTag.getServiceHandle(), getTechnologyId());
+
+            if (errorCode == ErrorCodes.SUCCESS) {
+                // Store this in the tag object
+                mTag.setConnectedTechnology(getTechnologyId());
+                mIsConnected = true;
+            } else {
+                throw new IOException();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service dead", e);
+            throw new IOException("NFC service died");
+        }
+    }
+
+    /**
+     * Re-connect to the {@link Tag} associated with this connection.
+     * <p>
+     * Reconnecting to a tag can be used to reset the state of the tag itself.
+     * This method blocks until the connection is re-established.
+     * <p>
+     * {@link #close} can be called from another thread to cancel this connection
+     * attempt.
+     * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     * @throws IOException if the target is lost, or connect canceled
+     */
+    @Override
+    public void reconnect() throws IOException {
+        if (!mIsConnected) {
+            throw new IllegalStateException("Technology not connected yet");
+        }
+
+        try {
+            int errorCode = mTagService.reconnect(mTag.getServiceHandle());
+
+            if (errorCode != ErrorCodes.SUCCESS) {
+                mIsConnected = false;
+                mTag.setTechnologyDisconnected();
+                throw new IOException();
+            }
+        } catch (RemoteException e) {
+            mIsConnected = false;
+            mTag.setTechnologyDisconnected();
+            Log.e(TAG, "NFC service dead", e);
+            throw new IOException("NFC service died");
+        }
     }
 
     /**
@@ -160,14 +191,32 @@
      */
     @Override
     public void close() {
-        mIsConnected = false;
         try {
             /* Note that we don't want to physically disconnect the tag,
              * but just reconnect to it to reset its state
              */
             mTagService.reconnect(mTag.getServiceHandle());
         } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
+            Log.e(TAG, "NFC service dead", e);
+        } finally {
+            mIsConnected = false;
+            mTag.setTechnologyDisconnected();
+        }
+    }
+
+    /** internal transceive */
+    /*package*/ byte[] transceive(byte[] data, boolean raw) throws IOException {
+        checkConnected();
+
+        try {
+            byte[] response = mTagService.transceive(mTag.getServiceHandle(), data, raw);
+            if (response == null) {
+                throw new IOException("transceive failed");
+            }
+            return response;
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service dead", e);
+            throw new IOException("NFC service died");
         }
     }
 
@@ -183,15 +232,6 @@
      * @throws IOException if the target is lost or connection closed
      */
     public byte[] transceive(byte[] data) throws IOException {
-        try {
-            byte[] response = mTagService.transceive(mTag.getServiceHandle(), data, true);
-            if (response == null) {
-                throw new IOException("transceive failed");
-            }
-            return response;
-        } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
-            throw new IOException("NFC service died");
-        }
+        return transceive(data, true);
     }
 }
diff --git a/core/java/android/nfc/technology/IsoDep.java b/core/java/android/nfc/technology/IsoDep.java
index 5346c67..b1f3ed1 100644
--- a/core/java/android/nfc/technology/IsoDep.java
+++ b/core/java/android/nfc/technology/IsoDep.java
@@ -27,7 +27,7 @@
  * A low-level connection to a {@link Tag} using the ISO-DEP technology, also known as
  * ISO1443-4.
  *
- * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * <p>You can acquire this kind of connection with {@link Tag#getTechnology}.
  * Use this class to send and receive data with {@link #transceive transceive()}.
  *
  * <p>Applications must implement their own protocol stack on top of
@@ -39,18 +39,18 @@
  */
 public final class IsoDep extends BasicTagTechnology {
     /** @hide */
-    public static final String EXTRA_ATTRIB = "attrib";
+    public static final String EXTRA_HI_LAYER_RESP = "hiresp";
     /** @hide */
     public static final String EXTRA_HIST_BYTES = "histbytes";
 
-    private byte[] mAttrib = null;
+    private byte[] mHiLayerResponse = null;
     private byte[] mHistBytes = null;
 
     public IsoDep(NfcAdapter adapter, Tag tag, Bundle extras)
             throws RemoteException {
         super(adapter, tag, TagTechnology.ISO_DEP);
         if (extras != null) {
-            mAttrib = extras.getByteArray(EXTRA_ATTRIB);
+            mHiLayerResponse = extras.getByteArray(EXTRA_HI_LAYER_RESP);
             mHistBytes = extras.getByteArray(EXTRA_HIST_BYTES);
         }
     }
@@ -58,23 +58,14 @@
     /**
      * 3A only
      */
-    public byte[] getHistoricalBytes() { return mHistBytes; }
+    public byte[] getHistoricalBytes() {
+        return mHistBytes;
+    }
 
     /**
      * 3B only
      */
-    public byte[] getAttrib() { return mAttrib; }
-
-    /**
-     * Attempts to select the given application on the tag. Note that this only works
-     * if the tag supports ISO7816-4, which not all IsoDep tags support. If the tag doesn't
-     * support ISO7816-4 this will throw {@link UnsupportedOperationException}.
-     *
-     * This method requires that you call {@link #connect} before calling it.
-     *
-     * @throws IOException, UnsupportedOperationException
-     */
-    public void selectAid(byte[] aid) throws IOException, UnsupportedOperationException {
-        throw new UnsupportedOperationException();
+    public byte[] getHiLayerResponse() {
+        return mHiLayerResponse;
     }
 }
diff --git a/core/java/android/nfc/technology/MifareClassic.java b/core/java/android/nfc/technology/MifareClassic.java
index defdcf2..c5fb361 100644
--- a/core/java/android/nfc/technology/MifareClassic.java
+++ b/core/java/android/nfc/technology/MifareClassic.java
@@ -26,13 +26,13 @@
 /**
  * Concrete class for TagTechnology.MIFARE_CLASSIC
  *
- * Mifare classic has n sectors, with varying sizes, although
- * they are at least the same pattern for any one mifare classic
+ * MIFARE Classic has n sectors, with varying sizes, although
+ * they are at least the same pattern for any one MIFARE Classic
  * product. Each sector has two keys. Authentication with the correct
  * key is needed before access to any sector.
  *
  * Each sector has k blocks.
- * Block size is constant across the whole mifare classic family.
+ * Block size is constant across the whole MIFARE classic family.
  */
 public final class MifareClassic extends BasicTagTechnology {
     /**
@@ -43,12 +43,12 @@
     public static final byte[] KEY_DEFAULT =
             {(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
     /**
-     * The well-known, default Mifare Application Directory read key.
+     * The well-known, default MIFARE Application Directory read key.
      */
     public static final byte[] KEY_MIFARE_APPLICATION_DIRECTORY =
             {(byte)0xA0,(byte)0xA1,(byte)0xA2,(byte)0xA3,(byte)0xA4,(byte)0xA5};
     /**
-     * The well-known, default read key for NDEF data on a Mifare Classic
+     * The well-known, default read key for NDEF data on a MIFARE Classic
      */
     public static final byte[] KEY_NFC_FORUM =
             {(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7};
@@ -161,7 +161,9 @@
                 mSize = SIZE_4K;
                 break;
             default:
-                // Unknown, not MIFARE
+                // Unknown mifare
+                mType = TYPE_UNKNOWN;
+                mSize = SIZE_UNKNOWN;
                 break;
         }
     }
@@ -203,6 +205,15 @@
         return getBlockCount(sector) * 16;
     }
 
+    public int getTotalBlockCount() {
+        int totalBlocks = 0;
+        for (int sec = 0; sec < getSectorCount(); sec++) {
+            totalBlocks += getSectorSize(sec);
+        }
+
+        return totalBlocks;
+    }
+
     public int getBlockCount(int sector) {
         if (sector >= getSectorCount()) {
             throw new IllegalArgumentException("this card only has " + getSectorCount() +
@@ -226,9 +237,12 @@
 
     // Methods that require connect()
     /**
-     * Authenticate for a given sector.
+     * Authenticate for a given block.
+     * Note that this will authenticate the entire sector the block belongs to.
      */
-    public boolean authenticateSector(int sector, byte[] key, boolean keyA) {
+    public boolean authenticateBlock(int block, byte[] key, boolean keyA) {
+        checkConnected();
+
         byte[] cmd = new byte[12];
 
         // First byte is the command
@@ -239,7 +253,7 @@
         }
 
         // Second byte is block address
-        cmd[1] = firstBlockInSector(sector);
+        cmd[1] = (byte) block;
 
         // Next 4 bytes are last 4 bytes of UID
         byte[] uid = getTag().getId();
@@ -249,7 +263,7 @@
         System.arraycopy(key, 0, cmd, 6, 6);
 
         try {
-            if ((transceive(cmd) != null)) {
+            if ((transceive(cmd, false) != null)) {
                 return true;
             }
         } catch (IOException e) {
@@ -259,56 +273,105 @@
     }
 
     /**
+     * Authenticate for a given sector.
+     */
+    public boolean authenticateSector(int sector, byte[] key, boolean keyA) {
+        checkConnected();
+
+        byte addr = (byte) ((firstBlockInSector(sector)) & 0xff);
+
+        // Note that authenticating a block of a sector, will authenticate
+        // the entire sector.
+        return authenticateBlock(addr, key, keyA);
+    }
+
+    /**
      * Sector indexing starts at 0.
      * Block indexing starts at 0, and resets in each sector.
      * @throws IOException
      */
     public byte[] readBlock(int sector, int block) throws IOException {
-        byte addr = (byte) ((firstBlockInSector(sector) + block) & 0xff);
-        byte[] blockread_cmd = { 0x30, addr }; // phHal_eMifareRead
+        checkConnected();
 
-        // TODO deal with authentication problems
-        return transceive(blockread_cmd);
+        byte addr = (byte) ((firstBlockInSector(sector) + block) & 0xff);
+        return readBlock(addr);
+
     }
 
-//    public byte[] readSector(int sector);
-    //TODO: define an enumeration for access control settings
-//    public int readSectorAccessControl(int sector);
-
     /**
+     * Reads absolute block index.
      * @throws IOException
-     * @throws NotAuthenticatedException
      */
-/*
-    public void writeBlock(int block, byte[] data);
-    public void writeSector(int block, byte[] sector);
-    public void writeSectorAccessControl(int sector, int access);
-    public void increment(int block);
-    public void decrement(int block);
+    public byte[] readBlock(int block) throws IOException {
+        checkConnected();
 
-*/
+        byte addr = (byte) block;
+        byte[] blockread_cmd = { 0x30, addr };
+
+        return transceive(blockread_cmd, false);
+    }
+
     /**
-     * Send data to a tag and receive the response.
-     * <p>
-     * This method will block until the response is received. It can be canceled
-     * with {@link #close}.
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param data bytes to send
-     * @return bytes received in response
-     * @throws IOException if the target is lost or connection closed
+     * Writes absolute block index.
+     * @throws IOException
      */
-    @Override
-    public byte[] transceive(byte[] data) throws IOException {
-        try {
-            byte[] response = mTagService.transceive(mTag.getServiceHandle(), data, false);
-            if (response == null) {
-                throw new IOException("transceive failed");
-            }
-            return response;
-        } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
-            throw new IOException("NFC service died");
-        }
+    public void writeBlock(int block, byte[] data) throws IOException {
+        checkConnected();
+
+        byte addr = (byte) block;
+        byte[] blockwrite_cmd = new byte[data.length + 2];
+        blockwrite_cmd[0] = (byte) 0xA0; // MF write command
+        blockwrite_cmd[1] = addr;
+        System.arraycopy(data, 0, blockwrite_cmd, 2, data.length);
+
+        transceive(blockwrite_cmd, false);
+    }
+
+    /**
+     * Writes relative block in sector.
+     * @throws IOException
+     */
+    public void writeBlock(int sector, int block, byte[] data) throws IOException {
+        checkConnected();
+
+        byte addr = (byte) ((firstBlockInSector(sector) + block) & 0xff);
+
+        writeBlock(addr, data);
+    }
+
+    public void increment(int block) throws IOException {
+        checkConnected();
+
+        byte addr = (byte) block;
+        byte[] incr_cmd = { (byte) 0xC1, (byte) block };
+
+        transceive(incr_cmd, false);
+    }
+
+    public void decrement(int block) throws IOException {
+        checkConnected();
+
+        byte addr = (byte) block;
+        byte[] decr_cmd = { (byte) 0xC0, (byte) block };
+
+        transceive(decr_cmd, false);
+    }
+
+    public void transfer(int block) throws IOException {
+        checkConnected();
+
+        byte addr = (byte) block;
+        byte[] trans_cmd = { (byte) 0xB0, (byte) block };
+
+        transceive(trans_cmd, false);
+    }
+
+    public void restore(int block) throws IOException {
+        checkConnected();
+
+        byte addr = (byte) block;
+        byte[] rest_cmd = { (byte) 0xC2, (byte) block };
+
+        transceive(rest_cmd, false);
     }
 }
diff --git a/core/java/android/nfc/technology/MifareUltralight.java b/core/java/android/nfc/technology/MifareUltralight.java
index 58d2645..e53061f 100644
--- a/core/java/android/nfc/technology/MifareUltralight.java
+++ b/core/java/android/nfc/technology/MifareUltralight.java
@@ -26,13 +26,13 @@
 /**
  * Concrete class for TagTechnology.MIFARE_ULTRALIGHT
  *
- * Mifare classic has n sectors, with varying sizes, although
- * they are at least the same pattern for any one mifare classic
+ * MIFARE Ultralight has n sectors, with varying sizes, although
+ * they are at least the same pattern for any one MIFARE Ultralight
  * product. Each sector has two keys. Authentication with the correct
  * key is needed before access to any sector.
  *
  * Each sector has k blocks.
- * Block size is constant across the whole mifare classic family.
+ * Block size is constant across the whole MIFARE Ultralight family.
  */
 public final class MifareUltralight extends BasicTagTechnology {
     public static final int TYPE_ULTRALIGHT = 1;
@@ -66,41 +66,40 @@
      * @throws IOException
      */
     public byte[] readBlock(int block) throws IOException {
-        byte[] blockread_cmd = { 0x30, (byte)block }; // phHal_eMifareRead
-        return transceive(blockread_cmd);
-    }
+        checkConnected();
 
-    /**
-     * Send data to a tag and receive the response.
-     * <p>
-     * This method will block until the response is received. It can be canceled
-     * with {@link #close}.
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param data bytes to send
-     * @return bytes received in response
-     * @throws IOException if the target is lost or connection closed
-     */
-    @Override
-    public byte[] transceive(byte[] data) throws IOException {
-        try {
-            byte[] response = mTagService.transceive(mTag.getServiceHandle(), data, false);
-            if (response == null) {
-                throw new IOException("transceive failed");
-            }
-            return response;
-        } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
-            throw new IOException("NFC service died");
-        }
+        byte[] blockread_cmd = { 0x30, (byte)block }; // phHal_eMifareRead
+        return transceive(blockread_cmd, false);
     }
 
     /**
      * @throws IOException
      */
-    /*
-    public byte[] readOTP();
-    public void writePage(int block, byte[] data);
-    public void writeBlock(int block, byte[] data);
-     */
+    public byte[] readOTP() throws IOException {
+        checkConnected();
+
+        return readBlock(3); // OTP is at page 3
+    }
+
+    public void writePage(int block, byte[] data) throws IOException {
+        checkConnected();
+
+        byte[] pagewrite_cmd = new byte[data.length + 2];
+        pagewrite_cmd[0] = (byte) 0xA2;
+        pagewrite_cmd[1] = (byte) block;
+        System.arraycopy(data, 0, pagewrite_cmd, 2, data.length);
+
+        transceive(pagewrite_cmd, false);
+    }
+
+    public void writeBlock(int block, byte[] data) throws IOException {
+        checkConnected();
+
+        byte[] blockwrite_cmd = new byte[data.length + 2];
+        blockwrite_cmd[0] = (byte) 0xA0;
+        blockwrite_cmd[1] = (byte) block;
+        System.arraycopy(data, 0, blockwrite_cmd, 2, data.length);
+
+        transceive(blockwrite_cmd, false);
+    }
 }
diff --git a/core/java/android/nfc/technology/Ndef.java b/core/java/android/nfc/technology/Ndef.java
index 7e194aa..f033220 100644
--- a/core/java/android/nfc/technology/Ndef.java
+++ b/core/java/android/nfc/technology/Ndef.java
@@ -23,6 +23,7 @@
 import android.nfc.Tag;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.util.Log;
 
 import java.io.IOException;
 
@@ -31,13 +32,15 @@
  * to interact with NDEF data. MiFare Classic cards that present NDEF data may also be used
  * via this class. To determine the exact technology being used call {@link #getTechnologyId()}
  *
- * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * <p>You can acquire this kind of connection with {@link Tag#getTechnology}.
  *
  * <p class="note"><strong>Note:</strong>
  * Use of this class requires the {@link android.Manifest.permission#NFC}
  * permission.
  */
 public final class Ndef extends BasicTagTechnology {
+    private static final String TAG = "NFC";
+
     /** @hide */
     public static final int NDEF_MODE_READ_ONLY = 1;
     /** @hide */
@@ -54,9 +57,22 @@
     /** @hide */
     public static final String EXTRA_NDEF_CARDSTATE = "ndefcardstate";
 
+    /** @hide */
+    public static final String EXTRA_NDEF_TYPE = "ndeftype";
+
+    //TODO: consider removing OTHER entirely - and not allowing Ndef to
+    // enumerate for tag types outside of (NFC Forum 1-4, MifareClassic)
+    public static final int OTHER = -1;
+    public static final int NFC_FORUM_TYPE_1 = 1;
+    public static final int NFC_FORUM_TYPE_2 = 2;
+    public static final int NFC_FORUM_TYPE_3 = 3;
+    public static final int NFC_FORUM_TYPE_4 = 4;
+    public static final int MIFARE_CLASSIC = 105;
+
     private final int mMaxNdefSize;
     private final int mCardState;
     private final NdefMessage mNdefMsg;
+    private final int mNdefType;
 
     /**
      * Internal constructor, to be used by NfcAdapter
@@ -68,6 +84,7 @@
             mMaxNdefSize = extras.getInt(EXTRA_NDEF_MAXLENGTH);
             mCardState = extras.getInt(EXTRA_NDEF_CARDSTATE);
             mNdefMsg = extras.getParcelable(EXTRA_NDEF_MSG);
+            mNdefType = extras.getInt(EXTRA_NDEF_TYPE);
         } else {
             throw new NullPointerException("NDEF tech extras are null.");
         }
@@ -92,6 +109,24 @@
     }
 
     /**
+     * Get NDEF tag type.
+     * <p>Returns one of {@link #NFC_FORUM_TYPE_1}, {@link #NFC_FORUM_TYPE_2},
+     * {@link #NFC_FORUM_TYPE_3}, {@link #NFC_FORUM_TYPE_4},
+     * {@link #MIFARE_CLASSIC} or {@link #OTHER}.
+     * <p>Platforms of this API revision will always return one of the above
+     * values. Platforms at future API revisions may return other values, which
+     * can be treated as {@link #OTHER} by applications targeting this API.
+     * <p>Android devices with NFC support must always correctly enumerate
+     * NFC Forum tag types, and may optionally enumerate
+     * {@link #MIFARE_CLASSIC} since it requires proprietary technology.
+     * Devices that cannot enumerate {@link #MIFARE_CLASSIC} will use
+     * {@link #OTHER} instead.
+     */
+    public int getType() {
+        return mNdefType;
+    }
+
+    /**
      * Get maximum NDEF message size in bytes
      */
     public int getMaxSize() {
@@ -113,6 +148,8 @@
      * and requires a connection.
      */
     public NdefMessage getNdefMessage() throws IOException, FormatException {
+        checkConnected();
+
         try {
             int serviceHandle = mTag.getServiceHandle();
             if (mTagService.isNdef(serviceHandle)) {
@@ -134,30 +171,39 @@
                 return null;
             }
         } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
+            Log.e(TAG, "NFC service dead", e);
             return null;
         }
     }
+
     /**
      * Overwrite the primary NDEF message
      * @throws IOException
      */
     public void writeNdefMessage(NdefMessage msg) throws IOException, FormatException {
+        checkConnected();
+
         try {
-            int errorCode = mTagService.ndefWrite(mTag.getServiceHandle(), msg);
-            switch (errorCode) {
-                case ErrorCodes.SUCCESS:
-                    break;
-                case ErrorCodes.ERROR_IO:
-                    throw new IOException();
-                case ErrorCodes.ERROR_INVALID_PARAM:
-                    throw new FormatException();
-                default:
-                    // Should not happen
-                    throw new IOException();
+            int serviceHandle = mTag.getServiceHandle();
+            if (mTagService.isNdef(serviceHandle)) {
+                int errorCode = mTagService.ndefWrite(serviceHandle, msg);
+                switch (errorCode) {
+                    case ErrorCodes.SUCCESS:
+                        break;
+                    case ErrorCodes.ERROR_IO:
+                        throw new IOException();
+                    case ErrorCodes.ERROR_INVALID_PARAM:
+                        throw new FormatException();
+                    default:
+                        // Should not happen
+                        throw new IOException();
+                }
+            }
+            else {
+                throw new IOException("Tag is not ndef");
             }
         } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
+            Log.e(TAG, "NFC service dead", e);
         }
     }
 
@@ -172,14 +218,33 @@
      * @throws IOException
      */
     public void writeExtraNdefMessage(int i, NdefMessage msg) throws IOException, FormatException {
+        checkConnected();
+
         throw new UnsupportedOperationException();
     }
 
     /**
-     * Set the CC field to indicate this tag is read-only
+     * Indicates whether a tag can be made read-only with
+     * {@link #makeReadonly()}
+     */
+    public boolean canMakeReadonly() {
+        if (mNdefType == NFC_FORUM_TYPE_1 || mNdefType == NFC_FORUM_TYPE_2) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Sets the CC field to indicate this tag is read-only
+     * and permanently sets the lock bits to prevent any further NDEF
+     * modifications.
+     * This is a one-way process and can not be reverted!
      * @throws IOException
      */
     public boolean makeReadonly() throws IOException {
+        checkConnected();
+
         try {
             int errorCode = mTagService.ndefMakeReadOnly(mTag.getServiceHandle());
             switch (errorCode) {
@@ -194,22 +259,15 @@
                     throw new IOException();
             }
         } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
+            Log.e(TAG, "NFC service dead", e);
             return false;
         }
     }
 
-    /**
-     * Attempt to use tag specific technology to really make
-     * the tag read-only
-     * For NFC Forum Type 1 and 2 only.
-     */
-    public void makeLowLevelReadonly() {
-        throw new UnsupportedOperationException();
-    }
-
     @Override
     public byte[] transceive(byte[] data) {
+        checkConnected();
+
         throw new UnsupportedOperationException();
     }
 }
diff --git a/core/java/android/nfc/technology/NdefFormatable.java b/core/java/android/nfc/technology/NdefFormatable.java
index bd21e58..39bd596 100644
--- a/core/java/android/nfc/technology/NdefFormatable.java
+++ b/core/java/android/nfc/technology/NdefFormatable.java
@@ -23,19 +23,22 @@
 import android.nfc.Tag;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.util.Log;
 
 import java.io.IOException;
 
 /**
  * An interface to a {@link Tag} allowing to format the tag as NDEF.
  *
- * <p>You can acquire this kind of interface with {@link Tag#getTechnology(int)}.
+ * <p>You can acquire this kind of interface with {@link Tag#getTechnology}.
  *
  * <p class="note"><strong>Note:</strong>
  * Use of this class requires the {@link android.Manifest.permission#NFC}
  * permission.
  */
 public final class NdefFormatable extends BasicTagTechnology {
+    private static final String TAG = "NFC";
+
     /**
      * Internal constructor, to be used by NfcAdapter
      * @hide
@@ -45,18 +48,12 @@
     }
 
     /**
-     * Returns whether a tag can be formatted with {@link
-     * NdefFormatable#format(NdefMessage)}
-     */
-    public boolean canBeFormatted() throws IOException {
-      throw new UnsupportedOperationException();
-    }
-
-    /**
      * Formats a tag as NDEF, if possible. You may supply a first
      * NdefMessage to be written on the tag.
      */
     public void format(NdefMessage firstMessage) throws IOException, FormatException {
+        checkConnected();
+
         try {
             byte[] DEFAULT_KEY = {(byte)0xFF,(byte)0xFF,(byte)0xFF,
                                   (byte)0xFF,(byte)0xFF,(byte)0xFF};
@@ -91,12 +88,14 @@
                 throw new IOException();
             }
         } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
+            Log.e(TAG, "NFC service dead", e);
         }
     }
 
     @Override
     public byte[] transceive(byte[] data) {
+        checkConnected();
+
         throw new UnsupportedOperationException();
     }
 }
diff --git a/core/java/android/nfc/technology/NfcA.java b/core/java/android/nfc/technology/NfcA.java
index ef46762..5cb8190 100644
--- a/core/java/android/nfc/technology/NfcA.java
+++ b/core/java/android/nfc/technology/NfcA.java
@@ -25,7 +25,7 @@
  * A low-level connection to a {@link Tag} using the NFC-A technology, also known as
  * ISO1443-3A.
  *
- * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * <p>You can acquire this kind of connection with {@link Tag#getTechnology}.
  * Use this class to send and receive data with {@link #transceive transceive()}.
  *
  * <p>Applications must implement their own protocol stack on top of
diff --git a/core/java/android/nfc/technology/NfcB.java b/core/java/android/nfc/technology/NfcB.java
index 64cb08a..dc9dd7a 100644
--- a/core/java/android/nfc/technology/NfcB.java
+++ b/core/java/android/nfc/technology/NfcB.java
@@ -25,7 +25,7 @@
  * A low-level connection to a {@link Tag} using the NFC-B technology, also known as
  * ISO1443-3B.
  *
- * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * <p>You can acquire this kind of connection with {@link Tag#getTechnology}.
  * Use this class to send and receive data with {@link #transceive transceive()}.
  *
  * <p>Applications must implement their own protocol stack on top of
@@ -37,19 +37,34 @@
  */
 public final class NfcB extends BasicTagTechnology {
     /** @hide */
-    public static final String EXTRA_ATQB = "atqb";
+    public static final String EXTRA_APPDATA = "appdata";
+    /** @hide */
+    public static final String EXTRA_PROTINFO = "protinfo";
 
-    private byte[] mAtqb;
+    private byte[] mAppData;
+    private byte[] mProtInfo;
 
     public NfcB(NfcAdapter adapter, Tag tag, Bundle extras)
             throws RemoteException {
         super(adapter, tag, TagTechnology.NFC_B);
+        mAppData = extras.getByteArray(EXTRA_APPDATA);
+        mProtInfo = extras.getByteArray(EXTRA_PROTINFO);
     }
 
     /**
-     * Returns the ATQB/SENSB_RES bytes discovered at tag discovery.
+     * Returns the Application Data bytes from the ATQB/SENSB_RES
+     * bytes discovered at tag discovery.
      */
-    public byte[] getAtqb() {
-        return mAtqb;
+    public byte[] getApplicationData() {
+        return mAppData;
     }
+
+    /**
+     * Returns the Protocol Info bytes from the ATQB/SENSB_RES
+     * bytes discovered at tag discovery.
+     */
+    public byte[] getProtocolInfo() {
+        return mProtInfo;
+    }
+
 }
diff --git a/core/java/android/nfc/technology/NfcF.java b/core/java/android/nfc/technology/NfcF.java
index 6741ac8..dd0e2f9 100644
--- a/core/java/android/nfc/technology/NfcF.java
+++ b/core/java/android/nfc/technology/NfcF.java
@@ -25,7 +25,7 @@
  * A low-level connection to a {@link Tag} using the NFC-F technology, also known as
  * JIS6319-4.
  *
- * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * <p>You can acquire this kind of connection with {@link Tag#getTechnology}.
  * Use this class to send and receive data with {@link #transceive transceive()}.
  *
  * <p>Applications must implement their own protocol stack on top of
diff --git a/core/java/android/nfc/technology/NfcV.java b/core/java/android/nfc/technology/NfcV.java
index 9b6a16a..da73f5d 100644
--- a/core/java/android/nfc/technology/NfcV.java
+++ b/core/java/android/nfc/technology/NfcV.java
@@ -25,7 +25,7 @@
  * A low-level connection to a {@link Tag} using the NFC-V technology, also known as
  * ISO15693.
  *
- * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * <p>You can acquire this kind of connection with {@link Tag#getTechnology}.
  * Use this class to send and receive data with {@link #transceive transceive()}.
  *
  * <p>Applications must implement their own protocol stack on top of
@@ -36,8 +36,27 @@
  * permission.
  */
 public final class NfcV extends BasicTagTechnology {
+    /** @hide */
+    public static final String EXTRA_RESP_FLAGS = "respflags";
+
+    /** @hide */
+    public static final String EXTRA_DSFID = "dsfid";
+
+    private byte mRespFlags;
+    private byte mDsfId;
+
     public NfcV(NfcAdapter adapter, Tag tag, Bundle extras)
             throws RemoteException {
         super(adapter, tag, TagTechnology.NFC_V);
+        mRespFlags = extras.getByte(EXTRA_RESP_FLAGS);
+        mDsfId = extras.getByte(EXTRA_DSFID);
+    }
+
+    public byte getResponseFlags() {
+        return mRespFlags;
+    }
+
+    public byte getDsfId() {
+        return mDsfId;
     }
 }
diff --git a/core/java/android/nfc/technology/TagTechnology.java b/core/java/android/nfc/technology/TagTechnology.java
index bef1cc4..62216c1 100644
--- a/core/java/android/nfc/technology/TagTechnology.java
+++ b/core/java/android/nfc/technology/TagTechnology.java
@@ -82,6 +82,11 @@
     public void connect() throws IOException;
 
     /**
+     * @throws IOException
+     */
+    public void reconnect() throws IOException;
+
+    /**
      * Non-blocking. Immediately causes all blocking calls
      * to throw IOException.
      */
diff --git a/core/java/android/nfc/technology/package.html b/core/java/android/nfc/technology/package.html
deleted file mode 100644
index 26b8a32..0000000
--- a/core/java/android/nfc/technology/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<HTML>
-<BODY>
-{@hide}
-</BODY>
-</HTML>
\ No newline at end of file
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index f0309d6..9f7e31c 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -26,6 +26,7 @@
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -111,6 +112,15 @@
  *     computation finishes. The result of the background computation is passed to
  *     this step as a parameter.</li>
  * </ol>
+ * 
+ * <h2>Cancelling a task</h2>
+ * <p>A task can be cancelled at any time by invoking {@link #cancel(boolean)}. Invoking
+ * this method will cause subsequent calls to {@link #isCancelled()} to return true.
+ * After invoking this method, {@link #onCancelled(Object)}, instead of
+ * {@link #onPostExecute(Object)} will be invoked after {@link #doInBackground(Object[])}
+ * returns. To ensure that a task is cancelled as quickly as possible, you should always
+ * check the return value of {@link #isCancelled()} periodically from
+ * {@link #doInBackground(Object[])}, if possible (inside a loop for instance.)</p>
  *
  * <h2>Threading rules</h2>
  * <p>There are a few threading rules that must be followed for this class to
@@ -157,7 +167,6 @@
 
     private static final int MESSAGE_POST_RESULT = 0x1;
     private static final int MESSAGE_POST_PROGRESS = 0x2;
-    private static final int MESSAGE_POST_CANCEL = 0x3;
 
     private static final InternalHandler sHandler = new InternalHandler();
 
@@ -165,6 +174,8 @@
     private final FutureTask<Result> mFuture;
 
     private volatile Status mStatus = Status.PENDING;
+    
+    private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
 
     /**
      * Indicates the current status of the task. Each status will be set only once
@@ -196,52 +207,49 @@
     public AsyncTask() {
         mWorker = new WorkerRunnable<Params, Result>() {
             public Result call() throws Exception {
+                mTaskInvoked.set(true);
+
                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-                return doInBackground(mParams);
+                return postResult(doInBackground(mParams));
             }
         };
 
         mFuture = new FutureTask<Result>(mWorker) {
-
-            @Override
-            protected void set(Result v) {
-                super.set(v);
-                if (isCancelled()) {
-                    Message message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
-                            new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
-                    message.sendToTarget();
-                }
-            }
-
             @Override
             protected void done() {
-                Message message;
-                Result result = null;
-
                 try {
-                    result = get();
+                    final Result result = get();
+
+                    postResultIfNotInvoked(result);
                 } catch (InterruptedException e) {
                     android.util.Log.w(LOG_TAG, e);
                 } catch (ExecutionException e) {
                     throw new RuntimeException("An error occured while executing doInBackground()",
                             e.getCause());
                 } catch (CancellationException e) {
-                    message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
-                            new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
-                    message.sendToTarget();
-                    return;
+                    postResultIfNotInvoked(null);
                 } catch (Throwable t) {
                     throw new RuntimeException("An error occured while executing "
                             + "doInBackground()", t);
                 }
-
-                message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
-                        new AsyncTaskResult<Result>(AsyncTask.this, result));
-                message.sendToTarget();
             }
         };
     }
 
+    private void postResultIfNotInvoked(Result result) {
+        final boolean wasTaskInvoked = mTaskInvoked.get();
+        if (!wasTaskInvoked) {
+            postResult(result);
+        }
+    }
+
+    private Result postResult(Result result) {
+        Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
+                new AsyncTaskResult<Result>(this, result));
+        message.sendToTarget();
+        return result;
+    }
+
     /**
      * Returns the current status of this task.
      *
@@ -279,14 +287,16 @@
     }
 
     /**
-     * Runs on the UI thread after {@link #doInBackground}. The
-     * specified result is the value returned by {@link #doInBackground}
-     * or null if the task was cancelled or an exception occured.
+     * <p>Runs on the UI thread after {@link #doInBackground}. The
+     * specified result is the value returned by {@link #doInBackground}.</p>
+     * 
+     * <p>This method won't be invoked if the task was cancelled.</p>
      *
      * @param result The result of the operation computed by {@link #doInBackground}.
      *
      * @see #onPreExecute
      * @see #doInBackground
+     * @see #onCancelled(Object) 
      */
     @SuppressWarnings({"UnusedDeclaration"})
     protected void onPostExecute(Result result) {
@@ -306,8 +316,33 @@
     }
 
     /**
-     * Runs on the UI thread after {@link #cancel(boolean)} is invoked.
+     * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
+     * {@link #doInBackground(Object[])} has finished.</p>
+     * 
+     * <p>The default implementation simply invokes {@link #onCancelled()} and
+     * ignores the result. If you write your own implementation, do not call
+     * <code>super.onCancelled(result)</code>.</p>
      *
+     * @param result The result, if any, computed in
+     *               {@link #doInBackground(Object[])}, can be null
+     * 
+     * @see #cancel(boolean)
+     * @see #isCancelled()
+     */
+    @SuppressWarnings({"UnusedParameters"})
+    protected void onCancelled(Result result) {
+        onCancelled();
+    }    
+    
+    /**
+     * <p>Applications should preferably override {@link #onCancelled(Object)}.
+     * This method is invoked by the default implementation of
+     * {@link #onCancelled(Object)}.</p>
+     * 
+     * <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
+     * {@link #doInBackground(Object[])} has finished.</p>
+     *
+     * @see #onCancelled(Object) 
      * @see #cancel(boolean)
      * @see #isCancelled()
      */
@@ -316,7 +351,9 @@
 
     /**
      * Returns <tt>true</tt> if this task was cancelled before it completed
-     * normally.
+     * normally. If you are calling {@link #cancel(boolean)} on the task,
+     * the value returned by this method should be checked periodically from
+     * {@link #doInBackground(Object[])} to end the task as soon as possible.
      *
      * @return <tt>true</tt> if task was cancelled before it completed
      *
@@ -327,14 +364,22 @@
     }
 
     /**
-     * Attempts to cancel execution of this task.  This attempt will
+     * <p>Attempts to cancel execution of this task.  This attempt will
      * fail if the task has already completed, already been cancelled,
      * or could not be cancelled for some other reason. If successful,
      * and this task has not started when <tt>cancel</tt> is called,
-     * this task should never run.  If the task has already started,
+     * this task should never run. If the task has already started,
      * then the <tt>mayInterruptIfRunning</tt> parameter determines
      * whether the thread executing this task should be interrupted in
-     * an attempt to stop the task.
+     * an attempt to stop the task.</p>
+     * 
+     * <p>Calling this method will result in {@link #onCancelled(Object)} being
+     * invoked on the UI thread after {@link #doInBackground(Object[])}
+     * returns. Calling this method guarantees that {@link #onPostExecute(Object)}
+     * is never invoked. After invoking this method, you should check the
+     * value returned by {@link #isCancelled()} periodically from
+     * {@link #doInBackground(Object[])} to finish the task as early as
+     * possible.</p>
      *
      * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
      *        task should be interrupted; otherwise, in-progress tasks are allowed
@@ -345,7 +390,7 @@
      *         <tt>true</tt> otherwise
      *
      * @see #isCancelled()
-     * @see #onCancelled()
+     * @see #onCancelled(Object)
      */
     public final boolean cancel(boolean mayInterruptIfRunning) {
         return mFuture.cancel(mayInterruptIfRunning);
@@ -444,8 +489,11 @@
     }
 
     private void finish(Result result) {
-        if (isCancelled()) result = null;
-        onPostExecute(result);
+        if (isCancelled()) {
+            onCancelled(result);
+        } else {
+            onPostExecute(result);
+        }
         mStatus = Status.FINISHED;
     }
 
@@ -462,9 +510,6 @@
                 case MESSAGE_POST_PROGRESS:
                     result.mTask.onProgressUpdate(result.mData);
                     break;
-                case MESSAGE_POST_CANCEL:
-                    result.mTask.onCancelled();
-                    break;
             }
         }
     }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 7dd5e31..6e6731e 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -132,6 +132,7 @@
     private static final String NETWORK_DATA = "nt";
     private static final String USER_ACTIVITY_DATA = "ua";
     private static final String BATTERY_DATA = "bt";
+    private static final String BATTERY_DISCHARGE_DATA = "dc";
     private static final String BATTERY_LEVEL_DATA = "lv";
     private static final String WIFI_LOCK_DATA = "wfl";
     private static final String MISC_DATA = "m";
@@ -804,6 +805,30 @@
     public abstract int getHighDischargeAmountSinceCharge();
 
     /**
+     * Get the amount the battery has discharged while the screen was on,
+     * since the last time power was unplugged.
+     */
+    public abstract int getDischargeAmountScreenOn();
+
+    /**
+     * Get the amount the battery has discharged while the screen was on,
+     * since the last time the device was charged.
+     */
+    public abstract int getDischargeAmountScreenOnSinceCharge();
+
+    /**
+     * Get the amount the battery has discharged while the screen was off,
+     * since the last time power was unplugged.
+     */
+    public abstract int getDischargeAmountScreenOff();
+
+    /**
+     * Get the amount the battery has discharged while the screen was off,
+     * since the last time the device was charged.
+     */
+    public abstract int getDischargeAmountScreenOffSinceCharge();
+
+    /**
      * Returns the total, last, or current battery uptime in microseconds.
      *
      * @param curTime the elapsed realtime in microseconds.
@@ -1098,6 +1123,17 @@
                     getDischargeCurrentLevel());
         }
         
+        if (which == STATS_SINCE_UNPLUGGED) {
+            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
+                    getDischargeStartLevel()-getDischargeCurrentLevel(),
+                    getDischargeStartLevel()-getDischargeCurrentLevel(),
+                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
+        } else {
+            dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
+                    getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
+                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
+        }
+        
         if (reqUid < 0) {
             Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
             if (kernelWakelocks.size() > 0) {
@@ -1454,6 +1490,10 @@
                 pw.print(prefix); pw.print("    Last discharge cycle end level: "); 
                         pw.println(getDischargeCurrentLevel());
             }
+            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
+                    pw.println(getDischargeAmountScreenOn());
+            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
+                    pw.println(getDischargeAmountScreenOff());
             pw.println(" ");
         } else {
             pw.print(prefix); pw.println("  Device battery use since last full charge");
@@ -1461,6 +1501,10 @@
                     pw.println(getLowDischargeAmountSinceCharge());
             pw.print(prefix); pw.print("    Amount discharged (upper bound): ");
                     pw.println(getHighDischargeAmountSinceCharge());
+            pw.print(prefix); pw.print("    Amount discharged while screen on: ");
+                    pw.println(getDischargeAmountScreenOnSinceCharge());
+            pw.print(prefix); pw.print("    Amount discharged while screen off: ");
+                    pw.println(getDischargeAmountScreenOffSinceCharge());
             pw.println(" ");
         }
         
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 8d9867e..87aeccb 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -559,18 +559,57 @@
         /* cumulative elapsed time for class initialization, in usec */
         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
     }
+
+    /**
+     * Returns the global count of external allocation requests.  The
+     * external allocation tracking feature was removed in Honeycomb.
+     * This method exists for compatibility and always returns 0.
+     *
+     * @deprecated This method is now obsolete.
+     */
+    @Deprecated
     public static int getGlobalExternalAllocCount() {
-        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_OBJECTS);
+        return 0;
     }
+
+    /**
+     * Returns the global count of bytes externally allocated.  The
+     * external allocation tracking feature was removed in Honeycomb.
+     * This method exists for compatibility and always returns 0.
+     *
+     * @deprecated This method is now obsolete.
+     */
+    @Deprecated
     public static int getGlobalExternalAllocSize() {
-        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_BYTES);
+        return 0;
     }
+
+    /**
+     * Returns the global count of freed external allocation requests.
+     * The external allocation tracking feature was removed in
+     * Honeycomb.  This method exists for compatibility and always
+     * returns 0.
+     *
+     * @deprecated This method is now obsolete.
+     */
+    @Deprecated
     public static int getGlobalExternalFreedCount() {
-        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_OBJECTS);
+        return 0;
     }
+
+    /**
+     * Returns the global count of freed bytes from external
+     * allocation requests.  The external allocation tracking feature
+     * was removed in Honeycomb.  This method exists for compatibility
+     * and always returns 0.
+     *
+     * @deprecated This method is now obsolete.
+     */
+    @Deprecated
     public static int getGlobalExternalFreedSize() {
-        return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_BYTES);
+        return 0;
     }
+
     public static int getGlobalGcInvocationCount() {
         return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
     }
@@ -580,12 +619,32 @@
     public static int getThreadAllocSize() {
         return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
     }
+
+    /**
+     * Returns the count of external allocation requests made by the
+     * current thread.  The external allocation tracking feature was
+     * removed in Honeycomb.  This method exists for compatibility and
+     * always returns 0.
+     *
+     * @deprecated This method is now obsolete.
+     */
+    @Deprecated
     public static int getThreadExternalAllocCount() {
-        return VMDebug.getAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_OBJECTS);
+        return 0;
     }
+
+    /**
+     * Returns the global count of bytes externally allocated.  The
+     * external allocation tracking feature was removed in Honeycomb.
+     * This method exists for compatibility and always returns 0.
+     *
+     * @deprecated This method is now obsolete.
+     */
+    @Deprecated
     public static int getThreadExternalAllocSize() {
-        return VMDebug.getAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_BYTES);
+        return 0;
     }
+
     public static int getThreadGcInvocationCount() {
         return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
     }
@@ -608,18 +667,48 @@
     public static void resetGlobalClassInitTime() {
         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
     }
-    public static void resetGlobalExternalAllocCount() {
-        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_OBJECTS);
-    }
-    public static void resetGlobalExternalAllocSize() {
-        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_ALLOCATED_BYTES);
-    }
-    public static void resetGlobalExternalFreedCount() {
-        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_OBJECTS);
-    }
-    public static void resetGlobalExternalFreedSize() {
-        VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_EXT_FREED_BYTES);
-    }
+
+    /**
+     * Resets the global count of external allocation requests.  The
+     * external allocation tracking feature was removed in Honeycomb.
+     * This method exists for compatibility and has no effect.
+     *
+     * @deprecated This method is now obsolete.
+     */
+    @Deprecated
+    public static void resetGlobalExternalAllocCount() {}
+
+    /**
+     * Resets the global count of bytes externally allocated.  The
+     * external allocation tracking feature was removed in Honeycomb.
+     * This method exists for compatibility and has no effect.
+     *
+     * @deprecated This method is now obsolete.
+     */
+    @Deprecated
+    public static void resetGlobalExternalAllocSize() {}
+
+    /**
+     * Resets the global count of freed external allocations.  The
+     * external allocation tracking feature was removed in Honeycomb.
+     * This method exists for compatibility and has no effect.
+     *
+     * @deprecated This method is now obsolete.
+     */
+    @Deprecated
+    public static void resetGlobalExternalFreedCount() {}
+
+    /**
+     * Resets the global count counter of freed bytes from external
+     * allocations.  The external allocation tracking feature was
+     * removed in Honeycomb.  This method exists for compatibility and
+     * has no effect.
+     *
+     * @deprecated This method is now obsolete.
+     */
+    @Deprecated
+    public static void resetGlobalExternalFreedSize() {}
+
     public static void resetGlobalGcInvocationCount() {
         VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
     }
@@ -629,12 +718,29 @@
     public static void resetThreadAllocSize() {
         VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
     }
-    public static void resetThreadExternalAllocCount() {
-        VMDebug.resetAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_OBJECTS);
-    }
-    public static void resetThreadExternalAllocSize() {
-        VMDebug.resetAllocCount(VMDebug.KIND_THREAD_EXT_ALLOCATED_BYTES);
-    }
+
+    /**
+     * Resets the count of external allocation requests made by the
+     * current thread.  The external allocation tracking feature was
+     * removed in Honeycomb.  This method exists for compatibility and
+     * has no effect.
+     *
+     * @deprecated This method is now obsolete.
+     */
+    @Deprecated
+    public static void resetThreadExternalAllocCount() {}
+
+    /**
+     * Resets the count of bytes externally allocated by the current
+     * thread.  The external allocation tracking feature was removed
+     * in Honeycomb.  This method exists for compatibility and has no
+     * effect.
+     *
+     * @deprecated This method is now obsolete.
+     */
+    @Deprecated
+    public static void resetThreadExternalAllocSize() {}
+
     public static void resetThreadGcInvocationCount() {
         VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
     }
@@ -674,50 +780,30 @@
     public static native void getMemoryInfo(int pid, MemoryInfo memoryInfo);
 
     /**
-     * Establish an object allocation limit in the current thread.  Useful
-     * for catching regressions in code that is expected to operate
-     * without causing any allocations.
+     * Establish an object allocation limit in the current thread.
+     * This feature was never enabled in release builds.  The
+     * allocation limits feature was removed in Honeycomb.  This
+     * method exists for compatibility and always returns -1 and has
+     * no effect.
      *
-     * <p>Pass in the maximum number of allowed allocations.  Use -1 to disable
-     * the limit.  Returns the previous limit.</p>
-     *
-     * <p>The preferred way to use this is:
-     * <pre>
-     *  int prevLimit = -1;
-     *  try {
-     *      prevLimit = Debug.setAllocationLimit(0);
-     *      ... do stuff that's not expected to allocate memory ...
-     *  } finally {
-     *      Debug.setAllocationLimit(prevLimit);
-     *  }
-     * </pre>
-     * This allows limits to be nested.  The try/finally ensures that the
-     * limit is reset if something fails.</p>
-     *
-     * <p>Exceeding the limit causes a dalvik.system.AllocationLimitError to
-     * be thrown from a memory allocation call.  The limit is reset to -1
-     * when this happens.</p>
-     *
-     * <p>The feature may be disabled in the VM configuration.  If so, this
-     * call has no effect, and always returns -1.</p>
+     * @deprecated This method is now obsolete.
      */
+    @Deprecated
     public static int setAllocationLimit(int limit) {
-        return VMDebug.setAllocationLimit(limit);
+        return -1;
     }
 
     /**
-     * Establish a global object allocation limit.  This is similar to
-     * {@link #setAllocationLimit(int)} but applies to all threads in
-     * the VM.  It will coexist peacefully with per-thread limits.
+     * Establish a global object allocation limit.  This feature was
+     * never enabled in release builds.  The allocation limits feature
+     * was removed in Honeycomb.  This method exists for compatibility
+     * and always returns -1 and has no effect.
      *
-     * [ The value of "limit" is currently restricted to 0 (no allocations
-     *   allowed) or -1 (no global limit).  This may be changed in a future
-     *   release. ]
+     * @deprecated This method is now obsolete.
      */
+    @Deprecated
     public static int setGlobalAllocationLimit(int limit) {
-        if (limit != 0 && limit != -1)
-            throw new IllegalArgumentException("limit must be 0 or -1");
-        return VMDebug.setGlobalAllocationLimit(limit);
+        return -1;
     }
 
     /**
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 4688847..4f188f8 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -414,8 +414,6 @@
      * emulated. If true, the device does not have real external storage
      * and certain system services such as the package manager use this
      * to determine where to install an application.
-     *
-     * @hide
      */
     public static boolean isExternalStorageEmulated() {
         if (mIsExternalStorageEmulated == null) {
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index 174f3b6..8ae8008 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -162,7 +162,7 @@
      * @param code The action to perform.  This should
      * be a number between {@link #FIRST_CALL_TRANSACTION} and
      * {@link #LAST_CALL_TRANSACTION}.
-     * @param data Marshalled data to send to the target.  Most not be null.
+     * @param data Marshalled data to send to the target.  Must not be null.
      * If you are not sending any data, you must create an empty Parcel
      * that is given here.
      * @param reply Marshalled data to be received from the target.  May be
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 5f6c4f0..3a5d26b 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -153,6 +153,7 @@
     private static native int createPipeNative(FileDescriptor[] outFds);
 
     /**
+     * @hide Please use createPipe() or ContentProvider.openPipeHelper().
      * Gets a file descriptor for a read-only copy of the given data.
      *
      * @param data Data to copy.
@@ -161,6 +162,7 @@
      * @return A ParcelFileDescriptor.
      * @throws IOException if there is an error while creating the shared memory area.
      */
+    @Deprecated
     public static ParcelFileDescriptor fromData(byte[] data, String name) throws IOException {
         if (data == null) return null;
         MemoryFile file = new MemoryFile(name, data.length);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 507cfab..0c6ab9e 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -98,6 +98,12 @@
     public static final int NFC_UID = 1022;
 
     /**
+     * Defines the GID for the group that allows write access to the internal media storage.
+     * @hide
+     */
+    public static final int MEDIA_RW_GID = 1023;
+
+    /**
      * Defines the start of a range of UIDs (and GIDs), going from this
      * number to {@link #LAST_APPLICATION_UID} that are reserved for assigning
      * to applications.
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index e314fce..0f062cc 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1632,7 +1632,6 @@
      */
     public static void noteDiskRead() {
         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
-        Log.d(TAG, "noteDiskRead; policy=" + policy);
         if (!(policy instanceof AndroidBlockGuardPolicy)) {
             // StrictMode not enabled.
             return;
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 3a2add4..b9d4711 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -586,6 +586,40 @@
                 }
                 return _result;
             }
+
+            public int decryptStorage(String password) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                int _result;
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(password);
+                    mRemote.transact(Stub.TRANSACTION_decryptStorage, _data, _reply, 0);
+                    _reply.readException();
+                    _result = _reply.readInt();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+                return _result;
+            }
+
+            public int encryptStorage(String password) throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                int _result;
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(password);
+                    mRemote.transact(Stub.TRANSACTION_encryptStorage, _data, _reply, 0);
+                    _reply.readException();
+                    _result = _reply.readInt();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+                return _result;
+            }
         }
 
         private static final String DESCRIPTOR = "IMountService";
@@ -642,6 +676,10 @@
 
         static final int TRANSACTION_isExternalStorageEmulated = IBinder.FIRST_CALL_TRANSACTION + 25;
 
+        static final int TRANSACTION_decryptStorage = IBinder.FIRST_CALL_TRANSACTION + 26;
+
+        static final int TRANSACTION_encryptStorage = IBinder.FIRST_CALL_TRANSACTION + 27;
+
         /**
          * Cast an IBinder object into an IMountService interface, generating a
          * proxy if needed.
@@ -923,6 +961,22 @@
                     reply.writeInt(emulated ? 1 : 0);
                     return true;
                 }
+                case TRANSACTION_decryptStorage: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String password = data.readString();
+                    int result = decryptStorage(password);
+                    reply.writeNoException();
+                    reply.writeInt(result);
+                    return true;
+                }
+                case TRANSACTION_encryptStorage: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String password = data.readString();
+                    int result = encryptStorage(password);
+                    reply.writeNoException();
+                    reply.writeInt(result);
+                    return true;
+                }
             }
             return super.onTransact(code, data, reply, flags);
         }
@@ -1082,4 +1136,14 @@
      * Returns whether or not the external storage is emulated.
      */
     public boolean isExternalStorageEmulated() throws RemoteException;
+
+    /**
+     * Decrypts any encrypted volumes.
+     */
+    public int decryptStorage(String password) throws RemoteException;
+
+    /**
+     * Encrypts storage.
+     */
+    public int encryptStorage(String password) throws RemoteException;
 }
diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java
index b93dfd8..3401cb1 100644
--- a/core/java/android/provider/AlarmClock.java
+++ b/core/java/android/provider/AlarmClock.java
@@ -68,4 +68,15 @@
      * 59.
      */
     public static final String EXTRA_MINUTES = "android.intent.extra.alarm.MINUTES";
+
+    /**
+     * Activity Extra: Optionally skip the application UI.
+     * <p>
+     * This value can be passed as an extra field to the Intent created with
+     * ACTION_SET_ALARM.  If true, the application is asked to bypass any
+     * intermediate UI and instead pop a toast indicating the result then
+     * finish the Activity.  If false, the application may display intermediate
+     * UI like a confirmation dialog or alarm settings.  The default is false.
+     */
+    public static final String EXTRA_SKIP_UI = "android.intent.extra.alarm.SKIP_UI";
 }
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 14d6485..3bfd005 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -26,6 +26,7 @@
 import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.provider.BrowserContract.Bookmarks;
+import android.provider.BrowserContract.Combined;
 import android.provider.BrowserContract.History;
 import android.provider.BrowserContract.Searches;
 import android.util.Log;
@@ -244,8 +245,9 @@
      */
     public static final Cursor getAllVisitedUrls(ContentResolver cr) throws
             IllegalStateException {
-        return cr.query(History.CONTENT_URI,
-                new String[] { History.URL }, null, null, null);
+        return cr.query(Combined.CONTENT_URI,
+                new String[] { Combined.URL }, null, null,
+                Combined.DATE_CREATED + " ASC");
     }
 
     private static final void addOrUrlEquals(StringBuilder sb) {
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d1ca0c9..ee091f0 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3430,12 +3430,6 @@
      * <th colspan='4'>PhoneLookup</th>
      * </tr>
      * <tr>
-     * <td>long</td>
-     * <td>{@link #_ID}</td>
-     * <td>read-only</td>
-     * <td>Data row ID.</td>
-     * </tr>
-     * <tr>
      * <td>String</td>
      * <td>{@link #NUMBER}</td>
      * <td>read-only</td>
@@ -3462,6 +3456,12 @@
      * <th colspan='4'>Join with {@link Contacts}</th>
      * </tr>
      * <tr>
+     * <td>long</td>
+     * <td>{@link #_ID}</td>
+     * <td>read-only</td>
+     * <td>Contact ID.</td>
+     * </tr>
+     * <tr>
      * <td>String</td>
      * <td>{@link #LOOKUP_KEY}</td>
      * <td>read-only</td>
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index fb4bed7..9f0ea32 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -1028,6 +1028,13 @@
             public static final String ALBUM_ARTIST = "album_artist";
 
             /**
+             * Whether the song is part of a compilation
+             * <P>Type: TEXT</P>
+             * @hide
+             */
+            public static final String COMPILATION = "compilation";
+
+            /**
              * A non human readable key calculated from the ARTIST, used for
              * searching, sorting and grouping
              * <P>Type: TEXT</P>
diff --git a/core/java/android/provider/Ptp.java b/core/java/android/provider/Ptp.java
deleted file mode 100644
index 0072f3d..0000000
--- a/core/java/android/provider/Ptp.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import android.content.ContentUris;
-import android.net.Uri;
-import android.util.Log;
-
-/**
- * The PTP provider supports accessing content on PTP devices.
- * Currently the provider supports:
- * - enumerating the storage units, files and directories on PTP devices
- * - deleting files and directories on PTP devices
- * - importing a file from PTP device into the host device's storage
- *   and adding it to the media provider
- *
- * @hide
- */
-public final class Ptp
-{
-    private final static String TAG = "Ptp";
-
-    public static final String AUTHORITY = "ptp";
-
-    private static final String CONTENT_AUTHORITY_SLASH = "content://" + AUTHORITY + "/";
-    private static final String CONTENT_AUTHORITY_DEVICE_SLASH = "content://" + AUTHORITY + "/device/";
-
-    /**
-     * Contains list of all PTP devices
-     * The BaseColumns._ID column contains a hardware specific identifier for the attached
-     * USB device, and is not guaranteed to be persistent across USB disconnects.
-     */
-    public static final class Device implements BaseColumns {
-
-        public static final Uri CONTENT_URI = Uri.parse(CONTENT_AUTHORITY_SLASH + "device");
-
-        public static Uri getContentUri(int deviceID) {
-            return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID);
-        }
-
-        /**
-         * The manufacturer of the device
-         * <P>Type: TEXT</P>
-         */
-        public static final String MANUFACTURER = "manufacturer";
-
-        /**
-         * The model name of the device
-         * <P>Type: TEXT</P>
-         */
-        public static final String MODEL = "model";
-    }
-
-    /**
-     * Contains list of storage units for an PTP device.
-     * The BaseColumns._ID column contains the PTP StorageID for the storage unit.
-     */
-    public static final class Storage implements BaseColumns {
-
-        public static Uri getContentUri(int deviceID) {
-            return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID + "/storage");
-        }
-
-        public static Uri getContentUri(int deviceID, long storageID) {
-            return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID + "/storage/" + storageID);
-        }
-
-        /**
-         * Storage unit identifier
-         * <P>Type: TEXT</P>
-         */
-        public static final String IDENTIFIER = "identifier";
-
-        /**
-         * Storage unit description
-         * <P>Type: TEXT</P>
-         */
-        public static final String DESCRIPTION = "description";
-    }
-
-    /**
-     * Contains list of objects on a PTP device.
-     * The columns in this table correspond directly to the ObjectInfo dataset
-     * described in the PTP specification (PIMA 15740:2000).
-     * The BaseColumns._ID column contains the object's PTP ObjectHandle.
-     */
-    public static final class Object implements BaseColumns {
-
-        public static Uri getContentUri(int deviceID, long objectID) {
-            return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
-                    + "/object/" + objectID);
-        }
-
-        public static Uri getContentUriForObjectChildren(int deviceID, long objectID) {
-            return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
-                    + "/object/" + objectID + "/child");
-        }
-
-        public static Uri getContentUriForStorageChildren(int deviceID, long storageID) {
-            return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
-                    + "/storage/" + storageID + "/child");
-        }
-
-        /**
-         * Used for copying files from device to host.
-         * Constructs a Uri based on the ID of the device and object for the source file,
-         * and the path for the destination file.
-         * When passed to the ContentProvider.insert() method, the file will be transferred
-         * to the specified destination directory and insert() will return a content Uri
-         * for the new file in the MediaProvider.
-         * ContentProvider.insert() will throw IllegalArgumentException if the destination
-         * path is not in the external storage or internal media directory.
-         */
-        public static Uri getContentUriForImport(int deviceID, long objectID, String destPath) {
-            if (destPath.length() == 0 || destPath.charAt(0) != '/') {
-                throw new IllegalArgumentException(
-                        "destPath must be a full path in getContentUriForImport");
-            }
-            return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
-                    + "/import/" + objectID + "?" +  destPath);
-        }
-
-        /**
-         * The following columns correspond to the fields in the ObjectInfo dataset
-         * as described in the PTP specification.
-         */
-
-        /**
-         * The ID of the storage unit containing the object.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String STORAGE_ID = "storage_id";
-
-        /**
-         * The object's format.  Can be any of the valid PTP object formats
-         * as defined in the PTP specification.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String FORMAT = "format";
-
-        /**
-         * The protection status of the object.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String PROTECTION_STATUS = "protection_status";
-
-        /**
-         * The size of the object in bytes.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String SIZE = "size";
-
-        /**
-         * The object's thumbnail format.  Can be any of the valid PTP object formats
-         * as defined in the PTP specification.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String THUMB_FORMAT = "thumb_format";
-
-        /**
-         * The size of the object's thumbnail in bytes.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String THUMB_SIZE = "thumb_size";
-
-        /**
-         * The width of the object's thumbnail in pixels.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String THUMB_WIDTH = "thumb_width";
-
-        /**
-         * The height of the object's thumbnail in pixels.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String THUMB_HEIGHT = "thumb_height";
-
-        /**
-         * The object's thumbnail.
-         * <P>Type: BLOB</P>
-         */
-        public static final String THUMB = "thumb";
-
-        /**
-         * The width of the object in pixels.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String IMAGE_WIDTH = "image_width";
-
-        /**
-         * The height of the object in pixels.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String IMAGE_HEIGHT = "image_height";
-
-        /**
-         * The depth of the object in bits per pixel.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String IMAGE_DEPTH = "image_depth";
-
-        /**
-         * The ID of the object's parent, or zero if the object
-         * is in the root of its storage unit.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String PARENT = "parent";
-
-        /**
-         * The association type for a container object.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String ASSOCIATION_TYPE = "association_type";
-
-        /**
-         * Contains additional information about container objects.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String ASSOCIATION_DESC = "association_desc";
-
-        /**
-         * The sequence number of the object, typically used for an association
-         * containing images taken in sequence.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String SEQUENCE_NUMBER = "sequence_number";
-
-        /**
-         * The name of the object.
-         * <P>Type: TEXT</P>
-         */
-        public static final String NAME = "name";
-
-        /**
-         * The date the object was created, in seconds since January 1, 1970.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String DATE_CREATED = "date_created";
-
-        /**
-         * The date the object was last modified, in seconds since January 1, 1970.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String DATE_MODIFIED = "date_modified";
-
-        /**
-         * A list of keywords associated with an object, separated by spaces.
-         * <P>Type: TEXT</P>
-         */
-        public static final String KEYWORDS = "keywords";
-    }
-}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 873674d2..cec99e9 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3244,8 +3244,8 @@
 
         /**
          * Minimum percentage of free storage on the device that is used to determine if
-         * the device is running low on storage.
-         * Say this value is set to 10, the device is considered running low on storage
+         * the device is running low on storage.  The default is 10.
+         * <p>Say this value is set to 10, the device is considered running low on storage
          * if 90% or more of the device storage is filled up.
          * @hide
          */
@@ -3253,6 +3253,16 @@
                 "sys_storage_threshold_percentage";
 
         /**
+         * Maximum byte size of the low storage threshold.  This is to ensure
+         * that {@link #SYS_STORAGE_THRESHOLD_PERCENTAGE} does not result in
+         * an overly large threshold for large storage devices.  Currently this
+         * must be less than 2GB.  This default is 500MB.
+         * @hide
+         */
+        public static final String SYS_STORAGE_THRESHOLD_MAX_BYTES =
+                "sys_storage_threshold_max_bytes";
+
+        /**
          * Minimum bytes of free storage on the device before the data
          * partition is considered full. By default, 1 MB is reserved
          * to avoid system-wide SQLite disk full exceptions.
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 3b2e254..539a696 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -420,12 +420,16 @@
         if (name.equals("Connected")) {
             if (propValues[1].equals("false")) {
                 mBluetoothService.handlePanDeviceStateChange(device,
-                                          BluetoothInputDevice.STATE_DISCONNECTED);
+                                          BluetoothPan.STATE_DISCONNECTED,
+                                          BluetoothPan.LOCAL_PANU_ROLE);
             }
         } else if (name.equals("Interface")) {
             String iface = propValues[1];
-            mBluetoothService.handlePanDeviceStateChange(device, iface,
-                                            BluetoothInputDevice.STATE_CONNECTED);
+            if (!iface.equals("")) {
+                mBluetoothService.handlePanDeviceStateChange(device, iface,
+                                              BluetoothPan.STATE_CONNECTED,
+                                              BluetoothPan.LOCAL_PANU_ROLE);
+            }
         }
     }
 
@@ -489,7 +493,7 @@
         mWakeLock.acquire();
         Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PASSKEY, passkey);
+        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, passkey);
         intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
                 BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION);
         mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
@@ -519,6 +523,9 @@
 
         String pendingOutgoingAddress =
                 mBluetoothService.getPendingOutgoingBonding();
+        BluetoothClass btClass = new BluetoothClass(mBluetoothService.getRemoteClass(address));
+        int btDeviceClass = btClass.getDeviceClass();
+
         if (address.equals(pendingOutgoingAddress)) {
             // we initiated the bonding
 
@@ -529,10 +536,8 @@
                 return;
             }
 
-            BluetoothClass btClass = new BluetoothClass(mBluetoothService.getRemoteClass(address));
-
             // try 0000 once if the device looks dumb
-            switch (btClass.getDeviceClass()) {
+            switch (btDeviceClass) {
             case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
             case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
             case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
@@ -542,6 +547,23 @@
                 if (mBluetoothService.attemptAutoPair(address)) return;
            }
         }
+
+        if (btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD ||
+            btDeviceClass == BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING) {
+            // Its a keyboard. Follow the HID spec recommendation of creating the
+            // passkey and displaying it to the user. If the keyboard doesn't follow
+            // the spec recommendation, check if the keyboard has a fixed PIN zero
+            // and pair.
+            if (mBluetoothService.isFixedPinZerosAutoPairKeyboard(address)) {
+                mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes("0000"));
+                return;
+            }
+
+            // Generate a variable PIN. This is not truly random but good enough.
+            int pin = (int) Math.floor(Math.random() * 10000);
+            sendDisplayPinIntent(address, pin);
+            return;
+        }
         // Acquire wakelock during PIN code request to bring up LCD display
         mWakeLock.acquire();
         Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
@@ -561,7 +583,7 @@
         mWakeLock.acquire();
         Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
-        intent.putExtra(BluetoothDevice.EXTRA_PASSKEY, passkey);
+        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, passkey);
         intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
                         BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY);
         mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
@@ -569,6 +591,19 @@
         mWakeLock.release();
     }
 
+    private void sendDisplayPinIntent(String address, int pin) {
+        // Acquire wakelock during PIN code request to bring up LCD display
+        mWakeLock.acquire();
+        Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
+        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mAdapter.getRemoteDevice(address));
+        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, pin);
+        intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
+                        BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN);
+        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
+        //Release wakelock to allow the LCD to go off after the PIN popup notifcation.
+        mWakeLock.release();
+    }
+
     private void onRequestOobData(String objectPath , int nativeData) {
         String address = checkPairingRequestAndGetAddress(objectPath, nativeData);
         if (address == null) return;
@@ -682,6 +717,8 @@
 
     private void onDiscoverServicesResult(String deviceObjectPath, boolean result) {
         String address = mBluetoothService.getAddressFromObjectPath(deviceObjectPath);
+        if (address == null) return;
+
         // We don't parse the xml here, instead just query Bluez for the properties.
         if (result) {
             mBluetoothService.updateRemoteDevicePropertiesCache(address);
@@ -751,18 +788,21 @@
             }
             int newState = connected? BluetoothPan.STATE_CONNECTED :
                 BluetoothPan.STATE_DISCONNECTED;
-            mBluetoothService.handlePanDeviceStateChange(device, newState);
+            mBluetoothService.handlePanDeviceStateChange(device, newState,
+                                                  BluetoothPan.LOCAL_PANU_ROLE);
         }
     }
 
     private void onNetworkDeviceDisconnected(String address) {
         BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        mBluetoothService.handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED);
+        mBluetoothService.handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED,
+                                                      BluetoothPan.LOCAL_NAP_ROLE);
     }
 
     private void onNetworkDeviceConnected(String address, String iface, int destUuid) {
         BluetoothDevice device = mAdapter.getRemoteDevice(address);
-        mBluetoothService.handlePanDeviceStateChange(device, iface, BluetoothPan.STATE_CONNECTED);
+        mBluetoothService.handlePanDeviceStateChange(device, iface, BluetoothPan.STATE_CONNECTED,
+                                                      BluetoothPan.LOCAL_NAP_ROLE);
     }
 
     private void onRestartRequired() {
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 9e5abdc..dd88838 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -34,6 +34,7 @@
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothProfileState;
 import android.bluetooth.BluetoothSocket;
+import android.bluetooth.BluetoothTetheringDataTracker;
 import android.bluetooth.BluetoothUuid;
 import android.bluetooth.IBluetooth;
 import android.bluetooth.IBluetoothCallback;
@@ -54,7 +55,6 @@
 import android.os.ParcelUuid;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemService;
 import android.provider.Settings;
 import android.util.Log;
 import android.util.Pair;
@@ -79,11 +79,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 public class BluetoothService extends IBluetooth.Stub {
     private static final String TAG = "BluetoothService";
@@ -169,6 +167,8 @@
     private static String mDockAddress;
     private String mDockPin;
 
+    private String mIface;
+
     private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
 
     private static class RemoteService {
@@ -678,6 +678,11 @@
         return false;
     }
 
+    /*package*/ synchronized boolean isFixedPinZerosAutoPairKeyboard(String address) {
+        // Check for keyboards which have fixed PIN 0000 as the pairing pin
+        return mBondState.isFixedPinZerosAutoPairKeyboard(address);
+    }
+
     /*package*/ synchronized void onCreatePairedDeviceResult(String address, int result) {
         if (result == BluetoothDevice.BOND_SUCCESS) {
             setBondState(address, BluetoothDevice.BOND_BONDED);
@@ -748,6 +753,7 @@
         private ArrayList<String>  mAutoPairingAddressBlacklist;
         private ArrayList<String> mAutoPairingExactNameBlacklist;
         private ArrayList<String> mAutoPairingPartialNameBlacklist;
+        private ArrayList<String> mAutoPairingFixedPinZerosKeyboardList;
         // Addresses added to blacklist dynamically based on usage.
         private ArrayList<String> mAutoPairingDynamicAddressBlacklist;
 
@@ -863,6 +869,19 @@
             return false;
         }
 
+        public boolean isFixedPinZerosAutoPairKeyboard(String address) {
+            // Note: the meaning of blacklist is reversed in this case.
+            // If its in the list, we can go ahead and auto pair since
+            // by default keyboard should have a variable PIN that we don't
+            // auto pair using 0000.
+            if (mAutoPairingFixedPinZerosKeyboardList != null) {
+                for (String blacklistAddress : mAutoPairingFixedPinZerosKeyboardList) {
+                    if (address.startsWith(blacklistAddress)) return true;
+                }
+            }
+            return false;
+        }
+
         public synchronized int getBondState(String address) {
             Integer state = mState.get(address);
             if (state == null) {
@@ -929,7 +948,6 @@
             FileOutputStream out = null;
             try {
                 file = new File(DYNAMIC_AUTO_PAIRING_BLACKLIST);
-                if (file.exists()) return;
 
                 in = new FileInputStream(AUTO_PAIRING_BLACKLIST);
                 out= new FileOutputStream(DYNAMIC_AUTO_PAIRING_BLACKLIST);
@@ -975,6 +993,9 @@
                         } else if (value[0].equalsIgnoreCase("PartialNameBlacklist")) {
                             mAutoPairingPartialNameBlacklist =
                                 new ArrayList<String>(Arrays.asList(val));
+                        } else if (value[0].equalsIgnoreCase("FixedPinZerosKeyboardBlacklist")) {
+                            mAutoPairingFixedPinZerosKeyboardList =
+                                new ArrayList<String>(Arrays.asList(val));
                         } else if (value[0].equalsIgnoreCase("DynamicAddressBlacklist")) {
                             mAutoPairingDynamicAddressBlacklist =
                                 new ArrayList<String>(Arrays.asList(val));
@@ -1513,12 +1534,14 @@
             return false;
         }
 
-        handlePanDeviceStateChange(device, BluetoothPan.STATE_CONNECTING);
-        if (connectPanDeviceNative(objectPath, "nap", "panu")) {
+        handlePanDeviceStateChange(device, BluetoothPan.STATE_CONNECTING,
+                                           BluetoothPan.LOCAL_PANU_ROLE);
+        if (connectPanDeviceNative(objectPath, "nap")) {
             log ("connecting to PAN");
             return true;
         } else {
-            handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED);
+            handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED,
+                                                BluetoothPan.LOCAL_PANU_ROLE);
             log ("could not connect to PAN");
             return false;
         }
@@ -1560,13 +1583,15 @@
         if (getPanDeviceState(device) != BluetoothPan.STATE_CONNECTED) {
             log (device + " already disconnected from PAN");
         }
-        handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTING);
+        handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTING,
+                                    BluetoothPan.LOCAL_PANU_ROLE);
         return disconnectPanDeviceNative(objectPath);
     }
 
     /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device,
                                                              String iface,
-                                                             int state) {
+                                                             int state,
+                                                             int role) {
         int prevState;
         String ifaceAddr = null;
 
@@ -1578,13 +1603,25 @@
         }
         if (prevState == state) return;
 
-        if (state == BluetoothPan.STATE_CONNECTED) {
-            ifaceAddr = enableTethering(iface);
-            if (ifaceAddr == null) Log.e(TAG, "Error seting up tether interface");
-        } else if (state == BluetoothPan.STATE_DISCONNECTED) {
-            if (ifaceAddr != null) {
-                mBluetoothIfaceAddresses.remove(ifaceAddr);
-                ifaceAddr = null;
+        if (role == BluetoothPan.LOCAL_NAP_ROLE) {
+            if (state == BluetoothPan.STATE_CONNECTED) {
+                ifaceAddr = enableTethering(iface);
+                if (ifaceAddr == null) Log.e(TAG, "Error seting up tether interface");
+            } else if (state == BluetoothPan.STATE_DISCONNECTED) {
+                if (ifaceAddr != null) {
+                    mBluetoothIfaceAddresses.remove(ifaceAddr);
+                    ifaceAddr = null;
+                }
+            }
+        } else {
+            // PANU Role = reverse Tether
+            if (state == BluetoothPan.STATE_CONNECTED) {
+                mIface = iface;
+                BluetoothTetheringDataTracker.getInstance().startReverseTether(iface, device);
+            } else if (state == BluetoothPan.STATE_DISCONNECTED &&
+                  (prevState == BluetoothPan.STATE_CONNECTED ||
+                  prevState == BluetoothPan.STATE_DISCONNECTING)) {
+                BluetoothTetheringDataTracker.getInstance().stopReverseTether(mIface);
             }
         }
 
@@ -1595,6 +1632,7 @@
         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
         intent.putExtra(BluetoothPan.EXTRA_PREVIOUS_PAN_STATE, prevState);
         intent.putExtra(BluetoothPan.EXTRA_PAN_STATE, state);
+        intent.putExtra(BluetoothPan.EXTRA_LOCAL_ROLE, role);
         mContext.sendBroadcast(intent, BLUETOOTH_PERM);
 
         if (DBG) log("Pan Device state : device: " + device + " State:" + prevState + "->" + state);
@@ -1602,8 +1640,8 @@
     }
 
     /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device,
-                                                             int state) {
-        handlePanDeviceStateChange(device, null, state);
+                                                             int state, int role) {
+        handlePanDeviceStateChange(device, null, state, role);
     }
 
     private String createNewTetheringAddressLocked() {
@@ -1662,7 +1700,8 @@
             ifcg = service.getInterfaceConfig(iface);
             if (ifcg != null) {
                 ifcg.mask = InetAddress.getByName(BLUETOOTH_NETMASK);
-                if (ifcg.addr == null) {
+
+                if (ifcg.addr == null || ifcg.addr.equals(InetAddress.getByName("0.0.0.0"))) {
                     ifcg.addr = InetAddress.getByName(address);
                     ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
                 }
@@ -1716,7 +1755,8 @@
                                                 "Need BLUETOOTH_ADMIN permission");
 
         String objectPath = getObjectPathFromAddress(device.getAddress());
-        if (objectPath == null || getConnectedInputDevices().size() == 0) {
+        if (objectPath == null ||
+                getInputDeviceState(device) == BluetoothInputDevice.STATE_DISCONNECTED) {
             return false;
         }
         BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
@@ -2884,7 +2924,7 @@
     private native boolean disconnectInputDeviceNative(String path);
 
     private native boolean setBluetoothTetheringNative(boolean value, String nap, String bridge);
-    private native boolean connectPanDeviceNative(String path, String srcRole, String dstRole);
+    private native boolean connectPanDeviceNative(String path, String dstRole);
     private native boolean disconnectPanDeviceNative(String path);
 
     private native int[] addReservedServiceRecordsNative(int[] uuuids);
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 52b0643..a859e3c 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -517,8 +517,11 @@
                         mLayout.windowAnimations =
                                 com.android.internal.R.style.Animation_Wallpaper;
                         mInputChannel = new InputChannel();
-                        mSession.add(mWindow, mLayout, View.VISIBLE, mContentInsets,
-                                mInputChannel);
+                        if (mSession.add(mWindow, mLayout, View.VISIBLE, mContentInsets,
+                                mInputChannel) < 0) {
+                            Log.w(TAG, "Failed to add window while updating wallpaper surface.");
+                            return;
+                        }
                         mCreated = true;
 
                         InputQueue.registerInputChannel(mInputChannel, mInputHandler,
diff --git a/core/java/android/speech/RecognizerIntent.java b/core/java/android/speech/RecognizerIntent.java
index d55a943..02c324c 100644
--- a/core/java/android/speech/RecognizerIntent.java
+++ b/core/java/android/speech/RecognizerIntent.java
@@ -82,7 +82,11 @@
 
     /**
      * Starts an activity that will prompt the user for speech, sends it through a
-     * speech recognizer, and invokes and displays a web search result.
+     * speech recognizer, and invokes and either displays a web search result or triggers
+     * another type of action based on the user's speech.
+     *
+     * <p>If you want to avoid triggering any type of action besides web search, you can use
+     * the {@link #EXTRA_WEB_SEARCH_ONLY} extra.
      * 
      * <p>Required extras:
      * <ul>
@@ -95,6 +99,7 @@
      *   <li>{@link #EXTRA_LANGUAGE}
      *   <li>{@link #EXTRA_MAX_RESULTS}
      *   <li>{@link #EXTRA_PARTIAL_RESULTS}
+     *   <li>{@link #EXTRA_WEB_SEARCH_ONLY}
      * </ul>
      * 
      * <p> Result extras (returned in the result, not to be specified in the request):
@@ -182,6 +187,13 @@
      * will choose how many results to return. Must be an integer.
      */
     public static final String EXTRA_MAX_RESULTS = "android.speech.extra.MAX_RESULTS";
+    
+    /**
+     * Optional boolean, to be used with {@link #ACTION_WEB_SEARCH}, to indicate whether to
+     * only fire web searches in response to a user's speech. The default is false, meaning
+     * that other types of actions can be taken based on the user's speech.
+     */
+    public static final String EXTRA_WEB_SEARCH_ONLY = "android.speech.extra.WEB_SEARCH_ONLY";
 
     /**
      * Optional boolean to indicate whether partial results should be returned by the recognizer
diff --git a/core/java/android/speech/RecognizerResultsIntent.java b/core/java/android/speech/RecognizerResultsIntent.java
index b45e4b1..15ac57c 100644
--- a/core/java/android/speech/RecognizerResultsIntent.java
+++ b/core/java/android/speech/RecognizerResultsIntent.java
@@ -34,8 +34,6 @@
  * the search results. If that is not available, then the corresponding url for that result in
  * {@link #EXTRA_VOICE_SEARCH_RESULT_URLS} should be used. And if even that is not available,
  * then a search url should be constructed from the actual recognition result string.
- * 
- * @hide for making public in a later release
  */
 public class RecognizerResultsIntent {
     private RecognizerResultsIntent() {
@@ -58,8 +56,6 @@
      * and, possibly, the full html to display for that result at index N of
      * {@link #EXTRA_VOICE_SEARCH_RESULT_HTML}. If full html is provided, a base url (or
      * list of base urls) should be provided with {@link #EXTRA_VOICE_SEARCH_RESULT_HTML_BASE_URLS}.
-     * 
-     * @hide for making public in a later release
      */
     public static final String ACTION_VOICE_SEARCH_RESULTS =
             "android.speech.action.VOICE_SEARCH_RESULTS";
@@ -67,8 +63,6 @@
     /**
      * The key to an extra {@link ArrayList} of {@link String}s that contains the list of
      * recognition alternates from voice search, in order from highest to lowest confidence.
-     * 
-     * @hide for making public in a later release
      */
     public static final String EXTRA_VOICE_SEARCH_RESULT_STRINGS =
             "android.speech.extras.VOICE_SEARCH_RESULT_STRINGS";
@@ -81,8 +75,6 @@
      * search url, that entry in this ArrayList should be <code>null</code>, and the implementor of
      * {@link #ACTION_VOICE_SEARCH_RESULTS} should execute a search of its own choosing,
      * based on the recognition result string.
-     * 
-     * @hide for making public in a later release
      */
     public static final String EXTRA_VOICE_SEARCH_RESULT_URLS =
             "android.speech.extras.VOICE_SEARCH_RESULT_URLS";
@@ -102,8 +94,6 @@
      * uri or some other identifier. Anyone who reads this extra should confirm that a result is
      * in fact an "inline:" uri and back off to the urls or strings gracefully if it is not, thus
      * maintaining future backwards compatibility if this changes.
-     * 
-     * @hide not to be exposed immediately as the implementation details may change
      */
     public static final String EXTRA_VOICE_SEARCH_RESULT_HTML =
             "android.speech.extras.VOICE_SEARCH_RESULT_HTML";
@@ -116,8 +106,6 @@
      * A list of the same size as {@link #EXTRA_VOICE_SEARCH_RESULT_STRINGS} may be provided
      * to apply different base urls to each different html result in the
      * {@link #EXTRA_VOICE_SEARCH_RESULT_HTML} list.
-     * 
-     * @hide not to be exposed immediately as the implementation details may change
      */
     public static final String EXTRA_VOICE_SEARCH_RESULT_HTML_BASE_URLS =
             "android.speech.extras.VOICE_SEARCH_RESULT_HTML_BASE_URLS";
@@ -132,16 +120,14 @@
      * apply different HTTP headers to each different web result in the list. These headers will
      * only be used in the case that the url for a particular web result (from
      * {@link #EXTRA_VOICE_SEARCH_RESULT_URLS}) is loaded.
-     *
-     * @hide not to be exposed immediately as the implementation details may change
      */
     public static final String EXTRA_VOICE_SEARCH_RESULT_HTTP_HEADERS =
             "android.speech.extras.EXTRA_VOICE_SEARCH_RESULT_HTTP_HEADERS";
 
     /**
      * The scheme used currently for html content in {@link #EXTRA_VOICE_SEARCH_RESULT_HTML}.
-     * 
-     * @hide not to be exposed immediately as the implementation details may change
+     * Note that this should only be used in tandem with this particular extra; it should
+     * NOT be used for generic URIs such as those found in the data field of an Intent.
      */
     public static final String URI_SCHEME_INLINE = "inline";
 }
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 841257f..f010076 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -151,6 +151,23 @@
         /**
          * {@hide}
          */
+        public static final float DEFAULT_VOLUME = 1.0f;
+        /**
+         * {@hide}
+         */
+        protected static final String DEFAULT_VOLUME_STRING = "1.0";
+        /**
+         * {@hide}
+         */
+        public static final float DEFAULT_PAN = 0.0f;
+        /**
+         * {@hide}
+         */
+        protected static final String DEFAULT_PAN_STRING = "0.0";
+
+        /**
+         * {@hide}
+         */
         public static final int USE_DEFAULTS = 0; // false
         /**
          * {@hide}
@@ -331,6 +348,24 @@
          * @see TextToSpeech#synthesizeToFile(String, HashMap, String)
          */
         public static final String KEY_PARAM_UTTERANCE_ID = "utteranceId";
+        /**
+         * {@hide}
+         * Parameter key to specify the speech volume relative to the current stream type
+         * volume used when speaking text. Volume is specified as a float ranging from 0 to 1
+         * where 0 is silence, and 1 is the maximum volume.
+         * @see TextToSpeech#speak(String, int, HashMap)
+         * @see TextToSpeech#playEarcon(String, int, HashMap)
+         */
+        public static final String KEY_PARAM_VOLUME = "volume";
+        /**
+         * {@hide}
+         * Parameter key to specify how the speech is panned from left to right when speaking text.
+         * Pan is specified as a float ranging from -1 to +1 where -1 maps to a hard-left pan,
+         * 0 to center, and +1 to hard-right.
+         * @see TextToSpeech#speak(String, int, HashMap)
+         * @see TextToSpeech#playEarcon(String, int, HashMap)
+         */
+        public static final String KEY_PARAM_PAN = "pan";
 
         // key positions in the array of cached parameters
         /**
@@ -371,7 +406,18 @@
         /**
          * {@hide}
          */
-        protected static final int NB_CACHED_PARAMS = 8;
+        protected static final int PARAM_POSITION_VOLUME = 16;
+
+        /**
+         * {@hide}
+         */
+        protected static final int PARAM_POSITION_PAN = 18;
+
+
+        /**
+         * {@hide}
+         */
+        protected static final int NB_CACHED_PARAMS = 20;
     }
 
     /**
@@ -416,6 +462,8 @@
         mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID] = Engine.KEY_PARAM_UTTERANCE_ID;
         mCachedParams[Engine.PARAM_POSITION_ENGINE] = Engine.KEY_PARAM_ENGINE;
         mCachedParams[Engine.PARAM_POSITION_PITCH] = Engine.KEY_PARAM_PITCH;
+        mCachedParams[Engine.PARAM_POSITION_VOLUME] = Engine.KEY_PARAM_VOLUME;
+        mCachedParams[Engine.PARAM_POSITION_PAN] = Engine.KEY_PARAM_PAN;
 
         // Leave all defaults that are shown in Settings uninitialized/at the default
         // so that the values set in Settings will take effect if the application does
@@ -429,6 +477,8 @@
         mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = "";
         mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = "";
         mCachedParams[Engine.PARAM_POSITION_PITCH + 1] = "100";
+        mCachedParams[Engine.PARAM_POSITION_VOLUME + 1] = Engine.DEFAULT_VOLUME_STRING;
+        mCachedParams[Engine.PARAM_POSITION_PAN + 1] = Engine.DEFAULT_PAN_STRING;
 
         initTts();
     }
@@ -717,24 +767,18 @@
     {
         synchronized (mStartLock) {
             int result = ERROR;
-            Log.i("TTS received: ", text);
+            Log.i("TTS", "speak() queueMode=" + queueMode);
             if (!mStarted) {
                 return result;
             }
             try {
                 if ((params != null) && (!params.isEmpty())) {
-                    String extra = params.get(Engine.KEY_PARAM_STREAM);
-                    if (extra != null) {
-                        mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = extra;
-                    }
-                    extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
-                    if (extra != null) {
-                        mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
-                    }
-                    extra = params.get(Engine.KEY_PARAM_ENGINE);
-                    if (extra != null) {
-                        mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = extra;
-                    }
+                    setCachedParam(params, Engine.KEY_PARAM_STREAM, Engine.PARAM_POSITION_STREAM);
+                    setCachedParam(params, Engine.KEY_PARAM_UTTERANCE_ID,
+                            Engine.PARAM_POSITION_UTTERANCE_ID);
+                    setCachedParam(params, Engine.KEY_PARAM_ENGINE, Engine.PARAM_POSITION_ENGINE);
+                    setCachedParam(params, Engine.KEY_PARAM_VOLUME, Engine.PARAM_POSITION_VOLUME);
+                    setCachedParam(params, Engine.KEY_PARAM_PAN, Engine.PARAM_POSITION_PAN);
                 }
                 result = mITts.speak(mPackageName, text, queueMode, mCachedParams);
             } catch (RemoteException e) {
@@ -791,10 +835,9 @@
                     if (extra != null) {
                         mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = extra;
                     }
-                    extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
-                    if (extra != null) {
-                        mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
-                    }
+                    setCachedParam(params, Engine.KEY_PARAM_STREAM, Engine.PARAM_POSITION_STREAM);
+                    setCachedParam(params, Engine.KEY_PARAM_UTTERANCE_ID,
+                            Engine.PARAM_POSITION_UTTERANCE_ID);
                 }
                 result = mITts.playEarcon(mPackageName, earcon, queueMode, null);
             } catch (RemoteException e) {
@@ -845,10 +888,8 @@
             }
             try {
                 if ((params != null) && (!params.isEmpty())) {
-                    String extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
-                    if (extra != null) {
-                        mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
-                    }
+                    setCachedParam(params, Engine.KEY_PARAM_UTTERANCE_ID,
+                            Engine.PARAM_POSITION_UTTERANCE_ID);
                 }
                 result = mITts.playSilence(mPackageName, durationInMs, queueMode, mCachedParams);
             } catch (RemoteException e) {
@@ -870,6 +911,7 @@
                 mStarted = false;
                 initTts();
             } finally {
+                resetCachedParams();
                 return result;
             }
         }
@@ -1224,6 +1266,7 @@
      */
     public int synthesizeToFile(String text, HashMap<String,String> params,
             String filename) {
+        Log.i("TTS", "synthesizeToFile()");
         synchronized (mStartLock) {
             int result = ERROR;
             if (!mStarted) {
@@ -1232,14 +1275,9 @@
             try {
                 if ((params != null) && (!params.isEmpty())) {
                     // no need to read the stream type here
-                    String extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
-                    if (extra != null) {
-                        mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
-                    }
-                    extra = params.get(Engine.KEY_PARAM_ENGINE);
-                    if (extra != null) {
-                        mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = extra;
-                    }
+                    setCachedParam(params, Engine.KEY_PARAM_UTTERANCE_ID,
+                            Engine.PARAM_POSITION_UTTERANCE_ID);
+                    setCachedParam(params, Engine.KEY_PARAM_ENGINE, Engine.PARAM_POSITION_ENGINE);
                 }
                 result = mITts.synthesizeToFile(mPackageName, text, mCachedParams, filename) ?
                         SUCCESS : ERROR;
@@ -1277,6 +1315,19 @@
         mCachedParams[Engine.PARAM_POSITION_STREAM + 1] =
                 String.valueOf(Engine.DEFAULT_STREAM);
         mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID+ 1] = "";
+        mCachedParams[Engine.PARAM_POSITION_VOLUME + 1] = Engine.DEFAULT_VOLUME_STRING;
+        mCachedParams[Engine.PARAM_POSITION_PAN + 1] = Engine.DEFAULT_PAN_STRING;
+    }
+
+    /**
+     * Convenience method to save a parameter in the cached parameter array, at the given index,
+     * for a property saved in the given hashmap.
+     */
+    private void setCachedParam(HashMap<String,String> params, String key, int keyIndex) {
+        String extra = params.get(key);
+        if (extra != null) {
+            mCachedParams[keyIndex+1] = extra;
+        }
     }
 
     /**
diff --git a/core/java/android/text/ClipboardManager.java b/core/java/android/text/ClipboardManager.java
index 0b239cf..d030910 100644
--- a/core/java/android/text/ClipboardManager.java
+++ b/core/java/android/text/ClipboardManager.java
@@ -17,7 +17,7 @@
 package android.text;
 
 /**
- * @deprecated Old text-only interace to the clipboard.  See
+ * @deprecated Old text-only interface to the clipboard.  See
  * {@link android.content.ClipboardManager} for the modern API.
  */
 @Deprecated
diff --git a/core/java/android/text/InputType.java b/core/java/android/text/InputType.java
index 7b8acd9..6d066d6 100644
--- a/core/java/android/text/InputType.java
+++ b/core/java/android/text/InputType.java
@@ -257,7 +257,10 @@
     /**
      * Class for numeric text.  This class supports the following flag:
      * {@link #TYPE_NUMBER_FLAG_SIGNED} and
-     * {@link #TYPE_NUMBER_FLAG_DECIMAL}.
+     * {@link #TYPE_NUMBER_FLAG_DECIMAL}.  It also supports the following
+     * variations: {@link #TYPE_NUMBER_VARIATION_NORMAL} and
+     * {@link #TYPE_NUMBER_VARIATION_PASSWORD}.  If you do not recognize
+     * the variation, normal should be assumed.
      */
     public static final int TYPE_CLASS_NUMBER = 0x00000002;
     
@@ -274,6 +277,29 @@
     public static final int TYPE_NUMBER_FLAG_DECIMAL = 0x00002000;
     
     // ----------------------------------------------------------------------
+
+    /**
+     * Default variation of {@link #TYPE_CLASS_NUMBER}: plain normal
+     * numeric text.  This was added in
+     * {@link android.os.Build.VERSION_CODES#HONEYCOMB}.  An IME must target
+     * this API version or later to see this input type; if it doesn't, a request
+     * for this type will be dropped when passed through
+     * {@link android.view.inputmethod.EditorInfo#makeCompatible(int)
+     * EditorInfo.makeCompatible(int)}.
+     */
+    public static final int TYPE_NUMBER_VARIATION_NORMAL = 0x00000000;
+
+    /**
+     * Variation of {@link #TYPE_CLASS_NUMBER}: entering a numeric password.
+     * This was added in {@link android.os.Build.VERSION_CODES#HONEYCOMB}.  An
+     * IME must target this API version or later to see this input type; if it
+     * doesn't, a request for this type will be dropped when passed
+     * through {@link android.view.inputmethod.EditorInfo#makeCompatible(int)
+     * EditorInfo.makeCompatible(int)}.
+     */
+    public static final int TYPE_NUMBER_VARIATION_PASSWORD = 0x00000010;
+
+    // ----------------------------------------------------------------------
     // ----------------------------------------------------------------------
     // ----------------------------------------------------------------------
     
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 3dd1ecd..43dce53 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -361,101 +361,103 @@
                             if (fitbottom > okbottom)
                                 okbottom = fitbottom;
                         }
-                    } else if (breakOnlyAtSpaces) {
-                        if (ok != here) {
-                            // Log.e("text", "output ok " + here + " to " +ok);
-
-                            while (ok < spanEnd && chs[ok - paraStart] == ' ') {
-                                ok++;
-                            }
-
-                            v = out(source,
-                                    here, ok,
-                                    okascent, okdescent, oktop, okbottom,
-                                    v,
-                                    spacingmult, spacingadd, chooseht,
-                                    choosehtv, fm, hasTabOrEmoji,
-                                    needMultiply, paraStart, chdirs, dir, easy,
-                                    ok == bufend, includepad, trackpad,
-                                    chs, widths, here - paraStart,
-                                    where, ellipsizedWidth, okwidth,
-                                    paint);
-
-                            here = ok;
-                        } else {
-                            // Act like it fit even though it didn't.
-
-                            fitwidth = w;
-                            fit = j + 1;
-
-                            if (fmtop < fittop)
-                                fittop = fmtop;
-                            if (fmascent < fitascent)
-                                fitascent = fmascent;
-                            if (fmdescent > fitdescent)
-                                fitdescent = fmdescent;
-                            if (fmbottom > fitbottom)
-                                fitbottom = fmbottom;
-                        }
                     } else {
-                        if (ok != here) {
-                            // Log.e("text", "output ok " + here + " to " +ok);
+                        if (breakOnlyAtSpaces) {
+                            if (ok != here) {
+                                // Log.e("text", "output ok " + here + " to " +ok);
 
-                            while (ok < spanEnd && chs[ok - paraStart] == ' ') {
-                                ok++;
+                                while (ok < spanEnd && chs[ok - paraStart] == ' ') {
+                                    ok++;
+                                }
+
+                                v = out(source,
+                                        here, ok,
+                                        okascent, okdescent, oktop, okbottom,
+                                        v,
+                                        spacingmult, spacingadd, chooseht,
+                                        choosehtv, fm, hasTabOrEmoji,
+                                        needMultiply, paraStart, chdirs, dir, easy,
+                                        ok == bufend, includepad, trackpad,
+                                        chs, widths, here - paraStart,
+                                        where, ellipsizedWidth, okwidth,
+                                        paint);
+
+                                here = ok;
+                            } else {
+                                // Act like it fit even though it didn't.
+
+                                fitwidth = w;
+                                here = fit = j + 1;
+
+                                if (fmtop < fittop)
+                                    fittop = fmtop;
+                                if (fmascent < fitascent)
+                                    fitascent = fmascent;
+                                if (fmdescent > fitdescent)
+                                    fitdescent = fmdescent;
+                                if (fmbottom > fitbottom)
+                                    fitbottom = fmbottom;
                             }
-
-                            v = out(source,
-                                    here, ok,
-                                    okascent, okdescent, oktop, okbottom,
-                                    v,
-                                    spacingmult, spacingadd, chooseht,
-                                    choosehtv, fm, hasTabOrEmoji,
-                                    needMultiply, paraStart, chdirs, dir, easy,
-                                    ok == bufend, includepad, trackpad,
-                                    chs, widths, here - paraStart,
-                                    where, ellipsizedWidth, okwidth,
-                                    paint);
-
-                            here = ok;
-                        } else if (fit != here) {
-                            // Log.e("text", "output fit " + here + " to " +fit);
-                            v = out(source,
-                                    here, fit,
-                                    fitascent, fitdescent,
-                                    fittop, fitbottom,
-                                    v,
-                                    spacingmult, spacingadd, chooseht,
-                                    choosehtv, fm, hasTabOrEmoji,
-                                    needMultiply, paraStart, chdirs, dir, easy,
-                                    fit == bufend, includepad, trackpad,
-                                    chs, widths, here - paraStart,
-                                    where, ellipsizedWidth, fitwidth,
-                                    paint);
-
-                            here = fit;
                         } else {
-                            // Log.e("text", "output one " + here + " to " +(here + 1));
-                            // XXX not sure why the existing fm wasn't ok.
-                            // measureText(paint, mWorkPaint,
-                            //             source, here, here + 1, fm, tab,
-                            //             null);
+                            if (ok != here) {
+                                // Log.e("text", "output ok " + here + " to " +ok);
 
-                            v = out(source,
-                                    here, here+1,
-                                    fm.ascent, fm.descent,
-                                    fm.top, fm.bottom,
-                                    v,
-                                    spacingmult, spacingadd, chooseht,
-                                    choosehtv, fm, hasTabOrEmoji,
-                                    needMultiply, paraStart, chdirs, dir, easy,
-                                    here + 1 == bufend, includepad,
-                                    trackpad,
-                                    chs, widths, here - paraStart,
-                                    where, ellipsizedWidth,
-                                    widths[here - paraStart], paint);
+                                while (ok < spanEnd && chs[ok - paraStart] == ' ') {
+                                    ok++;
+                                }
 
-                            here = here + 1;
+                                v = out(source,
+                                        here, ok,
+                                        okascent, okdescent, oktop, okbottom,
+                                        v,
+                                        spacingmult, spacingadd, chooseht,
+                                        choosehtv, fm, hasTabOrEmoji,
+                                        needMultiply, paraStart, chdirs, dir, easy,
+                                        ok == bufend, includepad, trackpad,
+                                        chs, widths, here - paraStart,
+                                        where, ellipsizedWidth, okwidth,
+                                        paint);
+
+                                here = ok;
+                            } else if (fit != here) {
+                                // Log.e("text", "output fit " + here + " to " +fit);
+                                v = out(source,
+                                        here, fit,
+                                        fitascent, fitdescent,
+                                        fittop, fitbottom,
+                                        v,
+                                        spacingmult, spacingadd, chooseht,
+                                        choosehtv, fm, hasTabOrEmoji,
+                                        needMultiply, paraStart, chdirs, dir, easy,
+                                        fit == bufend, includepad, trackpad,
+                                        chs, widths, here - paraStart,
+                                        where, ellipsizedWidth, fitwidth,
+                                        paint);
+
+                                here = fit;
+                            } else {
+                                // Log.e("text", "output one " + here + " to " +(here + 1));
+                                // XXX not sure why the existing fm wasn't ok.
+                                // measureText(paint, mWorkPaint,
+                                //             source, here, here + 1, fm, tab,
+                                //             null);
+
+                                v = out(source,
+                                        here, here+1,
+                                        fm.ascent, fm.descent,
+                                        fm.top, fm.bottom,
+                                        v,
+                                        spacingmult, spacingadd, chooseht,
+                                        choosehtv, fm, hasTabOrEmoji,
+                                        needMultiply, paraStart, chdirs, dir, easy,
+                                        here + 1 == bufend, includepad,
+                                        trackpad,
+                                        chs, widths, here - paraStart,
+                                        where, ellipsizedWidth,
+                                        widths[here - paraStart], paint);
+
+                                here = here + 1;
+                            }
                         }
 
                         if (here < spanStart) {
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index baaa3ce..5ae65df 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -17,32 +17,33 @@
 package android.text.format;
 
 import android.content.Context;
+import android.net.NetworkUtils;
 
 /**
  * Utility class to aid in formatting common values that are not covered
- * by the standard java.util.Formatter.
+ * by {@link java.util.Formatter}
  */
 public final class Formatter {
 
     /**
      * Formats a content size to be in the form of bytes, kilobytes, megabytes, etc
-     * 
+     *
      * @param context Context to use to load the localized units
-     * @param number size value to be formated
-     * @return formated string with the number
+     * @param number size value to be formatted
+     * @return formatted string with the number
      */
     public static String formatFileSize(Context context, long number) {
         return formatFileSize(context, number, false);
     }
-    
+
     /**
      * Like {@link #formatFileSize}, but trying to generate shorter numbers
-     * (showing fewer digits of precisin).
+     * (showing fewer digits of precision).
      */
     public static String formatShortFileSize(Context context, long number) {
         return formatFileSize(context, number, true);
     }
-    
+
     private static String formatFileSize(Context context, long number, boolean shorter) {
         if (context == null) {
             return "";
@@ -92,21 +93,21 @@
             getString(com.android.internal.R.string.fileSizeSuffix,
                       value, context.getString(suffix));
     }
-    
+
     /**
      * Returns a string in the canonical IP format ###.###.###.### from a packed integer containing
      * the IP address.  The IP address is expected to be in little-endian format (LSB first). That
      * is, 0x01020304 will return "4.3.2.1".
-     * 
-     * @param addr the IP address as a packed integer with LSB first.
+     *
+     * @param ipv4Address the IP address as a packed integer with LSB first.
      * @return string with canonical IP address format.
+     *
+     * @deprecated this method doesn't support IPv6 addresses. Prefer {@link
+     *     java.net.InetAddress#getHostAddress()}, which supports both IPv4 and
+     *     IPv6 addresses.
      */
-    public static String formatIpAddress(int addr) {
-        StringBuffer buf = new StringBuffer();
-        buf.append(addr  & 0xff).append('.').
-            append((addr >>>= 8) & 0xff).append('.').
-            append((addr >>>= 8) & 0xff).append('.').
-            append((addr >>>= 8) & 0xff);
-        return buf.toString();
+    @Deprecated
+    public static String formatIpAddress(int ipv4Address) {
+        return NetworkUtils.intToInetAddress(ipv4Address).getHostAddress();
     }
 }
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index d724320..a61ff13 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -16,6 +16,7 @@
 
 package android.text.method;
 
+import android.graphics.Rect;
 import android.text.Layout;
 import android.text.Selection;
 import android.text.Spannable;
@@ -24,170 +25,185 @@
 import android.view.View;
 import android.widget.TextView;
 
-// XXX this doesn't extend MetaKeyKeyListener because the signatures
-// don't match.  Need to figure that out.  Meanwhile the meta keys
-// won't work in fields that don't take input.
-
-public class ArrowKeyMovementMethod implements MovementMethod {
-    private boolean isCap(Spannable buffer) {
+/**
+ * A movement method that provides cursor movement and selection.
+ * Supports displaying the context menu on DPad Center.
+ */
+public class ArrowKeyMovementMethod extends BaseMovementMethod implements MovementMethod {
+    private static boolean isSelecting(Spannable buffer) {
         return ((MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SHIFT_ON) == 1) ||
                 (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0));
     }
 
-    private boolean isAlt(Spannable buffer) {
-        return MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_ALT_ON) == 1;
+    private int getCurrentLineTop(Spannable buffer, Layout layout) {
+        return layout.getLineTop(layout.getLineForOffset(Selection.getSelectionEnd(buffer)));
     }
 
-    private boolean up(TextView widget, Spannable buffer) {
-        boolean cap = isCap(buffer);
-        boolean alt = isAlt(buffer);
-        Layout layout = widget.getLayout();
-
-        if (cap) {
-            if (alt) {
-                Selection.extendSelection(buffer, 0);
-                return true;
-            } else {
-                return Selection.extendUp(buffer, layout);
-            }
-        } else {
-            if (alt) {
-                Selection.setSelection(buffer, 0);
-                return true;
-            } else {
-                return Selection.moveUp(buffer, layout);
-            }
-        }
+    private int getPageHeight(TextView widget) {
+        // This calculation does not take into account the view transformations that
+        // may have been applied to the child or its containers.  In case of scaling or
+        // rotation, the calculated page height may be incorrect.
+        final Rect rect = new Rect();
+        return widget.getGlobalVisibleRect(rect) ? rect.height() : 0;
     }
 
-    private boolean down(TextView widget, Spannable buffer) {
-        boolean cap = isCap(buffer);
-        boolean alt = isAlt(buffer);
-        Layout layout = widget.getLayout();
-
-        if (cap) {
-            if (alt) {
-                Selection.extendSelection(buffer, buffer.length());
-                return true;
-            } else {
-                return Selection.extendDown(buffer, layout);
-            }
-        } else {
-            if (alt) {
-                Selection.setSelection(buffer, buffer.length());
-                return true;
-            } else {
-                return Selection.moveDown(buffer, layout);
-            }
-        }
-    }
-
-    private boolean left(TextView widget, Spannable buffer) {
-        boolean cap = isCap(buffer);
-        boolean alt = isAlt(buffer);
-        Layout layout = widget.getLayout();
-
-        if (cap) {
-            if (alt) {
-                return Selection.extendToLeftEdge(buffer, layout);
-            } else {
-                return Selection.extendLeft(buffer, layout);
-            }
-        } else {
-            if (alt) {
-                return Selection.moveToLeftEdge(buffer, layout);
-            } else {
-                return Selection.moveLeft(buffer, layout); 
-            }
-        }
-    }
-
-    private boolean right(TextView widget, Spannable buffer) {
-        boolean cap = isCap(buffer);
-        boolean alt = isAlt(buffer);
-        Layout layout = widget.getLayout();
-
-        if (cap) {
-            if (alt) {
-                return Selection.extendToRightEdge(buffer, layout);
-            } else {
-                return Selection.extendRight(buffer, layout);
-            }
-        } else {
-            if (alt) {
-                return Selection.moveToRightEdge(buffer, layout);
-            } else {
-                return Selection.moveRight(buffer, layout); 
-            }
-        }
-    }
-
-    public boolean onKeyDown(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
-        if (executeDown(widget, buffer, keyCode)) {
-            MetaKeyKeyListener.adjustMetaAfterKeypress(buffer);
-            MetaKeyKeyListener.resetLockedMeta(buffer);
-            return true;
-        }
-
-        return false;
-    }
-
-    private boolean executeDown(TextView widget, Spannable buffer, int keyCode) {
-        boolean handled = false;
-
+    @Override
+    protected boolean handleMovementKey(TextView widget, Spannable buffer, int keyCode,
+            int movementMetaState, KeyEvent event) {
         switch (keyCode) {
-        case KeyEvent.KEYCODE_DPAD_UP:
-            handled |= up(widget, buffer);
-            break;
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+                if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
+                    if (event.getAction() == KeyEvent.ACTION_DOWN
+                            && event.getRepeatCount() == 0
+                            && MetaKeyKeyListener.getMetaState(buffer,
+                                        MetaKeyKeyListener.META_SELECTING) != 0) {
+                        return widget.showContextMenu();
+                    }
+                }
+                break;
+        }
+        return super.handleMovementKey(widget, buffer, keyCode, movementMetaState, event);
+    }
 
-        case KeyEvent.KEYCODE_DPAD_DOWN:
-            handled |= down(widget, buffer);
-            break;
+    @Override
+    protected boolean left(TextView widget, Spannable buffer) {
+        final Layout layout = widget.getLayout();
+        if (isSelecting(buffer)) {
+            return Selection.extendLeft(buffer, layout);
+        } else {
+            return Selection.moveLeft(buffer, layout);
+        }
+    }
 
-        case KeyEvent.KEYCODE_DPAD_LEFT:
-            handled |= left(widget, buffer);
-            break;
+    @Override
+    protected boolean right(TextView widget, Spannable buffer) {
+        final Layout layout = widget.getLayout();
+        if (isSelecting(buffer)) {
+            return Selection.extendRight(buffer, layout);
+        } else {
+            return Selection.moveRight(buffer, layout);
+        }
+    }
 
-        case KeyEvent.KEYCODE_DPAD_RIGHT:
-            handled |= right(widget, buffer);
-            break;
+    @Override
+    protected boolean up(TextView widget, Spannable buffer) {
+        final Layout layout = widget.getLayout();
+        if (isSelecting(buffer)) {
+            return Selection.extendUp(buffer, layout);
+        } else {
+            return Selection.moveUp(buffer, layout);
+        }
+    }
 
-        case KeyEvent.KEYCODE_DPAD_CENTER:
-            if ((MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0) &&
-                (widget.showContextMenu())) {
-                    handled = true;
+    @Override
+    protected boolean down(TextView widget, Spannable buffer) {
+        final Layout layout = widget.getLayout();
+        if (isSelecting(buffer)) {
+            return Selection.extendDown(buffer, layout);
+        } else {
+            return Selection.moveDown(buffer, layout);
+        }
+    }
+
+    @Override
+    protected boolean pageUp(TextView widget, Spannable buffer) {
+        final Layout layout = widget.getLayout();
+        final boolean selecting = isSelecting(buffer);
+        final int targetY = getCurrentLineTop(buffer, layout) - getPageHeight(widget);
+        boolean handled = false;
+        for (;;) {
+            final int previousSelectionEnd = Selection.getSelectionEnd(buffer);
+            if (selecting) {
+                Selection.extendUp(buffer, layout);
+            } else {
+                Selection.moveUp(buffer, layout);
+            }
+            if (Selection.getSelectionEnd(buffer) == previousSelectionEnd) {
+                break;
+            }
+            handled = true;
+            if (getCurrentLineTop(buffer, layout) <= targetY) {
+                break;
             }
         }
-
-        if (handled) {
-            MetaKeyKeyListener.adjustMetaAfterKeypress(buffer);
-            MetaKeyKeyListener.resetLockedMeta(buffer);
-        }
-
         return handled;
     }
 
-    public boolean onKeyUp(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
-        return false;
-    }
-
-    public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) {
-        int code = event.getKeyCode();
-        if (code != KeyEvent.KEYCODE_UNKNOWN && event.getAction() == KeyEvent.ACTION_MULTIPLE) {
-            int repeat = event.getRepeatCount();
-            boolean handled = false;
-            while ((--repeat) > 0) {
-                handled |= executeDown(view, text, code);
+    @Override
+    protected boolean pageDown(TextView widget, Spannable buffer) {
+        final Layout layout = widget.getLayout();
+        final boolean selecting = isSelecting(buffer);
+        final int targetY = getCurrentLineTop(buffer, layout) + getPageHeight(widget);
+        boolean handled = false;
+        for (;;) {
+            final int previousSelectionEnd = Selection.getSelectionEnd(buffer);
+            if (selecting) {
+                Selection.extendDown(buffer, layout);
+            } else {
+                Selection.moveDown(buffer, layout);
             }
-            return handled;
+            if (Selection.getSelectionEnd(buffer) == previousSelectionEnd) {
+                break;
+            }
+            handled = true;
+            if (getCurrentLineTop(buffer, layout) >= targetY) {
+                break;
+            }
         }
-        return false;
+        return handled;
     }
 
-    public boolean onTrackballEvent(TextView widget, Spannable text, MotionEvent event) {
-        return false;
+    @Override
+    protected boolean top(TextView widget, Spannable buffer) {
+        if (isSelecting(buffer)) {
+            Selection.extendSelection(buffer, 0);
+        } else {
+            Selection.setSelection(buffer, 0);
+        }
+        return true;
     }
 
+    @Override
+    protected boolean bottom(TextView widget, Spannable buffer) {
+        if (isSelecting(buffer)) {
+            Selection.extendSelection(buffer, buffer.length());
+        } else {
+            Selection.setSelection(buffer, buffer.length());
+        }
+        return true;
+    }
+
+    @Override
+    protected boolean lineStart(TextView widget, Spannable buffer) {
+        final Layout layout = widget.getLayout();
+        if (isSelecting(buffer)) {
+            return Selection.extendToLeftEdge(buffer, layout);
+        } else {
+            return Selection.moveToLeftEdge(buffer, layout);
+        }
+    }
+
+    @Override
+    protected boolean lineEnd(TextView widget, Spannable buffer) {
+        final Layout layout = widget.getLayout();
+        if (isSelecting(buffer)) {
+            return Selection.extendToRightEdge(buffer, layout);
+        } else {
+            return Selection.moveToRightEdge(buffer, layout);
+        }
+    }
+
+    @Override
+    protected boolean home(TextView widget, Spannable buffer) {
+        return lineStart(widget, buffer);
+    }
+
+    @Override
+    protected boolean end(TextView widget, Spannable buffer) {
+        return lineEnd(widget, buffer);
+    }
+
+    @Override
     public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
         int initialScrollX = -1, initialScrollY = -1;
         final int action = event.getAction();
@@ -201,7 +217,7 @@
 
         if (widget.isFocused() && !widget.didTouchFocusSelect()) {
             if (action == MotionEvent.ACTION_DOWN) {
-              boolean cap = isCap(buffer);
+              boolean cap = isSelecting(buffer);
               if (cap) {
                   int offset = widget.getOffset((int) event.getX(), (int) event.getY());
                   
@@ -214,7 +230,7 @@
                   widget.getParent().requestDisallowInterceptTouchEvent(true);
               }
             } else if (action == MotionEvent.ACTION_MOVE) {
-                boolean cap = isCap(buffer);
+                boolean cap = isSelecting(buffer);
 
                 if (cap && handled) {
                     // Before selecting, make sure we've moved out of the "slop".
@@ -245,7 +261,7 @@
                 }
 
                 int offset = widget.getOffset((int) event.getX(), (int) event.getY());
-                if (isCap(buffer)) {
+                if (isSelecting(buffer)) {
                     buffer.removeSpan(LAST_TAP_DOWN);
                     Selection.extendSelection(buffer, offset);
                 } else {
@@ -262,14 +278,17 @@
         return handled;
     }
 
+    @Override
     public boolean canSelectArbitrarily() {
         return true;
     }
 
+    @Override
     public void initialize(TextView widget, Spannable text) {
         Selection.setSelection(text, 0);
     }
 
+    @Override
     public void onTakeFocus(TextView view, Spannable text, int dir) {
         if ((dir & (View.FOCUS_FORWARD | View.FOCUS_DOWN)) != 0) {
             if (view.getLayout() == null) {
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index 350c9a8..191c250 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -33,75 +33,116 @@
         implements KeyListener {
     /* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete();
 
+    private static final int MODIFIER_NONE = 0;
+    private static final int MODIFIER_ALT = 1;
+    private static final int MODIFIER_INVALID = 2;
+
+    private static int getModifier(Editable content, KeyEvent event) {
+        if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+            return MODIFIER_ALT;
+        }
+        if (!event.hasNoModifiers()) {
+            return MODIFIER_INVALID;
+        }
+        if (getMetaState(content, META_ALT_ON) == 1) {
+            return MODIFIER_ALT;
+        }
+        return MODIFIER_NONE;
+    }
+
     /**
-     * Performs the action that happens when you press the DEL key in
-     * a TextView.  If there is a selection, deletes the selection;
-     * otherwise, DEL alone deletes the character before the cursor,
-     * if any;
-     * ALT+DEL deletes everything on the line the cursor is on.
+     * Performs the action that happens when you press the {@link KeyEvent#KEYCODE_DEL} key in
+     * a {@link TextView}.  If there is a selection, deletes the selection; otherwise,
+     * deletes the character before the cursor, if any; ALT+DEL deletes everything on
+     * the line the cursor is on.
      *
      * @return true if anything was deleted; false otherwise.
      */
-    public boolean backspace(View view, Editable content, int keyCode,
-                             KeyEvent event) {
-        int selStart, selEnd;
-        boolean result = true;
-
-        {
-            int a = Selection.getSelectionStart(content);
-            int b = Selection.getSelectionEnd(content);
-
-            selStart = Math.min(a, b);
-            selEnd = Math.max(a, b);
+    public boolean backspace(View view, Editable content, int keyCode, KeyEvent event) {
+        int modifier = getModifier(content, event);
+        if (modifier == MODIFIER_INVALID) {
+            return false;
         }
 
-        if (selStart != selEnd) {
-            content.delete(selStart, selEnd);
-        } else if (altBackspace(view, content, keyCode, event)) {
-            result = true;
-        } else {
-            int to = TextUtils.getOffsetBefore(content, selEnd);
-
-            if (to != selEnd) {
-                content.delete(Math.min(to, selEnd), Math.max(to, selEnd));
-            }
-            else {
-                result = false;
-            }
+        if (deleteSelection(view, content)) {
+            return true;
         }
 
-        if (result)
-            adjustMetaAfterKeypress(content);
+        if (modifier == MODIFIER_ALT && deleteLine(view, content)) {
+            return true;
+        }
 
-        return result;
+        final int start = Selection.getSelectionEnd(content);
+        final int end = TextUtils.getOffsetBefore(content, start);
+        if (start != end) {
+            content.delete(Math.min(start, end), Math.max(start, end));
+            return true;
+        }
+
+        return false;
     }
 
-    private boolean altBackspace(View view, Editable content, int keyCode,
-                                 KeyEvent event) {
-        if (!event.isAltPressed() && getMetaState(content, META_ALT_ON) != 1) {
+    /**
+     * Performs the action that happens when you press the {@link KeyEvent#KEYCODE_FORWARD_DEL}
+     * key in a {@link TextView}.  If there is a selection, deletes the selection; otherwise,
+     * deletes the character before the cursor, if any; ALT+FORWARD_DEL deletes everything on
+     * the line the cursor is on.
+     *
+     * @return true if anything was deleted; false otherwise.
+     */
+    public boolean forwardDelete(View view, Editable content, int keyCode, KeyEvent event) {
+        int modifier = getModifier(content, event);
+        if (modifier == MODIFIER_INVALID) {
             return false;
         }
 
-        if (!(view instanceof TextView)) {
-            return false;
+        if (deleteSelection(view, content)) {
+            return true;
         }
 
-        Layout layout = ((TextView) view).getLayout();
-
-        if (layout == null) {
-            return false;
+        if (modifier == MODIFIER_ALT && deleteLine(view, content)) {
+            return true;
         }
 
-        int l = layout.getLineForOffset(Selection.getSelectionStart(content));
-        int start = layout.getLineStart(l);
-        int end = layout.getLineEnd(l);
-
-        if (end == start) {
-            return false;
+        final int start = Selection.getSelectionEnd(content);
+        final int end = TextUtils.getOffsetAfter(content, start);
+        if (start != end) {
+            content.delete(Math.min(start, end), Math.max(start, end));
+            return true;
         }
 
-        content.delete(start, end);
-        return true;
+        return false;
+    }
+
+    private boolean deleteSelection(View view, Editable content) {
+        int selectionStart = Selection.getSelectionStart(content);
+        int selectionEnd = Selection.getSelectionEnd(content);
+        if (selectionEnd < selectionStart) {
+            int temp = selectionEnd;
+            selectionEnd = selectionStart;
+            selectionStart = temp;
+        }
+        if (selectionStart != selectionEnd) {
+            content.delete(selectionStart, selectionEnd);
+            return true;
+        }
+        return false;
+    }
+
+    private boolean deleteLine(View view, Editable content) {
+        if (view instanceof TextView) {
+            final Layout layout = ((TextView) view).getLayout();
+            if (layout != null) {
+                final int line = layout.getLineForOffset(Selection.getSelectionStart(content));
+                final int start = layout.getLineStart(line);
+                final int end = layout.getLineEnd(line);
+                if (end != start) {
+                    content.delete(start, end);
+                    return true;
+                }
+            }
+        }
+        return false;
     }
 
     static int makeTextContentType(Capitalize caps, boolean autoText) {
@@ -122,17 +163,29 @@
         }
         return contentType;
     }
-    
+
     public boolean onKeyDown(View view, Editable content,
                              int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_DEL) {
-            backspace(view, content, keyCode, event);
-            return true;
+        boolean handled;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DEL:
+                handled = backspace(view, content, keyCode, event);
+                break;
+            case KeyEvent.KEYCODE_FORWARD_DEL:
+                handled = forwardDelete(view, content, keyCode, event);
+                break;
+            default:
+                handled = false;
+                break;
         }
-        
+
+        if (handled) {
+            adjustMetaAfterKeypress(content);
+        }
+
         return super.onKeyDown(view, content, keyCode, event);
     }
-    
+
     /**
      * Base implementation handles ACTION_MULTIPLE KEYCODE_UNKNOWN by inserting
      * the event's text into the content.
@@ -143,23 +196,21 @@
             // Not something we are interested in.
             return false;
         }
-        
-        int selStart, selEnd;
 
-        {
-            int a = Selection.getSelectionStart(content);
-            int b = Selection.getSelectionEnd(content);
-
-            selStart = Math.min(a, b);
-            selEnd = Math.max(a, b);
+        int selectionStart = Selection.getSelectionStart(content);
+        int selectionEnd = Selection.getSelectionEnd(content);
+        if (selectionEnd < selectionStart) {
+            int temp = selectionEnd;
+            selectionEnd = selectionStart;
+            selectionStart = temp;
         }
 
         CharSequence text = event.getCharacters();
         if (text == null) {
             return false;
         }
-        
-        content.replace(selStart, selEnd, text);
+
+        content.replace(selectionStart, selectionEnd, text);
         return true;
     }
 }
diff --git a/core/java/android/text/method/BaseMovementMethod.java b/core/java/android/text/method/BaseMovementMethod.java
new file mode 100644
index 0000000..2be18d6
--- /dev/null
+++ b/core/java/android/text/method/BaseMovementMethod.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.method;
+
+import android.text.Layout;
+import android.text.Spannable;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.widget.TextView;
+
+/**
+ * Base classes for movement methods.
+ */
+public class BaseMovementMethod implements MovementMethod {
+    @Override
+    public boolean canSelectArbitrarily() {
+        return false;
+    }
+
+    @Override
+    public void initialize(TextView widget, Spannable text) {
+    }
+
+    @Override
+    public boolean onKeyDown(TextView widget, Spannable text, int keyCode, KeyEvent event) {
+        final int movementMetaState = getMovementMetaState(text, event);
+        boolean handled = handleMovementKey(widget, text, keyCode, movementMetaState, event);
+        if (handled) {
+            MetaKeyKeyListener.adjustMetaAfterKeypress(text);
+            MetaKeyKeyListener.resetLockedMeta(text);
+        }
+        return handled;
+    }
+
+    @Override
+    public boolean onKeyOther(TextView widget, Spannable text, KeyEvent event) {
+        final int movementMetaState = getMovementMetaState(text, event);
+        final int keyCode = event.getKeyCode();
+        if (keyCode != KeyEvent.KEYCODE_UNKNOWN
+                && event.getAction() == KeyEvent.ACTION_MULTIPLE) {
+            final int repeat = event.getRepeatCount();
+            boolean handled = false;
+            for (int i = 0; i < repeat; i++) {
+                if (!handleMovementKey(widget, text, keyCode, movementMetaState, event)) {
+                    break;
+                }
+                handled = true;
+            }
+            if (handled) {
+                MetaKeyKeyListener.adjustMetaAfterKeypress(text);
+                MetaKeyKeyListener.resetLockedMeta(text);
+            }
+            return handled;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onKeyUp(TextView widget, Spannable text, int keyCode, KeyEvent event) {
+        return false;
+    }
+
+    @Override
+    public void onTakeFocus(TextView widget, Spannable text, int direction) {
+    }
+
+    @Override
+    public boolean onTouchEvent(TextView widget, Spannable text, MotionEvent event) {
+        return false;
+    }
+
+    @Override
+    public boolean onTrackballEvent(TextView widget, Spannable text, MotionEvent event) {
+        return false;
+    }
+
+    /**
+     * Gets the meta state used for movement using the modifiers tracked by the text
+     * buffer as well as those present in the key event.
+     *
+     * The movement meta state excludes the state of locked modifiers or the SHIFT key
+     * since they are not used by movement actions (but they may be used for selection).
+     *
+     * @param buffer The text buffer.
+     * @param event The key event.
+     * @return The keyboard meta states used for movement.
+     */
+    protected int getMovementMetaState(Spannable buffer, KeyEvent event) {
+        // We ignore locked modifiers and SHIFT.
+        int metaState = (event.getMetaState() | MetaKeyKeyListener.getMetaState(buffer))
+                & ~(MetaKeyKeyListener.META_ALT_LOCKED | MetaKeyKeyListener.META_SYM_LOCKED);
+        return KeyEvent.normalizeMetaState(metaState) & ~KeyEvent.META_SHIFT_MASK;
+    }
+
+    /**
+     * Performs a movement key action.
+     * The default implementation decodes the key down and invokes movement actions
+     * such as {@link #down} and {@link #up}.
+     * {@link #onKeyDown(TextView, Spannable, int, KeyEvent)} calls this method once
+     * to handle an {@link KeyEvent#ACTION_DOWN}.
+     * {@link #onKeyOther(TextView, Spannable, KeyEvent)} calls this method repeatedly
+     * to handle each repetition of an {@link KeyEvent#ACTION_MULTIPLE}.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @param event The key event.
+     * @param keyCode The key code.
+     * @param movementMetaState The keyboard meta states used for movement.
+     * @param event The key event.
+     * @return True if the event was handled.
+     */
+    protected boolean handleMovementKey(TextView widget, Spannable buffer,
+            int keyCode, int movementMetaState, KeyEvent event) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
+                    return left(widget, buffer);
+                } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
+                        KeyEvent.META_ALT_ON)) {
+                    return lineStart(widget, buffer);
+                }
+                break;
+
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
+                    return right(widget, buffer);
+                } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
+                        KeyEvent.META_ALT_ON)) {
+                    return lineEnd(widget, buffer);
+                }
+                break;
+
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
+                    return up(widget, buffer);
+                } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
+                        KeyEvent.META_ALT_ON)) {
+                    return top(widget, buffer);
+                }
+                break;
+
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
+                    return down(widget, buffer);
+                } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
+                        KeyEvent.META_ALT_ON)) {
+                    return bottom(widget, buffer);
+                }
+                break;
+
+            case KeyEvent.KEYCODE_PAGE_UP:
+                if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
+                    return pageUp(widget, buffer);
+                } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
+                        KeyEvent.META_ALT_ON)) {
+                    return top(widget, buffer);
+                }
+                break;
+
+            case KeyEvent.KEYCODE_PAGE_DOWN:
+                if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
+                    return pageDown(widget, buffer);
+                } else if (KeyEvent.metaStateHasModifiers(movementMetaState,
+                        KeyEvent.META_ALT_ON)) {
+                    return bottom(widget, buffer);
+                }
+                break;
+
+            case KeyEvent.KEYCODE_MOVE_HOME:
+                if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
+                    return home(widget, buffer);
+                }
+                break;
+
+            case KeyEvent.KEYCODE_MOVE_END:
+                if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
+                    return end(widget, buffer);
+                }
+                break;
+        }
+        return false;
+    }
+
+    /**
+     * Performs a left movement action.
+     * Moves the cursor or scrolls left by one character.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @return True if the event was handled.
+     */
+    protected boolean left(TextView widget, Spannable buffer) {
+        return false;
+    }
+
+    /**
+     * Performs a right movement action.
+     * Moves the cursor or scrolls right by one character.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @return True if the event was handled.
+     */
+    protected boolean right(TextView widget, Spannable buffer) {
+        return false;
+    }
+
+    /**
+     * Performs an up movement action.
+     * Moves the cursor or scrolls up by one line.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @return True if the event was handled.
+     */
+    protected boolean up(TextView widget, Spannable buffer) {
+        return false;
+    }
+
+    /**
+     * Performs a down movement action.
+     * Moves the cursor or scrolls down by one line.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @return True if the event was handled.
+     */
+    protected boolean down(TextView widget, Spannable buffer) {
+        return false;
+    }
+
+    /**
+     * Performs a page-up movement action.
+     * Moves the cursor or scrolls up by one page.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @return True if the event was handled.
+     */
+    protected boolean pageUp(TextView widget, Spannable buffer) {
+        return false;
+    }
+
+    /**
+     * Performs a page-down movement action.
+     * Moves the cursor or scrolls down by one page.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @return True if the event was handled.
+     */
+    protected boolean pageDown(TextView widget, Spannable buffer) {
+        return false;
+    }
+
+    /**
+     * Performs a top movement action.
+     * Moves the cursor or scrolls to the top of the buffer.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @return True if the event was handled.
+     */
+    protected boolean top(TextView widget, Spannable buffer) {
+        return false;
+    }
+
+    /**
+     * Performs a bottom movement action.
+     * Moves the cursor or scrolls to the bottom of the buffer.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @return True if the event was handled.
+     */
+    protected boolean bottom(TextView widget, Spannable buffer) {
+        return false;
+    }
+
+    /**
+     * Performs a line-start movement action.
+     * Moves the cursor or scrolls to the start of the line.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @return True if the event was handled.
+     */
+    protected boolean lineStart(TextView widget, Spannable buffer) {
+        return false;
+    }
+
+    /**
+     * Performs an line-end movement action.
+     * Moves the cursor or scrolls to the end of the line.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @return True if the event was handled.
+     */
+    protected boolean lineEnd(TextView widget, Spannable buffer) {
+        return false;
+    }
+
+    /**
+     * Performs a home movement action.
+     * Moves the cursor or scrolls to the start of the line or to the top of the
+     * document depending on whether the insertion point is being moved or
+     * the document is being scrolled.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @return True if the event was handled.
+     */
+    protected boolean home(TextView widget, Spannable buffer) {
+        return false;
+    }
+
+    /**
+     * Performs an end movement action.
+     * Moves the cursor or scrolls to the start of the line or to the top of the
+     * document depending on whether the insertion point is being moved or
+     * the document is being scrolled.
+     *
+     * @param widget The text view.
+     * @param buffer The text buffer.
+     * @return True if the event was handled.
+     */
+    protected boolean end(TextView widget, Spannable buffer) {
+        return false;
+    }
+}
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
index 22e9cc6..9e73371 100644
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ b/core/java/android/text/method/LinkMovementMethod.java
@@ -16,37 +16,40 @@
 
 package android.text.method;
 
-import android.content.Intent;
-import android.net.Uri;
+import android.text.Layout;
+import android.text.NoCopySpan;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.style.ClickableSpan;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
-import android.text.*;
-import android.text.style.*;
 import android.view.View;
 import android.widget.TextView;
 
-public class
-LinkMovementMethod
-extends ScrollingMovementMethod
-{
+/**
+ * A movement method that traverses links in the text buffer and scrolls if necessary.
+ * Supports clicking on links with DPad Center or Enter.
+ */
+public class LinkMovementMethod extends ScrollingMovementMethod {
     private static final int CLICK = 1;
     private static final int UP = 2;
     private static final int DOWN = 3;
 
     @Override
-    public boolean onKeyDown(TextView widget, Spannable buffer,
-                             int keyCode, KeyEvent event) {
+    protected boolean handleMovementKey(TextView widget, Spannable buffer, int keyCode,
+            int movementMetaState, KeyEvent event) {
         switch (keyCode) {
-        case KeyEvent.KEYCODE_DPAD_CENTER:
-        case KeyEvent.KEYCODE_ENTER:
-            if (event.getRepeatCount() == 0) {
-                if (action(CLICK, widget, buffer)) {
-                    return true;
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+            case KeyEvent.KEYCODE_ENTER:
+                if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
+                    if (event.getAction() == KeyEvent.ACTION_DOWN
+                            && event.getRepeatCount() == 0) {
+                        return action(CLICK, widget, buffer);
+                    }
                 }
-            }
+                break;
         }
-
-        return super.onKeyDown(widget, buffer, keyCode, event);
+        return super.handleMovementKey(widget, buffer, keyCode, movementMetaState, event);
     }
 
     @Override
@@ -86,8 +89,6 @@
     }
 
     private boolean action(int what, TextView widget, Spannable buffer) {
-        boolean handled = false;
-
         Layout layout = widget.getLayout();
 
         int padding = widget.getTotalPaddingTop() +
@@ -184,11 +185,6 @@
         return false;
     }
 
-    public boolean onKeyUp(TextView widget, Spannable buffer,
-                           int keyCode, KeyEvent event) {
-        return false;
-    }
-
     @Override
     public boolean onTouchEvent(TextView widget, Spannable buffer,
                                 MotionEvent event) {
@@ -229,11 +225,13 @@
         return super.onTouchEvent(widget, buffer, event);
     }
 
+    @Override
     public void initialize(TextView widget, Spannable text) {
         Selection.removeSelection(text);
         text.removeSpan(FROM_BELOW);
     }
 
+    @Override
     public void onTakeFocus(TextView view, Spannable text, int dir) {
         Selection.removeSelection(text);
 
diff --git a/core/java/android/text/method/MovementMethod.java b/core/java/android/text/method/MovementMethod.java
index 29f67a1..9167676 100644
--- a/core/java/android/text/method/MovementMethod.java
+++ b/core/java/android/text/method/MovementMethod.java
@@ -21,24 +21,32 @@
 import android.view.MotionEvent;
 import android.text.*;
 
-public interface MovementMethod
-{
+/**
+ * Provides cursor positioning, scrolling and text selection functionality in a {@link TextView}.
+ * <p>
+ * The {@link TextView} delegates handling of key events, trackball motions and touches to
+ * the movement method for purposes of content navigation.  The framework automatically
+ * selects an appropriate movement method based on the content of the {@link TextView}.
+ * </p><p>
+ * This interface is intended for use by the framework; it should not be implemented
+ * directly by applications.
+ * </p>
+ */
+public interface MovementMethod {
     public void initialize(TextView widget, Spannable text);
     public boolean onKeyDown(TextView widget, Spannable text, int keyCode, KeyEvent event);
     public boolean onKeyUp(TextView widget, Spannable text, int keyCode, KeyEvent event);
-    
+
     /**
      * If the key listener wants to other kinds of key events, return true,
      * otherwise return false and the caller (i.e. the widget host)
      * will handle the key.
      */
     public boolean onKeyOther(TextView view, Spannable text, KeyEvent event);
-    
+
     public void onTakeFocus(TextView widget, Spannable text, int direction);
-    public boolean onTrackballEvent(TextView widget, Spannable text,
-                                    MotionEvent event);
-    public boolean onTouchEvent(TextView widget, Spannable text,
-                                MotionEvent event);
+    public boolean onTrackballEvent(TextView widget, Spannable text, MotionEvent event);
+    public boolean onTouchEvent(TextView widget, Spannable text, MotionEvent event);
 
     /**
      * Returns true if this movement method allows arbitrary selection
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index 09388c0..4c82b81 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -295,7 +295,9 @@
             }
 
             return true;
-        } else if (keyCode == KeyEvent.KEYCODE_DEL && selStart == selEnd) {
+        } else if (keyCode == KeyEvent.KEYCODE_DEL
+                && (event.hasNoModifiers() || event.hasModifiers(KeyEvent.META_ALT_ON))
+                && selStart == selEnd) {
             // special backspace case for undoing autotext
 
             int consider = 1;
diff --git a/core/java/android/text/method/ScrollingMovementMethod.java b/core/java/android/text/method/ScrollingMovementMethod.java
index 563ceed..194ecc1 100644
--- a/core/java/android/text/method/ScrollingMovementMethod.java
+++ b/core/java/android/text/method/ScrollingMovementMethod.java
@@ -16,201 +16,216 @@
 
 package android.text.method;
 
-import android.util.Log;
-import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.text.*;
 import android.widget.TextView;
 import android.view.View;
 
-public class
-ScrollingMovementMethod
-implements MovementMethod
-{
-    /**
-     * Scrolls the text to the left if possible.
-     */
-    protected boolean left(TextView widget, Spannable buffer) {
-        Layout layout = widget.getLayout();
-        
-        int scrolly = widget.getScrollY();
-        int scr = widget.getScrollX();
-        int em = Math.round(layout.getPaint().getFontSpacing());
+/**
+ * A movement method that interprets movement keys by scrolling the text buffer.
+ */
+public class ScrollingMovementMethod extends BaseMovementMethod implements MovementMethod {
+    private int getTopLine(TextView widget) {
+        return widget.getLayout().getLineForVertical(widget.getScrollY());
+    }
 
-        int padding = widget.getTotalPaddingTop() +
-                      widget.getTotalPaddingBottom();
-        int top = layout.getLineForVertical(scrolly);
-        int bottom = layout.getLineForVertical(scrolly + widget.getHeight() -
-                                               padding);
+    private int getBottomLine(TextView widget) {
+        return widget.getLayout().getLineForVertical(widget.getScrollY() + getInnerHeight(widget));
+    }
+
+    private int getInnerWidth(TextView widget) {
+        return widget.getWidth() - widget.getTotalPaddingLeft() - widget.getTotalPaddingRight();
+    }
+
+    private int getInnerHeight(TextView widget) {
+        return widget.getHeight() - widget.getTotalPaddingTop() - widget.getTotalPaddingBottom();
+    }
+
+    private int getCharacterWidth(TextView widget) {
+        return (int) Math.ceil(widget.getPaint().getFontSpacing());
+    }
+
+    private int getScrollBoundsLeft(TextView widget) {
+        final Layout layout = widget.getLayout();
+        final int topLine = getTopLine(widget);
+        final int bottomLine = getBottomLine(widget);
+        if (topLine > bottomLine) {
+            return 0;
+        }
         int left = Integer.MAX_VALUE;
-
-        for (int i = top; i <= bottom; i++) {
-            left = (int) Math.min(left, layout.getLineLeft(i));
+        for (int line = topLine; line <= bottomLine; line++) {
+            final int lineLeft = (int) Math.floor(layout.getLineLeft(line));
+            if (lineLeft < left) {
+                left = lineLeft;
+            }
         }
+        return left;
+    }
 
-        if (scr > left) {
-            int s = Math.max(scr - em, left);
-            widget.scrollTo(s, widget.getScrollY());
+    private int getScrollBoundsRight(TextView widget) {
+        final Layout layout = widget.getLayout();
+        final int topLine = getTopLine(widget);
+        final int bottomLine = getBottomLine(widget);
+        if (topLine > bottomLine) {
+            return 0;
+        }
+        int right = Integer.MIN_VALUE;
+        for (int line = topLine; line <= bottomLine; line++) {
+            final int lineRight = (int) Math.ceil(layout.getLineRight(line));
+            if (lineRight > right) {
+                right = lineRight;
+            }
+        }
+        return right;
+    }
+
+    @Override
+    protected boolean left(TextView widget, Spannable buffer) {
+        final int minScrollX = getScrollBoundsLeft(widget);
+        int scrollX = widget.getScrollX();
+        if (scrollX > minScrollX) {
+            scrollX = Math.max(scrollX - getCharacterWidth(widget), minScrollX);
+            widget.scrollTo(scrollX, widget.getScrollY());
             return true;
         }
-
         return false;
     }
 
-    /**
-     * Scrolls the text to the right if possible.
-     */
+    @Override
     protected boolean right(TextView widget, Spannable buffer) {
-        Layout layout = widget.getLayout();
-
-        int scrolly = widget.getScrollY();
-        int scr = widget.getScrollX();
-        int em = Math.round(layout.getPaint().getFontSpacing());
-
-        int padding = widget.getTotalPaddingTop() +
-                      widget.getTotalPaddingBottom();
-        int top = layout.getLineForVertical(scrolly);
-        int bottom = layout.getLineForVertical(scrolly + widget.getHeight() -
-                                               padding);
-        int right = 0;
-
-        for (int i = top; i <= bottom; i++) {
-            right = (int) Math.max(right, layout.getLineRight(i));
-        }
-
-        padding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight();
-        if (scr < right - (widget.getWidth() - padding)) {
-            int s = Math.min(scr + em, right - (widget.getWidth() - padding));
-            widget.scrollTo(s, widget.getScrollY());
+        final int maxScrollX = getScrollBoundsRight(widget) - getInnerWidth(widget);
+        int scrollX = widget.getScrollX();
+        if (scrollX < maxScrollX) {
+            scrollX = Math.min(scrollX + getCharacterWidth(widget), maxScrollX);
+            widget.scrollTo(scrollX, widget.getScrollY());
             return true;
         }
-
         return false;
     }
 
-    /**
-     * Scrolls the text up if possible.
-     */
+    @Override
     protected boolean up(TextView widget, Spannable buffer) {
-        Layout layout = widget.getLayout();
-
-        int areatop = widget.getScrollY();
-        int line = layout.getLineForVertical(areatop);
-        int linetop = layout.getLineTop(line);
-
-        // If the top line is partially visible, bring it all the way
-        // into view; otherwise, bring the previous line into view.
-        if (areatop == linetop)
-            line--;
-
-        if (line >= 0) {
-            Touch.scrollTo(widget, layout,
-                           widget.getScrollX(), layout.getLineTop(line));
+        final Layout layout = widget.getLayout();
+        final int top = widget.getScrollY();
+        int topLine = layout.getLineForVertical(top);
+        if (layout.getLineTop(topLine) == top) {
+            // If the top line is partially visible, bring it all the way
+            // into view; otherwise, bring the previous line into view.
+            topLine -= 1;
+        }
+        if (topLine >= 0) {
+            Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine));
             return true;
         }
-
         return false;
     }
 
-    /**
-     * Scrolls the text down if possible.
-     */
+    @Override
     protected boolean down(TextView widget, Spannable buffer) {
-        Layout layout = widget.getLayout();
-
-        int padding = widget.getTotalPaddingTop() +
-                      widget.getTotalPaddingBottom();
-
-        int areabot = widget.getScrollY() + widget.getHeight() - padding;
-        int line = layout.getLineForVertical(areabot);
-
-        if (layout.getLineTop(line+1) < areabot + 1) {
+        final Layout layout = widget.getLayout();
+        final int innerHeight = getInnerHeight(widget);
+        final int bottom = widget.getScrollY() + innerHeight;
+        int bottomLine = layout.getLineForVertical(bottom);
+        if (layout.getLineTop(bottomLine + 1) < bottom + 1) {
             // Less than a pixel of this line is out of view,
             // so we must have tried to make it entirely in view
             // and now want the next line to be in view instead.
-
-            line++;
+            bottomLine += 1;
         }
-
-        if (line <= layout.getLineCount() - 1) {
-            widget.scrollTo(widget.getScrollX(), layout.getLineTop(line+1) -
-                            (widget.getHeight() - padding));
-            Touch.scrollTo(widget, layout,
-                                widget.getScrollX(), widget.getScrollY());
+        if (bottomLine <= layout.getLineCount() - 1) {
+            Touch.scrollTo(widget, layout, widget.getScrollX(),
+                    layout.getLineTop(bottomLine + 1) - innerHeight);
             return true;
         }
-
         return false;
     }
 
-    public boolean onKeyDown(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
-        return executeDown(widget, buffer, keyCode);
-    }
-
-    private boolean executeDown(TextView widget, Spannable buffer, int keyCode) {
-        boolean handled = false;
-
-        switch (keyCode) {
-        case KeyEvent.KEYCODE_DPAD_LEFT:
-            handled |= left(widget, buffer);
-            break;
-
-        case KeyEvent.KEYCODE_DPAD_RIGHT:
-            handled |= right(widget, buffer);
-            break;
-
-        case KeyEvent.KEYCODE_DPAD_UP:
-            handled |= up(widget, buffer);
-            break;
-
-        case KeyEvent.KEYCODE_DPAD_DOWN:
-            handled |= down(widget, buffer);
-            break;
-        }
-
-        return handled;
-    }
-
-    public boolean onKeyUp(TextView widget, Spannable buffer, int keyCode, KeyEvent event) {
-        return false;
-    }
-
-    public boolean onKeyOther(TextView view, Spannable text, KeyEvent event) {
-        int code = event.getKeyCode();
-        if (code != KeyEvent.KEYCODE_UNKNOWN
-                && event.getAction() == KeyEvent.ACTION_MULTIPLE) {
-            int repeat = event.getRepeatCount();
-            boolean first = true;
-            boolean handled = false;
-            while ((--repeat) > 0) {
-                if (first && executeDown(view, text, code)) {
-                    handled = true;
-                    MetaKeyKeyListener.adjustMetaAfterKeypress(text);
-                    MetaKeyKeyListener.resetLockedMeta(text);
-                }
-                first = false;
-            }
-            return handled;
+    @Override
+    protected boolean pageUp(TextView widget, Spannable buffer) {
+        final Layout layout = widget.getLayout();
+        final int top = widget.getScrollY() - getInnerHeight(widget);
+        int topLine = layout.getLineForVertical(top);
+        if (topLine >= 0) {
+            Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine));
+            return true;
         }
         return false;
     }
-    
-    public boolean onTrackballEvent(TextView widget, Spannable text,
-            MotionEvent event) {
+
+    @Override
+    protected boolean pageDown(TextView widget, Spannable buffer) {
+        final Layout layout = widget.getLayout();
+        final int innerHeight = getInnerHeight(widget);
+        final int bottom = widget.getScrollY() + innerHeight + innerHeight;
+        int bottomLine = layout.getLineForVertical(bottom);
+        if (bottomLine <= layout.getLineCount() - 1) {
+            Touch.scrollTo(widget, layout, widget.getScrollX(),
+                    layout.getLineTop(bottomLine + 1) - innerHeight);
+            return true;
+        }
         return false;
     }
-    
-    public boolean onTouchEvent(TextView widget, Spannable buffer,
-                                 MotionEvent event) {
+
+    @Override
+    protected boolean top(TextView widget, Spannable buffer) {
+        final Layout layout = widget.getLayout();
+        if (getTopLine(widget) >= 0) {
+            Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(0));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean bottom(TextView widget, Spannable buffer) {
+        final Layout layout = widget.getLayout();
+        final int lineCount = layout.getLineCount();
+        if (getBottomLine(widget) <= lineCount - 1) {
+            Touch.scrollTo(widget, layout, widget.getScrollX(),
+                    layout.getLineTop(lineCount) - getInnerHeight(widget));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean lineStart(TextView widget, Spannable buffer) {
+        final int minScrollX = getScrollBoundsLeft(widget);
+        int scrollX = widget.getScrollX();
+        if (scrollX > minScrollX) {
+            widget.scrollTo(minScrollX, widget.getScrollY());
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean lineEnd(TextView widget, Spannable buffer) {
+        final int maxScrollX = getScrollBoundsRight(widget) - getInnerWidth(widget);
+        int scrollX = widget.getScrollX();
+        if (scrollX < maxScrollX) {
+            widget.scrollTo(maxScrollX, widget.getScrollY());
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean home(TextView widget, Spannable buffer) {
+        return top(widget, buffer);
+    }
+
+    @Override
+    protected boolean end(TextView widget, Spannable buffer) {
+        return bottom(widget, buffer);
+    }
+
+    @Override
+    public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
         return Touch.onTouchEvent(widget, buffer, event);
     }
 
-    public void initialize(TextView widget, Spannable text) { }
-
-    public boolean canSelectArbitrarily() {
-        return false;
-    }
-
+    @Override
     public void onTakeFocus(TextView widget, Spannable text, int dir) {
         Layout layout = widget.getLayout();
 
diff --git a/core/java/android/util/CalendarUtils.java b/core/java/android/util/CalendarUtils.java
index 1b2a894..b2b4897 100644
--- a/core/java/android/util/CalendarUtils.java
+++ b/core/java/android/util/CalendarUtils.java
@@ -88,6 +88,12 @@
             @Override
             protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
                 synchronized (mTZCallbacks) {
+                    if (cursor == null) {
+                        mTZQueryInProgress = false;
+                        mFirstTZRequest = true;
+                        return;
+                    }
+
                     boolean writePrefs = false;
                     // Check the values in the db
                     int keyColumn = cursor.getColumnIndexOrThrow(CalendarCache.KEY);
diff --git a/core/java/android/util/DebugUtils.java b/core/java/android/util/DebugUtils.java
index 56f389c..65fc35c 100644
--- a/core/java/android/util/DebugUtils.java
+++ b/core/java/android/util/DebugUtils.java
@@ -101,4 +101,23 @@
         return match;
     }
 
+    /** @hide */
+    public static void buildShortClassTag(Object cls, StringBuilder out) {
+        if (cls == null) {
+            out.append("null");
+        } else {
+            String simpleName = cls.getClass().getSimpleName();
+            if (simpleName == null || simpleName.isEmpty()) {
+                simpleName = cls.getClass().getName();
+                int end = simpleName.lastIndexOf('.');
+                if (end > 0) {
+                    simpleName = simpleName.substring(end+1);
+                }
+            }
+            out.append(simpleName);
+            out.append('{');
+            out.append(Integer.toHexString(System.identityHashCode(cls)));
+        }
+    }
+
 }
diff --git a/core/java/android/util/Finalizers.java b/core/java/android/util/Finalizers.java
deleted file mode 100644
index 671f2d4..0000000
--- a/core/java/android/util/Finalizers.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import java.lang.ref.PhantomReference;
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-
-/**
- * This class can be used to implement reliable finalizers.
- * 
- * @hide
- */
-public final class Finalizers {
-    private static final String LOG_TAG = "Finalizers";
-    
-    private static final Object[] sLock = new Object[0];
-    private static boolean sInit;
-    private static Reclaimer sReclaimer;
-
-    /**
-     * Subclass of PhantomReference used to reclaim resources.
-     */
-    public static abstract class ReclaimableReference<T> extends PhantomReference<T> {
-        public ReclaimableReference(T r, ReferenceQueue<Object> q) {
-            super(r, q);
-        }
-        
-        public abstract void reclaim();
-    }
-
-    /**
-     * Returns the queue used to reclaim ReclaimableReferences.
-     * 
-     * @return A reference queue or null before initialization
-     */
-    public static ReferenceQueue<Object> getQueue() {
-        synchronized (sLock) {
-            if (!sInit) {
-                return null;
-            }
-            if (!sReclaimer.isRunning()) {
-                sReclaimer = new Reclaimer(sReclaimer.mQueue);
-                sReclaimer.start();
-            }
-            return sReclaimer.mQueue;
-        }
-    }
-
-    /**
-     * Invoked by Zygote. Don't touch!
-     */
-    public static void init() {
-        synchronized (sLock) {
-            if (!sInit && sReclaimer == null) {
-                sReclaimer = new Reclaimer();
-                sReclaimer.start();
-                sInit = true;
-            }
-        }
-    }
-    
-    private static class Reclaimer extends Thread {
-        ReferenceQueue<Object> mQueue;
-
-        private volatile boolean mRunning = false;
-
-        Reclaimer() {
-            this(new ReferenceQueue<Object>());
-        }
-
-        Reclaimer(ReferenceQueue<Object> queue) {
-            super("Reclaimer");
-            setDaemon(true);
-            mQueue = queue;            
-        }
-
-        @Override
-        public void start() {
-            mRunning = true;
-            super.start();
-        }
-
-        boolean isRunning() {
-            return mRunning;
-        }
-
-        @SuppressWarnings({"InfiniteLoopStatement"})
-        @Override
-        public void run() {
-            try {
-                while (true) {
-                    try {
-                        cleanUp(mQueue.remove());
-                    } catch (InterruptedException e) {
-                        // Ignore
-                    }
-                }
-            } catch (Exception e) {
-                Log.e(LOG_TAG, "Reclaimer thread exiting: ", e);
-            } finally {
-                mRunning = false;
-            }
-        }
-
-        private void cleanUp(Reference<?> reference) {
-            do {
-                reference.clear();
-                ((ReclaimableReference<?>) reference).reclaim();
-            } while ((reference = mQueue.poll()) != null);
-        }
-    }
-}
diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java
index 8025545..8f44895 100644
--- a/core/java/android/util/JsonReader.java
+++ b/core/java/android/util/JsonReader.java
@@ -16,6 +16,7 @@
 
 package android.util;
 
+import java.io.EOFException;
 import java.io.IOException;
 import java.io.Reader;
 import java.io.Closeable;
@@ -249,6 +250,13 @@
     }
 
     /**
+     * Returns true if this parser is liberal in what it accepts.
+     */
+    public boolean isLenient() {
+        return lenient;
+    }
+
+    /**
      * Consumes the next token from the JSON stream and asserts that it is the
      * beginning of a new array.
      */
@@ -311,7 +319,7 @@
             case EMPTY_DOCUMENT:
                 replaceTop(JsonScope.NONEMPTY_DOCUMENT);
                 JsonToken firstToken = nextValue();
-                if (token != JsonToken.BEGIN_ARRAY && token != JsonToken.BEGIN_OBJECT) {
+                if (!lenient && token != JsonToken.BEGIN_ARRAY && token != JsonToken.BEGIN_OBJECT) {
                     throw new IOException(
                             "Expected JSON document to start with '[' or '{' but was " + token);
                 }
@@ -327,7 +335,15 @@
             case NONEMPTY_OBJECT:
                 return nextInObject(false);
             case NONEMPTY_DOCUMENT:
-                return token = JsonToken.END_DOCUMENT;
+                try {
+                    JsonToken token = nextValue();
+                    if (lenient) {
+                        return token;
+                    }
+                    throw syntaxError("Expected EOF");
+                } catch (EOFException e) {
+                    return token = JsonToken.END_DOCUMENT; // TODO: avoid throwing here?
+                }
             case CLOSED:
                 throw new IllegalStateException("JsonReader is closed");
             default:
@@ -758,7 +774,7 @@
             }
         }
 
-        throw syntaxError("End of input");
+        throw new EOFException("End of input");
     }
 
     private void checkLenient() throws IOException {
@@ -1030,8 +1046,6 @@
      * form -12.34e+56. Fractional and exponential parts are optional. Leading
      * zeroes are not allowed in the value or exponential part, but are allowed
      * in the fraction.
-     *
-     * <p>This has a side effect of setting isInteger.
      */
     private JsonToken decodeNumber(char[] chars, int offset, int length) {
         int i = offset;
@@ -1085,8 +1099,8 @@
      * Throws a new IO exception with the given message and a context snippet
      * with this reader's content.
      */
-    public IOException syntaxError(String message) throws IOException {
-        throw new JsonSyntaxException(message + " near " + getSnippet());
+    private IOException syntaxError(String message) throws IOException {
+        throw new MalformedJsonException(message + " near " + getSnippet());
     }
 
     private CharSequence getSnippet() {
@@ -1097,10 +1111,4 @@
         snippet.append(buffer, pos, afterPos);
         return snippet;
     }
-
-    private static class JsonSyntaxException extends IOException {
-        private JsonSyntaxException(String s) {
-            super(s);
-        }
-    }
 }
diff --git a/core/java/android/util/JsonWriter.java b/core/java/android/util/JsonWriter.java
index 89cad79..47e84c5 100644
--- a/core/java/android/util/JsonWriter.java
+++ b/core/java/android/util/JsonWriter.java
@@ -138,6 +138,8 @@
      */
     private String separator = ":";
 
+    private boolean lenient;
+
     /**
      * Creates a new instance that writes a JSON-encoded stream to {@code out}.
      * For best performance, ensure {@link Writer} is buffered; wrapping in
@@ -169,6 +171,29 @@
     }
 
     /**
+     * Configure this writer to relax its syntax rules. By default, this writer
+     * only emits well-formed JSON as specified by <a
+     * href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>. Setting the writer
+     * to lenient permits the following:
+     * <ul>
+     *   <li>Top-level values of any type. With strict writing, the top-level
+     *       value must be an object or an array.
+     *   <li>Numbers may be {@link Double#isNaN() NaNs} or {@link
+     *       Double#isInfinite() infinities}.
+     * </ul>
+     */
+    public void setLenient(boolean lenient) {
+        this.lenient = lenient;
+    }
+
+    /**
+     * Returns true if this writer has relaxed syntax rules.
+     */
+    public boolean isLenient() {
+        return lenient;
+    }
+
+    /**
      * Begins encoding a new array. Each call to this method must be paired with
      * a call to {@link #endArray}.
      *
@@ -306,11 +331,11 @@
      * Encodes {@code value}.
      *
      * @param value a finite value. May not be {@link Double#isNaN() NaNs} or
-     *     {@link Double#isInfinite() infinities}.
+     *     {@link Double#isInfinite() infinities} unless this writer is lenient.
      * @return this writer.
      */
     public JsonWriter value(double value) throws IOException {
-        if (Double.isNaN(value) || Double.isInfinite(value)) {
+        if (!lenient && (Double.isNaN(value) || Double.isInfinite(value))) {
             throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
         }
         beforeValue(false);
@@ -330,6 +355,28 @@
     }
 
     /**
+     * Encodes {@code value}.
+     *
+     * @param value a finite value. May not be {@link Double#isNaN() NaNs} or
+     *     {@link Double#isInfinite() infinities} unless this writer is lenient.
+     * @return this writer.
+     */
+    public JsonWriter value(Number value) throws IOException {
+        if (value == null) {
+            return nullValue();
+        }
+
+        String string = value.toString();
+        if (!lenient &&
+                (string.equals("-Infinity") || string.equals("Infinity") || string.equals("NaN"))) {
+            throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
+        }
+        beforeValue(false);
+        out.append(string);
+        return this;
+    }
+
+    /**
      * Ensures all buffered data is written to the underlying {@link Writer}
      * and flushes that writer.
      */
@@ -364,7 +411,6 @@
             switch (c) {
                 case '"':
                 case '\\':
-                case '/':
                     out.write('\\');
                     out.write(c);
                     break;
@@ -439,7 +485,7 @@
     private void beforeValue(boolean root) throws IOException {
         switch (peek()) {
             case EMPTY_DOCUMENT: // first in document
-                if (!root) {
+                if (!lenient && !root) {
                     throw new IllegalStateException(
                             "JSON must start with an array or an object.");
                 }
diff --git a/core/java/android/util/MalformedJsonException.java b/core/java/android/util/MalformedJsonException.java
new file mode 100644
index 0000000..63c19ff
--- /dev/null
+++ b/core/java/android/util/MalformedJsonException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import java.io.IOException;
+
+/**
+ * Thrown when a reader encounters malformed JSON. Some syntax errors can be
+ * ignored by calling {@link JsonReader#setLenient(boolean)}.
+ */
+public final class MalformedJsonException extends IOException {
+    private static final long serialVersionUID = 1L;
+
+    public MalformedJsonException(String message) {
+        super(message);
+    }
+}
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index 2045a98..626f385 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.res.Resources;
+import android.os.Build;
 
 /**
  * A ContextWrapper that allows you to modify the theme from what is in the 
@@ -50,14 +51,19 @@
         initializeTheme();
     }
     
+    /** @hide */
+    @Override
+    public int getThemeResId() {
+        return mThemeResource;
+    }
+
     @Override public Resources.Theme getTheme() {
         if (mTheme != null) {
             return mTheme;
         }
 
-        if (mThemeResource == 0) {
-            mThemeResource = com.android.internal.R.style.Theme;
-        }
+        mThemeResource = Resources.selectDefaultTheme(mThemeResource,
+                getApplicationInfo().targetSdkVersion);
         initializeTheme();
 
         return mTheme;
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 34d7935..b74806486 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -136,6 +136,11 @@
         outMetrics.ydpi         = mDpiY;
     }
 
+    /**
+     * @hide Helper for our fake display size hack.
+     */
+    native public static int unmapDisplaySize(int newSize);
+    
     /*
      * We use a class initializer to allow the native code to cache some
      * field offsets.
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index e7c2231..959fae4 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -46,4 +46,19 @@
      * @see android.view.HardwareCanvas#drawDisplayList(DisplayList) 
      */
     abstract boolean isReady();
+
+    /**
+     * Invalidates the display list, indicating that it should be repopulated
+     * with new drawing commands prior to being used again. Calling this method
+     * causes calls to {@link #isValid()} to return <code>false</code>.
+     */
+    abstract void invalidate();
+
+    /**
+     * Returns whether the display list is currently usable. If this returns false,
+     * the display list should be re-recorded prior to replaying it.
+     *
+     * @return boolean true if the display list is able to be replayed, false otherwise.
+     */
+    abstract boolean isValid();
 }
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 8ad9a62..d9bf918 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -19,6 +19,8 @@
 import android.graphics.Rect;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 
 /**
  * The algorithm used for finding the next focusable view in a given direction
@@ -44,6 +46,7 @@
     Rect mFocusedRect = new Rect();
     Rect mOtherRect = new Rect();
     Rect mBestCandidateRect = new Rect();
+    SequentialFocusComparator mSequentialFocusComparator = new SequentialFocusComparator();
 
     // enforce thread local access
     private FocusFinder() {}
@@ -76,6 +79,7 @@
             switch (direction) {
                 case View.FOCUS_RIGHT:
                 case View.FOCUS_DOWN:
+                case View.FOCUS_FORWARD:
                     final int rootTop = root.getScrollY();
                     final int rootLeft = root.getScrollX();
                     mFocusedRect.set(rootLeft, rootTop, rootLeft, rootTop);
@@ -83,6 +87,7 @@
 
                 case View.FOCUS_LEFT:
                 case View.FOCUS_UP:
+                case View.FOCUS_BACKWARD:
                     final int rootBottom = root.getScrollY() + root.getHeight();
                     final int rootRight = root.getScrollX() + root.getWidth();
                     mFocusedRect.set(rootRight, rootBottom,
@@ -107,6 +112,48 @@
 
     private View findNextFocus(ViewGroup root, View focused, Rect focusedRect, int direction) {
         ArrayList<View> focusables = root.getFocusables(direction);
+        if (focusables.isEmpty()) {
+            // The focus cannot change.
+            return null;
+        }
+
+        if (direction == View.FOCUS_FORWARD || direction == View.FOCUS_BACKWARD) {
+            if (focused != null && !focusables.contains(focused)) {
+                // Add the currently focused view to the list to have it sorted
+                // along with the other views.
+                focusables.add(focused);
+            }
+
+            try {
+                // Note: This sort is stable.
+                mSequentialFocusComparator.setRoot(root);
+                Collections.sort(focusables, mSequentialFocusComparator);
+            } finally {
+                mSequentialFocusComparator.recycle();
+            }
+
+            final int count = focusables.size();
+            switch (direction) {
+                case View.FOCUS_FORWARD:
+                    if (focused != null) {
+                        int position = focusables.lastIndexOf(focused);
+                        if (position >= 0 && position + 1 < count) {
+                            return focusables.get(position + 1);
+                        }
+                    }
+                    return focusables.get(0);
+
+                case View.FOCUS_BACKWARD:
+                    if (focused != null) {
+                        int position = focusables.indexOf(focused);
+                        if (position > 0) {
+                            return focusables.get(position - 1);
+                        }
+                    }
+                    return focusables.get(count - 1);
+            }
+            return null;
+        }
 
         // initialize the best candidate to something impossible
         // (so the first plausible view will become the best choice)
@@ -477,4 +524,59 @@
         throw new IllegalArgumentException("direction must be one of "
                 + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
     }
+
+    /**
+     * Sorts views according to their visual layout and geometry for default tab order.
+     * This is used for sequential focus traversal.
+     */
+    private static final class SequentialFocusComparator implements Comparator<View> {
+        private final Rect mFirstRect = new Rect();
+        private final Rect mSecondRect = new Rect();
+        private ViewGroup mRoot;
+
+        public void recycle() {
+            mRoot = null;
+        }
+
+        public void setRoot(ViewGroup root) {
+            mRoot = root;
+        }
+
+        public int compare(View first, View second) {
+            if (first == second) {
+                return 0;
+            }
+
+            getRect(first, mFirstRect);
+            getRect(second, mSecondRect);
+
+            if (mFirstRect.top < mSecondRect.top) {
+                return -1;
+            } else if (mFirstRect.top > mSecondRect.top) {
+                return 1;
+            } else if (mFirstRect.left < mSecondRect.left) {
+                return -1;
+            } else if (mFirstRect.left > mSecondRect.left) {
+                return 1;
+            } else if (mFirstRect.bottom < mSecondRect.bottom) {
+                return -1;
+            } else if (mFirstRect.bottom > mSecondRect.bottom) {
+                return 1;
+            } else if (mFirstRect.right < mSecondRect.right) {
+                return -1;
+            } else if (mFirstRect.right > mSecondRect.right) {
+                return 1;
+            } else {
+                // The view are distinct but completely coincident so we consider
+                // them equal for our purposes.  Since the sort is stable, this
+                // means that the views will retain their layout order relative to one another.
+                return 0;
+            }
+        }
+
+        private void getRect(View view, Rect rect) {
+            view.getDrawingRect(rect);
+            mRoot.offsetDescendantRectToMyCoords(view, rect);
+        }
+    }
 }
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 773d734..5fac525 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -34,11 +34,6 @@
 import android.text.SpannableString;
 import android.text.SpannedString;
 import android.text.TextUtils;
-import android.util.Finalizers;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
 
 /**
  * An implementation of Canvas on top of OpenGL ES 2.0.
@@ -46,7 +41,11 @@
 class GLES20Canvas extends HardwareCanvas {
     private final boolean mOpaque;
     private int mRenderer;
-    
+
+    // The native renderer will be destroyed when this object dies.
+    // DO NOT overwrite this reference once it is set.
+    private CanvasFinalizer mFinalizer;
+
     private int mWidth;
     private int mHeight;
     
@@ -74,51 +73,95 @@
     // Constructors
     ///////////////////////////////////////////////////////////////////////////
 
+    /**
+     * Creates a canvas to render directly on screen.
+     */
     GLES20Canvas(boolean translucent) {
         this(false, translucent);
     }
+
+    /**
+     * Creates a canvas to render into an FBO.
+     */
+    GLES20Canvas(int layer, boolean translucent) {
+        mOpaque = !translucent;
+        mRenderer = nCreateLayerRenderer(layer);
+        setupFinalizer();
+    }
     
-    GLES20Canvas(boolean record, boolean translucent) {
+    protected GLES20Canvas(boolean record, boolean translucent) {
         mOpaque = !translucent;
 
+        setupRenderer(record);
+    }
+
+    protected void setupRenderer(boolean record) {
         if (record) {
-            mRenderer = nCreateDisplayListRenderer();
+            mRenderer = nGetDisplayListRenderer(mRenderer);
         } else {
             mRenderer = nCreateRenderer();
         }
-       
+
+        setupFinalizer();
+    }
+
+    private void setupFinalizer() {
         if (mRenderer == 0) {
             throw new IllegalStateException("Could not create GLES20Canvas renderer");
         } else {
-            new CanvasFinalizer(this);
+            mFinalizer = CanvasFinalizer.getFinalizer(mFinalizer, mRenderer);
         }
     }
 
-    private native int nCreateRenderer();    
-    private native int nCreateDisplayListRenderer();    
-
+    private static native int nCreateRenderer();
+    private static native int nCreateLayerRenderer(int layer);
+    private static native int nGetDisplayListRenderer(int renderer);
     private static native void nDestroyRenderer(int renderer);
 
-    private static class CanvasFinalizer extends Finalizers.ReclaimableReference<GLES20Canvas> {
-        private static final Set<CanvasFinalizer> sFinalizers = Collections.synchronizedSet(
-                new HashSet<CanvasFinalizer>());
+    private static class CanvasFinalizer {
+        int mRenderer;
 
-        private int mRenderer;
+        // Factory method returns new instance if old one is null, or old instance
+        // otherwise, destroying native renderer along the way as necessary
+        static CanvasFinalizer getFinalizer(CanvasFinalizer oldFinalizer, int renderer) {
+            if (oldFinalizer == null) {
+                return new CanvasFinalizer(renderer);
+            }
+            oldFinalizer.replaceNativeObject(renderer);
+            return oldFinalizer;
+        }
 
-        CanvasFinalizer(GLES20Canvas canvas) {
-            super(canvas, Finalizers.getQueue());
-            mRenderer = canvas.mRenderer;
-            sFinalizers.add(this);
+        private CanvasFinalizer(int renderer) {
+            mRenderer = renderer;
+        }
+
+        private void replaceNativeObject(int newRenderer) {
+            if (mRenderer != 0 && newRenderer != mRenderer) {
+                nDestroyRenderer(mRenderer);
+            }
+            mRenderer = newRenderer;
         }
 
         @Override
-        public void reclaim() {
-            nDestroyRenderer(mRenderer);
-            sFinalizers.remove(this);
+        protected void finalize() throws Throwable {
+            try {
+                replaceNativeObject(0);
+            } finally {
+                super.finalize();
+            }
         }
     }
 
     ///////////////////////////////////////////////////////////////////////////
+    // Hardware layers
+    ///////////////////////////////////////////////////////////////////////////
+    
+    static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo);
+    static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo);
+    static native void nDestroyLayer(int layerId);
+    static native void nDestroyLayerDeferred(int layerId);
+
+    ///////////////////////////////////////////////////////////////////////////
     // Canvas management
     ///////////////////////////////////////////////////////////////////////////
 
@@ -191,10 +234,10 @@
     ///////////////////////////////////////////////////////////////////////////
 
     int getDisplayList() {
-        return nCreateDisplayList(mRenderer);
+        return nGetDisplayList(mRenderer);
     }
 
-    private native int nCreateDisplayList(int renderer);
+    private native int nGetDisplayList(int renderer);
     
     static void destroyDisplayList(int displayList) {
         nDestroyDisplayList(displayList);
@@ -210,6 +253,31 @@
     private native void nDrawDisplayList(int renderer, int displayList);
 
     ///////////////////////////////////////////////////////////////////////////
+    // Hardware layer
+    ///////////////////////////////////////////////////////////////////////////
+    
+    void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
+        final GLES20Layer glLayer = (GLES20Layer) layer;
+        boolean hasColorFilter = paint != null && setupColorFilter(paint);
+        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+        nDrawLayer(mRenderer, glLayer.getLayer(), x, y, nativePaint);
+        if (hasColorFilter) nResetModifiers(mRenderer);
+    }
+
+    private native void nDrawLayer(int renderer, int layer, float x, float y, int paint);
+    
+    void interrupt() {
+        nInterrupt(mRenderer);
+    }
+    
+    void resume() {
+        nResume(mRenderer);
+    }
+
+    private native void nInterrupt(int renderer);
+    private native void nResume(int renderer);
+
+    ///////////////////////////////////////////////////////////////////////////
     // Clipping
     ///////////////////////////////////////////////////////////////////////////
 
@@ -382,8 +450,11 @@
     @Override
     public int saveLayer(float left, float top, float right, float bottom, Paint paint,
             int saveFlags) {
-        int nativePaint = paint == null ? 0 : paint.mNativePaint;
-        return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
+        boolean hasColorFilter = paint != null && setupColorFilter(paint);
+        final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+        int count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
+        if (hasColorFilter) nResetModifiers(mRenderer);
+        return count;
     }
 
     private native int nSaveLayer(int renderer, float left, float top, float right, float bottom,
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index 11e6d30..e813bc9 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -16,12 +16,6 @@
 
 package android.view;
 
-import android.util.Finalizers;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
 /**
  * An implementation of display list for OpenGL ES 2.0.
  */
@@ -30,30 +24,53 @@
 
     private boolean mStarted = false;
     private boolean mRecorded = false;
+    private boolean mValid = false;
 
     int mNativeDisplayList;
 
+    // The native display list will be destroyed when this object dies.
+    // DO NOT overwrite this reference once it is set.
+    @SuppressWarnings("unused")
+    private DisplayListFinalizer mFinalizer;
+
     @Override
     HardwareCanvas start() {
         if (mStarted) {
             throw new IllegalStateException("Recording has already started");
         }
 
-        mCanvas = new GLES20Canvas(true, true);
+        if (mCanvas != null) {
+            ((GLES20RecordingCanvas) mCanvas).reset();
+        } else {
+            mCanvas = new GLES20RecordingCanvas(true);
+        }
         mStarted = true;
         mRecorded = false;
+        mValid = true;
 
         return mCanvas;
     }
 
     @Override
+    void invalidate() {
+        mStarted = false;
+        mRecorded = false;
+        mValid = false;
+    }
+
+    @Override
+    boolean isValid() {
+        return mValid;
+    }
+
+    @Override
     void end() {
         if (mCanvas != null) {
             mStarted = false;
             mRecorded = true;
 
             mNativeDisplayList = mCanvas.getDisplayList();
-            new DisplayListFinalizer(this);
+            mFinalizer = DisplayListFinalizer.getFinalizer(mFinalizer, mNativeDisplayList);
         }
     }
 
@@ -62,22 +79,38 @@
         return !mStarted && mRecorded;
     }
 
-    private static class DisplayListFinalizer extends Finalizers.ReclaimableReference<DisplayList> {
-        private static final Set<DisplayListFinalizer> sFinalizers = Collections.synchronizedSet(
-                new HashSet<DisplayListFinalizer>());
+    private static class DisplayListFinalizer {
+        int mNativeDisplayList;
 
-        private int mNativeDisplayList;
+        // Factory method returns new instance if old one is null, or old instance
+        // otherwise, destroying native display list along the way as necessary
+        static DisplayListFinalizer getFinalizer(DisplayListFinalizer oldFinalizer,
+                int nativeDisplayList) {
+            if (oldFinalizer == null) {
+                return new DisplayListFinalizer(nativeDisplayList);
+            }
+            oldFinalizer.replaceNativeObject(nativeDisplayList);
+            return oldFinalizer;
+        }
 
-        DisplayListFinalizer(GLES20DisplayList displayList) {
-            super(displayList, Finalizers.getQueue());
-            mNativeDisplayList = displayList.mNativeDisplayList;
-            sFinalizers.add(this);
+        private DisplayListFinalizer(int nativeDisplayList) {
+            mNativeDisplayList = nativeDisplayList;
+        }
+
+        private void replaceNativeObject(int newNativeDisplayList) {
+            if (mNativeDisplayList != 0 && mNativeDisplayList != newNativeDisplayList) {
+                GLES20Canvas.destroyDisplayList(mNativeDisplayList);
+            }
+            mNativeDisplayList = newNativeDisplayList;
         }
 
         @Override
-        public void reclaim() {
-            GLES20Canvas.destroyDisplayList(mNativeDisplayList);
-            sFinalizers.remove(this);
+        protected void finalize() throws Throwable {
+            try {
+                replaceNativeObject(0);
+            } finally {
+                super.finalize();
+            }
         }
     }
 }
diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java
new file mode 100644
index 0000000..0230430
--- /dev/null
+++ b/core/java/android/view/GLES20Layer.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.graphics.Canvas;
+
+/**
+ * An OpenGL ES 2.0 implementation of {@link HardwareLayer}.
+ */
+class GLES20Layer extends HardwareLayer {
+    private int mLayer;
+
+    private int mLayerWidth;
+    private int mLayerHeight;
+
+    private final GLES20Canvas mCanvas;
+
+    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
+    private final Finalizer mFinalizer;
+
+    GLES20Layer(int width, int height, boolean isOpaque) {
+        super(width, height, isOpaque);
+
+        int[] layerInfo = new int[2];
+        mLayer = GLES20Canvas.nCreateLayer(width, height, isOpaque, layerInfo);
+        if (mLayer != 0) {
+            mLayerWidth = layerInfo[0];
+            mLayerHeight = layerInfo[1];
+
+            mCanvas = new GLES20Canvas(mLayer, !isOpaque);
+            mFinalizer = new Finalizer(mLayer);
+        } else {
+            mCanvas = null;
+            mFinalizer = null;
+        }
+    }
+
+    /**
+     * Returns the native layer object used to render this layer.
+     * 
+     * @return A pointer to the native layer object, or 0 if the object is NULL
+     */
+    public int getLayer() {
+        return mLayer;
+    }
+
+    @Override
+    boolean isValid() {
+        return mLayer != 0 && mLayerWidth > 0 && mLayerHeight > 0;
+    }
+
+    @Override
+    void resize(int width, int height) {
+        if (!isValid() || width <= 0 || height <= 0) return;
+        if (width > mLayerWidth || height > mLayerHeight) {
+            mWidth = width;
+            mHeight = height;
+
+            int[] layerInfo = new int[2];
+
+            GLES20Canvas.nResizeLayer(mLayer, width, height, layerInfo);
+
+            mLayerWidth = layerInfo[0];
+            mLayerHeight = layerInfo[1];
+        }
+    }
+
+    @Override
+    HardwareCanvas getCanvas() {
+        return mCanvas;
+    }
+
+    @Override
+    void end(Canvas currentCanvas) {
+        if (currentCanvas instanceof GLES20Canvas) {
+            ((GLES20Canvas) currentCanvas).resume();
+        }
+    }
+
+    @Override
+    HardwareCanvas start(Canvas currentCanvas) {
+        if (currentCanvas instanceof GLES20Canvas) {
+            ((GLES20Canvas) currentCanvas).interrupt();
+        }
+        return getCanvas();
+    }
+
+    @Override
+    void destroy() {
+        mFinalizer.destroy();
+        mLayer = 0;
+    }
+
+    private static class Finalizer {
+        private int mLayerId;
+
+        public Finalizer(int layerId) {
+            mLayerId = layerId;
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
+            try {
+                if (mLayerId != 0) {
+                    GLES20Canvas.nDestroyLayerDeferred(mLayerId);
+                }
+            } finally {
+                super.finalize();
+            }
+        }
+
+        void destroy() {
+            GLES20Canvas.nDestroyLayer(mLayerId);
+            mLayerId = 0;
+        }
+    }
+}
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
new file mode 100644
index 0000000..2603281
--- /dev/null
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Shader;
+
+import java.util.HashSet;
+
+/**
+ * An implementation of a GL canvas that records drawing operations.
+ * This is intended for use with a DisplayList. This class keeps a list of all the Paint and
+ * Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while
+ * the DisplayList is still holding a native reference to the memory.
+ */
+class GLES20RecordingCanvas extends GLES20Canvas {
+    // These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long
+    // as the DisplayList is alive.
+    @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
+    private final HashSet<Bitmap> mBitmaps = new HashSet<Bitmap>();
+
+    GLES20RecordingCanvas(boolean translucent) {
+        super(true, translucent);
+    }
+
+    private void recordShaderBitmap(Paint paint) {
+        if (paint != null) {
+            final Shader shader = paint.getShader();
+            if (shader instanceof BitmapShader) {
+                mBitmaps.add(((BitmapShader) shader).mBitmap);
+            }
+        }
+    }
+
+    void reset() {
+        mBitmaps.clear();
+        setupRenderer(true);
+    }
+
+    @Override
+    public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) {
+        super.drawPatch(bitmap, chunks, dst, paint);
+        mBitmaps.add(bitmap);
+        // Shaders in the Paint are ignored when drawing a Bitmap
+    }
+
+    @Override
+    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
+        super.drawBitmap(bitmap, left, top, paint);
+        mBitmaps.add(bitmap);
+        // Shaders in the Paint are ignored when drawing a Bitmap
+    }
+
+    @Override
+    public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
+        super.drawBitmap(bitmap, matrix, paint);
+        mBitmaps.add(bitmap);
+        // Shaders in the Paint are ignored when drawing a Bitmap
+    }
+
+    @Override
+    public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
+        super.drawBitmap(bitmap, src, dst, paint);
+        mBitmaps.add(bitmap);
+        // Shaders in the Paint are ignored when drawing a Bitmap
+    }
+
+    @Override
+    public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
+        super.drawBitmap(bitmap, src, dst, paint);
+        mBitmaps.add(bitmap);
+        // Shaders in the Paint are ignored when drawing a Bitmap
+    }
+
+    @Override
+    public void drawBitmap(int[] colors, int offset, int stride, float x, float y, int width,
+            int height, boolean hasAlpha, Paint paint) {
+        super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
+        // Shaders in the Paint are ignored when drawing a Bitmap
+    }
+
+    @Override
+    public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width,
+            int height, boolean hasAlpha, Paint paint) {
+        super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
+        // Shaders in the Paint are ignored when drawing a Bitmap
+    }
+
+    @Override
+    public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
+            int vertOffset, int[] colors, int colorOffset, Paint paint) {
+        super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset,
+                paint);
+        mBitmaps.add(bitmap);
+        // Shaders in the Paint are ignored when drawing a Bitmap
+    }
+
+    @Override
+    public void drawCircle(float cx, float cy, float radius, Paint paint) {
+        super.drawCircle(cx, cy, radius, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
+        super.drawLine(startX, startY, stopX, stopY, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawLines(float[] pts, int offset, int count, Paint paint) {
+        super.drawLines(pts, offset, count, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawLines(float[] pts, Paint paint) {
+        super.drawLines(pts, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawOval(RectF oval, Paint paint) {
+        super.drawOval(oval, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawPaint(Paint paint) {
+        super.drawPaint(paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawPath(Path path, Paint paint) {
+        super.drawPath(path, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawPoint(float x, float y, Paint paint) {
+        super.drawPoint(x, y, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawPoints(float[] pts, int offset, int count, Paint paint) {
+        super.drawPoints(pts, offset, count, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawPoints(float[] pts, Paint paint) {
+        super.drawPoints(pts, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
+        super.drawPosText(text, index, count, pos, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawPosText(String text, float[] pos, Paint paint) {
+        super.drawPosText(text, pos, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawRect(float left, float top, float right, float bottom, Paint paint) {
+        super.drawRect(left, top, right, bottom, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawRect(Rect r, Paint paint) {
+        super.drawRect(r, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawRect(RectF r, Paint paint) {
+        super.drawRect(r, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
+        super.drawRoundRect(rect, rx, ry, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
+        super.drawText(text, index, count, x, y, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
+        super.drawText(text, start, end, x, y, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawText(String text, int start, int end, float x, float y, Paint paint) {
+        super.drawText(text, start, end, x, y, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawText(String text, float x, float y, Paint paint) {
+        super.drawText(text, x, y, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
+            float vOffset, Paint paint) {
+        super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
+        super.drawTextOnPath(text, path, hOffset, vOffset, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
+            float x, float y, int dir, Paint paint) {
+        super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, dir, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawTextRun(CharSequence text, int start, int end, int contextStart,
+            int contextEnd, float x, float y, int dir, Paint paint) {
+        super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, dir, paint);
+        recordShaderBitmap(paint);
+    }
+
+    @Override
+    public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
+            float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
+            int indexOffset, int indexCount, Paint paint) {
+        super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, colors,
+                colorOffset, indices, indexOffset, indexCount, paint);
+        recordShaderBitmap(paint);
+    }
+}
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 8b8d15e..2273238 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Paint;
 
 /**
  * Hardware accelerated canvas. 
@@ -48,5 +49,15 @@
      * 
      * @param displayList The display list to replay.
      */
-    public abstract void drawDisplayList(DisplayList displayList);
+    abstract void drawDisplayList(DisplayList displayList);
+
+    /**
+     * Draws the specified layer onto this canvas.
+     *
+     * @param layer The layer to composite on this canvas
+     * @param x The left coordinate of the layer
+     * @param y The top coordinate of the layer
+     * @param paint The paint used to draw the layer
+     */
+    abstract void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint); 
 }
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
new file mode 100644
index 0000000..d01b8ce
--- /dev/null
+++ b/core/java/android/view/HardwareLayer.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.graphics.Canvas;
+
+/**
+ * A hardware layer can be used to render graphics operations into a hardware
+ * friendly buffer. For instance, with an OpenGL backend, a hardware layer
+ * would use a Frame Buffer Object (FBO.) The hardware layer can be used as
+ * a drawing cache when a complex set of graphics operations needs to be
+ * drawn several times.
+ */
+abstract class HardwareLayer {
+    int mWidth;
+    int mHeight;
+
+    final boolean mOpaque;
+
+    /**
+     * Creates a new hardware layer at least as large as the supplied
+     * dimensions.
+     * 
+     * @param width The minimum width of the layer
+     * @param height The minimum height of the layer
+     * @param isOpaque Whether the layer should be opaque or not
+     */
+    HardwareLayer(int width, int height, boolean isOpaque) {
+        mWidth = width;
+        mHeight = height;
+        mOpaque = isOpaque;
+    }
+
+    /**
+     * Returns the minimum width of the layer.
+     * 
+     * @return The minimum desired width of the hardware layer 
+     */
+    int getWidth() {
+        return mWidth;
+    }
+
+    /**
+     * Returns the minimum height of the layer.
+     * 
+     * @return The minimum desired height of the hardware layer 
+     */
+    int getHeight() {
+        return mHeight;
+    }
+
+    /**
+     * Returns whether or not this layer is opaque.
+     * 
+     * @return True if the layer is opaque, false otherwise
+     */
+    boolean isOpaque() {
+        return mOpaque;
+    }
+
+    /**
+     * Indicates whether this layer can be rendered.
+     * 
+     * @return True if the layer can be rendered into, false otherwise
+     */
+    abstract boolean isValid();
+
+    /**
+     * Resizes the layer, if necessary, to be at least as large
+     * as the supplied dimensions.
+     * 
+     * @param width The new desired minimum width for this layer
+     * @param height The new desired minimum height for this layer
+     */
+    abstract void resize(int width, int height);
+
+    /**
+     * Returns a hardware canvas that can be used to render onto
+     * this layer.
+     * 
+     * @return A hardware canvas, or null if a canvas cannot be created
+     */
+    abstract HardwareCanvas getCanvas();
+
+    /**
+     * Destroys resources without waiting for a GC. 
+     */
+    abstract void destroy();
+
+    /**
+     * This must be invoked before drawing onto this layer.
+     * @param currentCanvas
+     */
+    abstract HardwareCanvas start(Canvas currentCanvas);
+    
+    /**
+     * This must be invoked after drawing onto this layer.
+     * @param currentCanvas
+     */
+    abstract void end(Canvas currentCanvas);
+}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 63490ee..f9a6c1b 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -36,7 +36,7 @@
  * @hide
  */
 public abstract class HardwareRenderer {
-    private static final String LOG_TAG = "HardwareRenderer";
+    static final String LOG_TAG = "HardwareRenderer";
 
     /**
      * A process can set this flag to false to prevent the use of hardware
@@ -116,6 +116,17 @@
     abstract DisplayList createDisplayList();
 
     /**
+     * Creates a new hardware layer.
+     * 
+     * @param width The minimum width of the layer
+     * @param height The minimum height of the layer
+     * @param isOpaque Whether the layer should be opaque or not
+     * 
+     * @return A hardware layer
+     */
+    abstract HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque);
+    
+    /**
      * Initializes the hardware renderer for the specified surface and setup the
      * renderer for drawing, if needed. This is invoked when the ViewRoot has
      * potentially lost the hardware renderer. The hardware renderer should be
@@ -682,6 +693,11 @@
         DisplayList createDisplayList() {
             return new GLES20DisplayList();
         }
+        
+        @Override
+        HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) {
+            return new GLES20Layer(width, height, isOpaque);
+        }
 
         static HardwareRenderer create(boolean translucent) {
             if (GLES20Canvas.isAvailable()) {
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 23fae42..a5f405a 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -121,7 +121,7 @@
      * the drag to the OS and passes that as the return value.  A return value of
      * null indicates failure.
      */
-    IBinder prepareDrag(IWindow window, boolean localOnly,
+    IBinder prepareDrag(IWindow window, int flags,
             int thumbnailWidth, int thumbnailHeight, out Surface outSurface);
 
     /**
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 97d7ad5..ecf1aef 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -991,6 +991,34 @@
     public static final int META_SCROLL_LOCK_ON = 0x400000;
 
     /**
+     * This mask is a combination of {@link #META_SHIFT_ON}, {@link #META_SHIFT_LEFT_ON}
+     * and {@link #META_SHIFT_RIGHT_ON}.
+     */
+    public static final int META_SHIFT_MASK = META_SHIFT_ON
+            | META_SHIFT_LEFT_ON | META_SHIFT_RIGHT_ON;
+
+    /**
+     * This mask is a combination of {@link #META_ALT_ON}, {@link #META_ALT_LEFT_ON}
+     * and {@link #META_ALT_RIGHT_ON}.
+     */
+    public static final int META_ALT_MASK = META_ALT_ON
+            | META_ALT_LEFT_ON | META_ALT_RIGHT_ON;
+
+    /**
+     * This mask is a combination of {@link #META_CTRL_ON}, {@link #META_CTRL_LEFT_ON}
+     * and {@link #META_CTRL_RIGHT_ON}.
+     */
+    public static final int META_CTRL_MASK = META_CTRL_ON
+            | META_CTRL_LEFT_ON | META_CTRL_RIGHT_ON;
+
+    /**
+     * This mask is a combination of {@link #META_META_ON}, {@link #META_META_LEFT_ON}
+     * and {@link #META_META_RIGHT_ON}.
+     */
+    public static final int META_META_MASK = META_META_ON
+            | META_META_LEFT_ON | META_META_RIGHT_ON;
+
+    /**
      * This mask is set if the device woke because of this key event.
      */
     public static final int FLAG_WOKE_HERE = 0x1;
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index d24af52..6b44f9e 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -38,7 +38,7 @@
  * for the device you are running on.  For example:
  *
  * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
- *      Context.LAYOUT_INFLATER_SERVICE);</pre>
+ *      (Context.LAYOUT_INFLATER_SERVICE);</pre>
  * 
  * <p>
  * To create a new LayoutInflater with an additional {@link Factory} for your
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index 7d5dcd8..ab515c9 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -379,15 +379,15 @@
 
             if (itemActionViewClassName != null) {
                 try {
-                    final Class<?> clazz = Class.forName(itemActionViewClassName);
+                    final Class<?> clazz = Class.forName(itemActionViewClassName, true,
+                            mContext.getClassLoader());
                     Constructor<?> c = clazz.getConstructor(ACTION_VIEW_CONSTRUCTOR_SIGNATURE);
                     item.setActionView((View) c.newInstance(mContext));
                 } catch (Exception e) {
                     throw new InflateException(e);
                 }
             } else if (itemActionViewLayout > 0) {
-                final LayoutInflater inflater = LayoutInflater.from(mContext);
-                item.setActionView(inflater.inflate(itemActionViewLayout, null));
+                item.setActionView(itemActionViewLayout);
             }
         }
         
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index 602c765..780c52e 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -433,6 +433,18 @@
     public MenuItem setActionView(View view);
 
     /**
+     * Set an action view for this menu item. An action view will be displayed in place
+     * of an automatically generated menu item element in the UI when this item is shown
+     * as an action within a parent.
+     *
+     * @param resId Layout resource to use for presenting this item to the user.
+     * @return This Item so additional setters can be called.
+     *
+     * @see #setShowAsAction(int)
+     */
+    public MenuItem setActionView(int resId);
+
+    /**
      * Returns the currently set action view for this menu item.
      *
      * @return This item's action view
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index e81aa98..db2cd50 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1550,6 +1550,7 @@
     @Override
     public String toString() {
         return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this))
+            + " pointerId=" + getPointerId(0)
             + " action=" + actionToString(mAction)
             + " x=" + getX()
             + " y=" + getY()
@@ -1567,6 +1568,8 @@
             + " edgeFlags=0x" + Integer.toHexString(mEdgeFlags)
             + " device=" + mDeviceId
             + " source=0x" + Integer.toHexString(mSource)
+            + (getPointerCount() > 1 ?
+                " pointerId2=" + getPointerId(1) + " x2=" + getX(2) + " y2=" + getY(2) : "")
             + "}";
     }
 
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index b8d72a6..e203355 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -24,7 +24,7 @@
 import android.util.Log;
 
 /**
- * Handle on to a raw buffer that is being managed by the screen compositor.
+ * Handle onto a raw buffer that is being managed by the screen compositor.
  */
 public class Surface implements Parcelable {
     private static final String LOG_TAG = "Surface";
@@ -41,7 +41,7 @@
     @Deprecated
     public static final int HARDWARE            = 0x00000010;
 
-    /** Implies "HARDWARE", the surface is to be used by the GPU
+    /** Implies "HARDWARE", the surface is to be used by the GPU;
      * additionally the backbuffer is never preserved for these
      * surfaces. 
      * @deprecated this is ignored, this value is set automatically when needed.
@@ -81,9 +81,9 @@
     
     /**
      * Creates a surface without a rendering buffer. Instead, the content
-     * of the surface must be pushed by an external entity. This is type
+     * of the surface must be pushed by an external entity. This type
      * of surface can be used for efficient camera preview or movie
-     * play back.
+     * playback.
      *
      * @deprecated not support by the system anymore
      */
@@ -99,7 +99,7 @@
      */
     public static final int OPAQUE              = 0x00000400;
     
-    /** Creates a normal surface. This is the default */
+    /** Creates a normal surface. This is the default. */
     public static final int FX_SURFACE_NORMAL   = 0x00000000;
     
     /** Creates a Blur surface. Everything behind this surface is blurred
@@ -111,7 +111,7 @@
     public static final int FX_SURFACE_BLUR     = 0x00010000;
     
     /** Creates a Dim surface. Everything behind this surface is dimmed
-     * by the amount specified in setAlpha(). 
+     * by the amount specified in {@link #setAlpha}.
      * It is an error to lock a Dim surface, since it doesn't have
      * a backing store.
      */
@@ -122,14 +122,14 @@
 
     /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
     
-    /** Hide the surface. Equivalent to calling hide() */
+    /** Hide the surface. Equivalent to calling hide(). */
     public static final int SURFACE_HIDDEN    = 0x01;
     
-    /** Freeze the surface. Equivalent to calling freeze() */ 
+    /** Freeze the surface. Equivalent to calling freeze(). */
     public static final int SURFACE_FROZEN     = 0x02;
 
     /**
-     * @deprecated use {@link #SURFACE_FROZEN} instead.
+     * @deprecated Use {@link #SURFACE_FROZEN} instead.
      */
     @Deprecated
     public static final int SURACE_FROZEN     = 0x02;
@@ -241,7 +241,7 @@
      *  like obtained from getMatrix. This is a hack to handle the case that an application
      *  uses getMatrix to keep the original matrix, set matrix of its own, then set the original
      *  matrix back. There is no perfect solution that works for all cases, and there are a lot of
-     *  cases that this model dose not work, but we hope this works for many apps.
+     *  cases that this model does not work, but we hope this works for many apps.
      * </ul>
      */
     private class CompatibleCanvas extends Canvas {
@@ -284,7 +284,7 @@
     }
 
     /**
-     * Sets the display metrics used to provide canva's width/height in compatibility mode.
+     * Sets the display metrics used to provide canvas's width/height in compatibility mode.
      */
     void setCompatibleDisplayMetrics(DisplayMetrics metrics, Translator translator) {
         mCompatibleDisplayMetrics = metrics;
diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java
index 1b242b3..2a16725 100644
--- a/core/java/android/view/SurfaceHolder.java
+++ b/core/java/android/view/SurfaceHolder.java
@@ -25,9 +25,10 @@
  * monitor changes to the surface.  This interface is typically available
  * through the {@link SurfaceView} class.
  * 
- * <p>When using this interface from a thread different than the one running
+ * <p>When using this interface from a thread other than the one running
  * its {@link SurfaceView}, you will want to carefully read the
- * {@link #lockCanvas} and {@link Callback#surfaceCreated Callback.surfaceCreated}.
+ * methods
+ * {@link #lockCanvas} and {@link Callback#surfaceCreated Callback.surfaceCreated()}.
  */
 public interface SurfaceHolder {
 
@@ -46,7 +47,7 @@
 
     /**
      * Exception that is thrown from {@link #lockCanvas} when called on a Surface
-     * whose is SURFACE_TYPE_PUSH_BUFFERS.
+     * whose type is SURFACE_TYPE_PUSH_BUFFERS.
      */
     public static class BadSurfaceTypeException extends RuntimeException {
         public BadSurfaceTypeException() {
@@ -62,7 +63,7 @@
      * changes to the surface.  When used with a {@link SurfaceView}, the
      * Surface being held is only available between calls to
      * {@link #surfaceCreated(SurfaceHolder)} and
-     * {@link #surfaceDestroyed(SurfaceHolder).  The Callback is set with
+     * {@link #surfaceDestroyed(SurfaceHolder)}.  The Callback is set with
      * {@link SurfaceHolder#addCallback SurfaceHolder.addCallback} method.
      */
     public interface Callback {
@@ -110,7 +111,7 @@
         /**
          * Called when the application needs to redraw the content of its
          * surface, after it is resized or for some other reason.  By not
-         * returning here until the redraw is complete, you can ensure that
+         * returning from here until the redraw is complete, you can ensure that
          * the user will not see your surface in a bad state (at its new
          * size before it has been correctly drawn that way).  This will
          * typically be preceeded by a call to {@link #surfaceChanged}.
@@ -122,7 +123,7 @@
 
     /**
      * Add a Callback interface for this holder.  There can several Callback
-     * interfaces associated to a holder.
+     * interfaces associated with a holder.
      * 
      * @param callback The new Callback interface.
      */
@@ -187,7 +188,7 @@
      * surface is displayed.  The default is false, allowing it to turn off.
      * This is safe to call from any thread.
      * 
-     * @param screenOn Supply to true to force the screen to stay on, false
+     * @param screenOn Set to true to force the screen to stay on, false
      * to allow it to turn off.
      */
     public void setKeepScreenOn(boolean screenOn);
@@ -195,14 +196,14 @@
     /**
      * Start editing the pixels in the surface.  The returned Canvas can be used
      * to draw into the surface's bitmap.  A null is returned if the surface has
-     * not been created or otherwise can not be edited.  You will usually need
+     * not been created or otherwise cannot be edited.  You will usually need
      * to implement {@link Callback#surfaceCreated Callback.surfaceCreated}
      * to find out when the Surface is available for use.
      * 
      * <p>The content of the Surface is never preserved between unlockCanvas() and
      * lockCanvas(), for this reason, every pixel within the Surface area
      * must be written. The only exception to this rule is when a dirty
-     * rectangle is specified, in which case, non dirty pixels will be
+     * rectangle is specified, in which case, non-dirty pixels will be
      * preserved.
      * 
      * <p>If you call this repeatedly when the Surface is not ready (before
@@ -213,7 +214,7 @@
      * <p>If null is not returned, this function internally holds a lock until
      * the corresponding {@link #unlockCanvasAndPost} call, preventing
      * {@link SurfaceView} from creating, destroying, or modifying the surface
-     * while it is being drawn.  This can be more convenience than accessing
+     * while it is being drawn.  This can be more convenient than accessing
      * the Surface directly, as you do not need to do special synchronization
      * with a drawing thread in {@link Callback#surfaceDestroyed
      * Callback.surfaceDestroyed}.
@@ -224,7 +225,7 @@
 
     
     /**
-     * Just like {@link #lockCanvas()} but allows to specify a dirty rectangle.
+     * Just like {@link #lockCanvas()} but allows specification of a dirty rectangle.
      * Every
      * pixel within that rectangle must be written; however pixels outside
      * the dirty rectangle will be preserved by the next call to lockCanvas().
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 7021604..6451d47 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -65,7 +65,7 @@
  * Surface is created and destroyed as the window is shown and hidden.
  * 
  * <p>One of the purposes of this class is to provide a surface in which a
- * secondary thread can render in to the screen.  If you are going to use it
+ * secondary thread can render into the screen.  If you are going to use it
  * this way, you need to be aware of some threading semantics:
  * 
  * <ul>
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d27e99d..f05ef8c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,6 +16,10 @@
 
 package android.view;
 
+import com.android.internal.R;
+import com.android.internal.util.Predicate;
+import com.android.internal.view.menu.MenuBuilder;
+
 import android.content.ClipData;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -54,6 +58,7 @@
 import android.util.Pools;
 import android.util.SparseArray;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.view.View.MeasureSpec;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityEventSource;
 import android.view.accessibility.AccessibilityManager;
@@ -63,8 +68,6 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.ScrollBarDrawable;
-import com.android.internal.R;
-import com.android.internal.view.menu.MenuBuilder;
 
 import java.lang.ref.WeakReference;
 import java.lang.reflect.InvocationTargetException;
@@ -543,6 +546,10 @@
  * subtree rooted by that node. When an animation is started, the framework will
  * take care of redrawing the appropriate views until the animation completes.
  * </p>
+ * <p>
+ * Starting with Android 3.0, the preferred way of animating views is to use the
+ * {@link android.animation} package APIs.
+ * </p>
  *
  * <a name="Security"></a>
  * <h3>Security</h3>
@@ -566,6 +573,7 @@
  * See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
  * </p>
  *
+ * @attr ref android.R.styleable#View_alpha
  * @attr ref android.R.styleable#View_background
  * @attr ref android.R.styleable#View_clickable
  * @attr ref android.R.styleable#View_contentDescription
@@ -581,6 +589,7 @@
  * @attr ref android.R.styleable#View_focusableInTouchMode
  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
  * @attr ref android.R.styleable#View_keepScreenOn
+ * @attr ref android.R.styleable#View_layerType
  * @attr ref android.R.styleable#View_longClickable
  * @attr ref android.R.styleable#View_minHeight
  * @attr ref android.R.styleable#View_minWidth
@@ -2041,6 +2050,7 @@
     private Bitmap mDrawingCache;
     private Bitmap mUnscaledDrawingCache;
     private DisplayList mDisplayList;
+    private HardwareLayer mHardwareLayer;
 
     /**
      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
@@ -2066,6 +2076,12 @@
      */
     private int mNextFocusDownId = View.NO_ID;
 
+    /**
+     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
+     * the user may specify which view to go to next.
+     */
+    int mNextFocusForwardId = View.NO_ID;
+
     private CheckForLongPress mPendingCheckForLongPress;
     private CheckForTap mPendingCheckForTap = null;
     private PerformClick mPerformClick;
@@ -2123,6 +2139,12 @@
     boolean mCanAcceptDrop;
 
     /**
+     * Flag indicating that a drag can cross window boundaries
+     * @hide
+     */
+    public static final int DRAG_FLAG_GLOBAL = 1;
+
+    /**
      * Position of the vertical scroll bar.
      */
     private int mVerticalScrollbarPosition;
@@ -2143,6 +2165,77 @@
     public static final int SCROLLBAR_POSITION_RIGHT = 2;
 
     /**
+     * Indicates that the view does not have a layer.
+     * 
+     * @see #getLayerType() 
+     * @see #setLayerType(int, android.graphics.Paint) 
+     * @see #LAYER_TYPE_SOFTWARE
+     * @see #LAYER_TYPE_HARDWARE 
+     */
+    public static final int LAYER_TYPE_NONE = 0;
+
+    /**
+     * <p>Indicates that the view has a software layer. A software layer is backed
+     * by a bitmap and causes the view to be rendered using Android's software
+     * rendering pipeline, even if hardware acceleration is enabled.</p>
+     * 
+     * <p>Software layers have various usages:</p>
+     * <p>When the application is not using hardware acceleration, a software layer
+     * is useful to apply a specific color filter and/or blending mode and/or
+     * translucency to a view and all its children.</p>
+     * <p>When the application is using hardware acceleration, a software layer
+     * is useful to render drawing primitives not supported by the hardware
+     * accelerated pipeline. It can also be used to cache a complex view tree
+     * into a texture and reduce the complexity of drawing operations. For instance,
+     * when animating a complex view tree with a translation, a software layer can
+     * be used to render the view tree only once.</p>
+     * <p>Software layers should be avoided when the affected view tree updates
+     * often. Every update will require to re-render the software layer, which can
+     * potentially be slow (particularly when hardware acceleration is turned on
+     * since the layer will have to be uploaded into a hardware texture after every
+     * update.)</p>
+     * 
+     * @see #getLayerType() 
+     * @see #setLayerType(int, android.graphics.Paint) 
+     * @see #LAYER_TYPE_NONE
+     * @see #LAYER_TYPE_HARDWARE 
+     */
+    public static final int LAYER_TYPE_SOFTWARE = 1;
+
+    /**
+     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
+     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
+     * OpenGL hardware) and causes the view to be rendered using Android's hardware
+     * rendering pipeline, but only if hardware acceleration is turned on for the
+     * view hierarchy. When hardware acceleration is turned off, hardware layers
+     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
+     * 
+     * <p>A hardware layer is useful to apply a specific color filter and/or
+     * blending mode and/or translucency to a view and all its children.</p>
+     * <p>A hardware layer can be used to cache a complex view tree into a
+     * texture and reduce the complexity of drawing operations. For instance,
+     * when animating a complex view tree with a translation, a hardware layer can
+     * be used to render the view tree only once.</p>
+     * <p>A hardware layer can also be used to increase the rendering quality when
+     * rotation transformations are applied on a view. It can also be used to
+     * prevent potential clipping issues when applying 3D transforms on a view.</p>
+     * 
+     * @see #getLayerType() 
+     * @see #setLayerType(int, android.graphics.Paint)
+     * @see #LAYER_TYPE_NONE
+     * @see #LAYER_TYPE_SOFTWARE
+     */
+    public static final int LAYER_TYPE_HARDWARE = 2;
+    
+    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
+            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
+            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
+            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
+    })
+    int mLayerType = LAYER_TYPE_NONE;
+    Paint mLayerPaint;
+
+    /**
      * Simple constructor to use when creating a view from code.
      *
      * @param context The Context the view is running in, through which it can
@@ -2424,6 +2517,9 @@
                 case R.styleable.View_nextFocusDown:
                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
                     break;
+                case R.styleable.View_nextFocusForward:
+                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
+                    break;
                 case R.styleable.View_minWidth:
                     mMinWidth = a.getDimensionPixelSize(attr, 0);
                     break;
@@ -2477,6 +2573,9 @@
                 case R.styleable.View_verticalScrollbarPosition:
                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
                     break;
+                case R.styleable.View_layerType:
+                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
+                    break;
             }
         }
 
@@ -2795,7 +2894,6 @@
 
     /**
      * Gets the current list of listeners for layout changes.
-     * @return
      */
     public List<OnLayoutChangeListener> getOnLayoutChangeListeners() {
         return mOnLayoutChangeListeners;
@@ -3112,9 +3210,9 @@
      * @param gainFocus True if the View has focus; false otherwise.
      * @param direction The direction focus has moved when requestFocus()
      *                  is called to give this view focus. Values are
-     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT} or
-     *                  {@link #FOCUS_RIGHT}. It may not always apply, in which
-     *                  case use the default.
+     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
+     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
+     *                  It may not always apply, in which case use the default.
      * @param previouslyFocusedRect The rectangle, in this view's coordinate
      *        system, of the previously focused view.  If applicable, this will be
      *        passed in as finer grained information about where the focus is coming
@@ -3163,6 +3261,9 @@
      * {@inheritDoc}
      */
     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
+        if (!isShown()) {
+            return;
+        }
         event.setClassName(getClass().getName());
         event.setPackageName(getContext().getPackageName());
         event.setEnabled(isEnabled());
@@ -3359,7 +3460,8 @@
     }
 
     /**
-     * @return The user specified next focus ID.
+     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
+     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
      *
      * @attr ref android.R.styleable#View_nextFocusLeft
      */
@@ -3368,9 +3470,9 @@
     }
 
     /**
-     * Set the id of the view to use for the next focus
-     *
-     * @param nextFocusLeftId
+     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
+     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
+     * decide automatically.
      *
      * @attr ref android.R.styleable#View_nextFocusLeft
      */
@@ -3379,7 +3481,8 @@
     }
 
     /**
-     * @return The user specified next focus ID.
+     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
+     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
      *
      * @attr ref android.R.styleable#View_nextFocusRight
      */
@@ -3388,9 +3491,9 @@
     }
 
     /**
-     * Set the id of the view to use for the next focus
-     *
-     * @param nextFocusRightId
+     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
+     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
+     * decide automatically.
      *
      * @attr ref android.R.styleable#View_nextFocusRight
      */
@@ -3399,7 +3502,8 @@
     }
 
     /**
-     * @return The user specified next focus ID.
+     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
+     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
      *
      * @attr ref android.R.styleable#View_nextFocusUp
      */
@@ -3408,9 +3512,9 @@
     }
 
     /**
-     * Set the id of the view to use for the next focus
-     *
-     * @param nextFocusUpId
+     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
+     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
+     * decide automatically.
      *
      * @attr ref android.R.styleable#View_nextFocusUp
      */
@@ -3419,7 +3523,8 @@
     }
 
     /**
-     * @return The user specified next focus ID.
+     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
+     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
      *
      * @attr ref android.R.styleable#View_nextFocusDown
      */
@@ -3428,9 +3533,9 @@
     }
 
     /**
-     * Set the id of the view to use for the next focus
-     *
-     * @param nextFocusDownId
+     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
+     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
+     * decide automatically.
      *
      * @attr ref android.R.styleable#View_nextFocusDown
      */
@@ -3439,6 +3544,27 @@
     }
 
     /**
+     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
+     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
+     *
+     * @attr ref android.R.styleable#View_nextFocusForward
+     */
+    public int getNextFocusForwardId() {
+        return mNextFocusForwardId;
+    }
+
+    /**
+     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
+     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
+     * decide automatically.
+     *
+     * @attr ref android.R.styleable#View_nextFocusForward
+     */
+    public void setNextFocusForwardId(int nextFocusForwardId) {
+        mNextFocusForwardId = nextFocusForwardId;
+    }
+
+    /**
      * Returns the visibility of this view and all of its ancestors
      *
      * @return True if this view and all of its ancestors are {@link #VISIBLE}
@@ -3949,10 +4075,10 @@
 
     /**
      * If a user manually specified the next view id for a particular direction,
-     * use the root to look up the view.  Once a view is found, it is cached
-     * for future lookups.
+     * use the root to look up the view.
      * @param root The root view of the hierarchy containing this view.
-     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
+     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
+     * or FOCUS_BACKWARD.
      * @return The user specified next view, or null if there is none.
      */
     View findUserSetNextFocus(View root, int direction) {
@@ -3969,6 +4095,18 @@
             case FOCUS_DOWN:
                 if (mNextFocusDownId == View.NO_ID) return null;
                 return findViewShouldExist(root, mNextFocusDownId);
+            case FOCUS_FORWARD:
+                if (mNextFocusForwardId == View.NO_ID) return null;
+                return findViewShouldExist(root, mNextFocusForwardId);
+            case FOCUS_BACKWARD: {
+                final int id = mID;
+                return root.findViewByPredicate(new Predicate<View>() {
+                    @Override
+                    public boolean apply(View t) {
+                        return t.mNextFocusForwardId == id;
+                    }
+                });
+            }
         }
         return null;
     }
@@ -4627,8 +4765,8 @@
     }
 
     /**
-     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
-     * KeyEvent.Callback.onKeyMultiple()}: perform press of the view
+     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
+     * KeyEvent.Callback.onKeyDown()}: perform press of the view
      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
      * is released, if the view is enabled and clickable.
      *
@@ -4671,8 +4809,8 @@
     }
 
     /**
-     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
-     * KeyEvent.Callback.onKeyMultiple()}: perform clicking of the view
+     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
+     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
      * {@link KeyEvent#KEYCODE_ENTER} is released.
      *
@@ -4720,7 +4858,10 @@
     }
 
     /**
-     * Called when an unhandled key shortcut event occurs.
+     * Called on the focused view when a key shortcut event is not handled.
+     * Override this method to implement local key shortcuts for the View.
+     * Key shortcuts can also be implemented by setting the
+     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
      *
      * @param keyCode The value in event.getKeyCode().
      * @param event Description of the key event.
@@ -5398,11 +5539,11 @@
 
             // Figure out if we need to update the pivot point
             if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
-                if ((mRight - mLeft) != mPrevWidth && (mBottom - mTop) != mPrevHeight) {
+                if ((mRight - mLeft) != mPrevWidth || (mBottom - mTop) != mPrevHeight) {
                     mPrevWidth = mRight - mLeft;
                     mPrevHeight = mBottom - mTop;
-                    mPivotX = (float) mPrevWidth / 2f;
-                    mPivotY = (float) mPrevHeight / 2f;
+                    mPivotX = mPrevWidth / 2f;
+                    mPivotY = mPrevHeight / 2f;
                 }
             }
             mMatrix.reset();
@@ -5712,11 +5853,18 @@
     }
 
     /**
-     * Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
-     * completely transparent and 1 means the view is completely opaque.
+     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
+     * completely transparent and 1 means the view is completely opaque.</p>
+     * 
+     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
+     * responsible for applying the opacity itself. Otherwise, calling this method is
+     * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
+     * setting a hardware layer.</p> 
      *
      * @param alpha The opacity of the view.
      *
+     * @see #setLayerType(int, android.graphics.Paint) 
+     * 
      * @attr ref android.R.styleable#View_alpha
      */
     public void setAlpha(float alpha) {
@@ -5780,9 +5928,14 @@
             onSizeChanged(width, mBottom - mTop, width, oldHeight);
 
             if (!mMatrixIsIdentity) {
+                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                    // A change in dimension means an auto-centered pivot point changes, too
+                    mMatrixDirty = true;
+                }
                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
                 invalidate();
             }
+            mBackgroundSizeChanged = true;
         }
     }
 
@@ -5797,6 +5950,15 @@
     }
 
     /**
+     * True if this view has changed since the last time being drawn.
+     *
+     * @return The dirty state of this view.
+     */
+    public boolean isDirty() {
+        return (mPrivateFlags & DIRTY_MASK) != 0;
+    }
+
+    /**
      * Sets the bottom position of this view relative to its parent. This method is meant to be
      * called by the layout system and should not generally be called otherwise, because the
      * property may be changed at any time by the layout.
@@ -5832,9 +5994,14 @@
             onSizeChanged(width, mBottom - mTop, width, oldHeight);
 
             if (!mMatrixIsIdentity) {
+                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                    // A change in dimension means an auto-centered pivot point changes, too
+                    mMatrixDirty = true;
+                }
                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
                 invalidate();
             }
+            mBackgroundSizeChanged = true;
         }
     }
 
@@ -5887,10 +6054,14 @@
             onSizeChanged(mRight - mLeft, height, oldWidth, height);
 
             if (!mMatrixIsIdentity) {
+                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                    // A change in dimension means an auto-centered pivot point changes, too
+                    mMatrixDirty = true;
+                }
                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
                 invalidate();
             }
-
+            mBackgroundSizeChanged = true;
         }
     }
 
@@ -5940,9 +6111,14 @@
             onSizeChanged(mRight - mLeft, height, oldWidth, height);
 
             if (!mMatrixIsIdentity) {
+                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                    // A change in dimension means an auto-centered pivot point changes, too
+                    mMatrixDirty = true;
+                }
                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
                 invalidate();
             }
+            mBackgroundSizeChanged = true;
         }
     }
 
@@ -7383,6 +7559,7 @@
             initialAwakenScrollBars();
             mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
         }
+        jumpDrawablesToCurrentState();
     }
 
     /**
@@ -7393,9 +7570,23 @@
      */
     protected void onDetachedFromWindow() {
         mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
+
         removeUnsetPressCallback();
         removeLongPressCallback();
+
         destroyDrawingCache();
+
+        if (mHardwareLayer != null) {
+            mHardwareLayer.destroy();
+            mHardwareLayer = null;
+        }
+
+        if (mAttachInfo != null) {
+            mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_MSG, this);
+            mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_RECT_MSG, this);
+        }
+
+        mCurrentAnimation = null;
     }
 
     /**
@@ -7642,6 +7833,9 @@
      *
      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
      * property is enabled, an exception will be thrown.</p>
+     * 
+     * <p>Note: if the child view uses and updates additionnal states which are unknown to the
+     * parent, these states should not be affected by this method.</p>
      *
      * @param enabled True to enable duplication of the parent's drawable state, false
      *                to disable it.
@@ -7667,18 +7861,176 @@
     }
 
     /**
+     * <p>Specifies the type of layer backing this view. The layer can be
+     * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
+     * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
+     * 
+     * <p>A layer is associated with an optional {@link android.graphics.Paint}
+     * instance that controls how the layer is composed on screen. The following
+     * properties of the paint are taken into account when composing the layer:</p>
+     * <ul>
+     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
+     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
+     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
+     * </ul>
+     * 
+     * <p>If this view has an alpha value set to < 1.0 by calling
+     * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
+     * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
+     * equivalent to setting a hardware layer on this view and providing a paint with
+     * the desired alpha value.<p>
+     * 
+     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
+     * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
+     * for more information on when and how to use layers.</p>
+     * 
+     * @param layerType The ype of layer to use with this view, must be one of
+     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
+     *        {@link #LAYER_TYPE_HARDWARE}
+     * @param paint The paint used to compose the layer. This argument is optional
+     *        and can be null. It is ignored when the layer type is
+     *        {@link #LAYER_TYPE_NONE}
+     * 
+     * @see #getLayerType() 
+     * @see #LAYER_TYPE_NONE
+     * @see #LAYER_TYPE_SOFTWARE
+     * @see #LAYER_TYPE_HARDWARE
+     * @see #setAlpha(float) 
+     * 
+     * @attr ref android.R.styleable#View_layerType
+     */
+    public void setLayerType(int layerType, Paint paint) {
+        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
+            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, " 
+                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
+        }
+        
+        if (layerType == mLayerType) return;
+
+        // Destroy any previous software drawing cache if needed
+        switch (mLayerType) {
+            case LAYER_TYPE_SOFTWARE:
+                if (mDrawingCache != null) {
+                    mDrawingCache.recycle();
+                    mDrawingCache = null;
+                }
+    
+                if (mUnscaledDrawingCache != null) {
+                    mUnscaledDrawingCache.recycle();
+                    mUnscaledDrawingCache = null;
+                }
+                break;
+            case LAYER_TYPE_HARDWARE:
+                if (mHardwareLayer != null) {
+                    mHardwareLayer.destroy();
+                    mHardwareLayer = null;
+                }
+                break;
+            default:
+                break;
+        }
+
+        mLayerType = layerType;
+        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
+
+        // TODO: Make sure we invalidate the parent's display list
+        invalidate();
+    }
+
+    /**
+     * Indicates what type of layer is currently associated with this view. By default
+     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
+     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
+     * for more information on the different types of layers.
+     * 
+     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
+     *         {@link #LAYER_TYPE_HARDWARE}
+     * 
+     * @see #setLayerType(int, android.graphics.Paint) 
+     * @see #LAYER_TYPE_NONE
+     * @see #LAYER_TYPE_SOFTWARE
+     * @see #LAYER_TYPE_HARDWARE
+     */
+    public int getLayerType() {
+        return mLayerType;
+    }
+    
+    /**
+     * <p>Returns a hardware layer that can be used to draw this view again
+     * without executing its draw method.</p>
+     *
+     * @return A HardwareLayer ready to render, or null if an error occurred.
+     */
+    HardwareLayer getHardwareLayer(Canvas currentCanvas) {
+        if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
+            return null;
+        }
+
+        final int width = mRight - mLeft;
+        final int height = mBottom - mTop;
+        
+        if (width == 0 || height == 0) {
+            return null;
+        }
+
+        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
+            if (mHardwareLayer == null) {
+                mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
+                        width, height, isOpaque());
+            } else if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
+                mHardwareLayer.resize(width, height);
+            }
+
+            final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas);
+            try {
+                canvas.setViewport(width, height);
+                canvas.onPreDraw();
+
+                computeScroll();
+                canvas.translate(-mScrollX, -mScrollY);
+
+                final int restoreCount = canvas.save();
+
+                mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
+    
+                // Fast path for layouts with no backgrounds
+                if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+                    mPrivateFlags &= ~DIRTY_MASK;
+                    dispatchDraw(canvas);
+                } else {
+                    draw(canvas);
+                }
+    
+                canvas.restoreToCount(restoreCount);
+            } finally {
+                canvas.onPostDraw();
+                mHardwareLayer.end(currentCanvas);
+            }
+        }
+
+        return mHardwareLayer;
+    }
+
+    /**
      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
      * null.</p>
+     * 
+     * <p>Enabling the drawing cache is similar to
+     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
+     * acceleration is turned off. When hardware acceleration is turned on enabling the
+     * drawing cache has either no effect or the cache used at drawing time is not a bitmap.
+     * This API can however be used to manually generate a bitmap copy of this view.</p>
      *
      * @param enabled true to enable the drawing cache, false otherwise
      *
      * @see #isDrawingCacheEnabled()
      * @see #getDrawingCache()
      * @see #buildDrawingCache()
+     * @see #setLayerType(int, android.graphics.Paint) 
      */
     public void setDrawingCacheEnabled(boolean enabled) {
         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
@@ -7712,9 +8064,12 @@
         }
 
         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED &&
-                ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mDisplayList == null)) {
+                ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
+                        mDisplayList == null || !mDisplayList.isValid())) {
 
-            mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList();
+            if (mDisplayList == null) {
+                mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList();
+            }
 
             final HardwareCanvas canvas = mDisplayList.start();
             try {
@@ -7815,7 +8170,7 @@
             mUnscaledDrawingCache = null;
         }
         if (mDisplayList != null) {
-            mDisplayList = null;
+            mDisplayList.invalidate();
         }
     }
 
@@ -7994,7 +8349,8 @@
             canvas.translate(-mScrollX, -mScrollY);
 
             mPrivateFlags |= DRAWN;
-            if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated) {
+            if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
+                    mLayerType != LAYER_TYPE_NONE) {
                 mPrivateFlags |= DRAWING_CACHE_VALID;
             }
 
@@ -8206,8 +8562,9 @@
     /**
      * Manually render this view (and all of its children) to the given Canvas.
      * The view must have already done a full layout before this function is
-     * called.  When implementing a view, do not override this method; instead,
-     * you should implement {@link #onDraw}.
+     * called.  When implementing a view, implement {@link #onDraw} instead of
+     * overriding this method. If you do need to override this method, call
+     * the superclass version.
      *
      * @param canvas The Canvas to which the View is rendered.
      */
@@ -8540,11 +8897,12 @@
      * (The first is measuring). In this phase, each parent calls
      * layout on all of its children to position them.
      * This is typically done using the child measurements
-     * that were stored in the measure pass().
+     * that were stored in the measure pass().</p>
      *
+     * <p>Derived classes should not override this method.
      * Derived classes with children should override
      * onLayout. In that method, they should
-     * call layout on each of their children.
+     * call layout on each of their children.</p>
      *
      * @param l Left position, relative to parent
      * @param t Top position, relative to parent
@@ -8552,7 +8910,7 @@
      * @param b Bottom position, relative to parent
      */
     @SuppressWarnings({"unchecked"})
-    public final void layout(int l, int t, int r, int b) {
+    public void layout(int l, int t, int r, int b) {
         int oldL = mLeft;
         int oldT = mTop;
         int oldB = mBottom;
@@ -8639,6 +8997,10 @@
             int newHeight = bottom - top;
 
             if (newWidth != oldWidth || newHeight != oldHeight) {
+                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
+                    // A change in dimension means an auto-centered pivot point changes, too
+                    mMatrixDirty = true;
+                }
                 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
             }
 
@@ -8646,7 +9008,7 @@
                 // If we are visible, force the DRAWN bit to on so that
                 // this invalidate will go through (at least to our parent).
                 // This is because someone may have invalidated this view
-                // before this call to setFrame came in, therby clearing
+                // before this call to setFrame came in, thereby clearing
                 // the DRAWN bit.
                 mPrivateFlags |= DRAWN;
                 invalidate();
@@ -9358,6 +9720,18 @@
     }
 
     /**
+     * {@hide}
+     * @param predicate The predicate to evaluate.
+     * @return The first view that matches the predicate or null.
+     */
+    protected View findViewByPredicateTraversal(Predicate<View> predicate) {
+        if (predicate.apply(this)) {
+            return this;
+        }
+        return null;
+    }
+
+    /**
      * Look for a child view with the given id.  If this view has the given
      * id, return this view.
      *
@@ -9386,6 +9760,18 @@
     }
 
     /**
+     * {@hide}
+     * Look for a child view that matches the specified predicate.
+     * If this view matches the predicate, return this view.
+     *
+     * @param predicate The predicate to evaluate.
+     * @return The first view that matches the predicate or null.
+     */
+    public final View findViewByPredicate(Predicate<View> predicate) {
+        return findViewByPredicateTraversal(predicate);
+    }
+
+    /**
      * Sets the identifier for this view. The identifier does not have to be
      * unique in this view's hierarchy. The identifier should be a positive
      * number.
@@ -10202,17 +10588,17 @@
     /**
      * !!! TODO: real docs
      *
-     * The base class implementation makes the thumbnail the same size and appearance
+     * The base class implementation makes the shadow the same size and appearance
      * as the view itself, and positions it with its center at the touch point.
      */
-    public static class DragThumbnailBuilder {
+    public static class DragShadowBuilder {
         private final WeakReference<View> mView;
 
         /**
-         * Construct a thumbnail builder object for use with the given view.
+         * Construct a shadow builder object for use with the given view.
          * @param view
          */
-        public DragThumbnailBuilder(View view) {
+        public DragShadowBuilder(View view) {
             mView = new WeakReference<View>(view);
         }
 
@@ -10221,99 +10607,99 @@
         }
 
         /**
-         * Provide the draggable-thumbnail metrics for the operation: the dimensions of
-         * the thumbnail image itself, and the point within that thumbnail that should
+         * Provide the draggable-shadow metrics for the operation: the dimensions of
+         * the shadow image itself, and the point within that shadow that should
          * be centered under the touch location while dragging.
          * <p>
-         * The default implementation sets the dimensions of the thumbnail to be the
-         * same as the dimensions of the View itself and centers the thumbnail under
+         * The default implementation sets the dimensions of the shadow to be the
+         * same as the dimensions of the View itself and centers the shadow under
          * the touch point.
          *
-         * @param thumbnailSize The application should set the {@code x} member of this
-         *        parameter to the desired thumbnail width, and the {@code y} member to
+         * @param shadowSize The application should set the {@code x} member of this
+         *        parameter to the desired shadow width, and the {@code y} member to
          *        the desired height.
-         * @param thumbnailTouchPoint The application should set this point to be the
-         *        location within the thumbnail that should track directly underneath
+         * @param shadowTouchPoint The application should set this point to be the
+         *        location within the shadow that should track directly underneath
          *        the touch point on the screen during a drag.
          */
-        public void onProvideThumbnailMetrics(Point thumbnailSize, Point thumbnailTouchPoint) {
+        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
             final View view = mView.get();
             if (view != null) {
-                thumbnailSize.set(view.getWidth(), view.getHeight());
-                thumbnailTouchPoint.set(thumbnailSize.x / 2, thumbnailSize.y / 2);
+                shadowSize.set(view.getWidth(), view.getHeight());
+                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
             } else {
                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
             }
         }
 
         /**
-         * Draw the thumbnail image for the upcoming drag.  The thumbnail canvas was
-         * created with the dimensions supplied by the onProvideThumbnailMetrics()
-         * callback.
+         * Draw the shadow image for the upcoming drag.  The shadow canvas was
+         * created with the dimensions supplied by the
+         * {@link #onProvideShadowMetrics(Point, Point)} callback.
          *
          * @param canvas
          */
-        public void onDrawThumbnail(Canvas canvas) {
+        public void onDrawShadow(Canvas canvas) {
             final View view = mView.get();
             if (view != null) {
                 view.draw(canvas);
             } else {
-                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag thumb but no view");
+                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
             }
         }
     }
 
     /**
-     * Drag and drop.  App calls startDrag(), then callbacks to the thumbnail builder's
-     * onProvideThumbnailMetrics() and onDrawThumbnail() methods happen, then the drag
+     * Drag and drop.  App calls startDrag(), then callbacks to the shadow builder's
+     * {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)} and
+     * {@link DragShadowBuilder#onDrawShadow(Canvas)} methods happen, then the drag
      * operation is handed over to the OS.
      * !!! TODO: real docs
      *
      * @param data !!! TODO
-     * @param thumbBuilder !!! TODO
-     * @param myWindowOnly When {@code true}, indicates that the drag operation should be
-     *     restricted to the calling application. In this case only the calling application
-     *     will see any DragEvents related to this drag operation.
+     * @param shadowBuilder !!! TODO
      * @param myLocalState An arbitrary object that will be passed as part of every DragEvent
      *     delivered to the calling application during the course of the current drag operation.
      *     This object is private to the application that called startDrag(), and is not
      *     visible to other applications. It provides a lightweight way for the application to
      *     propagate information from the initiator to the recipient of a drag within its own
      *     application; for example, to help disambiguate between 'copy' and 'move' semantics.
+     * @param flags Flags affecting the drag operation.  At present no flags are defined;
+     *     pass 0 for this parameter.
      * @return {@code true} if the drag operation was initiated successfully; {@code false} if
      *     an error prevented the drag from taking place.
      */
-    public final boolean startDrag(ClipData data, DragThumbnailBuilder thumbBuilder,
-            boolean myWindowOnly, Object myLocalState) {
+    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
+            Object myLocalState, int flags) {
         if (ViewDebug.DEBUG_DRAG) {
-            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " local=" + myWindowOnly);
+            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
         }
         boolean okay = false;
 
-        Point thumbSize = new Point();
-        Point thumbTouchPoint = new Point();
-        thumbBuilder.onProvideThumbnailMetrics(thumbSize, thumbTouchPoint);
+        Point shadowSize = new Point();
+        Point shadowTouchPoint = new Point();
+        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
 
-        if ((thumbSize.x < 0) || (thumbSize.y < 0) ||
-                (thumbTouchPoint.x < 0) || (thumbTouchPoint.y < 0)) {
-            throw new IllegalStateException("Drag thumb dimensions must not be negative");
+        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
+                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
+            throw new IllegalStateException("Drag shadow dimensions must not be negative");
         }
 
         if (ViewDebug.DEBUG_DRAG) {
-            Log.d(VIEW_LOG_TAG, "drag thumb: width=" + thumbSize.x + " height=" + thumbSize.y
-                    + " thumbX=" + thumbTouchPoint.x + " thumbY=" + thumbTouchPoint.y);
+            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
+                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
         }
         Surface surface = new Surface();
         try {
             IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
-                    myWindowOnly, thumbSize.x, thumbSize.y, surface);
+                    flags, shadowSize.x, shadowSize.y, surface);
             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
                     + " surface=" + surface);
             if (token != null) {
                 Canvas canvas = surface.lockCanvas(null);
                 try {
                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
-                    thumbBuilder.onDrawThumbnail(canvas);
+                    shadowBuilder.onDrawShadow(canvas);
                 } finally {
                     surface.unlockCanvasAndPost(canvas);
                 }
@@ -10323,12 +10709,12 @@
                 // Cache the local state object for delivery with DragEvents
                 root.setLocalDragState(myLocalState);
 
-                // repurpose 'thumbSize' for the last touch point
-                root.getLastTouchPoint(thumbSize);
+                // repurpose 'shadowSize' for the last touch point
+                root.getLastTouchPoint(shadowSize);
 
                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
-                        (float) thumbSize.x, (float) thumbSize.y,
-                        (float) thumbTouchPoint.x, (float) thumbTouchPoint.y, data);
+                        shadowSize.x, shadowSize.y,
+                        shadowTouchPoint.x, shadowTouchPoint.y, data);
                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
             }
         } catch (Exception e) {
@@ -10788,7 +11174,7 @@
          *
          * @param v The view that was clicked and held.
          *
-         * return True if the callback consumed the long click, false otherwise
+         * @return true if the callback consumed the long click, false otherwise.
          */
         boolean onLongClick(View v);
     }
@@ -11203,8 +11589,8 @@
 
         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
 
-        private final float[] mOpaque = { 255.0f };
-        private final float[] mTransparent = { 0.0f };
+        private static final float[] OPAQUE = { 255 };
+        private static final float[] TRANSPARENT = { 0.0f };
         
         /**
          * When fading should start. This time moves into the future every time
@@ -11264,11 +11650,11 @@
                 Interpolator interpolator = scrollBarInterpolator;
 
                 // Start opaque
-                interpolator.setKeyFrame(framesCount++, nextFrame, mOpaque);
+                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
 
                 // End transparent
                 nextFrame += scrollBarFadeDuration;
-                interpolator.setKeyFrame(framesCount, nextFrame, mTransparent);
+                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
 
                 state = FADING;
 
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 11e68c5..d5c440c 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -138,7 +138,7 @@
      * Enables detailed logging of drag/drop operations.
      * @hide
      */
-    public static final boolean DEBUG_DRAG = true;
+    public static final boolean DEBUG_DRAG = false;
 
     /**
      * <p>Enables or disables views consistency check. Even when this property is enabled,
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index a9aa8f9..f6b6778 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -18,6 +18,7 @@
 
 import android.animation.LayoutTransition;
 import com.android.internal.R;
+import com.android.internal.util.Predicate;
 
 import android.content.Context;
 import android.content.res.Configuration;
@@ -30,6 +31,7 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
+import android.os.Build;
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.util.AttributeSet;
@@ -42,6 +44,7 @@
 import android.view.animation.Transformation;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 
 /**
  * <p>
@@ -109,6 +112,10 @@
     // View currently under an ongoing drag
     private View mCurrentDragView;
 
+    // Metadata about the ongoing drag
+    private DragEvent mCurrentDrag;
+    private HashSet<View> mDragNotifiedChildren;
+
     // Does this group have a child that can accept the current drag payload?
     private boolean mChildAcceptsDrag;
 
@@ -127,6 +134,19 @@
     private int[] mTmpPointerIds;
     private MotionEvent.PointerCoords[] mTmpPointerCoords;
 
+    // For debugging only.  You can see these in hierarchyviewer.
+    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
+    @ViewDebug.ExportedProperty(category = "events")
+    private long mLastTouchDownTime;
+    @ViewDebug.ExportedProperty(category = "events")
+    private int mLastTouchDownIndex = -1;
+    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
+    @ViewDebug.ExportedProperty(category = "events")
+    private float mLastTouchDownX;
+    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
+    @ViewDebug.ExportedProperty(category = "events")
+    private float mLastTouchDownY;
+
     /**
      * Internal flags.
      *
@@ -303,6 +323,9 @@
     private View[] mChildren;
     // Number of valid children in the mChildren array, the rest should be null or not
     // considered as children
+
+    private boolean mLayoutSuppressed = false;
+
     private int mChildrenCount;
 
     private static final int ARRAY_INITIAL_CAPACITY = 12;
@@ -349,6 +372,10 @@
         mGroupFlags |= FLAG_ANIMATION_CACHE;
         mGroupFlags |= FLAG_ALWAYS_DRAWN_WITH_CACHE;
 
+        if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
+            mGroupFlags |= FLAG_SPLIT_MOTION_EVENTS;
+        }
+
         setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS);
 
         mChildren = new View[ARRAY_INITIAL_CAPACITY];
@@ -781,6 +808,13 @@
                 }
             }
         }
+
+        // in all cases, for drags
+        if (mCurrentDrag != null) {
+            if (visibility == VISIBLE) {
+                notifyChildOfDrag(child);
+            }
+        }
     }
 
     /**
@@ -872,6 +906,14 @@
             // clear state to recalculate which views we drag over
             mCurrentDragView = null;
 
+            // Set up our tracking of drag-started notifications
+            mCurrentDrag = DragEvent.obtain(event);
+            if (mDragNotifiedChildren == null) {
+                mDragNotifiedChildren = new HashSet<View>();
+            } else {
+                mDragNotifiedChildren.clear();
+            }
+
             // Now dispatch down to our children, caching the responses
             mChildAcceptsDrag = false;
             final int count = mChildrenCount;
@@ -879,8 +921,7 @@
             for (int i = 0; i < count; i++) {
                 final View child = children[i];
                 if (child.getVisibility() == VISIBLE) {
-                    final boolean handled = children[i].dispatchDragEvent(event);
-                    children[i].mCanAcceptDrop = handled;
+                    final boolean handled = notifyChildOfDrag(children[i]);
                     if (handled) {
                         mChildAcceptsDrag = true;
                     }
@@ -894,15 +935,16 @@
         } break;
 
         case DragEvent.ACTION_DRAG_ENDED: {
-            // Notify all of our children that the drag is over
-            final int count = mChildrenCount;
-            final View[] children = mChildren;
-            for (int i = 0; i < count; i++) {
-                final View child = children[i];
-                if (child.getVisibility() == VISIBLE) {
-                    child.dispatchDragEvent(event);
-                }
+            // If a child was notified about an ongoing drag, it's told that it's over
+            for (View child : mDragNotifiedChildren) {
+                child.dispatchDragEvent(event);
             }
+
+            // Release the bookkeeping now that the drag lifecycle has ended
+            mDragNotifiedChildren.clear();
+            mCurrentDrag.recycle();
+            mCurrentDrag = null;
+
             // We consider drag-ended to have been handled if one of our children
             // had offered to handle the drag.
             if (mChildAcceptsDrag) {
@@ -1014,6 +1056,18 @@
         return null;
     }
 
+    boolean notifyChildOfDrag(View child) {
+        if (ViewDebug.DEBUG_DRAG) {
+            Log.d(View.VIEW_LOG_TAG, "Sending drag-started to view: " + child);
+        }
+
+        if (! mDragNotifiedChildren.contains(child)) {
+            mDragNotifiedChildren.add(child);
+            child.mCanAcceptDrop = child.dispatchDragEvent(mCurrentDrag);
+        }
+        return child.mCanAcceptDrop;
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -1151,6 +1205,10 @@
                         resetCancelNextUpFlag(child);
                         if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
                             // Child wants to receive touch within its bounds.
+                            mLastTouchDownTime = ev.getDownTime();
+                            mLastTouchDownIndex = i;
+                            mLastTouchDownX = ev.getX();
+                            mLastTouchDownY = ev.getY();
                             newTouchTarget = addTouchTarget(child, idBitsToAssign);
                             alreadyDispatchedToNewTouchTarget = true;
                             break;
@@ -1567,7 +1625,8 @@
 
     /**
      * Enable or disable the splitting of MotionEvents to multiple children during touch event
-     * dispatch. This behavior is disabled by default.
+     * dispatch. This behavior is enabled by default for applications that target an
+     * SDK version of {@link Build.VERSION_CODES#HONEYCOMB} or newer.
      *
      * <p>When this option is enabled MotionEvents may be split and dispatched to different child
      * views depending on where each pointer initially went down. This allows for user interactions
@@ -1590,6 +1649,7 @@
     }
 
     /**
+     * Returns true if MotionEvents dispatched to this ViewGroup can be split to multiple children.
      * @return true if MotionEvents dispatched to this ViewGroup can be split to multiple children.
      */
     public boolean isMotionEventSplittingEnabled() {
@@ -1803,6 +1863,16 @@
         // first send it an ACTION_CANCEL motion event.
         cancelAndClearTouchTargets(null);
 
+        // In case view is detached while transition is running
+        mLayoutSuppressed = false;
+
+        // Tear down our drag tracking
+        mDragNotifiedChildren = null;
+        if (mCurrentDrag != null) {
+            mCurrentDrag.recycle();
+            mCurrentDrag = null;
+        }
+
         final int count = mChildrenCount;
         final View[] children = mChildren;
         for (int i = 0; i < count; i++) {
@@ -2153,11 +2223,15 @@
         boolean concatMatrix = false;
 
         boolean scalingRequired = false;
-        boolean caching = false;
+        boolean caching;
+        int layerType = child.getLayerType();
+        
         if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
                 (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
             caching = true;
             if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
+        } else {
+            caching = layerType != LAYER_TYPE_NONE;
         }
 
         if (a != null) {
@@ -2248,9 +2322,18 @@
         Bitmap cache = null;
         if (caching) {
             if (!canvas.isHardwareAccelerated()) {
+                if (layerType != LAYER_TYPE_NONE) {
+                    layerType = LAYER_TYPE_SOFTWARE;
+                    child.buildDrawingCache(true);
+                }
                 cache = child.getDrawingCache(true);
             } else {
-                displayList = child.getDisplayList();
+                if (layerType == LAYER_TYPE_SOFTWARE) {
+                    child.buildDrawingCache(true);
+                    cache = child.getDrawingCache(true);
+                } else {
+                    displayList = child.getDisplayList();
+                }
             }
         }
 
@@ -2268,6 +2351,8 @@
                 canvas.scale(scale, scale);
             }
         }
+        
+        boolean layerSaved = false;
 
         if (transformToApply != null || alpha < 1.0f || !child.hasIdentityMatrix()) {
             if (transformToApply != null || !childHasIdentityMatrix) {
@@ -2309,12 +2394,22 @@
                     final int multipliedAlpha = (int) (255 * alpha);
                     if (!child.onSetAlpha(multipliedAlpha)) {
                         int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
-                        if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
+                        if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN ||
+                                layerType != LAYER_TYPE_NONE) {
                             layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
                         }
-                        canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct, multipliedAlpha,
-                                layerFlags);
+                        if (layerType != LAYER_TYPE_NONE && child.mLayerPaint != null) {
+                            child.mLayerPaint.setAlpha(multipliedAlpha);
+                        } else {
+                            canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct,
+                                    multipliedAlpha, layerFlags);
+                            layerSaved = true;
+                        }
                     } else {
+                        // Alpha is handled by the child directly, clobber the layer's alpha
+                        if (layerType != LAYER_TYPE_NONE && child.mLayerPaint != null) {
+                            child.mLayerPaint.setAlpha(255);
+                        }
                         child.mPrivateFlags |= ALPHA_SET;
                     }
                 }
@@ -2337,30 +2432,53 @@
         }
 
         if (hasNoCache) {
-            if (!hasDisplayList) {
-                // Fast path for layouts with no backgrounds
-                if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
-                    if (ViewDebug.TRACE_HIERARCHY) {
-                        ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
-                    }
-                    child.mPrivateFlags &= ~DIRTY_MASK;
-                    child.dispatchDraw(canvas);
+            boolean layerRendered = false;
+            if (!layerSaved && layerType == LAYER_TYPE_HARDWARE) {
+                final HardwareLayer layer = child.getHardwareLayer(canvas);
+                if (layer != null && layer.isValid()) {
+                    ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, child.mLayerPaint);
+                    layerRendered = true;
                 } else {
-                    child.draw(canvas);
+                    canvas.saveLayer(sx, sy, sx + cr - cl, sy + cb - ct, child.mLayerPaint,
+                            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
                 }
-            } else {
-                child.mPrivateFlags &= ~DIRTY_MASK;
-                ((HardwareCanvas) canvas).drawDisplayList(displayList);
+            }
+
+            if (!layerRendered) {
+                if (!hasDisplayList) {
+                    // Fast path for layouts with no backgrounds
+                    if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+                        if (ViewDebug.TRACE_HIERARCHY) {
+                            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
+                        }
+                        child.mPrivateFlags &= ~DIRTY_MASK;
+                        child.dispatchDraw(canvas);
+                    } else {
+                        child.draw(canvas);
+                    }
+                } else {
+                    child.mPrivateFlags &= ~DIRTY_MASK;
+                    ((HardwareCanvas) canvas).drawDisplayList(displayList);
+                }
             }
         } else if (cache != null) {
             child.mPrivateFlags &= ~DIRTY_MASK;
-            final Paint cachePaint = mCachePaint;
-            if (alpha < 1.0f) {
-                cachePaint.setAlpha((int) (alpha * 255));
-                mGroupFlags |= FLAG_ALPHA_LOWER_THAN_ONE;
-            } else if  ((flags & FLAG_ALPHA_LOWER_THAN_ONE) == FLAG_ALPHA_LOWER_THAN_ONE) {
-                cachePaint.setAlpha(255);
-                mGroupFlags &= ~FLAG_ALPHA_LOWER_THAN_ONE;
+            Paint cachePaint;
+
+            if (layerType == LAYER_TYPE_NONE || child.mLayerPaint == null) {
+                cachePaint = mCachePaint;
+                if (alpha < 1.0f) {
+                    cachePaint.setAlpha((int) (alpha * 255));
+                    mGroupFlags |= FLAG_ALPHA_LOWER_THAN_ONE;
+                } else if  ((flags & FLAG_ALPHA_LOWER_THAN_ONE) == FLAG_ALPHA_LOWER_THAN_ONE) {
+                    cachePaint.setAlpha(255);
+                    mGroupFlags &= ~FLAG_ALPHA_LOWER_THAN_ONE;
+                }
+            } else {
+                cachePaint = child.mLayerPaint;
+                if (alpha < 1.0f) {
+                    cachePaint.setAlpha((int) (alpha * 255));
+                }
             }
             canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
         }
@@ -2516,6 +2634,33 @@
     }
 
     /**
+     * {@hide}
+     */
+    @Override
+    protected View findViewByPredicateTraversal(Predicate<View> predicate) {
+        if (predicate.apply(this)) {
+            return this;
+        }
+
+        final View[] where = mChildren;
+        final int len = mChildrenCount;
+
+        for (int i = 0; i < len; i++) {
+            View v = where[i];
+
+            if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+                v = v.findViewByPredicate(predicate);
+
+                if (v != null) {
+                    return v;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
      * Adds a child view. If no layout parameters are already set on the child, the
      * default parameters for this ViewGroup are set on the child.
      *
@@ -2770,6 +2915,9 @@
             }
             children[index] = child;
             mChildrenCount++;
+            if (mLastTouchDownIndex >= index) {
+                mLastTouchDownIndex++;
+            }
         } else {
             throw new IndexOutOfBoundsException("index=" + index + " count=" + count);
         }
@@ -2790,6 +2938,12 @@
         } else {
             throw new IndexOutOfBoundsException();
         }
+        if (mLastTouchDownIndex == index) {
+            mLastTouchDownTime = 0;
+            mLastTouchDownIndex = -1;
+        } else if (mLastTouchDownIndex > index) {
+            mLastTouchDownIndex--;
+        }
     }
 
     // This method also sets the children's mParent to null
@@ -3295,7 +3449,7 @@
                         child.getAnimation() == null;
                 // Mark the child as dirty, using the appropriate flag
                 // Make sure we do not set both flags at the same time
-                final int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY;
+                int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY;
 
                 final int[] location = attachInfo.mInvalidateChildLocation;
                 location[CHILD_LEFT_INDEX] = child.mLeft;
@@ -3326,8 +3480,14 @@
 
                     // If the parent is dirty opaque or not dirty, mark it dirty with the opaque
                     // flag coming from the child that initiated the invalidate
-                    if (view != null && (view.mPrivateFlags & DIRTY_MASK) != DIRTY) {
-                        view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag;
+                    if (view != null) {
+                        if ((view.mViewFlags & FADING_EDGE_MASK) != 0 &&
+                                view.getSolidColor() == 0 && !view.isOpaque()) {
+                            opaqueFlag = DIRTY;
+                        }
+                        if ((view.mPrivateFlags & DIRTY_MASK) != DIRTY) {
+                            view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag;
+                        }
                     }
 
                     parent = parent.invalidateChildInParent(location, dirty);
@@ -3506,6 +3666,19 @@
      * {@inheritDoc}
      */
     @Override
+    public final void layout(int l, int t, int r, int b) {
+        if (mTransition == null || !mTransition.isChangingLayout()) {
+            super.layout(l, t, r, b);
+        } else {
+            // record the fact that we noop'd it; request layout when transition finishes
+            mLayoutSuppressed = true;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     protected abstract void onLayout(boolean changed,
             int l, int t, int r, int b);
 
@@ -4190,6 +4363,10 @@
         @Override
         public void endTransition(LayoutTransition transition, ViewGroup container,
                 View view, int transitionType) {
+            if (mLayoutSuppressed && !transition.isChangingLayout()) {
+                requestLayout();
+                mLayoutSuppressed = false;
+            }
             if (transitionType == LayoutTransition.DISAPPEARING && mTransitioningViews != null) {
                 endViewTransition(view);
             }
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 95949b9..ad9e6863 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -345,8 +345,6 @@
                 mWindowAttributes.copyFrom(attrs);
                 attrs = mWindowAttributes;
                 
-                enableHardwareAcceleration(attrs);
-
                 if (view instanceof RootViewSurfaceTaker) {
                     mSurfaceHolderCallback =
                             ((RootViewSurfaceTaker)view).willYouTakeTheSurface();
@@ -355,6 +353,12 @@
                         mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
                     }
                 }
+
+                // If the application owns the surface, don't enable hardware acceleration
+                if (mSurfaceHolder == null) {
+                    enableHardwareAcceleration(attrs);
+                }
+
                 Resources resources = mView.getContext().getResources();
                 CompatibilityInfo compatibilityInfo = resources.getCompatibilityInfo();
                 mTranslator = compatibilityInfo.getTranslator();
@@ -481,10 +485,17 @@
     private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
         mAttachInfo.mHardwareAccelerated = false;
         mAttachInfo.mHardwareAccelerationRequested = false;
-        
+
         // Try to enable hardware acceleration if requested
         if (attrs != null &&
                 (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) {
+            // Don't enable hardware acceleration when we're not on the main thread
+            if (Looper.getMainLooper() != Looper.myLooper()) {
+                Log.w(HardwareRenderer.LOG_TAG, "Attempting to initialize hardware acceleration "
+                        + "outside of the main thread, aborting");
+                return;
+            }
+
             // Only enable hardware acceleration if we are not in the system process
             // The window manager creates ViewRoots to display animated preview windows
             // of launching apps and we don't want those to be hardware accelerated
@@ -1069,11 +1080,6 @@
                             }
                         }
                         surfaceChanged = true;
-
-                        if (mAttachInfo.mHardwareRenderer != null) {
-                            // This will bail out early if already initialized
-                            mAttachInfo.mHardwareRenderer.initialize(mHolder);
-                        }
                     }
                     if (surfaceChanged) {
                         mSurfaceHolderCallback.surfaceChanged(mSurfaceHolder,
@@ -1104,7 +1110,7 @@
                 }
             }
 
-            if (hwInitialized || (windowShouldResize &&
+            if (hwInitialized || ((windowShouldResize || params != null) &&
                     mAttachInfo.mHardwareRenderer != null &&
                     mAttachInfo.mHardwareRenderer.isEnabled())) {
                 mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
@@ -2415,81 +2421,78 @@
     }
 
     /**
-     * @param keyCode The key code
-     * @return True if the key is directional.
+     * Returns true if the key is used for keyboard navigation.
+     * @param keyEvent The key event.
+     * @return True if the key is used for keyboard navigation.
      */
-    static boolean isDirectional(int keyCode) {
-        switch (keyCode) {
+    private static boolean isNavigationKey(KeyEvent keyEvent) {
+        switch (keyEvent.getKeyCode()) {
         case KeyEvent.KEYCODE_DPAD_LEFT:
         case KeyEvent.KEYCODE_DPAD_RIGHT:
         case KeyEvent.KEYCODE_DPAD_UP:
         case KeyEvent.KEYCODE_DPAD_DOWN:
+        case KeyEvent.KEYCODE_DPAD_CENTER:
+        case KeyEvent.KEYCODE_PAGE_UP:
+        case KeyEvent.KEYCODE_PAGE_DOWN:
+        case KeyEvent.KEYCODE_MOVE_HOME:
+        case KeyEvent.KEYCODE_MOVE_END:
+        case KeyEvent.KEYCODE_TAB:
+        case KeyEvent.KEYCODE_SPACE:
+        case KeyEvent.KEYCODE_ENTER:
             return true;
         }
         return false;
     }
 
     /**
-     * Returns true if this key is a keyboard key.
+     * Returns true if the key is used for typing.
      * @param keyEvent The key event.
-     * @return whether this key is a keyboard key.
+     * @return True if the key is used for typing.
      */
-    private static boolean isKeyboardKey(KeyEvent keyEvent) {
-      final int convertedKey = keyEvent.getUnicodeChar();
-        return convertedKey > 0;
+    private static boolean isTypingKey(KeyEvent keyEvent) {
+        return keyEvent.getUnicodeChar() > 0;
     }
 
-
-
     /**
-     * See if the key event means we should leave touch mode (and leave touch
-     * mode if so).
+     * See if the key event means we should leave touch mode (and leave touch mode if so).
      * @param event The key event.
      * @return Whether this key event should be consumed (meaning the act of
      *   leaving touch mode alone is considered the event).
      */
     private boolean checkForLeavingTouchModeAndConsume(KeyEvent event) {
-        final int action = event.getAction();
-        if (action != KeyEvent.ACTION_DOWN && action != KeyEvent.ACTION_MULTIPLE) {
-            return false;
-        }
-        if ((event.getFlags()&KeyEvent.FLAG_KEEP_TOUCH_MODE) != 0) {
-            return false;
-        }
-
-        // only relevant if we are in touch mode
+        // Only relevant in touch mode.
         if (!mAttachInfo.mInTouchMode) {
             return false;
         }
 
-        // if something like an edit text has focus and the user is typing,
-        // leave touch mode
-        //
-        // note: the condition of not being a keyboard key is kind of a hacky
-        // approximation of whether we think the focused view will want the
-        // key; if we knew for sure whether the focused view would consume
-        // the event, that would be better.
-        if (isKeyboardKey(event) && mView != null && mView.hasFocus()) {
-            mFocusedView = mView.findFocus();
-            if ((mFocusedView instanceof ViewGroup)
-                    && ((ViewGroup) mFocusedView).getDescendantFocusability() ==
-                    ViewGroup.FOCUS_AFTER_DESCENDANTS) {
-                // something has focus, but is holding it weakly as a container
-                return false;
-            }
-            if (ensureTouchMode(false)) {
-                throw new IllegalStateException("should not have changed focus "
-                        + "when leaving touch mode while a view has focus.");
-            }
+        // Only consider leaving touch mode on DOWN or MULTIPLE actions, never on UP.
+        final int action = event.getAction();
+        if (action != KeyEvent.ACTION_DOWN && action != KeyEvent.ACTION_MULTIPLE) {
             return false;
         }
 
-        if (isDirectional(event.getKeyCode())) {
-            // no view has focus, so we leave touch mode (and find something
-            // to give focus to).  the event is consumed if we were able to
-            // find something to give focus to.
+        // Don't leave touch mode if the IME told us not to.
+        if ((event.getFlags() & KeyEvent.FLAG_KEEP_TOUCH_MODE) != 0) {
+            return false;
+        }
+
+        // If the key can be used for keyboard navigation then leave touch mode
+        // and select a focused view if needed (in ensureTouchMode).
+        // When a new focused view is selected, we consume the navigation key because
+        // navigation doesn't make much sense unless a view already has focus so
+        // the key's purpose is to set focus.
+        if (isNavigationKey(event)) {
             return ensureTouchMode(false);
         }
+
+        // If the key can be used for typing then leave touch mode
+        // and select a focused view if needed (in ensureTouchMode).
+        // Always allow the view to process the typing key.
+        if (isTypingKey(event)) {
+            ensureTouchMode(false);
+            return false;
+        }
+
         return false;
     }
 
@@ -2629,6 +2632,16 @@
             return;
         }
 
+        // If the Control modifier is held, try to interpret the key as a shortcut.
+        if (event.getAction() == KeyEvent.ACTION_UP
+                && event.isCtrlPressed()
+                && !KeyEvent.isModifierKey(event.getKeyCode())) {
+            if (mView.dispatchKeyShortcutEvent(event)) {
+                finishKeyEvent(event, sendDone, true);
+                return;
+            }
+        }
+
         // Apply the fallback event policy.
         if (mFallbackEventHandler.dispatchKeyEvent(event)) {
             finishKeyEvent(event, sendDone, true);
@@ -2640,16 +2653,31 @@
             int direction = 0;
             switch (event.getKeyCode()) {
             case KeyEvent.KEYCODE_DPAD_LEFT:
-                direction = View.FOCUS_LEFT;
+                if (event.hasNoModifiers()) {
+                    direction = View.FOCUS_LEFT;
+                }
                 break;
             case KeyEvent.KEYCODE_DPAD_RIGHT:
-                direction = View.FOCUS_RIGHT;
+                if (event.hasNoModifiers()) {
+                    direction = View.FOCUS_RIGHT;
+                }
                 break;
             case KeyEvent.KEYCODE_DPAD_UP:
-                direction = View.FOCUS_UP;
+                if (event.hasNoModifiers()) {
+                    direction = View.FOCUS_UP;
+                }
                 break;
             case KeyEvent.KEYCODE_DPAD_DOWN:
-                direction = View.FOCUS_DOWN;
+                if (event.hasNoModifiers()) {
+                    direction = View.FOCUS_DOWN;
+                }
+                break;
+            case KeyEvent.KEYCODE_TAB:
+                if (event.hasNoModifiers()) {
+                    direction = View.FOCUS_FORWARD;
+                } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
+                    direction = View.FOCUS_BACKWARD;
+                }
                 break;
             }
 
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 5385cd9..2f27935 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -150,6 +150,17 @@
         public boolean dispatchKeyEvent(KeyEvent event);
 
         /**
+         * Called to process a key shortcut event.
+         * At the very least your implementation must call
+         * {@link android.view.Window#superDispatchKeyShortcutEvent} to do the
+         * standard key shortcut processing.
+         *
+         * @param event The key shortcut event.
+         * @return True if this event was consumed.
+         */
+        public boolean dispatchKeyShortcutEvent(KeyEvent event);
+
+        /**
          * Called to process touch screen events.  At the very least your
          * implementation must call
          * {@link android.view.Window#superDispatchTouchEvent} to do the
@@ -576,14 +587,16 @@
 
     /**
      * Set the width and height layout parameters of the window.  The default
-     * for both of these is MATCH_PARENT; you can change them to WRAP_CONTENT to
-     * make a window that is not full-screen.
+     * for both of these is MATCH_PARENT; you can change them to WRAP_CONTENT
+     * or an absolute value to make a window that is not full-screen.
      *
      * @param width The desired layout width of the window.
      * @param height The desired layout height of the window.
+     *
+     * @see ViewGroup.LayoutParams#height
+     * @see ViewGroup.LayoutParams#width
      */
-    public void setLayout(int width, int height)
-    {
+    public void setLayout(int width, int height) {
         final WindowManager.LayoutParams attrs = getAttributes();
         attrs.width = width;
         attrs.height = height;
@@ -1026,6 +1039,14 @@
     public abstract boolean superDispatchKeyEvent(KeyEvent event);
 
     /**
+     * Used by custom windows, such as Dialog, to pass the key shortcut press event
+     * further down the view hierarchy. Application developers should
+     * not need to implement or call this.
+     *
+     */
+    public abstract boolean superDispatchKeyShortcutEvent(KeyEvent event);
+
+    /**
      * Used by custom windows, such as Dialog, to pass the touch screen event
      * further down the view hierarchy. Application developers should
      * not need to implement or call this.
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e8792ff..c54a3cf 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -381,6 +381,11 @@
          */
         public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17;
 
+        /**
+         * Window type: (mouse) pointer
+         * @hide
+         */
+        public static final int TYPE_POINTER = FIRST_SYSTEM_WINDOW+18;
 
         /**
          * End of types of system windows.
@@ -631,8 +636,33 @@
         public static final int FLAG_SPLIT_TOUCH = 0x00800000;
         
         /**
-         * Indicates whether this window should be hardware accelerated.
-         * Requesting hardware acceleration does not guarantee it will happen.
+         * <p>Indicates whether this window should be hardware accelerated.
+         * Requesting hardware acceleration does not guarantee it will happen.</p>
+         * 
+         * <p>This flag can be controlled programmatically <em>only</em> to enable
+         * hardware acceleration. To enable hardware acceleration for a given
+         * window programmatically, do the following:</p>
+         * 
+         * <pre>
+         * Window w = activity.getWindow(); // in Activity's onCreate() for instance
+         * w.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+         *         WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+         * </pre>
+         * 
+         * <p>It is important to remember that this flag <strong>must</strong>
+         * be set before setting the content view of your activity or dialog.</p>
+         * 
+         * <p>This flag cannot be used to disable hardware acceleration after it
+         * was enabled in your manifest using
+         * {@link android.R.attr#hardwareAccelerated}. If you need to selectively
+         * and programmatically disable hardware acceleration (for automated testing
+         * for instance), make sure it is turned off in your manifest and enable it
+         * on your activity or dialog when you need it instead, using the method
+         * described above.</p>
+         * 
+         * <p>This flag is automatically set by the system if the
+         * {@link android.R.attr#hardwareAccelerated android:hardwareAccelerated}
+         * XML attribute is set to true on an activity or on the application.</p>
          */
         public static final int FLAG_HARDWARE_ACCELERATED = 0x01000000;
 
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 3479bf5..e8d67da 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -23,6 +23,9 @@
 import android.os.LocalPowerManager;
 import android.view.animation.Animation;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 /**
  * This interface supplies all UI-specific behavior of the window manager.  An
  * instance of it is created by the window manager when it starts up, and allows
@@ -85,6 +88,17 @@
 
     public final static boolean WATCH_POINTER = false;
 
+    /**
+     * Sticky broadcast of the current HDMI plugged state.
+     */
+    public final static String ACTION_HDMI_PLUGGED = "android.intent.action.HDMI_PLUGGED";
+
+    /**
+     * Extra in {@link #ACTION_HDMI_PLUGGED} indicating the state: true if
+     * plugged in to HDMI, false if not.
+     */
+    public final static String EXTRA_HDMI_PLUGGED_STATE = "state";
+
     // flags for interceptKeyTq
     /**
      * Pass this event to the user / app.  To be returned from {@link #interceptKeyTq}.
@@ -806,4 +820,15 @@
      *                 {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}. 
      */
     public void setUserRotationMode(int mode, int rotation);
+
+    /**
+     * Print the WindowManagerPolicy's state into the given stream.
+     *
+     * @param prefix Text to print at the front of each line.
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param writer The PrintWriter to which you should dump your state.  This will be
+     * closed for you after you return.
+     * @param args additional arguments to the dump request.
+     */
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
 }
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 300e5d6..ac378fc 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -275,7 +275,9 @@
      * that was developed against the given target API version.  This can
      * impact the following input types:
      * {@link InputType#TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS},
-     * {@link InputType#TYPE_TEXT_VARIATION_WEB_PASSWORD}.
+     * {@link InputType#TYPE_TEXT_VARIATION_WEB_PASSWORD},
+     * {@link InputType#TYPE_NUMBER_VARIATION_NORMAL},
+     * {@link InputType#TYPE_NUMBER_VARIATION_PASSWORD}.
      *
      * <p>This is called by the framework for input method implementations;
      * you should not generally need to call it yourself.
@@ -288,11 +290,16 @@
             switch (inputType&(TYPE_MASK_CLASS|TYPE_MASK_VARIATION)) {
                 case TYPE_CLASS_TEXT|TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS:
                     inputType = TYPE_CLASS_TEXT|TYPE_TEXT_VARIATION_EMAIL_ADDRESS
-                            | (inputType&(~TYPE_MASK_FLAGS));
+                            | (inputType&TYPE_MASK_FLAGS);
                     break;
                 case TYPE_CLASS_TEXT|TYPE_TEXT_VARIATION_WEB_PASSWORD:
                     inputType = TYPE_CLASS_TEXT|TYPE_TEXT_VARIATION_PASSWORD
-                            | (inputType&(~TYPE_MASK_FLAGS));
+                            | (inputType&TYPE_MASK_FLAGS);
+                    break;
+                case TYPE_CLASS_NUMBER|TYPE_NUMBER_VARIATION_NORMAL:
+                case TYPE_CLASS_NUMBER|TYPE_NUMBER_VARIATION_PASSWORD:
+                    inputType = TYPE_CLASS_NUMBER
+                            | (inputType&TYPE_MASK_FLAGS);
                     break;
             }
         }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 867bb83..d310237 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -506,9 +506,10 @@
         }
     }
 
-    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi) {
+    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
+            boolean allowsImplicitlySelectedSubtypes) {
         try {
-            return mService.getEnabledInputMethodSubtypeList(imi);
+            return mService.getEnabledInputMethodSubtypeList(imi, allowsImplicitlySelectedSubtypes);
         } catch (RemoteException e) {
             throw new RuntimeException(e);
         }
diff --git a/core/java/android/webkit/AccessibilityInjector.java b/core/java/android/webkit/AccessibilityInjector.java
index ba16c8a..6bb4320 100644
--- a/core/java/android/webkit/AccessibilityInjector.java
+++ b/core/java/android/webkit/AccessibilityInjector.java
@@ -20,7 +20,6 @@
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
 import android.util.Log;
-import android.util.SparseArray;
 import android.view.KeyEvent;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -41,7 +40,7 @@
  *       aware of one navigation axis which is in fact the default behavior
  *       of webViews while using the DPAD/TrackBall.
  * </p>
- * In general a key binding is a mapping from meta state + key code to
+ * In general a key binding is a mapping from modifiers + key code to
  * a sequence of actions. For more detail how to specify key bindings refer to
  * {@link android.provider.Settings.Secure#ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS}.
  * </p>
@@ -71,13 +70,14 @@
     private static final int ACTION_TRAVERSE_CURRENT_AXIS = 1;
     private static final int ACTION_TRAVERSE_GIVEN_AXIS = 2;
     private static final int ACTION_PERFORM_AXIS_TRANSITION = 3;
+    private static final int ACTION_TRAVERSE_DEFAULT_WEB_VIEW_BEHAVIOR_AXIS = 4;
 
     // the default WebView behavior abstracted as a navigation axis
     private static final int NAVIGATION_AXIS_DEFAULT_WEB_VIEW_BEHAVIOR = 7;
 
     // these are the same for all instances so make them process wide
-    private static SparseArray<AccessibilityWebContentKeyBinding> sBindings =
-        new SparseArray<AccessibilityWebContentKeyBinding>();
+    private static ArrayList<AccessibilityWebContentKeyBinding> sBindings =
+        new ArrayList<AccessibilityWebContentKeyBinding>();
 
     // handle to the WebView this injector is associated with.
     private final WebView mWebView;
@@ -119,10 +119,15 @@
 
         mLastDownEventHandled = false;
 
-        int key = event.getMetaState() << AccessibilityWebContentKeyBinding.OFFSET_META_STATE |
-            event.getKeyCode() << AccessibilityWebContentKeyBinding.OFFSET_KEY_CODE;
+        AccessibilityWebContentKeyBinding binding = null;
+        for (AccessibilityWebContentKeyBinding candidate : sBindings) {
+            if (event.getKeyCode() == candidate.getKeyCode()
+                    && event.hasModifiers(candidate.getModifiers())) {
+                binding = candidate;
+                break;
+            }
+        }
 
-        AccessibilityWebContentKeyBinding binding = sBindings.get(key);
         if (binding == null) {
             return false;
         }
@@ -139,9 +144,8 @@
                     break;
                 case ACTION_TRAVERSE_CURRENT_AXIS:
                     int direction = binding.getFirstArgument(i);
-                    // on second null selection string in same direction => WebView handle the event
+                    // on second null selection string in same direction - WebView handles the event
                     if (direction == mLastDirection && mIsLastSelectionStringNull) {
-                        mLastDirection = direction;
                         mIsLastSelectionStringNull = false;
                         return false;
                     }
@@ -154,7 +158,6 @@
                     direction = binding.getFirstArgument(i);
                     // on second null selection string in same direction => WebView handle the event
                     if (direction == mLastDirection && mIsLastSelectionStringNull) {
-                        mLastDirection = direction;
                         mIsLastSelectionStringNull = false;
                         return false;
                     }
@@ -171,6 +174,22 @@
                     prefromAxisTransition(fromAxis, toAxis, sendEvent, contentDescription);
                     mLastDownEventHandled = true;
                     break;
+                case ACTION_TRAVERSE_DEFAULT_WEB_VIEW_BEHAVIOR_AXIS:
+                    // This is a special case since we treat the default WebView navigation
+                    // behavior as one of the possible navigation axis the user can use.
+                    // If we are not on the default WebView navigation axis this is NOP.
+                    if (mCurrentAxis == NAVIGATION_AXIS_DEFAULT_WEB_VIEW_BEHAVIOR) {
+                        // While WebVew handles navigation we do not get null selection
+                        // strings so do not check for that here as the cases above.
+                        mLastDirection = binding.getFirstArgument(i);
+                        sendEvent = (binding.getSecondArgument(i) == 1);
+                        traverseGivenAxis(mLastDirection, NAVIGATION_AXIS_DEFAULT_WEB_VIEW_BEHAVIOR,
+                            sendEvent, contentDescription);
+                        mLastDownEventHandled = false;
+                    } else {
+                        mLastDownEventHandled = true;
+                    }
+                    break;
                 default:
                     Log.w(LOG_TAG, "Unknown action code: " + actionCode);
             }
@@ -237,21 +256,26 @@
      */
     private boolean traverseGivenAxis(int direction, int axis, boolean sendEvent,
             String contentDescription) {
-        // if the axis is the default let WebView handle the event
+        WebViewCore webViewCore = mWebView.getWebViewCore();
+        if (webViewCore == null) {
+            return false;
+        }
+
+        AccessibilityEvent event = null;
+        if (sendEvent) {
+            event = getPartialyPopulatedAccessibilityEvent();
+            // the text will be set upon receiving the selection string
+            event.setContentDescription(contentDescription);
+        }
+        mScheduledEventStack.push(event);
+
+        // if the axis is the default let WebView handle the event which will
+        // result in cursor ring movement and selection of its content
         if (axis == NAVIGATION_AXIS_DEFAULT_WEB_VIEW_BEHAVIOR) {
             return false;
         }
-        WebViewCore webViewCore = mWebView.getWebViewCore();
-        if (webViewCore != null) {
-            AccessibilityEvent event = null;
-            if (sendEvent) {
-                event = getPartialyPopulatedAccessibilityEvent();
-                // the text will be set upon receiving the selection string
-                event.setContentDescription(contentDescription);
-            }
-            mScheduledEventStack.push(event);
-            webViewCore.sendMessage(EventHub.MODIFY_SELECTION, direction, axis);
-        }
+
+        webViewCore.sendMessage(EventHub.MODIFY_SELECTION, direction, axis);
         return true;
     }
 
@@ -259,7 +283,13 @@
      * Called when the <code>selectionString</code> has changed.
      */
     public void onSelectionStringChange(String selectionString) {
+        if (DEBUG) {
+            Log.d(LOG_TAG, "Selection string: " + selectionString);
+        }
         mIsLastSelectionStringNull = (selectionString == null);
+        if (mScheduledEventStack.isEmpty()) {
+            return;
+        }
         AccessibilityEvent event = mScheduledEventStack.pop();
         if (event != null) {
             event.getText().add(selectionString);
@@ -276,7 +306,12 @@
         if (DEBUG) {
             Log.d(LOG_TAG, "Dispatching: " + event);
         }
-        AccessibilityManager.getInstance(mWebView.getContext()).sendAccessibilityEvent(event);
+        // accessibility may be disabled while waiting for the selection string
+        AccessibilityManager accessibilityManager =
+            AccessibilityManager.getInstance(mWebView.getContext());
+        if (accessibilityManager.isEnabled()) {
+            accessibilityManager.sendAccessibilityEvent(event);
+        }
     }
 
     /**
@@ -306,99 +341,71 @@
         SimpleStringSplitter semiColonSplitter = new SimpleStringSplitter(';');
         semiColonSplitter.setString(webContentKeyBindingsString);
 
-        ArrayList<AccessibilityWebContentKeyBinding> bindings =
-            new ArrayList<AccessibilityWebContentKeyBinding>();
-
         while (semiColonSplitter.hasNext()) {
             String bindingString = semiColonSplitter.next();
             if (TextUtils.isEmpty(bindingString)) {
-                Log.e(LOG_TAG, "Malformed Web content key binding: "
+                Log.e(LOG_TAG, "Disregarding malformed Web content key binding: "
                         + webContentKeyBindingsString);
                 continue;
             }
             String[] keyValueArray = bindingString.split("=");
             if (keyValueArray.length != 2) {
-                Log.e(LOG_TAG, "Disregarding malformed Web content key binding: " +
-                        bindingString);
+                Log.e(LOG_TAG, "Disregarding malformed Web content key binding: " + bindingString);
                 continue;
             }
             try {
-                SimpleStringSplitter colonSplitter = new SimpleStringSplitter(':');//remove
-                int key = Integer.decode(keyValueArray[0].trim());
+                long keyCodeAndModifiers = Long.decode(keyValueArray[0].trim());
                 String[] actionStrings = keyValueArray[1].split(":");
                 int[] actions = new int[actionStrings.length];
                 for (int i = 0, count = actions.length; i < count; i++) {
                     actions[i] = Integer.decode(actionStrings[i].trim());
                 }
-
-                bindings.add(new AccessibilityWebContentKeyBinding(key, actions));
+                sBindings.add(new AccessibilityWebContentKeyBinding(keyCodeAndModifiers, actions));
             } catch (NumberFormatException nfe) {
                 Log.e(LOG_TAG, "Disregarding malformed key binding: " + bindingString);
             }
         }
-
-        for (AccessibilityWebContentKeyBinding binding : bindings) {
-            sBindings.put(binding.getKey(), binding);
-        }
     }
 
     /**
      * Represents a web content key-binding.
      */
-    private class AccessibilityWebContentKeyBinding {
+    private static final class AccessibilityWebContentKeyBinding {
 
-        private static final int OFFSET_META_STATE = 0x00000010;
+        private static final int MODIFIERS_OFFSET = 32;
+        private static final long MODIFIERS_MASK = 0xFFFFFFF00000000L;
 
-        private static final int MASK_META_STATE = 0xFFFF0000;
+        private static final int KEY_CODE_OFFSET = 0;
+        private static final long KEY_CODE_MASK = 0x00000000FFFFFFFFL;
 
-        private static final int OFFSET_KEY_CODE = 0x00000000;
+        private static final int ACTION_OFFSET = 24;
+        private static final int ACTION_MASK = 0xFF000000;
 
-        private static final int MASK_KEY_CODE = 0x0000FFFF;
+        private static final int FIRST_ARGUMENT_OFFSET = 16;
+        private static final int FIRST_ARGUMENT_MASK = 0x00FF0000;
 
-        private static final int OFFSET_ACTION = 0x00000018;
+        private static final int SECOND_ARGUMENT_OFFSET = 8;
+        private static final int SECOND_ARGUMENT_MASK = 0x0000FF00;
 
-        private static final int MASK_ACTION = 0xFF000000;
+        private static final int THIRD_ARGUMENT_OFFSET = 0;
+        private static final int THIRD_ARGUMENT_MASK = 0x000000FF;
 
-        private static final int OFFSET_FIRST_ARGUMENT = 0x00000010;
+        private final long mKeyCodeAndModifiers;
 
-        private static final int MASK_FIRST_ARGUMENT = 0x00FF0000;
-
-        private static final int OFFSET_SECOND_ARGUMENT = 0x00000008;
-
-        private static final int MASK_SECOND_ARGUMENT = 0x0000FF00;
-
-        private static final int OFFSET_THIRD_ARGUMENT = 0x00000000;
-
-        private static final int MASK_THIRD_ARGUMENT = 0x000000FF;
-
-        private int mKey;
-
-        private int [] mActionSequence;
-
-        /**
-         * @return The binding key with key code and meta state.
-         *
-         * @see #MASK_KEY_CODE
-         * @see #MASK_META_STATE
-         * @see #OFFSET_KEY_CODE
-         * @see #OFFSET_META_STATE
-         */
-        public int getKey() {
-            return mKey;
-        }
+        private final int [] mActionSequence;
 
         /**
          * @return The key code of the binding key.
          */
         public int getKeyCode() {
-            return (mKey & MASK_KEY_CODE) >> OFFSET_KEY_CODE;
+            return (int) ((mKeyCodeAndModifiers & KEY_CODE_MASK) >> KEY_CODE_OFFSET);
         }
 
         /**
          * @return The meta state of the binding key.
          */
-        public int getMetaState() {
-            return (mKey & MASK_META_STATE) >> OFFSET_META_STATE;
+        public int getModifiers() {
+            return (int) ((mKeyCodeAndModifiers & MODIFIERS_MASK) >> MODIFIERS_OFFSET);
         }
 
         /**
@@ -419,48 +426,45 @@
          * @param index The action code for a given action <code>index</code>.
          */
         public int getActionCode(int index) {
-            return (mActionSequence[index] & MASK_ACTION) >> OFFSET_ACTION;
+            return (mActionSequence[index] & ACTION_MASK) >> ACTION_OFFSET;
         }
 
         /**
          * @param index The first argument for a given action <code>index</code>.
          */
         public int getFirstArgument(int index) {
-            return (mActionSequence[index] & MASK_FIRST_ARGUMENT) >> OFFSET_FIRST_ARGUMENT;
+            return (mActionSequence[index] & FIRST_ARGUMENT_MASK) >> FIRST_ARGUMENT_OFFSET;
         }
 
         /**
          * @param index The second argument for a given action <code>index</code>.
          */
         public int getSecondArgument(int index) {
-            return (mActionSequence[index] & MASK_SECOND_ARGUMENT) >> OFFSET_SECOND_ARGUMENT;
+            return (mActionSequence[index] & SECOND_ARGUMENT_MASK) >> SECOND_ARGUMENT_OFFSET;
         }
 
         /**
          * @param index The third argument for a given action <code>index</code>.
          */
         public int getThirdArgument(int index) {
-            return (mActionSequence[index] & MASK_THIRD_ARGUMENT) >> OFFSET_THIRD_ARGUMENT;
+            return (mActionSequence[index] & THIRD_ARGUMENT_MASK) >> THIRD_ARGUMENT_OFFSET;
         }
 
         /**
          * Creates a new instance.
-         * @param key The key for the binding (key and meta state)
+         * @param keyCodeAndModifiers The key for the binding (key and modifiers).
          * @param actionSequence The sequence of action for the binding.
-         * @see #getKey()
          */
-        public AccessibilityWebContentKeyBinding(int key, int[] actionSequence) {
-            mKey = key;
+        public AccessibilityWebContentKeyBinding(long keyCodeAndModifiers, int[] actionSequence) {
+            mKeyCodeAndModifiers = keyCodeAndModifiers;
             mActionSequence = actionSequence;
         }
 
         @Override
         public String toString() {
             StringBuilder builder = new StringBuilder();
-            builder.append("key: ");
-            builder.append(getKey());
-            builder.append(", metaState: ");
-            builder.append(getMetaState());
+            builder.append("modifiers: ");
+            builder.append(getModifiers());
             builder.append(", keyCode: ");
             builder.append(getKeyCode());
             builder.append(", actions[");
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 97bbd5a..e246717 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -217,7 +217,7 @@
 
         if (sConfigCallback == null) {
             sConfigCallback = new ConfigCallback(
-                    (WindowManager) context.getSystemService(
+                    (WindowManager) appContext.getSystemService(
                             Context.WINDOW_SERVICE));
             ViewRoot.addConfigCallback(sConfigCallback);
         }
@@ -488,8 +488,10 @@
                         }
                     }
                 }
-                WebViewWorker.getHandler().sendEmptyMessage(
-                        WebViewWorker.MSG_TRIM_CACHE);
+                if (!JniUtil.useChromiumHttpStack()) {
+                    WebViewWorker.getHandler().sendEmptyMessage(
+                            WebViewWorker.MSG_TRIM_CACHE);
+                }
                 break;
             }
 
@@ -736,7 +738,8 @@
             }
 
         // content://
-        } else if (url.startsWith(ANDROID_CONTENT)) {
+        } else if (mSettings.getAllowContentAccess() &&
+                   url.startsWith(ANDROID_CONTENT)) {
             try {
                 // Strip off mimetype, for compatibility with ContentLoader.java
                 // If we don't do this, we can fail to load Gmail attachments,
diff --git a/core/java/android/webkit/CacheLoader.java b/core/java/android/webkit/CacheLoader.java
index 05c02b0..0721045 100644
--- a/core/java/android/webkit/CacheLoader.java
+++ b/core/java/android/webkit/CacheLoader.java
@@ -18,6 +18,7 @@
 
 import android.net.http.Headers;
 import android.text.TextUtils;
+import android.webkit.JniUtil;
 
 /**
  * This class is a concrete implementation of StreamLoader that uses a
@@ -36,6 +37,9 @@
      */
     CacheLoader(LoadListener loadListener, CacheManager.CacheResult result) {
         super(loadListener);
+
+        assert !JniUtil.useChromiumHttpStack();
+
         mCacheResult = result;
     }
 
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index f4ee2384..6073f7a 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -44,7 +44,10 @@
  * this component and if they can not be resolved by the cache, the HTTP headers
  * are attached, as appropriate, to the request for revalidation of content. The
  * class also manages the cache size.
+ *
+ * @deprecated Access to the HTTP cache will be removed in a future release.
  */
+@Deprecated
 public final class CacheManager {
 
     private static final String LOGTAG = "cache";
@@ -85,7 +88,10 @@
      * This class represents a resource retrieved from the HTTP cache.
      * Instances of this class can be obtained by invoking the
      * CacheManager.getCacheFile() method.
+     *
+     * @deprecated Access to the HTTP cache will be removed in a future release.
      */
+    @Deprecated
     public static class CacheResult {
         // these fields are saved to the database
         int httpStatusCode;
@@ -167,33 +173,51 @@
         public void setEncoding(String encoding) {
             this.encoding = encoding;
         }
+
+        /**
+         * @hide
+         */
+        public void setContentLength(long contentLength) {
+            this.contentLength = contentLength;
+        }
     }
 
     /**
-     * initialize the CacheManager. WebView should handle this for each process.
-     * 
+     * Initialize the CacheManager.
+     *
+     * Note that this is called automatically when a {@link android.webkit.WebView} is created.
+     *
      * @param context The application context.
      */
     static void init(Context context) {
+        if (JniUtil.useChromiumHttpStack()) {
+            // This isn't actually where the real cache lives, but where we put files for the
+            // purpose of getCacheFile().
+            mBaseDir = new File(context.getCacheDir(), "webviewCacheChromiumStaging");
+            if (!mBaseDir.exists()) {
+                mBaseDir.mkdirs();
+            } else {
+                // TODO: Should we clear out old files?
+            }
+            return;
+        }
+
         mDataBase = WebViewDatabase.getInstance(context.getApplicationContext());
         mBaseDir = new File(context.getCacheDir(), "webviewCache");
         if (createCacheDirectory() && mClearCacheOnInit) {
             removeAllCacheFiles();
             mClearCacheOnInit = false;
         }
-        // If we're using the Chrome HTTP stack, disable the cache.
-        // Chrome has its own cache, and we don't provide programmatic access to it.
-        if (JniUtil.useChromiumHttpStack()) {
-            setCacheDisabled(true);
-        }
     }
-    
+
     /**
      * Create the cache directory if it does not already exist.
-     * 
+     *
      * @return true if the cache directory didn't exist and was created.
      */
     static private boolean createCacheDirectory() {
+        assert !JniUtil.useChromiumHttpStack();
+
         if (!mBaseDir.exists()) {
             if(!mBaseDir.mkdirs()) {
                 Log.w(LOGTAG, "Unable to create webviewCache directory");
@@ -203,7 +227,7 @@
                     mBaseDir.toString(),
                     FileUtils.S_IRWXU | FileUtils.S_IRWXG,
                     -1, -1);
-            // If we did create the directory, we need to flush 
+            // If we did create the directory, we need to flush
             // the cache database. The directory could be recreated
             // because the system flushed all the data/cache directories
             // to free up disk space.
@@ -216,21 +240,27 @@
     }
 
     /**
-     * get the base directory of the cache. With localPath of the CacheResult,
-     * it identifies the cache file.
-     * 
+     * Get the base directory of the cache. Together with the local path of the CacheResult,
+     * obtained from {@link android.webkit.CacheManager.CacheResult#getLocalPath}, this
+     * identifies the cache file.
+     *
      * @return File The base directory of the cache.
+     *
+     * @deprecated Access to the HTTP cache will be removed in a future release.
      */
+    @Deprecated
     public static File getCacheFileBaseDir() {
         return mBaseDir;
     }
 
     /**
-     * set the flag to control whether cache is enabled or disabled
-     * 
-     * @param disabled true to disable the cache
+     * Sets whether the cache is disabled.
+     *
+     * @param disabled Whether the cache should be disabled
      */
     static void setCacheDisabled(boolean disabled) {
+        assert !JniUtil.useChromiumHttpStack();
+
         if (disabled == mDisabled) {
             return;
         }
@@ -238,17 +268,16 @@
         if (mDisabled) {
             removeAllCacheFiles();
         }
-        if (!mDisabled && JniUtil.useChromiumHttpStack()) {
-            Log.w(LOGTAG, "CacheManager enabled, but it will not work as "
-                    + "expected because the Chrome HTTP stack is in use.");
-        }
     }
 
     /**
-     * get the state of the current cache, enabled or disabled
-     * 
-     * @return return if it is disabled
+     * Whether the cache is disabled.
+     *
+     * @return return Whether the cache is disabled
+     *
+     * @deprecated Access to the HTTP cache will be removed in a future release.
      */
+    @Deprecated
     public static boolean cacheDisabled() {
         return mDisabled;
     }
@@ -256,6 +285,8 @@
     // only called from WebViewWorkerThread
     // make sure to call enableTransaction/disableTransaction in pair
     static boolean enableTransaction() {
+        assert !JniUtil.useChromiumHttpStack();
+
         if (++mRefCount == 1) {
             mDataBase.startCacheTransaction();
             return true;
@@ -266,6 +297,8 @@
     // only called from WebViewWorkerThread
     // make sure to call enableTransaction/disableTransaction in pair
     static boolean disableTransaction() {
+        assert !JniUtil.useChromiumHttpStack();
+
         if (--mRefCount == 0) {
             mDataBase.endCacheTransaction();
             return true;
@@ -276,12 +309,16 @@
     // only called from WebViewWorkerThread
     // make sure to call startTransaction/endTransaction in pair
     static boolean startTransaction() {
+        assert !JniUtil.useChromiumHttpStack();
+
         return mDataBase.startCacheTransaction();
     }
 
     // only called from WebViewWorkerThread
     // make sure to call startTransaction/endTransaction in pair
     static boolean endTransaction() {
+        assert !JniUtil.useChromiumHttpStack();
+
         boolean ret = mDataBase.endCacheTransaction();
         if (++mTrimCacheCount >= TRIM_CACHE_INTERVAL) {
             mTrimCacheCount = 0;
@@ -311,13 +348,18 @@
     }
 
     /**
-     * Given a url, returns the CacheResult if exists. Otherwise returns null.
-     * If headers are provided and a cache needs validation,
-     * HEADER_KEY_IFNONEMATCH or HEADER_KEY_IFMODIFIEDSINCE will be set in the
-     * cached headers.
-     * 
-     * @return the CacheResult for a given url
+     * Given a URL, returns the corresponding CacheResult if it exists, or null otherwise.
+     *
+     * The input stream of the CacheEntry object is initialized and opened and should be closed by
+     * the caller when access to the underlying file is no longer required.
+     * If a non-zero value is provided for the headers map, and the cache entry needs validation,
+     * HEADER_KEY_IFNONEMATCH or HEADER_KEY_IFMODIFIEDSINCE will be set in headers.
+     *
+     * @return The CacheResult for the given URL
+     *
+     * @deprecated Access to the HTTP cache will be removed in a future release.
      */
+    @Deprecated
     public static CacheResult getCacheFile(String url,
             Map<String, String> headers) {
         return getCacheFile(url, 0, headers);
@@ -329,43 +371,62 @@
             return null;
         }
 
-        String databaseKey = getDatabaseKey(url, postIdentifier);
-
-        CacheResult result = mDataBase.getCache(databaseKey);
-        if (result != null) {
-            if (result.contentLength == 0) {
-                if (!checkCacheRedirect(result.httpStatusCode)) {
-                    // this should not happen. If it does, remove it.
-                    mDataBase.removeCache(databaseKey);
-                    return null;
-                }
-            } else {
-                File src = new File(mBaseDir, result.localPath);
-                try {
-                    // open here so that even the file is deleted, the content
-                    // is still readable by the caller until close() is called
-                    result.inStream = new FileInputStream(src);
-                } catch (FileNotFoundException e) {
-                    // the files in the cache directory can be removed by the
-                    // system. If it is gone, clean up the database
-                    mDataBase.removeCache(databaseKey);
-                    return null;
-                }
+        if (JniUtil.useChromiumHttpStack()) {
+            CacheResult result = nativeGetCacheResult(url);
+            if (result == null) {
+                return null;
             }
-        } else {
-            return null;
+            // A temporary local file will have been created native side and localPath set
+            // appropriately.
+            File src = new File(mBaseDir, result.localPath);
+            try {
+                // Open the file here so that even if it is deleted, the content
+                // is still readable by the caller until close() is called.
+                result.inStream = new FileInputStream(src);
+            } catch (FileNotFoundException e) {
+                Log.v(LOGTAG, "getCacheFile(): Failed to open file: " + e);
+                // TODO: The files in the cache directory can be removed by the
+                // system. If it is gone, what should we do?
+                return null;
+            }
+            return result;
         }
 
-        // null headers request coming from CACHE_MODE_CACHE_ONLY
-        // which implies that it needs cache even it is expired.
-        // negative expires means time in the far future.
+        String databaseKey = getDatabaseKey(url, postIdentifier);
+        CacheResult result = mDataBase.getCache(databaseKey);
+        if (result == null) {
+            return null;
+        }
+        if (result.contentLength == 0) {
+            if (!isCachableRedirect(result.httpStatusCode)) {
+                // This should not happen. If it does, remove it.
+                mDataBase.removeCache(databaseKey);
+                return null;
+            }
+        } else {
+            File src = new File(mBaseDir, result.localPath);
+            try {
+                // Open the file here so that even if it is deleted, the content
+                // is still readable by the caller until close() is called.
+                result.inStream = new FileInputStream(src);
+            } catch (FileNotFoundException e) {
+                // The files in the cache directory can be removed by the
+                // system. If it is gone, clean up the database.
+                mDataBase.removeCache(databaseKey);
+                return null;
+            }
+        }
+
+        // A null value for headers is used by CACHE_MODE_CACHE_ONLY to imply
+        // that we should provide the cache result even if it is expired.
+        // Note that a negative expires value means a time in the far future.
         if (headers != null && result.expires >= 0
                 && result.expires <= System.currentTimeMillis()) {
             if (result.lastModified == null && result.etag == null) {
                 return null;
             }
-            // return HEADER_KEY_IFNONEMATCH or HEADER_KEY_IFMODIFIEDSINCE
-            // for requesting validation
+            // Return HEADER_KEY_IFNONEMATCH or HEADER_KEY_IFMODIFIEDSINCE
+            // for requesting validation.
             if (result.etag != null) {
                 headers.put(HEADER_KEY_IFNONEMATCH, result.etag);
             }
@@ -392,9 +453,17 @@
      * @return CacheResult for a given url
      * @hide - hide createCacheFile since it has a parameter of type headers, which is
      * in a hidden package.
+     *
+     * @deprecated Access to the HTTP cache will be removed in a future release.
      */
+    @Deprecated
     public static CacheResult createCacheFile(String url, int statusCode,
             Headers headers, String mimeType, boolean forceCache) {
+        if (JniUtil.useChromiumHttpStack()) {
+            // This method is public but hidden. We break functionality.
+            return null;
+        }
+
         return createCacheFile(url, statusCode, headers, mimeType, 0,
                 forceCache);
     }
@@ -402,6 +471,8 @@
     static CacheResult createCacheFile(String url, int statusCode,
             Headers headers, String mimeType, long postIdentifier,
             boolean forceCache) {
+        assert !JniUtil.useChromiumHttpStack();
+
         if (!forceCache && mDisabled) {
             return null;
         }
@@ -417,7 +488,7 @@
 
         // like the other browsers, do not cache redirects containing a cookie
         // header.
-        if (checkCacheRedirect(statusCode) && !headers.getSetCookie().isEmpty()) {
+        if (isCachableRedirect(statusCode) && !headers.getSetCookie().isEmpty()) {
             // remove the saved cache if there is any
             mDataBase.removeCache(databaseKey);
             return null;
@@ -457,7 +528,10 @@
     /**
      * Save the info of a cache file for a given url to the CacheMap so that it
      * can be reused later
+     *
+     * @deprecated Access to the HTTP cache will be removed in a future release.
      */
+    @Deprecated
     public static void saveCacheFile(String url, CacheResult cacheRet) {
         saveCacheFile(url, 0, cacheRet);
     }
@@ -470,12 +544,25 @@
             return;
         }
 
+        if (JniUtil.useChromiumHttpStack()) {
+            // This method is exposed in the public API but the API provides no way to obtain a
+            // new CacheResult object with a non-null output stream ...
+            // - CacheResult objects returned by getCacheFile() have a null output stream.
+            // - new CacheResult objects have a null output stream and no setter is provided.
+            // Since for the Android HTTP stack this method throws a null pointer exception in this
+            // case, this method is effectively useless from the point of view of the public API.
+
+            // We should already have thrown an exception above, to maintain 'backward
+            // compatibility' with the Android HTTP stack.
+            assert false;
+        }
+
         if (!cacheRet.outFile.exists()) {
             // the file in the cache directory can be removed by the system
             return;
         }
 
-        boolean redirect = checkCacheRedirect(cacheRet.httpStatusCode);
+        boolean redirect = isCachableRedirect(cacheRet.httpStatusCode);
         if (redirect) {
             // location is in database, no need to keep the file
             cacheRet.contentLength = 0;
@@ -497,6 +584,8 @@
     }
 
     static boolean cleanupCacheFile(CacheResult cacheRet) {
+        assert !JniUtil.useChromiumHttpStack();
+
         try {
             cacheRet.outStream.close();
         } catch (IOException e) {
@@ -506,11 +595,13 @@
     }
 
     /**
-     * remove all cache files
-     * 
-     * @return true if it succeeds
+     * Remove all cache files.
+     *
+     * @return Whether the removal succeeded.
      */
     static boolean removeAllCacheFiles() {
+        assert !JniUtil.useChromiumHttpStack();
+
         // Note, this is called before init() when the database is
         // created or upgraded.
         if (mBaseDir == null) {
@@ -546,14 +637,9 @@
         return true;
     }
 
-    /**
-     * Return true if the cache is empty.
-     */
-    static boolean cacheEmpty() {
-        return mDataBase.hasCache();
-    }
-
     static void trimCacheIfNeeded() {
+        assert !JniUtil.useChromiumHttpStack();
+
         if (mDataBase.getCacheTotalSize() > CACHE_THRESHOLD) {
             List<String> pathList = mDataBase.trimCache(CACHE_TRIM_AMOUNT);
             int size = pathList.size();
@@ -587,11 +673,13 @@
     }
 
     static void clearCache() {
+        assert !JniUtil.useChromiumHttpStack();
+
         // delete database
         mDataBase.clearCache();
     }
 
-    private static boolean checkCacheRedirect(int statusCode) {
+    private static boolean isCachableRedirect(int statusCode) {
         if (statusCode == 301 || statusCode == 302 || statusCode == 307) {
             // as 303 can't be cached, we do not return true
             return true;
@@ -601,12 +689,16 @@
     }
 
     private static String getDatabaseKey(String url, long postIdentifier) {
+        assert !JniUtil.useChromiumHttpStack();
+
         if (postIdentifier == 0) return url;
         return postIdentifier + url;
     }
 
     @SuppressWarnings("deprecation")
     private static void setupFiles(String url, CacheResult cacheRet) {
+        assert !JniUtil.useChromiumHttpStack();
+
         if (true) {
             // Note: SHA1 is much stronger hash. But the cost of setupFiles() is
             // 3.2% cpu time for a fresh load of nytimes.com. While a simple
@@ -673,6 +765,8 @@
     }
 
     private static void appendAsHex(int i, StringBuffer ret) {
+        assert !JniUtil.useChromiumHttpStack();
+
         String hex = Integer.toHexString(i);
         switch (hex.length()) {
             case 1:
@@ -702,6 +796,8 @@
 
     private static CacheResult parseHeaders(int statusCode, Headers headers,
             String mimeType) {
+        assert !JniUtil.useChromiumHttpStack();
+
         // if the contentLength is already larger than CACHE_MAX_SIZE, skip it
         if (headers.getContentLength() > CACHE_MAX_SIZE) return null;
 
@@ -718,8 +814,7 @@
         CacheResult ret = new CacheResult();
         ret.httpStatusCode = statusCode;
 
-        String location = headers.getLocation();
-        if (location != null) ret.location = location;
+        ret.location = headers.getLocation();
 
         ret.expires = -1;
         ret.expiresString = headers.getExpires();
@@ -738,15 +833,9 @@
             }
         }
 
-        String contentDisposition = headers.getContentDisposition();
-        if (contentDisposition != null) {
-            ret.contentdisposition = contentDisposition;
-        }
+        ret.contentdisposition = headers.getContentDisposition();
 
-        String crossDomain = headers.getXPermittedCrossDomainPolicies();
-        if (crossDomain != null) {
-            ret.crossDomain = crossDomain;
-        }
+        ret.crossDomain = headers.getXPermittedCrossDomainPolicies();
 
         // lastModified and etag may be set back to http header. So they can't
         // be empty string.
@@ -756,7 +845,9 @@
         }
 
         String etag = headers.getEtag();
-        if (etag != null && etag.length() > 0) ret.etag = etag;
+        if (etag != null && etag.length() > 0) {
+            ret.etag = etag;
+        }
 
         String cacheControl = headers.getCacheControl();
         if (cacheControl != null) {
@@ -857,4 +948,6 @@
 
         return ret;
     }
+
+    private static native CacheResult nativeGetCacheResult(String url);
 }
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index 7c25987..a322fa3d 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -34,7 +34,7 @@
 import android.view.inputmethod.InputMethodManager;
 
 class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
-        View.OnLongClickListener {
+        View.OnLongClickListener, View.OnClickListener {
     private View mCustomView;
     private EditText mEditText;
     private TextView mMatches;
@@ -53,6 +53,7 @@
         // Override long click so that select ActionMode is not opened, which
         // would exit find ActionMode.
         mEditText.setOnLongClickListener(this);
+        mEditText.setOnClickListener(this);
         setText("");
         mMatches = (TextView) mCustomView.findViewById(
                 com.android.internal.R.id.matches);
@@ -105,7 +106,17 @@
             throw new AssertionError(
                     "No WebView for FindActionModeCallback::findNext");
         }
+        if (!mMatchesFound) {
+            findAll();
+            return;
+        }
+        if (0 == mNumberOfMatches) {
+            // There are no matches, so moving to the next match will not do
+            // anything.
+            return;
+        }
         mWebView.findNext(next);
+        updateMatchesString();
     }
 
     /*
@@ -134,9 +145,16 @@
         }
     }
 
+    public void showSoftInput() {
+        mInput.startGettingWindowFocus(mEditText.getRootView());
+        mInput.focusIn(mEditText);
+        mInput.showSoftInput(mEditText, 0);
+    }
+
     /*
      * Update the string which tells the user how many matches were found, and
      * which match is currently highlighted.
+     * Not to be called when mNumberOfMatches is 0.
      */
     private void updateMatchesString() {
         String template = mResources.getQuantityString(
@@ -151,6 +169,13 @@
     @Override
     public boolean onLongClick(View v) { return true; }
 
+    // OnClickListener implementation
+
+    @Override
+    public void onClick(View v) {
+        findNext(true);
+    }
+
     // ActionMode.Callback implementation
 
     @Override
@@ -165,7 +190,6 @@
         mMatchesFound = false;
         mMatches.setText("0");
         mEditText.requestFocus();
-        mInput.showSoftInput(mEditText, 0);
         return true;
     }
 
@@ -187,10 +211,6 @@
                     "No WebView for FindActionModeCallback::onActionItemClicked");
         }
         mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
-        if (!mMatchesFound) {
-            findAll();
-            return true;
-        }
         switch(item.getItemId()) {
             case com.android.internal.R.id.find_prev:
                 findNext(false);
@@ -201,7 +221,6 @@
             default:
                 return false;
         }
-        updateMatchesString();
         return true;
     }
 
diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java
index 951dab3..0d80302 100644
--- a/core/java/android/webkit/FrameLoader.java
+++ b/core/java/android/webkit/FrameLoader.java
@@ -22,6 +22,7 @@
 import android.os.Build;
 import android.util.Log;
 import android.webkit.CacheManager.CacheResult;
+import android.webkit.JniUtil;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -56,6 +57,8 @@
     
     FrameLoader(LoadListener listener, WebSettings settings,
             String method, WebResourceResponse interceptResponse) {
+        assert !JniUtil.useChromiumHttpStack();
+
         mListener = listener;
         mHeaders = null;
         mMethod = method;
@@ -148,9 +151,10 @@
 
     }
 
-    /* package */
-    static boolean handleLocalFile(String url, LoadListener loadListener,
+    private static boolean handleLocalFile(String url, LoadListener loadListener,
             WebSettings settings) {
+        assert !JniUtil.useChromiumHttpStack();
+
         // Attempt to decode the percent-encoded url before passing to the
         // local loaders.
         try {
@@ -199,7 +203,8 @@
                                 settings.getAllowFileAccess())).sendToTarget();
             }
             return true;
-        } else if (URLUtil.isContentUrl(url)) {
+        } else if (settings.getAllowContentAccess() &&
+                   URLUtil.isContentUrl(url)) {
             // Send the raw url to the ContentLoader because it will do a
             // permission check and the url has to match.
             if (loadListener.isSynchronous()) {
diff --git a/core/java/android/webkit/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java
index 908526f..976e786 100644
--- a/core/java/android/webkit/JWebCoreJavaBridge.java
+++ b/core/java/android/webkit/JWebCoreJavaBridge.java
@@ -307,4 +307,5 @@
     public native void addPackageNames(Set<String> packageNames);
     public native void addPackageName(String packageName);
     public native void removePackageName(String packageName);
+    public native void updateProxy(String newProxy);
 }
diff --git a/core/java/android/webkit/JniUtil.java b/core/java/android/webkit/JniUtil.java
index 8de30c5..62b415c 100644
--- a/core/java/android/webkit/JniUtil.java
+++ b/core/java/android/webkit/JniUtil.java
@@ -17,14 +17,20 @@
 package android.webkit;
 
 import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+import java.io.InputStream;
 
 class JniUtil {
+    private static final String LOGTAG = "webkit";
     private JniUtil() {} // Utility class, do not instantiate.
 
     // Used by the Chromium HTTP stack.
     private static String sDatabaseDirectory;
     private static String sCacheDirectory;
     private static Boolean sUseChromiumHttpStack;
+    private static Context sContext;
 
     private static boolean initialized = false;
 
@@ -38,9 +44,7 @@
         if (initialized)
             return;
 
-        Context appContext = context.getApplicationContext();
-        sDatabaseDirectory = appContext.getDatabasePath("dummy").getParent();
-        sCacheDirectory = appContext.getCacheDir().getAbsolutePath();
+        sContext = context.getApplicationContext();
         initialized = true;
     }
 
@@ -50,6 +54,10 @@
      */
     private static synchronized String getDatabaseDirectory() {
         checkIntialized();
+
+        if (sDatabaseDirectory == null)
+            sDatabaseDirectory = sContext.getDatabasePath("dummy").getParent();
+
         return sDatabaseDirectory;
     }
 
@@ -59,9 +67,82 @@
      */
     private static synchronized String getCacheDirectory() {
         checkIntialized();
+
+        if (sCacheDirectory == null)
+            sCacheDirectory = sContext.getCacheDir().getAbsolutePath();
+
         return sCacheDirectory;
     }
 
+    private static final String ANDROID_CONTENT = "content:";
+
+    /**
+     * Called by JNI. Calculates the size of an input stream by reading it.
+     * @return long The size of the stream
+     */
+    private static synchronized long contentUrlSize(String url) {
+        // content://
+        if (url.startsWith(ANDROID_CONTENT)) {
+            try {
+                // Strip off mimetype, for compatibility with ContentLoader.java
+                // If we don't do this, we can fail to load Gmail attachments,
+                // because the URL being loaded doesn't exactly match the URL we
+                // have permission to read.
+                int mimeIndex = url.lastIndexOf('?');
+                if (mimeIndex != -1) {
+                    url = url.substring(0, mimeIndex);
+                }
+                Uri uri = Uri.parse(url);
+                InputStream is = sContext.getContentResolver().openInputStream(uri);
+                byte[] buffer = new byte[1024];
+                int n;
+                long size = 0;
+                try {
+                    while ((n = is.read(buffer)) != -1) {
+                        size += n;
+                    }
+                } finally {
+                    is.close();
+                }
+                return size;
+            } catch (Exception e) {
+                Log.e(LOGTAG, "Exception: " + url);
+                return 0;
+            }
+        } else {
+            return 0;
+        }
+    }
+
+    /**
+     * Called by JNI.
+     *
+     * @return  Opened input stream to content
+     * TODO: Make all content loading use this instead of BrowserFrame.java
+     */
+    private static synchronized InputStream contentUrlStream(String url) {
+        // content://
+        if (url.startsWith(ANDROID_CONTENT)) {
+            try {
+                // Strip off mimetype, for compatibility with ContentLoader.java
+                // If we don't do this, we can fail to load Gmail attachments,
+                // because the URL being loaded doesn't exactly match the URL we
+                // have permission to read.
+                int mimeIndex = url.lastIndexOf('?');
+                if (mimeIndex != -1) {
+                    url = url.substring(0, mimeIndex);
+                }
+                Uri uri = Uri.parse(url);
+                return sContext.getContentResolver().openInputStream(uri);
+            } catch (Exception e) {
+                Log.e(LOGTAG, "Exception: " + url);
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
     /**
      * Returns true if we're using the Chromium HTTP stack.
      *
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index a29299d..6d1d39a 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -35,6 +35,7 @@
 import android.os.Message;
 import android.util.Log;
 import android.webkit.CacheManager.CacheResult;
+import android.webkit.JniUtil;
 
 import com.android.internal.R;
 
@@ -156,6 +157,8 @@
             int nativeLoader, boolean synchronous, boolean isMainPageLoader,
             boolean isMainResource, boolean userGesture, long postIdentifier,
             String username, String password) {
+        assert !JniUtil.useChromiumHttpStack();
+
         if (DebugFlags.LOAD_LISTENER) {
             Log.v(LOGTAG, "LoadListener constructor url=" + url);
         }
@@ -991,6 +994,7 @@
      * URL.
      */
     static boolean willLoadFromCache(String url, long identifier) {
+        assert !JniUtil.useChromiumHttpStack();
         boolean inCache =
                 CacheManager.getCacheFile(url, identifier, null) != null;
         if (DebugFlags.LOAD_LISTENER) {
diff --git a/core/java/android/webkit/SelectActionModeCallback.java b/core/java/android/webkit/SelectActionModeCallback.java
index 54c9d9a..ea09fc0 100644
--- a/core/java/android/webkit/SelectActionModeCallback.java
+++ b/core/java/android/webkit/SelectActionModeCallback.java
@@ -34,7 +34,11 @@
     }
 
     void finish() {
-        mActionMode.finish();
+        // It is possible that onCreateActionMode was never called, in the case
+        // where there is no ActionBar, for example.
+        if (mActionMode != null) {
+            mActionMode.finish();
+        }
     }
 
     // ActionMode.Callback implementation
@@ -74,7 +78,7 @@
             case com.android.internal.R.id.find:
                 String sel= mWebView.getSelection();
                 mode.finish();
-                mWebView.showFindDialog(sel);
+                mWebView.showFindDialog(sel, false);
                 break;
             case com.android.internal.R.id.websearch:
                 mode.finish();
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 2e69d99..0670c4e 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -215,6 +215,7 @@
     private boolean         mBuiltInZoomControls = false;
     private boolean         mDisplayZoomControls = true;
     private boolean         mAllowFileAccess = true;
+    private boolean         mAllowContentAccess = true;
     private boolean         mLoadWithOverviewMode = false;
     private boolean         mEnableSmoothTransition = false;
 
@@ -485,11 +486,12 @@
             // default to "en"
             buffer.append("en");
         }
-        buffer.append("; ");
+        buffer.append(";");
         // add the model for the release build
         if ("REL".equals(Build.VERSION.CODENAME)) {
             final String model = Build.MODEL;
             if (model.length() > 0) {
+                buffer.append(" ");
                 buffer.append(model);
             }
         }
@@ -586,7 +588,9 @@
 
     /**
      * Enable or disable file access within WebView. File access is enabled by
-     * default.
+     * default.  Note that this enables or disables file system access only.
+     * Assets and resources are still accessible using file:///android_asset and
+     * file:///android_res.
      */
     public void setAllowFileAccess(boolean allow) {
         mAllowFileAccess = allow;
@@ -600,6 +604,22 @@
     }
 
     /**
+     * Enable or disable content url access within WebView.  Content url access
+     * allows WebView to load content from a content provider installed in the
+     * system.  The default is enabled.
+     */
+    public void setAllowContentAccess(boolean allow) {
+        mAllowContentAccess = allow;
+    }
+
+    /**
+     * Returns true if this WebView supports content url access.
+     */
+    public boolean getAllowContentAccess() {
+        return mAllowContentAccess;
+    }
+
+    /**
      * Set whether the WebView loads a page with overview mode.
      */
     public void setLoadWithOverviewMode(boolean overview) {
@@ -657,10 +677,11 @@
     }
 
     /**
-     *  Return whether the WebView is saving form data.
+     *  Return whether the WebView is saving form data and displaying prior
+     *  entries/autofill++.  Always false in private browsing mode.
      */
     public boolean getSaveFormData() {
-        return mSaveFormData;
+        return mSaveFormData && !mPrivateBrowsingEnabled;
     }
 
     /**
@@ -1587,10 +1608,11 @@
     }
 
     /**
-     * Returns whether to use fixed viewport.
+     * Returns whether to use fixed viewport.  Fixed viewport should operate only
+     * when wide viewport is on.
      */
     /* package */ boolean getUseFixedViewport() {
-        return mUseFixedViewport;
+        return getUseWideViewPort() && mUseFixedViewport;
     }
 
     /**
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index bb18270..1313fcc 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -204,11 +204,6 @@
             case KeyEvent.KEYCODE_DPAD_RIGHT:
             case KeyEvent.KEYCODE_DPAD_UP:
             case KeyEvent.KEYCODE_DPAD_DOWN:
-                if (!mWebView.nativeCursorMatchesFocus()) {
-                    return down ? mWebView.onKeyDown(keyCode, event) : mWebView
-                            .onKeyUp(keyCode, event);
-
-                }
                 isArrowKey = true;
                 break;
         }
@@ -238,7 +233,8 @@
             }
         }
 
-        if ((mSingle && KeyEvent.KEYCODE_ENTER == keyCode)) {
+        if (mSingle && (KeyEvent.KEYCODE_ENTER == keyCode
+                    || KeyEvent.KEYCODE_NUMPAD_ENTER == keyCode)) {
             if (isPopupShowing()) {
                 return super.dispatchKeyEvent(event);
             }
@@ -257,10 +253,6 @@
             if (isPopupShowing()) {
                 return super.dispatchKeyEvent(event);
             }
-            if (!mWebView.nativeCursorMatchesFocus()) {
-                return down ? mWebView.onKeyDown(keyCode, event) : mWebView
-                        .onKeyUp(keyCode, event);
-            }
             // Center key should be passed to a potential onClick
             if (!down) {
                 mWebView.centerKeyPressOnTextField();
@@ -296,7 +288,8 @@
             // so do not pass down to javascript, and instead
             // return true.  If it is an arrow key or a delete key, we can go
             // ahead and pass it down.
-            if (KeyEvent.KEYCODE_ENTER == keyCode) {
+            if (KeyEvent.KEYCODE_ENTER == keyCode
+                        || KeyEvent.KEYCODE_NUMPAD_ENTER == keyCode) {
                 // For multi-line text boxes, newlines will
                 // trigger onTextChanged for key down (which will send both
                 // key up and key down) but not key up.
@@ -751,12 +744,7 @@
         if (event.getAction() != MotionEvent.ACTION_MOVE) {
             return false;
         }
-        // If the Cursor is not on the text input, webview should handle the
-        // trackball
-        if (!mWebView.nativeCursorMatchesFocus()) {
-            return mWebView.onTrackballEvent(event);
-        }
-        Spannable text = (Spannable) getText();
+        Spannable text = getText();
         MovementMethod move = getMovementMethod();
         if (move != null && getLayout() != null &&
             move.onTrackballEvent(this, text, event)) {
@@ -1175,10 +1163,12 @@
             mWebView.requestLabel(mWebView.nativeFocusCandidateFramePointer(),
                     mNodePointer);
             maxLength = mWebView.nativeFocusCandidateMaxLength();
-            if (type != PASSWORD) {
+            boolean autoComplete = mWebView.nativeFocusCandidateIsAutoComplete();
+            if (type != PASSWORD && (mAutoFillable || autoComplete)) {
                 String name = mWebView.nativeFocusCandidateName();
                 if (name != null && name.length() > 0) {
-                    mWebView.requestFormData(name, mNodePointer, mAutoFillable);
+                    mWebView.requestFormData(name, mNodePointer, mAutoFillable,
+                            autoComplete);
                 }
             }
         }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index bbfcc08..eddfffe 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -48,12 +48,15 @@
 import android.graphics.Region;
 import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
+import android.net.Proxy;
+import android.net.ProxyProperties;
 import android.net.Uri;
 import android.net.http.SslCertificate;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.speech.tts.TextToSpeech;
 import android.text.Selection;
@@ -821,6 +824,11 @@
     private static final long SELECT_SCROLL_INTERVAL = 1000 / 60; // 60 / second
     private int mAutoScrollX = 0;
     private int mAutoScrollY = 0;
+    private int mMinAutoScrollX = 0;
+    private int mMaxAutoScrollX = 0;
+    private int mMinAutoScrollY = 0;
+    private int mMaxAutoScrollY = 0;
+    private Rect mScrollingLayerBounds = new Rect();
     private boolean mSentAutoScrollMessage = false;
 
     // Used to notify listeners of a new picture.
@@ -981,6 +989,7 @@
          */
         init();
         setupPackageListener(context);
+        setupProxyListener(context);
         updateMultiTouchSupport(context);
 
         if (privateBrowsing) {
@@ -990,11 +999,58 @@
         mAutoFillData = new WebViewCore.AutoFillData();
     }
 
+    private static class ProxyReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(Proxy.PROXY_CHANGE_ACTION)) {
+                handleProxyBroadcast(intent);
+            }
+        }
+    }
+
     /*
-     * The intent receiver that monitors for changes to relevant packages (e.g.,
-     * sGoogleApps) and notifies WebViewCore of their existence.
+     * A variable to track if there is a receiver added for PROXY_CHANGE_ACTION
      */
-    private static BroadcastReceiver sPackageInstallationReceiver = null;
+    private static boolean sProxyReceiverAdded;
+
+    private static synchronized void setupProxyListener(Context context) {
+        if (sProxyReceiverAdded) {
+            return;
+        }
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Proxy.PROXY_CHANGE_ACTION);
+        Intent currentProxy = context.getApplicationContext().registerReceiver(
+                new ProxyReceiver(), filter);
+        sProxyReceiverAdded = true;
+        if (currentProxy != null) {
+            handleProxyBroadcast(currentProxy);
+        }
+    }
+
+    private static void handleProxyBroadcast(Intent intent) {
+        ProxyProperties proxyProperties = (ProxyProperties)intent.getExtra(Proxy.EXTRA_PROXY_INFO);
+        if (proxyProperties == null || proxyProperties.getHost() == null) {
+            WebViewCore.sendStaticMessage(EventHub.PROXY_CHANGED, "");
+            return;
+        }
+
+        String host = proxyProperties.getHost();
+        int port = proxyProperties.getPort();
+        if (port != 0)
+            host += ": " + port;
+
+        // TODO: Handle exclusion list
+        // The plan is to make an AndroidProxyResolver, and handle the blacklist
+        // there
+        String exclusionList = proxyProperties.getExclusionList();
+        WebViewCore.sendStaticMessage(EventHub.PROXY_CHANGED, host);
+    }
+
+    /*
+     * A variable to track if there is a receiver added for ACTION_PACKAGE_ADDED
+     * or ACTION_PACKAGE_REMOVED.
+     */
+    private static boolean sPackageInstallationReceiverAdded = false;
 
     /*
      * A set of Google packages we monitor for the
@@ -1007,6 +1063,32 @@
         sGoogleApps.add("com.google.android.youtube");
     }
 
+    private static class PackageListener extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            final String packageName = intent.getData().getSchemeSpecificPart();
+            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+            if (Intent.ACTION_PACKAGE_REMOVED.equals(action) && replacing) {
+                // if it is replacing, refreshPlugins() when adding
+                return;
+            }
+
+            if (sGoogleApps.contains(packageName)) {
+                if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+                    WebViewCore.sendStaticMessage(EventHub.ADD_PACKAGE_NAME, packageName);
+                } else {
+                    WebViewCore.sendStaticMessage(EventHub.REMOVE_PACKAGE_NAME, packageName);
+                }
+            }
+
+            PluginManager pm = PluginManager.getInstance(context);
+            if (pm.containsPluginPermissionAndSignatures(packageName)) {
+                pm.refreshPlugins(Intent.ACTION_PACKAGE_ADDED.equals(action));
+            }
+        }
+    }
+
     private void setupPackageListener(Context context) {
 
         /*
@@ -1018,41 +1100,16 @@
 
             // if the receiver already exists then we do not need to register it
             // again
-            if (sPackageInstallationReceiver != null) {
+            if (sPackageInstallationReceiverAdded) {
                 return;
             }
 
             IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
             filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
             filter.addDataScheme("package");
-            sPackageInstallationReceiver = new BroadcastReceiver() {
-
-                @Override
-                public void onReceive(Context context, Intent intent) {
-                    final String action = intent.getAction();
-                    final String packageName = intent.getData().getSchemeSpecificPart();
-                    final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-                    if (Intent.ACTION_PACKAGE_REMOVED.equals(action) && replacing) {
-                        // if it is replacing, refreshPlugins() when adding
-                        return;
-                    }
-
-                    if (sGoogleApps.contains(packageName) && mWebViewCore != null) {
-                        if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
-                            mWebViewCore.sendMessage(EventHub.ADD_PACKAGE_NAME, packageName);
-                        } else {
-                            mWebViewCore.sendMessage(EventHub.REMOVE_PACKAGE_NAME, packageName);
-                        }
-                    }
-
-                    PluginManager pm = PluginManager.getInstance(context);
-                    if (pm.containsPluginPermissionAndSignatures(packageName)) {
-                        pm.refreshPlugins(Intent.ACTION_PACKAGE_ADDED.equals(action));
-                    }
-                }
-            };
-
-            context.getApplicationContext().registerReceiver(sPackageInstallationReceiver, filter);
+            BroadcastReceiver packageListener = new PackageListener();
+            context.getApplicationContext().registerReceiver(packageListener, filter);
+            sPackageInstallationReceiverAdded = true;
         }
 
         // check if any of the monitored apps are already installed
@@ -2561,10 +2618,6 @@
     private int computeRealHorizontalScrollRange() {
         if (mDrawHistory) {
             return mHistoryWidth;
-        } else if (mHorizontalScrollBarMode == SCROLLBAR_ALWAYSOFF
-                && !mZoomManager.canZoomOut()) {
-            // only honor the scrollbar mode when it is at minimum zoom level
-            return computeHorizontalScrollExtent();
         } else {
             // to avoid rounding error caused unnecessary scrollbar, use floor
             return (int) Math.floor(mContentWidth * mZoomManager.getScale());
@@ -2595,10 +2648,6 @@
     private int computeRealVerticalScrollRange() {
         if (mDrawHistory) {
             return mHistoryHeight;
-        } else if (mVerticalScrollBarMode == SCROLLBAR_ALWAYSOFF
-                && !mZoomManager.canZoomOut()) {
-            // only honor the scrollbar mode when it is at minimum zoom level
-            return computeVerticalScrollExtent();
         } else {
             // to avoid rounding error caused unnecessary scrollbar, use floor
             return (int) Math.floor(mContentHeight * mZoomManager.getScale());
@@ -2900,19 +2949,33 @@
      * @param text If non-null, will be the initial text to search for.
      *             Otherwise, the last String searched for in this WebView will
      *             be used to start.
+     * @param showIme If true, show the IME, assuming the user will begin typing.
+     *             If false and text is non-null, perform a find all.
+     * @return boolean True if the find dialog is shown, false otherwise.
      */
-    public void showFindDialog(String text) {
-        mFindCallback = new FindActionModeCallback(mContext);
+    public boolean showFindDialog(String text, boolean showIme) {
+        FindActionModeCallback callback = new FindActionModeCallback(mContext);
+        if (startActionMode(callback) == null) {
+            // Could not start the action mode, so end Find on page
+            return false;
+        }
+        mFindCallback = callback;
         setFindIsUp(true);
         mFindCallback.setWebView(this);
-        View titleBar = mTitleBar;
-        startActionMode(mFindCallback);
+        if (showIme) {
+            mFindCallback.showSoftInput();
+        } else if (text != null) {
+            mFindCallback.setText(text);
+            mFindCallback.findAll();
+            return true;
+        }
         if (text == null) {
             text = mLastFind;
         }
         if (text != null) {
             mFindCallback.setText(text);
         }
+        return true;
     }
 
     /**
@@ -3219,6 +3282,9 @@
      * @param url The URL loaded by this {@link WebView}.
      */
     private void injectAccessibilityForUrl(String url) {
+        if (mWebViewCore == null) {
+            return;
+        }
         AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(mContext);
 
         if (!accessibilityManager.isEnabled()) {
@@ -3267,8 +3333,10 @@
      * @param present True to ensure an insance, false to ensure no instance.
      */
     private void ensureAccessibilityScriptInjectorInstance(boolean present) {
-        if (present && mAccessibilityInjector == null) {
-            mAccessibilityInjector = new AccessibilityInjector(this);
+        if (present) {
+            if (mAccessibilityInjector == null) {
+                mAccessibilityInjector = new AccessibilityInjector(this);
+            }
         } else {
             mAccessibilityInjector = null;
         }
@@ -3790,7 +3858,16 @@
     public boolean selectText() {
         int x = viewToContentX((int) mLastTouchX + mScrollX);
         int y = viewToContentY((int) mLastTouchY + mScrollY);
-        setUpSelect();
+        return selectText(x, y);
+    }
+
+    /**
+     * Select the word at the indicated content coordinates.
+     */
+    boolean selectText(int x, int y) {
+        if (!setUpSelect()) {
+            return false;
+        }
         if (mNativeClass != 0 && nativeWordSelection(x, y)) {
             nativeSetExtendSelection();
             mDrawSelectionPointer = false;
@@ -3818,17 +3895,21 @@
      */
     private SelectActionModeCallback mSelectCallback;
 
+    // These values are possible options for didUpdateWebTextViewDimensions.
+    private static final int FULLY_ON_SCREEN = 0;
+    private static final int INTERSECTS_SCREEN = 1;
+    private static final int ANYWHERE = 2;
+
     /**
      * Check to see if the focused textfield/textarea is still on screen.  If it
      * is, update the the dimensions and location of WebTextView.  Otherwise,
      * remove the WebTextView.  Should be called when the zoom level changes.
-     * @param allowIntersect Whether to consider the textfield/textarea on
-     *         screen if it only intersects the screen (as opposed to being
-     *         completely on screen).
+     * @param intersection How to determine whether the textfield/textarea is
+     *        still on screen.
      * @return boolean True if the textfield/textarea is still on screen and the
      *         dimensions/location of WebTextView have been updated.
      */
-    private boolean didUpdateWebTextViewDimensions(boolean allowIntersect) {
+    private boolean didUpdateWebTextViewDimensions(int intersection) {
         Rect contentBounds = nativeFocusCandidateNodeBounds();
         Rect vBox = contentToViewRect(contentBounds);
         Rect visibleRect = new Rect();
@@ -3836,8 +3917,22 @@
         // If the textfield is on screen, place the WebTextView in
         // its new place, accounting for our new scroll/zoom values,
         // and adjust its textsize.
-        if (allowIntersect ? Rect.intersects(visibleRect, vBox)
-                : visibleRect.contains(vBox)) {
+        boolean onScreen;
+        switch (intersection) {
+            case FULLY_ON_SCREEN:
+                onScreen = visibleRect.contains(vBox);
+                break;
+            case INTERSECTS_SCREEN:
+                onScreen = Rect.intersects(visibleRect, vBox);
+                break;
+            case ANYWHERE:
+                onScreen = true;
+                break;
+            default:
+                throw new AssertionError(
+                        "invalid parameter passed to didUpdateWebTextViewDimensions");
+        }
+        if (onScreen) {
             mWebTextView.setRect(vBox.left, vBox.top, vBox.width(),
                     vBox.height());
             mWebTextView.updateTextSize();
@@ -3874,7 +3969,7 @@
 
     private void onZoomAnimationEnd() {
         // adjust the edit text view if needed
-        if (inEditingMode() && didUpdateWebTextViewDimensions(false)
+        if (inEditingMode() && didUpdateWebTextViewDimensions(FULLY_ON_SCREEN)
                 && nativeFocusCandidateIsPassword()) {
             // If it is a password field, start drawing the WebTextView once
             // again.
@@ -4011,7 +4106,7 @@
             // finishes.  We also do not need to do this unless the WebTextView
             // is showing.
             if (!animateZoom && inEditingMode()) {
-                didUpdateWebTextViewDimensions(true);
+                didUpdateWebTextViewDimensions(ANYWHERE);
             }
         }
     }
@@ -4116,7 +4211,7 @@
             if (inEditingMode()) {
                 imm.showSoftInput(mWebTextView, 0);
                 if (zoom) {
-                    didUpdateWebTextViewDimensions(true);
+                    didUpdateWebTextViewDimensions(INTERSECTS_SCREEN);
                 }
                 return;
             }
@@ -4248,13 +4343,16 @@
      *          retrieved.
      * @param autoFillable true if WebKit has determined this field is part of
      *          a form that can be auto filled.
+     * @param autoComplete true if the attribute "autocomplete" is set to true
+     *          on the textfield.
      */
-    /* package */ void requestFormData(String name, int nodePointer, boolean autoFillable) {
+    /* package */ void requestFormData(String name, int nodePointer,
+            boolean autoFillable, boolean autoComplete) {
         if (mWebViewCore.getSettings().getSaveFormData()) {
             Message update = mPrivateHandler.obtainMessage(REQUEST_FORM_DATA);
             update.arg1 = nodePointer;
             RequestFormData updater = new RequestFormData(name, getUrl(),
-                    update, autoFillable);
+                    update, autoFillable, autoComplete);
             Thread t = new Thread(updater);
             t.start();
         }
@@ -4281,16 +4379,19 @@
         private String mUrl;
         private Message mUpdateMessage;
         private boolean mAutoFillable;
+        private boolean mAutoComplete;
 
-        public RequestFormData(String name, String url, Message msg, boolean autoFillable) {
+        public RequestFormData(String name, String url, Message msg,
+                boolean autoFillable, boolean autoComplete) {
             mName = name;
             mUrl = url;
             mUpdateMessage = msg;
             mAutoFillable = autoFillable;
+            mAutoComplete = autoComplete;
         }
 
         public void run() {
-            ArrayList<String> pastEntries = new ArrayList();
+            ArrayList<String> pastEntries = new ArrayList<String>();
 
             if (mAutoFillable) {
                 // Note that code inside the adapter click handler in WebTextView depends
@@ -4312,7 +4413,9 @@
                 }
             }
 
-            pastEntries.addAll(mDatabase.getFormData(mUrl, mName));
+            if (mAutoComplete) {
+                pastEntries.addAll(mDatabase.getFormData(mUrl, mName));
+            }
 
             if (pastEntries.size() > 0) {
                 AutoCompleteAdapter adapter = new
@@ -4400,13 +4503,25 @@
         return false;
     }
 
+    private boolean isEnterActionKey(int keyCode) {
+        return keyCode == KeyEvent.KEYCODE_DPAD_CENTER
+                || keyCode == KeyEvent.KEYCODE_ENTER
+                || keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER;
+    }
+
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         if (DebugFlags.WEB_VIEW) {
             Log.v(LOGTAG, "keyDown at " + System.currentTimeMillis()
+                    + "keyCode=" + keyCode
                     + ", " + event + ", unicode=" + event.getUnicodeChar());
         }
 
+        // don't implement accelerator keys here; defer to host application
+        if (event.isCtrlPressed()) {
+            return false;
+        }
+
         if (mNativeClass == 0) {
             return false;
         }
@@ -4423,38 +4538,90 @@
         // Bubble up the key event if
         // 1. it is a system key; or
         // 2. the host application wants to handle it;
-        // 3. the accessibility injector is present and wants to handle it;
         if (event.isSystem()
-                || mCallbackProxy.uiOverrideKeyEvent(event)
-                || (mAccessibilityInjector != null && mAccessibilityInjector.onKeyEvent(event))) {
+                || mCallbackProxy.uiOverrideKeyEvent(event)) {
             return false;
         }
 
-        if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
-                || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
-            if (!pageShouldHandleShiftAndArrows() && !nativeCursorWantsKeyEvents()
-                    && !mSelectingText) {
-                setUpSelect();
+        // accessibility support
+        if (accessibilityScriptInjected()) {
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                // if an accessibility script is injected we delegate to it the key handling.
+                // this script is a screen reader which is a fully fledged solution for blind
+                // users to navigate in and interact with web pages.
+                mWebViewCore.sendMessage(EventHub.KEY_DOWN, event);
+                return true;
+            } else {
+                // Clean up if accessibility was disabled after loading the current URL.
+                mAccessibilityScriptInjected = false;
+            }
+        } else if (mAccessibilityInjector != null) {
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                if (mAccessibilityInjector.onKeyEvent(event)) {
+                    // if an accessibility injector is present (no JavaScript enabled or the site
+                    // opts out injecting our JavaScript screen reader) we let it decide whether
+                    // to act on and consume the event.
+                    return true;
+                }
+            } else {
+                // Clean up if accessibility was disabled after loading the current URL.
+                mAccessibilityInjector = null;
             }
         }
 
         if (keyCode == KeyEvent.KEYCODE_PAGE_UP) {
-            pageUp(false);
-            return true;
+            if (event.hasNoModifiers()) {
+                pageUp(false);
+                return true;
+            } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                pageUp(true);
+                return true;
+            }
         }
 
         if (keyCode == KeyEvent.KEYCODE_PAGE_DOWN) {
-            pageDown(false);
+            if (event.hasNoModifiers()) {
+                pageDown(false);
+                return true;
+            } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                pageDown(true);
+                return true;
+            }
+        }
+
+        if (keyCode == KeyEvent.KEYCODE_MOVE_HOME && event.hasNoModifiers()) {
+            pageUp(true);
+            return true;
+        }
+
+        if (keyCode == KeyEvent.KEYCODE_MOVE_END && event.hasNoModifiers()) {
+            pageDown(true);
             return true;
         }
 
         if (keyCode >= KeyEvent.KEYCODE_DPAD_UP
                 && keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT) {
             switchOutDrawHistory();
-            if (pageShouldHandleShiftAndArrows()) {
+            if (nativePageShouldHandleShiftAndArrows()) {
                 letPageHandleNavKey(keyCode, event.getEventTime(), true, event.getMetaState());
                 return true;
             }
+            if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                switch (keyCode) {
+                    case KeyEvent.KEYCODE_DPAD_UP:
+                        pageUp(true);
+                        return true;
+                    case KeyEvent.KEYCODE_DPAD_DOWN:
+                        pageDown(true);
+                        return true;
+                    case KeyEvent.KEYCODE_DPAD_LEFT:
+                        nativeClearCursor(); // start next trackball movement from page edge
+                        return pinScrollTo(0, mScrollY, true, 0);
+                    case KeyEvent.KEYCODE_DPAD_RIGHT:
+                        nativeClearCursor(); // start next trackball movement from page edge
+                        return pinScrollTo(mContentWidth, mScrollY, true, 0);
+                }
+            }
             if (mSelectingText) {
                 int xRate = keyCode == KeyEvent.KEYCODE_DPAD_LEFT
                     ? -1 : keyCode == KeyEvent.KEYCODE_DPAD_RIGHT ? 1 : 0;
@@ -4472,8 +4639,10 @@
             return false;
         }
 
-        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+        if (isEnterActionKey(keyCode)) {
             switchOutDrawHistory();
+            boolean wantsKeyEvents = nativeCursorNodePointer() == 0
+                || nativeCursorWantsKeyEvents();
             if (event.getRepeatCount() == 0) {
                 if (mSelectingText) {
                     return true; // discard press if copy in progress
@@ -4484,16 +4653,10 @@
                 // Already checked mNativeClass, so we do not need to check it
                 // again.
                 nativeRecordButtons(hasFocus() && hasWindowFocus(), true, true);
-                return true;
+                if (!wantsKeyEvents) return true;
             }
             // Bubble up the key event as WebView doesn't handle it
-            return false;
-        }
-
-        if (keyCode != KeyEvent.KEYCODE_SHIFT_LEFT
-                && keyCode != KeyEvent.KEYCODE_SHIFT_RIGHT) {
-            // turn off copy select if a shift-key combo is pressed
-            selectionDone();
+            if (!wantsKeyEvents) return false;
         }
 
         if (getSettings().getNavDump()) {
@@ -4517,8 +4680,8 @@
 
         if (nativeCursorIsTextInput()) {
             // This message will put the node in focus, for the DOM's notion
-            // of focus, and make the focuscontroller active
-            mWebViewCore.sendMessage(EventHub.CLICK, nativeCursorFramePointer(),
+            // of focus.
+            mWebViewCore.sendMessage(EventHub.FAKE_CLICK, nativeCursorFramePointer(),
                     nativeCursorNodePointer());
             // This will bring up the WebTextView and put it in focus, for
             // our view system's notion of focus
@@ -4575,24 +4738,40 @@
         // Bubble up the key event if
         // 1. it is a system key; or
         // 2. the host application wants to handle it;
-        // 3. the accessibility injector is present and wants to handle it;
         if (event.isSystem()
-                || mCallbackProxy.uiOverrideKeyEvent(event)
-                || (mAccessibilityInjector != null && mAccessibilityInjector.onKeyEvent(event))) {
+                || mCallbackProxy.uiOverrideKeyEvent(event)) {
             return false;
         }
 
-        if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT
-                || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
-            if (!pageShouldHandleShiftAndArrows() && copySelection()) {
-                selectionDone();
+        // accessibility support
+        if (accessibilityScriptInjected()) {
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                // if an accessibility script is injected we delegate to it the key handling.
+                // this script is a screen reader which is a fully fledged solution for blind
+                // users to navigate in and interact with web pages.
+                mWebViewCore.sendMessage(EventHub.KEY_UP, event);
                 return true;
+            } else {
+                // Clean up if accessibility was disabled after loading the current URL.
+                mAccessibilityScriptInjected = false;
+            }
+        } else if (mAccessibilityInjector != null) {
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                if (mAccessibilityInjector.onKeyEvent(event)) {
+                    // if an accessibility injector is present (no JavaScript enabled or the site
+                    // opts out injecting our JavaScript screen reader) we let it decide whether to
+                    // act on and consume the event.
+                    return true;
+                }
+            } else {
+                // Clean up if accessibility was disabled after loading the current URL.
+                mAccessibilityInjector = null;
             }
         }
 
         if (keyCode >= KeyEvent.KEYCODE_DPAD_UP
                 && keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT) {
-            if (pageShouldHandleShiftAndArrows()) {
+            if (nativePageShouldHandleShiftAndArrows()) {
                 letPageHandleNavKey(keyCode, event.getEventTime(), false, event.getMetaState());
                 return true;
             }
@@ -4601,7 +4780,7 @@
             return false;
         }
 
-        if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
+        if (isEnterActionKey(keyCode)) {
             // remove the long press message first
             mPrivateHandler.removeMessages(LONG_PRESS_CENTER);
             mGotCenterDown = false;
@@ -4638,11 +4817,14 @@
             }
             clearTextEntry();
             nativeShowCursorTimed();
-            if (!mCallbackProxy.uiOverrideUrlLoading(nativeCursorText())) {
+            if (mCallbackProxy.uiOverrideUrlLoading(nativeCursorText())) {
+                return true;
+            }
+            if (nativeCursorNodePointer() != 0 && !nativeCursorWantsKeyEvents()) {
                 mWebViewCore.sendMessage(EventHub.CLICK, data.mFrame,
                         nativeCursorNodePointer());
+                return true;
             }
-            return true;
         }
 
         // TODO: should we pass all the keys to DOM or check the meta tag
@@ -4657,10 +4839,15 @@
         return false;
     }
 
-    private void setUpSelect() {
-        if (0 == mNativeClass) return; // client isn't initialized
-        if (inFullScreenMode()) return;
-        if (mSelectingText) return;
+    /*
+     * Enter selecting text mode.  Returns true if the WebView is now in
+     * selecting text mode (including if it was already in that mode, and this
+     * method did nothing).
+     */
+    private boolean setUpSelect() {
+        if (0 == mNativeClass) return false; // client isn't initialized
+        if (inFullScreenMode()) return false;
+        if (mSelectingText) return true;
         mExtendSelection = false;
         mSelectingText = mDrawSelectionPointer = true;
         // don't let the picture change during text selection
@@ -4680,7 +4867,38 @@
         nativeHideCursor();
         mSelectCallback = new SelectActionModeCallback();
         mSelectCallback.setWebView(this);
-        startActionMode(mSelectCallback);
+        if (startActionMode(mSelectCallback) == null) {
+            // There is no ActionMode, so do not allow the user to modify a
+            // selection.
+            selectionDone();
+            return false;
+        }
+        mMinAutoScrollX = 0;
+        mMaxAutoScrollX = getViewWidth();
+        mMinAutoScrollY = 0;
+        mMaxAutoScrollY = getViewHeightWithTitle();
+        mScrollingLayer = nativeScrollableLayer(viewToContentX(mSelectX),
+                viewToContentY(mSelectY), mScrollingLayerRect,
+                mScrollingLayerBounds);
+        if (mScrollingLayer != 0) {
+            if (mScrollingLayerRect.left != mScrollingLayerRect.right) {
+                mMinAutoScrollX = Math.max(mMinAutoScrollX,
+                        contentToViewX(mScrollingLayerBounds.left));
+                mMaxAutoScrollX = Math.min(mMaxAutoScrollX,
+                        contentToViewX(mScrollingLayerBounds.right));
+            }
+            if (mScrollingLayerRect.top != mScrollingLayerRect.bottom) {
+                mMinAutoScrollY = Math.max(mMinAutoScrollY,
+                        contentToViewY(mScrollingLayerBounds.top));
+                mMaxAutoScrollY = Math.min(mMaxAutoScrollY,
+                        contentToViewY(mScrollingLayerBounds.bottom));
+            }
+        }
+        mMinAutoScrollX += SELECT_SCROLL;
+        mMaxAutoScrollX -= SELECT_SCROLL;
+        mMinAutoScrollY += SELECT_SCROLL;
+        mMaxAutoScrollY -= SELECT_SCROLL;
+        return true;
     }
 
     /**
@@ -4693,11 +4911,17 @@
 
     /**
      * Select all of the text in this WebView.
+     *
+     * @hide pending API council approval.
      */
-    void selectAll() {
+    public void selectAll() {
         if (0 == mNativeClass) return; // client isn't initialized
         if (inFullScreenMode()) return;
-        if (!mSelectingText) setUpSelect();
+        if (!mSelectingText) {
+            // retrieve a point somewhere within the text
+            Point select = nativeSelectableText();
+            if (!selectText(select.x, select.y)) return;
+        }
         nativeSelectAll();
         mDrawSelectionPointer = false;
         mExtendSelection = true;
@@ -4725,11 +4949,13 @@
 
     /**
      * Copy the selection to the clipboard
+     *
+     * @hide pending API council approval.
      */
-    boolean copySelection() {
+    public boolean copySelection() {
         boolean copiedSomething = false;
         String selection = getSelection();
-        if (selection != "") {
+        if (selection != null && selection != "") {
             if (DebugFlags.WEB_VIEW) {
                 Log.v(LOGTAG, "copySelection \"" + selection + "\"");
             }
@@ -5003,7 +5229,8 @@
         // Textfields, plugins, and contentEditable nodes need to receive the
         // shift up key even if another key was released while the shift key
         // was held down.
-        if (!inEditingMode() && (mNativeClass == 0
+        boolean inEditingMode = inEditingMode();
+        if (!inEditingMode && (mNativeClass == 0
                 || !nativePageShouldHandleShiftAndArrows())) {
             if (event.getAction() == KeyEvent.ACTION_DOWN) {
                 mGotKeyDown = true;
@@ -5020,7 +5247,13 @@
         }
 
         if (dispatch) {
-            return super.dispatchKeyEvent(event);
+            if (inEditingMode) {
+                // Ensure that the WebTextView gets the event, even if it does
+                // not currently have a bounds.
+                return mWebTextView.dispatchKeyEvent(event);
+            } else {
+                return super.dispatchKeyEvent(event);
+            }
         } else {
             // We didn't dispatch, so let something else handle the key
             return false;
@@ -5087,7 +5320,7 @@
         int contentX = viewToContentX((int) x + mScrollX);
         int contentY = viewToContentY((int) y + mScrollY);
         mScrollingLayer = nativeScrollableLayer(contentX, contentY,
-                mScrollingLayerRect);
+                mScrollingLayerRect, mScrollingLayerBounds);
         if (mScrollingLayer != 0) {
             mTouchMode = TOUCH_DRAG_LAYER_MODE;
         }
@@ -5113,17 +5346,10 @@
                 + " numPointers=" + ev.getPointerCount());
         }
 
-        int action = ev.getAction();
-        float x = ev.getX();
-        float y = ev.getY();
-        long eventTime = ev.getEventTime();
-
-        // mDeferMultitouch is a hack for layout tests, where it is used to
-        // force passing multi-touch events to webkit.
-        // FIXME: always pass multi-touch events to webkit and remove everything
-        // related to mDeferMultitouch.
-        if (ev.getPointerCount() > 1 &&
-                (mDeferMultitouch || mZoomManager.isZoomScaleFixed())) {
+        // Always pass multi-touch event to WebKit first.
+        // If WebKit doesn't consume it and set preventDefault to true,
+        // WebView's private handler will handle it.
+        if (ev.getPointerCount() > 1) {
             if (DebugFlags.WEB_VIEW) {
                 Log.v(LOGTAG, "passing " + ev.getPointerCount() + " points to webkit");
             }
@@ -5131,59 +5357,18 @@
             return true;
         }
 
-        final ScaleGestureDetector detector =
-                mZoomManager.getMultiTouchGestureDetector();
+        return handleTouchEventCommon(ev, ev.getX(), ev.getY());
+    }
 
-        if (mZoomManager.supportsMultiTouchZoom() && ev.getPointerCount() > 1) {
-            if (!detector.isInProgress() &&
-                    ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) {
-                // Insert a fake pointer down event in order to start
-                // the zoom scale detector.
-                MotionEvent temp = MotionEvent.obtain(ev);
-                // Clear the original event and set it to
-                // ACTION_POINTER_DOWN.
-                try {
-                    temp.setAction(temp.getAction() &
-                            ~MotionEvent.ACTION_MASK |
-                            MotionEvent.ACTION_POINTER_DOWN);
-                    detector.onTouchEvent(temp);
-                } finally {
-                    temp.recycle();
-                }
-            }
+    /*
+     * Common code for single touch and multi-touch.
+     * (x, y) denotes current focus point, which is the touch point for single touch
+     * and the middle point for multi-touch.
+     */
+    private boolean handleTouchEventCommon(MotionEvent ev, float x, float y) {
+        int action = ev.getAction();
+        long eventTime = ev.getEventTime();
 
-            detector.onTouchEvent(ev);
-
-            if (detector.isInProgress()) {
-                mLastTouchTime = eventTime;
-                cancelLongPress();
-                mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-                if (!mZoomManager.supportsPanDuringZoom()) {
-                    return true;
-                }
-                mTouchMode = TOUCH_DRAG_MODE;
-                if (mVelocityTracker == null) {
-                    mVelocityTracker = VelocityTracker.obtain();
-                }
-            }
-
-            x = detector.getFocusX();
-            y = detector.getFocusY();
-            action = ev.getAction() & MotionEvent.ACTION_MASK;
-            if (action == MotionEvent.ACTION_POINTER_DOWN) {
-                cancelTouch();
-                action = MotionEvent.ACTION_DOWN;
-            } else if (action == MotionEvent.ACTION_POINTER_UP) {
-                // set mLastTouchX/Y to the remaining point
-                mLastTouchX = x;
-                mLastTouchY = y;
-            } else if (action == MotionEvent.ACTION_MOVE) {
-                // negative x or y indicate it is on the edge, skip it.
-                if (x < 0 || y < 0) {
-                    return true;
-                }
-            }
-        }
 
         // Due to the touch screen edge effect, a touch closer to the edge
         // always snapped to the edge. As getViewWidth() can be different from
@@ -5286,6 +5471,8 @@
                     if (shouldForwardTouchEvent()) {
                         TouchEventData ted = new TouchEventData();
                         ted.mAction = action;
+                        ted.mIds = new int[1];
+                        ted.mIds[0] = ev.getPointerId(0);
                         ted.mPoints = new Point[1];
                         ted.mPoints[0] = new Point(contentX, contentY);
                         ted.mMetaState = ev.getMetaState();
@@ -5328,6 +5515,8 @@
                         || eventTime - mLastSentTouchTime > mCurrentTouchInterval)) {
                     TouchEventData ted = new TouchEventData();
                     ted.mAction = action;
+                    ted.mIds = new int[1];
+                    ted.mIds[0] = ev.getPointerId(0);
                     ted.mPoints = new Point[1];
                     ted.mPoints[0] = new Point(contentX, contentY);
                     ted.mMetaState = ev.getMetaState();
@@ -5354,8 +5543,9 @@
                             + "mPreventDefault = " + mPreventDefault
                             + " mDeferTouchProcess = " + mDeferTouchProcess
                             + " mTouchMode = " + mTouchMode);
+                } else {
+                    mVelocityTracker.addMovement(ev);
                 }
-                mVelocityTracker.addMovement(ev);
                 if (mSelectingText && mSelectionStarted) {
                     if (DebugFlags.WEB_VIEW) {
                         Log.v(LOGTAG, "extend=" + contentX + "," + contentY);
@@ -5364,24 +5554,20 @@
                     if (parent != null) {
                         parent.requestDisallowInterceptTouchEvent(true);
                     }
-                    int layer = nativeScrollableLayer(contentX, contentY, mScrollingLayerRect);
-                    if (layer == 0) {
-                        mAutoScrollX = x <= SELECT_SCROLL ? -SELECT_SCROLL
-                            : x >= getViewWidth() - SELECT_SCROLL
-                            ? SELECT_SCROLL : 0;
-                        mAutoScrollY = y <= SELECT_SCROLL ? -SELECT_SCROLL
-                            : y >= getViewHeightWithTitle() - SELECT_SCROLL
-                            ? SELECT_SCROLL : 0;
-                        if (!mSentAutoScrollMessage) {
-                            mSentAutoScrollMessage = true;
-                            mPrivateHandler.sendEmptyMessageDelayed(
-                                    SCROLL_SELECT_TEXT, SELECT_SCROLL_INTERVAL);
-                        }
-                    } else {
-                        // TODO: allow scrollable overflow div to autoscroll
+                    mAutoScrollX = x <= mMinAutoScrollX ? -SELECT_SCROLL
+                            : x >= mMaxAutoScrollX ? SELECT_SCROLL : 0;
+                    mAutoScrollY = y <= mMinAutoScrollY ? -SELECT_SCROLL
+                            : y >= mMaxAutoScrollY ? SELECT_SCROLL : 0;
+                    if ((mAutoScrollX != 0 || mAutoScrollY != 0)
+                            && !mSentAutoScrollMessage) {
+                        mSentAutoScrollMessage = true;
+                        mPrivateHandler.sendEmptyMessageDelayed(
+                                SCROLL_SELECT_TEXT, SELECT_SCROLL_INTERVAL);
                     }
-                    nativeExtendSelection(contentX, contentY);
-                    invalidate();
+                    if (deltaX != 0 || deltaY != 0) {
+                        nativeExtendSelection(contentX, contentY);
+                        invalidate();
+                    }
                     break;
                 }
 
@@ -5403,7 +5589,9 @@
                     // Only lock dragging to one axis if we don't have a scale in progress.
                     // Scaling implies free-roaming movement. Note this is only ever a question
                     // if mZoomManager.supportsPanDuringZoom() is true.
-                    if (detector != null && !detector.isInProgress()) {
+                    final ScaleGestureDetector detector =
+                      mZoomManager.getMultiTouchGestureDetector();
+                    if (detector == null || !detector.isInProgress()) {
                         // if it starts nearly horizontal or vertical, enforce it
                         int ax = Math.abs(deltaX);
                         int ay = Math.abs(deltaY);
@@ -5516,6 +5704,8 @@
                 // pass the touch events from UI thread to WebCore thread
                 if (shouldForwardTouchEvent()) {
                     TouchEventData ted = new TouchEventData();
+                    ted.mIds = new int[1];
+                    ted.mIds[0] = ev.getPointerId(0);
                     ted.mAction = action;
                     ted.mPoints = new Point[1];
                     ted.mPoints[0] = new Point(contentX, contentY);
@@ -5524,12 +5714,17 @@
                     mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
                 }
                 mLastTouchUpTime = eventTime;
+                if (mSentAutoScrollMessage) {
+                    mAutoScrollX = mAutoScrollY = 0;
+                }
                 switch (mTouchMode) {
                     case TOUCH_DOUBLE_TAP_MODE: // double tap
                         mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
                         mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
                         if (inFullScreenMode() || mDeferTouchProcess) {
                             TouchEventData ted = new TouchEventData();
+                            ted.mIds = new int[1];
+                            ted.mIds[0] = ev.getPointerId(0);
                             ted.mAction = WebViewCore.ACTION_DOUBLETAP;
                             ted.mPoints = new Point[1];
                             ted.mPoints[0] = new Point(contentX, contentY);
@@ -5611,8 +5806,9 @@
                                         + mPreventDefault
                                         + " mDeferTouchProcess = "
                                         + mDeferTouchProcess);
+                            } else {
+                                mVelocityTracker.addMovement(ev);
                             }
-                            mVelocityTracker.addMovement(ev);
                             // set to MOTIONLESS_IGNORE so that it won't keep
                             // removing and sending message in
                             // drawCoreAndCursorRing()
@@ -5662,26 +5858,105 @@
         TouchEventData ted = new TouchEventData();
         ted.mAction = ev.getAction() & MotionEvent.ACTION_MASK;
         final int count = ev.getPointerCount();
+        ted.mIds = new int[count];
         ted.mPoints = new Point[count];
         for (int c = 0; c < count; c++) {
+            ted.mIds[c] = ev.getPointerId(c);
             int x = viewToContentX((int) ev.getX(c) + mScrollX);
             int y = viewToContentY((int) ev.getY(c) + mScrollY);
             ted.mPoints[c] = new Point(x, y);
         }
         ted.mMetaState = ev.getMetaState();
-        ted.mReprocess = mDeferTouchProcess;
+        ted.mReprocess = true;
+        ted.mMotionEvent = MotionEvent.obtain(ev);
         mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
         cancelLongPress();
         mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
         mPreventDefault = PREVENT_DEFAULT_IGNORE;
     }
 
+    private boolean handleMultiTouchInWebView(MotionEvent ev) {
+        if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "multi-touch: " + ev + " at " + ev.getEventTime()
+                + " mTouchMode=" + mTouchMode
+                + " numPointers=" + ev.getPointerCount()
+                + " scrolloffset=(" + mScrollX + "," + mScrollY + ")");
+        }
+
+        final ScaleGestureDetector detector =
+            mZoomManager.getMultiTouchGestureDetector();
+
+        // A few apps use WebView but don't instantiate gesture detector.
+        // We don't need to support multi touch for them.
+        if (detector == null) return false;
+
+        float x = ev.getX();
+        float y = ev.getY();
+
+        if (!detector.isInProgress() &&
+            ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) {
+            // Insert a fake pointer down event in order to start
+            // the zoom scale detector.
+            MotionEvent temp = MotionEvent.obtain(ev);
+            // Clear the original event and set it to
+            // ACTION_POINTER_DOWN.
+            try {
+                temp.setAction(temp.getAction() &
+                ~MotionEvent.ACTION_MASK |
+                MotionEvent.ACTION_POINTER_DOWN);
+                detector.onTouchEvent(temp);
+            } finally {
+                temp.recycle();
+            }
+        }
+
+        detector.onTouchEvent(ev);
+
+        if (detector.isInProgress()) {
+            if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "detector is in progress");
+            }
+            mLastTouchTime = ev.getEventTime();
+            x = detector.getFocusX();
+            y = detector.getFocusY();
+
+            cancelLongPress();
+            mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+            if (!mZoomManager.supportsPanDuringZoom()) {
+                return false;
+            }
+            mTouchMode = TOUCH_DRAG_MODE;
+            if (mVelocityTracker == null) {
+                mVelocityTracker = VelocityTracker.obtain();
+            }
+        }
+
+        int action = ev.getActionMasked();
+        if (action == MotionEvent.ACTION_POINTER_DOWN) {
+            cancelTouch();
+            action = MotionEvent.ACTION_DOWN;
+        } else if (action == MotionEvent.ACTION_POINTER_UP) {
+            // set mLastTouchX/Y to the remaining point
+            mLastTouchX = x;
+            mLastTouchY = y;
+        } else if (action == MotionEvent.ACTION_MOVE) {
+            // negative x or y indicate it is on the edge, skip it.
+            if (x < 0 || y < 0) {
+                return false;
+            }
+        }
+
+        return handleTouchEventCommon(ev, x, y);
+    }
+
     private void cancelWebCoreTouchEvent(int x, int y, boolean removeEvents) {
         if (shouldForwardTouchEvent()) {
             if (removeEvents) {
                 mWebViewCore.removeMessages(EventHub.TOUCH_EVENT);
             }
             TouchEventData ted = new TouchEventData();
+            ted.mIds = new int[1];
+            ted.mIds[0] = 0;
             ted.mPoints = new Point[1];
             ted.mPoints[0] = new Point(x, y);
             ted.mAction = MotionEvent.ACTION_CANCEL;
@@ -5905,7 +6180,7 @@
             return false; // let common code in onKeyUp at it
         }
         if ((mMapTrackballToArrowKeys && (ev.getMetaState() & KeyEvent.META_SHIFT_ON) == 0) ||
-                (mAccessibilityInjector != null || mAccessibilityScriptInjected)) {
+                AccessibilityManager.getInstance(mContext).isEnabled()) {
             if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent gmail quit");
             return false;
         }
@@ -6771,7 +7046,16 @@
                         mSentAutoScrollMessage = false;
                         break;
                     }
-                    pinScrollBy(mAutoScrollX, mAutoScrollY, true, 0);
+                    if (mScrollingLayer == 0) {
+                        pinScrollBy(mAutoScrollX, mAutoScrollY, true, 0);
+                    } else {
+                        mScrollingLayerRect.left += mAutoScrollX;
+                        mScrollingLayerRect.top += mAutoScrollY;
+                        nativeScrollLayer(mScrollingLayer,
+                                mScrollingLayerRect.left,
+                                mScrollingLayerRect.top);
+                        invalidate();
+                    }
                     sendEmptyMessageDelayed(
                             SCROLL_SELECT_TEXT, SELECT_SCROLL_INTERVAL);
                     break;
@@ -6800,6 +7084,8 @@
                     if (inFullScreenMode() || mDeferTouchProcess) {
                         TouchEventData ted = new TouchEventData();
                         ted.mAction = WebViewCore.ACTION_LONGPRESS;
+                        ted.mIds = new int[1];
+                        ted.mIds[0] = 0;
                         ted.mPoints = new Point[1];
                         ted.mPoints[0] = new Point(viewToContentX((int) mLastTouchX + mScrollX),
                                                    viewToContentY((int) mLastTouchY + mScrollY));
@@ -7039,6 +7325,13 @@
                         // prevent default is not called in WebCore, so the
                         // message needs to be reprocessed in UI
                         TouchEventData ted = (TouchEventData) msg.obj;
+
+                        if (ted.mPoints.length > 1) {  // for multi-touch.
+                            handleMultiTouchInWebView(ted.mMotionEvent);
+                            break;
+                        }
+
+                        // Following is for single touch.
                         switch (ted.mAction) {
                             case MotionEvent.ACTION_DOWN:
                                 mLastDeferTouchX = contentToViewX(ted.mPoints[0].x)
@@ -7632,6 +7925,24 @@
                 cursorData());
     }
 
+    /*
+     * Called from JNI when the cursor has moved. This method
+     * sends a message to the WebCore requesting the given
+     * nodePtr in the given framePrt to be selected which will
+     * result in firing an accessibility event announing its
+     * content.
+     *
+     * Note: Accessibility support.
+     */
+    @SuppressWarnings("unused")
+    // called from JNI
+    private void sendMoveSelection(int framePtr, int nodePtr) {
+        if (AccessibilityManager.getInstance(mContext).isEnabled()
+                && mAccessibilityInjector != null) {
+            mWebViewCore.sendMessage(EventHub.MOVE_SELECTION, framePtr, nodePtr);
+        }
+    }
+
     // called by JNI
     private void sendMotionUp(int touchGeneration,
             int frame, int node, int x, int y) {
@@ -7726,6 +8037,9 @@
         Rect contentCursorRingBounds = nativeGetCursorRingBounds();
         if (contentCursorRingBounds.isEmpty()) return keyHandled;
         Rect viewCursorRingBounds = contentToViewRect(contentCursorRingBounds);
+        // set last touch so that context menu related functions will work
+        mLastTouchX = (viewCursorRingBounds.left + viewCursorRingBounds.right) / 2;
+        mLastTouchY = (viewCursorRingBounds.top + viewCursorRingBounds.bottom) / 2;
         Rect visRect = new Rect();
         calcOurVisibleRect(visRect);
         Rect outset = new Rect(visRect);
@@ -7761,13 +8075,13 @@
     }
 
     /**
-     * @return If the page should receive Shift and arrows.
+     * @return Whether accessibility script has been injected.
      */
-    private boolean pageShouldHandleShiftAndArrows() {
+    private boolean accessibilityScriptInjected() {
         // TODO: Maybe the injected script should announce its presence in
         // the page meta-tag so the nativePageShouldHandleShiftAndArrows
         // will check that as one of the conditions it looks for
-        return (nativePageShouldHandleShiftAndArrows() || mAccessibilityScriptInjected);
+        return mAccessibilityScriptInjected;
     }
 
     /**
@@ -7843,7 +8157,6 @@
     private native int      nativeCursorFramePointer();
     private native Rect     nativeCursorNodeBounds();
     private native int nativeCursorNodePointer();
-    /* package */ native boolean nativeCursorMatchesFocus();
     private native boolean  nativeCursorIntersects(Rect visibleRect);
     private native boolean  nativeCursorIsAnchor();
     private native boolean  nativeCursorIsTextInput();
@@ -7878,6 +8191,7 @@
     private native boolean  nativeFocusCandidateIsRtlText();
     private native boolean  nativeFocusCandidateIsTextInput();
     /* package */ native int      nativeFocusCandidateMaxLength();
+    /* package */ native boolean  nativeFocusCandidateIsAutoComplete();
     /* package */ native String   nativeFocusCandidateName();
     private native Rect     nativeFocusCandidateNodeBounds();
     /**
@@ -7930,6 +8244,7 @@
     private native void     nativeRecordButtons(boolean focused,
             boolean pressed, boolean invalidate);
     private native void     nativeResetSelection();
+    private native Point    nativeSelectableText();
     private native void     nativeSelectAll();
     private native void     nativeSelectBestAt(Rect rect);
     private native int      nativeSelectionX();
@@ -7959,6 +8274,7 @@
     native int nativeGetBlockLeftEdge(int x, int y, float scale);
 
     // Returns a pointer to the scrollable LayerAndroid at the given point.
-    private native int      nativeScrollableLayer(int x, int y, Rect scrollRect);
+    private native int      nativeScrollableLayer(int x, int y, Rect scrollRect,
+            Rect scrollBounds);
     private native boolean  nativeScrollLayer(int layer, int dx, int dy);
 }
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index b8c8913..c56f252 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -33,11 +33,13 @@
 import android.util.Log;
 import android.util.SparseBooleanArray;
 import android.view.KeyEvent;
+import android.view.MotionEvent;
 import android.view.SurfaceView;
 import android.view.View;
 import android.webkit.DeviceMotionService;
 import android.webkit.DeviceMotionAndOrientationManager;
 import android.webkit.DeviceOrientationService;
+import android.webkit.JniUtil;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -113,8 +115,8 @@
      */
     private int mViewportDensityDpi = -1;
 
-    private int mRestoredScale = 0;
-    private int mRestoredTextWrapScale = 0;
+    private float mRestoredScale = 0;
+    private float mRestoredTextWrapScale = 0;
     private int mRestoredX = 0;
     private int mRestoredY = 0;
 
@@ -514,7 +516,7 @@
             int repeatCount, boolean isShift, boolean isAlt, boolean isSym,
             boolean isDown);
 
-    private native void nativeClick(int framePtr, int nodePtr);
+    private native void nativeClick(int framePtr, int nodePtr, boolean fake);
 
     private native void nativeSendListBoxChoices(boolean[] choices, int size);
 
@@ -560,8 +562,8 @@
     private native void nativeTouchUp(int touchGeneration,
             int framePtr, int nodePtr, int x, int y);
 
-    private native boolean nativeHandleTouchEvent(int action, int[] x, int[] y,
-            int count, int metaState);
+    private native boolean nativeHandleTouchEvent(int action, int[] idArray,
+            int[] xArray, int[] yArray, int count, int metaState);
 
     private native void nativeUpdateFrameCache();
 
@@ -626,6 +628,8 @@
     /**
      * Modifies the current selection.
      *
+     * Note: Accessibility support.
+     *
      * @param direction The direction in which to alter the selection.
      * @param granularity The granularity of the selection modification.
      *
@@ -633,6 +637,18 @@
      */
     private native String nativeModifySelection(int direction, int granularity);
 
+    /**
+     * Moves the selection to given node i.e. selects that node.
+     *
+     * Note: Accessibility support.
+     *
+     * @param framePtr Pointer to the frame containing the node to be selected.
+     * @param nodePtr Pointer to the node to be selected.
+     *
+     * @return The selection string.
+     */
+    private native String nativeMoveSelection(int framePtr, int nodePtr);
+
     // EventHub for processing messages
     private final EventHub mEventHub;
     // WebCore thread handler
@@ -668,6 +684,30 @@
                                 Process.setThreadPriority(
                                         Process.THREAD_PRIORITY_DEFAULT);
                                 break;
+
+                            case EventHub.ADD_PACKAGE_NAME:
+                                if (BrowserFrame.sJavaBridge == null) {
+                                    throw new IllegalStateException(
+                                            "No WebView has been created in this process!");
+                                }
+                                BrowserFrame.sJavaBridge.addPackageName((String) msg.obj);
+                                break;
+
+                            case EventHub.REMOVE_PACKAGE_NAME:
+                                if (BrowserFrame.sJavaBridge == null) {
+                                    throw new IllegalStateException(
+                                            "No WebView has been created in this process!");
+                                }
+                                BrowserFrame.sJavaBridge.removePackageName((String) msg.obj);
+                                break;
+
+                            case EventHub.PROXY_CHANGED:
+                                if (BrowserFrame.sJavaBridge == null) {
+                                    throw new IllegalStateException(
+                                            "No WebView has been created in this process!");
+                                }
+                                BrowserFrame.sJavaBridge.updateProxy((String) msg.obj);
+                                break;
                         }
                     }
                 };
@@ -788,9 +828,11 @@
 
     static class TouchEventData {
         int mAction;
+        int[] mIds;  // Ids of the touch points
         Point[] mPoints;
         int mMetaState;
         boolean mReprocess;
+        MotionEvent mMotionEvent;
     }
 
     static class GeolocationPermissionsData {
@@ -825,7 +867,7 @@
             "CLICK", // = 118;
             "SET_NETWORK_STATE", // = 119;
             "DOC_HAS_IMAGES", // = 120;
-            "121", // = 121;
+            "FAKE_CLICK", // = 121;
             "DELETE_SELECTION", // = 122;
             "LISTBOX_CHOICES", // = 123;
             "SINGLE_LISTBOX_CHOICE", // = 124;
@@ -883,6 +925,7 @@
         static final int CLICK = 118;
         static final int SET_NETWORK_STATE = 119;
         static final int DOC_HAS_IMAGES = 120;
+        static final int FAKE_CLICK = 121;
         static final int DELETE_SELECTION = 122;
         static final int LISTBOX_CHOICES = 123;
         static final int SINGLE_LISTBOX_CHOICE = 124;
@@ -967,6 +1010,11 @@
 
         static final int AUTOFILL_FORM = 192;
 
+        static final int PROXY_CHANGED = 193;
+
+        // accessibility support
+        static final int MOVE_SELECTION = 194;
+
         // private message ids
         private static final int DESTROY =     200;
 
@@ -1127,8 +1175,12 @@
                             key((KeyEvent) msg.obj, false);
                             break;
 
+                        case FAKE_CLICK:
+                            nativeClick(msg.arg1, msg.arg2, true);
+                            break;
+
                         case CLICK:
-                            nativeClick(msg.arg1, msg.arg2);
+                            nativeClick(msg.arg1, msg.arg2, false);
                             break;
 
                         case VIEW_SIZE_CHANGED: {
@@ -1175,15 +1227,19 @@
                             Process.setThreadPriority(mTid,
                                     Process.THREAD_PRIORITY_BACKGROUND);
                             pauseTimers();
-                            WebViewWorker.getHandler().sendEmptyMessage(
-                                    WebViewWorker.MSG_PAUSE_CACHE_TRANSACTION);
+                            if (!JniUtil.useChromiumHttpStack()) {
+                                WebViewWorker.getHandler().sendEmptyMessage(
+                                        WebViewWorker.MSG_PAUSE_CACHE_TRANSACTION);
+                            }
                             break;
 
                         case RESUME_TIMERS:
                             Process.setThreadPriority(mTid, mSavedPriority);
                             resumeTimers();
-                            WebViewWorker.getHandler().sendEmptyMessage(
-                                    WebViewWorker.MSG_RESUME_CACHE_TRANSACTION);
+                            if (!JniUtil.useChromiumHttpStack()) {
+                                WebViewWorker.getHandler().sendEmptyMessage(
+                                        WebViewWorker.MSG_RESUME_CACHE_TRANSACTION);
+                            }
                             break;
 
                         case ON_PAUSE:
@@ -1281,8 +1337,8 @@
                                     mWebView.mPrivateHandler,
                                     WebView.PREVENT_TOUCH_ID,
                                     ted.mAction,
-                                    nativeHandleTouchEvent(ted.mAction, xArray,
-                                            yArray, count, ted.mMetaState) ? 1 : 0,
+                                    nativeHandleTouchEvent(ted.mAction, ted.mIds,
+                                        xArray, yArray, count, ted.mMetaState) ? 1 : 0,
                                     ted.mReprocess ? ted : null).sendToTarget();
                             break;
                         }
@@ -1370,9 +1426,16 @@
                             break;
 
                         case MODIFY_SELECTION:
-                            String selectionString = nativeModifySelection(msg.arg1, msg.arg2);
+                            String modifiedSelectionString = nativeModifySelection(msg.arg1,
+                                    msg.arg2);
                             mWebView.mPrivateHandler.obtainMessage(WebView.SELECTION_STRING_CHANGED,
-                                    selectionString).sendToTarget();
+                                    modifiedSelectionString).sendToTarget();
+                            break;
+
+                        case MOVE_SELECTION:
+                            String movedSelectionString = nativeMoveSelection(msg.arg1, msg.arg2);
+                            mWebView.mPrivateHandler.obtainMessage(WebView.SELECTION_STRING_CHANGED,
+                                    movedSelectionString).sendToTarget();
                             break;
 
                         case LISTBOX_CHOICES:
@@ -1488,24 +1551,6 @@
                                     (Set<String>) msg.obj);
                             break;
 
-                        case ADD_PACKAGE_NAME:
-                            if (BrowserFrame.sJavaBridge == null) {
-                                throw new IllegalStateException("No WebView " +
-                                        "has been created in this process!");
-                            }
-                            BrowserFrame.sJavaBridge.addPackageName(
-                                    (String) msg.obj);
-                            break;
-
-                        case REMOVE_PACKAGE_NAME:
-                            if (BrowserFrame.sJavaBridge == null) {
-                                throw new IllegalStateException("No WebView " +
-                                        "has been created in this process!");
-                            }
-                            BrowserFrame.sJavaBridge.removePackageName(
-                                    (String) msg.obj);
-                            break;
-
                         case GET_TOUCH_HIGHLIGHT_RECTS:
                             TouchHighlightData d = (TouchHighlightData) msg.obj;
                             ArrayList<Rect> rects = nativeGetTouchHighlightRects
@@ -1725,7 +1770,7 @@
 
     private void clearCache(boolean includeDiskFiles) {
         mBrowserFrame.clearCache();
-        if (includeDiskFiles) {
+        if (includeDiskFiles && !JniUtil.useChromiumHttpStack()) {
             CacheManager.removeAllCacheFiles();
         }
     }
@@ -1991,6 +2036,13 @@
                 .obtainMessage(WebCoreThread.RESUME_PRIORITY));
     }
 
+    static void sendStaticMessage(int messageType, Object argument) {
+        if (sWebCoreHandler == null)
+            return;
+
+        sWebCoreHandler.sendMessage(sWebCoreHandler.obtainMessage(messageType, argument));
+    }
+
     static void pauseUpdatePicture(WebViewCore core) {
         // Note: there is one possible failure mode. If pauseUpdatePicture() is
         // called from UI thread while WEBKIT_DRAW is just pulled out of the
@@ -2135,12 +2187,14 @@
     // called by JNI
     private void sendNotifyProgressFinished() {
         sendUpdateTextEntry();
-        // as CacheManager can behave based on database transaction, we need to
-        // call tick() to trigger endTransaction
-        WebViewWorker.getHandler().removeMessages(
-                WebViewWorker.MSG_CACHE_TRANSACTION_TICKER);
-        WebViewWorker.getHandler().sendEmptyMessage(
-                WebViewWorker.MSG_CACHE_TRANSACTION_TICKER);
+        if (!JniUtil.useChromiumHttpStack()) {
+            // as CacheManager can behave based on database transaction, we need to
+            // call tick() to trigger endTransaction
+            WebViewWorker.getHandler().removeMessages(
+                    WebViewWorker.MSG_CACHE_TRANSACTION_TICKER);
+            WebViewWorker.getHandler().sendEmptyMessage(
+                    WebViewWorker.MSG_CACHE_TRANSACTION_TICKER);
+        }
         contentDraw();
     }
 
@@ -2197,8 +2251,8 @@
         }
 
         // reset the scroll position, the restored offset and scales
-        mWebkitScrollX = mWebkitScrollY = mRestoredX = mRestoredY
-                = mRestoredScale = mRestoredTextWrapScale = 0;
+        mWebkitScrollX = mWebkitScrollY = mRestoredX = mRestoredY = 0;
+        mRestoredScale = mRestoredTextWrapScale = 0;
     }
 
     // called by JNI
@@ -2304,9 +2358,9 @@
         mInitialViewState.mMobileSite = (0 == mViewportWidth);
         if (mRestoredScale > 0) {
             mInitialViewState.mIsRestored = true;
-            mInitialViewState.mViewScale = mRestoredScale / 100.0f;
+            mInitialViewState.mViewScale = mRestoredScale;
             if (mRestoredTextWrapScale > 0) {
-                mInitialViewState.mTextWrapScale = mRestoredTextWrapScale / 100.0f;
+                mInitialViewState.mTextWrapScale = mRestoredTextWrapScale;
             } else {
                 mInitialViewState.mTextWrapScale = mInitialViewState.mViewScale;
             }
@@ -2363,7 +2417,7 @@
                 // know the exact scale. If mRestoredScale is non-zero, use it;
                 // otherwise just use mTextWrapScale as the initial scale.
                 data.mScale = mInitialViewState.mViewScale == 0
-                        ? (mRestoredScale > 0 ? mRestoredScale / 100.0f
+                        ? (mRestoredScale > 0 ? mRestoredScale
                                 : mInitialViewState.mTextWrapScale)
                         : mInitialViewState.mViewScale;
                 if (DebugFlags.WEB_VIEW_CORE) {
@@ -2396,7 +2450,7 @@
     }
 
     // called by JNI
-    private void restoreScale(int scale, int textWrapScale) {
+    private void restoreScale(float scale, float textWrapScale) {
         if (mBrowserFrame.firstLayoutDone() == false) {
             mRestoredScale = scale;
             if (mSettings.getUseWideViewPort()) {
@@ -2562,10 +2616,7 @@
                 .sendToTarget();
     }
 
-    // called by JNI.  PluginWidget functions for creating an embedded View for
-    // the surface drawing model.
-    private ViewManager.ChildView addSurface(View pluginView, int x, int y,
-                                             int width, int height) {
+    private ViewManager.ChildView createSurface(View pluginView) {
         if (mWebView == null) {
             return null;
         }
@@ -2583,6 +2634,14 @@
 
         ViewManager.ChildView view = mWebView.mViewManager.createView();
         view.mView = pluginView;
+        return view;
+    }
+    
+    // called by JNI.  PluginWidget functions for creating an embedded View for
+    // the surface drawing model.
+    private ViewManager.ChildView addSurface(View pluginView, int x, int y,
+                                             int width, int height) {
+        ViewManager.ChildView view = createSurface(pluginView);
         view.attachView(x, y, width, height);
         return view;
     }
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 8f89678..e1392ae 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -33,6 +33,7 @@
 import android.util.Log;
 import android.webkit.CookieManager.Cookie;
 import android.webkit.CacheManager.CacheResult;
+import android.webkit.JniUtil;
 
 public class WebViewDatabase {
     private static final String DATABASE_FILE = "webview.db";
@@ -202,6 +203,17 @@
             return;
         }
 
+        initDatabase(context);
+        if (!JniUtil.useChromiumHttpStack()) {
+            initCacheDatabase(context);
+        }
+
+        // Thread done, notify.
+        mInitialized = true;
+        notify();
+    }
+
+    private void initDatabase(Context context) {
         try {
             mDatabase = context.openOrCreateDatabase(DATABASE_FILE, 0, null);
         } catch (SQLiteException e) {
@@ -211,6 +223,7 @@
                         null);
             }
         }
+        mDatabase.enableWriteAheadLogging();
 
         // mDatabase should not be null,
         // the only case is RequestAPI test has problem to create db
@@ -221,7 +234,7 @@
         }
 
         if (mDatabase.getVersion() != DATABASE_VERSION) {
-            mDatabase.beginTransaction();
+            mDatabase.beginTransactionNonExclusive();
             try {
                 upgradeDatabase();
                 mDatabase.setTransactionSuccessful();
@@ -234,6 +247,10 @@
         // improves performance as database's ReentrantLock is
         // expansive
         mDatabase.setLockingEnabled(false);
+    }
+
+    private void initCacheDatabase(Context context) {
+        assert !JniUtil.useChromiumHttpStack();
 
         try {
             mCacheDatabase = context.openOrCreateDatabase(
@@ -245,6 +262,7 @@
                         CACHE_DATABASE_FILE, 0, null);
             }
         }
+        mCacheDatabase.enableWriteAheadLogging();
 
         // mCacheDatabase should not be null,
         // the only case is RequestAPI test has problem to create db
@@ -255,7 +273,7 @@
         }
 
         if (mCacheDatabase.getVersion() != CACHE_DATABASE_VERSION) {
-            mCacheDatabase.beginTransaction();
+            mCacheDatabase.beginTransactionNonExclusive();
             try {
                 upgradeCacheDatabase();
                 bootstrapCacheDatabase();
@@ -306,10 +324,6 @@
                 .getColumnIndex(CACHE_CONTENTDISPOSITION_COL);
         mCacheCrossDomainColIndex = mCacheInserter
                 .getColumnIndex(CACHE_CROSSDOMAIN_COL);
-
-        // Thread done, notify.
-        mInitialized = true;
-        notify();
     }
 
     private static void upgradeDatabase() {
@@ -636,7 +650,7 @@
                         + "WebViewWorkerThread instead of from "
                         + Thread.currentThread().getName());
             }
-            mCacheDatabase.beginTransaction();
+            mCacheDatabase.beginTransactionNonExclusive();
             return true;
         }
         return false;
@@ -668,6 +682,8 @@
      * @return CacheResult The CacheManager.CacheResult
      */
     CacheResult getCache(String url) {
+        assert !JniUtil.useChromiumHttpStack();
+
         if (url == null || !checkInitialized()) {
             return null;
         }
@@ -708,6 +724,8 @@
      * @param url The url
      */
     void removeCache(String url) {
+        assert !JniUtil.useChromiumHttpStack();
+
         if (url == null || !checkInitialized()) {
             return;
         }
@@ -722,6 +740,8 @@
      * @param c The CacheManager.CacheResult
      */
     void addCache(String url, CacheResult c) {
+        assert !JniUtil.useChromiumHttpStack();
+
         if (url == null || !checkInitialized()) {
             return;
         }
diff --git a/core/java/android/webkit/WebViewFragment.java b/core/java/android/webkit/WebViewFragment.java
new file mode 100644
index 0000000..466f174
--- /dev/null
+++ b/core/java/android/webkit/WebViewFragment.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebView;
+
+/**
+ * A fragment that displays a WebView.
+ * <p>
+ * The WebView is automically paused or resumed when the Fragment is paused or resumed.
+ */
+public class WebViewFragment extends Fragment {
+    private WebView mWebView;
+
+    public WebViewFragment() {
+    }
+
+    /**
+     * Called to instantiate the view. Creates and returns the WebView.
+     */
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        mWebView = new WebView(getActivity());
+        return mWebView;
+    }
+
+    /**
+     * Called when the fragment is visible to the user and actively running. Resumes the WebView.
+     */
+    @Override
+    public void onPause() {
+        super.onPause();
+        mWebView.onPause();
+    }
+
+    /**
+     * Called when the fragment is no longer resumed. Pauses the WebView.
+     */
+    @Override
+    public void onResume() {
+        mWebView.onResume();
+        super.onResume();
+    }
+
+    /**
+     * Called when the view has been detached from the fragment. Destroys the WebView.
+     */
+    @Override
+    public void onDestroyView() {
+        mWebView.destroy();
+        mWebView = null;
+        super.onDestroyView();
+    }
+
+    /**
+     * Gets the WebView.
+     */
+    public WebView getWebView() {
+        return mWebView;
+    }
+}
diff --git a/core/java/android/webkit/WebViewWorker.java b/core/java/android/webkit/WebViewWorker.java
index c488150..6a4ca29 100644
--- a/core/java/android/webkit/WebViewWorker.java
+++ b/core/java/android/webkit/WebViewWorker.java
@@ -125,6 +125,7 @@
                 break;
             }
             case MSG_CREATE_CACHE: {
+                assert !JniUtil.useChromiumHttpStack();
                 CacheCreateData data = (CacheCreateData) msg.obj;
                 CacheManager.CacheResult cache = CacheManager.createCacheFile(
                         data.mUrl, data.mStatusCode, data.mHeaders,
@@ -137,6 +138,7 @@
                 break;
             }
             case MSG_UPDATE_CACHE_ENCODING: {
+                assert !JniUtil.useChromiumHttpStack();
                 CacheEncoding data = (CacheEncoding) msg.obj;
                 CacheManager.CacheResult cache = mCacheResultMap
                         .get(data.mListener);
@@ -146,6 +148,7 @@
                 break;
             }
             case MSG_APPEND_CACHE: {
+                assert !JniUtil.useChromiumHttpStack();
                 CacheData data = (CacheData) msg.obj;
                 CacheManager.CacheResult cache = mCacheResultMap
                         .get(data.mListener);
@@ -168,6 +171,7 @@
                 break;
             }
             case MSG_SAVE_CACHE: {
+                assert !JniUtil.useChromiumHttpStack();
                 CacheSaveData data = (CacheSaveData) msg.obj;
                 CacheManager.CacheResult cache = mCacheResultMap
                         .get(data.mListener);
@@ -178,6 +182,7 @@
                 break;
             }
             case MSG_REMOVE_CACHE: {
+                assert !JniUtil.useChromiumHttpStack();
                 LoadListener listener = (LoadListener) msg.obj;
                 CacheManager.CacheResult cache = mCacheResultMap.get(listener);
                 if (cache != null) {
@@ -187,14 +192,17 @@
                 break;
             }
             case MSG_TRIM_CACHE: {
+                assert !JniUtil.useChromiumHttpStack();
                 CacheManager.trimCacheIfNeeded();
                 break;
             }
             case MSG_CLEAR_CACHE: {
+                assert !JniUtil.useChromiumHttpStack();
                 CacheManager.clearCache();
                 break;
             }
             case MSG_CACHE_TRANSACTION_TICKER: {
+                assert !JniUtil.useChromiumHttpStack();
                 if (!mCacheTickersBlocked) {
                     CacheManager.endTransaction();
                     CacheManager.startTransaction();
@@ -204,6 +212,7 @@
                 break;
             }
             case MSG_PAUSE_CACHE_TRANSACTION: {
+                assert !JniUtil.useChromiumHttpStack();
                 if (CacheManager.disableTransaction()) {
                     mCacheTickersBlocked = true;
                     removeMessages(MSG_CACHE_TRANSACTION_TICKER);
@@ -211,6 +220,7 @@
                 break;
             }
             case MSG_RESUME_CACHE_TRANSACTION: {
+                assert !JniUtil.useChromiumHttpStack();
                 if (CacheManager.enableTransaction()) {
                     mCacheTickersBlocked = false;
                     sendEmptyMessageDelayed(MSG_CACHE_TRANSACTION_TICKER,
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index c55d180..b4a33de 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -150,6 +150,12 @@
     private static float MINIMUM_SCALE_INCREMENT = 0.01f;
 
     /*
+     *  The touch points could be changed even the fingers stop moving.
+     *  We use the following to filter out the zooming jitters.
+     */
+    private static float MINIMUM_SCALE_WITHOUT_JITTER = 0.05f;
+
+    /*
      * The following member variables are only to be used for animating zoom. If
      * mZoomScale is non-zero then we are in the middle of a zoom animation. The
      * other variables are used as a cache (e.g. inverse) or as a way to store
@@ -260,8 +266,9 @@
     public final float getReadingLevelScale() {
         // The reading scale is at least 0.5f apart from the overview scale.
         final float MIN_SCALE_DIFF = 0.5f;
-        return Math.max(getZoomOverviewScale() + MIN_SCALE_DIFF,
-            DEFAULT_READING_LEVEL_SCALE);
+        return computeScaleWithLimits(
+                   Math.max(getZoomOverviewScale() + MIN_SCALE_DIFF,
+                            DEFAULT_READING_LEVEL_SCALE));
     }
 
     public final float getInvDefaultScale() {
@@ -683,6 +690,10 @@
                 } else {
                     scale = Math.max(scale, mActualScale * 0.8f);
                 }
+                // if the scale change is too small, regard it as jitter and skip it.
+                if (Math.abs(scale - mActualScale) < MINIMUM_SCALE_WITHOUT_JITTER) {
+                    return false;
+                }
                 setZoomCenter(detector.getFocusX(), detector.getFocusY());
                 setZoomScale(scale, false);
                 mWebView.invalidate();
@@ -800,28 +811,12 @@
      */
     public void onNewPicture(WebViewCore.DrawData drawData) {
         final int viewWidth = mWebView.getViewWidth();
+        final boolean zoomOverviewWidthChanged = setupZoomOverviewWidth(drawData, viewWidth);
         WebSettings settings = mWebView.getSettings();
-        if (settings.getUseWideViewPort()) {
-            if (!settings.getUseFixedViewport()) {
-                // limit mZoomOverviewWidth upper bound to
-                // sMaxViewportWidth so that if the page doesn't behave
-                // well, the WebView won't go insane. limit the lower
-                // bound to match the default scale for mobile sites.
-                setZoomOverviewWidth(Math.min(WebView.sMaxViewportWidth,
-                    Math.max((int) (viewWidth * mInvDefaultScale),
-                            Math.max(drawData.mMinPrefWidth, drawData.mViewSize.x))));
-            } else if (drawData.mContentSize.x > 0) {
-                // The webkitDraw for layers will not populate contentSize, and it'll be
-                // ignored for zoom overview width update.
-                final int contentWidth = Math.max(drawData.mContentSize.x, drawData.mMinPrefWidth);
-                final int newZoomOverviewWidth = Math.min(WebView.sMaxViewportWidth, contentWidth);
-                if (newZoomOverviewWidth != mZoomOverviewWidth) {
-                    setZoomOverviewWidth(newZoomOverviewWidth);
-                    if (settings.isNarrowColumnLayout() && (mInitialZoomOverview || mInZoomOverview)) {
-                        mTextWrapScale = getReadingLevelScale();
-                    }
-                }
-            }
+        if (zoomOverviewWidthChanged && settings.isNarrowColumnLayout() &&
+            settings.getUseFixedViewport() &&
+            (mInitialZoomOverview || mInZoomOverview)) {
+            mTextWrapScale = getReadingLevelScale();
         }
 
         final float zoomOverviewScale = getZoomOverviewScale();
@@ -838,6 +833,41 @@
     }
 
     /**
+     * Set up correct zoom overview width based on different settings.
+     *
+     * @param drawData webviewcore draw data
+     * @param viewWidth current view width
+     */
+    private boolean setupZoomOverviewWidth(WebViewCore.DrawData drawData, final int viewWidth) {
+        WebSettings settings = mWebView.getSettings();
+        int newZoomOverviewWidth = mZoomOverviewWidth;
+        if (settings.getUseWideViewPort()) {
+            if (!settings.getUseFixedViewport()) {
+                // limit mZoomOverviewWidth upper bound to
+                // sMaxViewportWidth so that if the page doesn't behave
+                // well, the WebView won't go insane. limit the lower
+                // bound to match the default scale for mobile sites.
+                newZoomOverviewWidth = Math.min(WebView.sMaxViewportWidth,
+                    Math.max((int) (viewWidth * mInvDefaultScale),
+                          Math.max(drawData.mMinPrefWidth, drawData.mViewSize.x)));
+            } else if (drawData.mContentSize.x > 0) {
+                // The webkitDraw for layers will not populate contentSize, and it'll be
+                // ignored for zoom overview width update.
+                final int contentWidth = Math.max(drawData.mContentSize.x, drawData.mMinPrefWidth);
+                newZoomOverviewWidth = Math.min(WebView.sMaxViewportWidth, contentWidth);
+            }
+        } else {
+            // If not use wide viewport, use view width as the zoom overview width.
+            newZoomOverviewWidth = viewWidth;
+        }
+        if (newZoomOverviewWidth != mZoomOverviewWidth) {
+            setZoomOverviewWidth(newZoomOverviewWidth);
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Updates zoom values after Webkit completes the initial page layout. It
      * is called when visiting a page for the first time as well as when the
      * user navigates back to a page (in which case we may need to restore the
@@ -853,15 +883,12 @@
         WebViewCore.ViewState viewState = drawData.mViewState;
         final Point viewSize = drawData.mViewSize;
         updateZoomRange(viewState, viewSize.x, drawData.mMinPrefWidth);
-        if (mWebView.getSettings().getUseWideViewPort() &&
-            mWebView.getSettings().getUseFixedViewport()) {
-            final int contentWidth = Math.max(drawData.mContentSize.x, drawData.mMinPrefWidth);
-            setZoomOverviewWidth(Math.min(WebView.sMaxViewportWidth, contentWidth));
-        }
+        setupZoomOverviewWidth(drawData, mWebView.getViewWidth());
 
         if (!mWebView.drawHistory()) {
             float scale;
             final float overviewScale = getZoomOverviewScale();
+            WebSettings settings = mWebView.getSettings();
 
             if (mInitialScale > 0) {
                 scale = mInitialScale;
@@ -870,12 +897,12 @@
                 scale = viewState.mViewScale;
             } else {
                 scale = overviewScale;
-                WebSettings settings = mWebView.getSettings();
                 if (!settings.getUseWideViewPort()
                     || !settings.getLoadWithOverviewMode()) {
                     scale = Math.max(viewState.mTextWrapScale, scale);
                 }
-                if (settings.isNarrowColumnLayout() && settings.getUseFixedViewport()) {
+                if (settings.isNarrowColumnLayout() &&
+                    settings.getUseFixedViewport()) {
                     // When first layout, reflow using the reading level scale to avoid
                     // reflow when double tapped.
                     mTextWrapScale = getReadingLevelScale();
@@ -883,8 +910,11 @@
             }
             boolean reflowText = false;
             if (!viewState.mIsRestored) {
-                scale = Math.max(scale, overviewScale);
-                mTextWrapScale = Math.max(mTextWrapScale, overviewScale);
+                if (settings.getUseFixedViewport()) {
+                    // Override the scale only in case of fixed viewport.
+                    scale = Math.max(scale, overviewScale);
+                    mTextWrapScale = Math.max(mTextWrapScale, overviewScale);
+                }
                 reflowText = exceedsMinScaleIncrement(mTextWrapScale, scale);
             }
             mInitialZoomOverview = !exceedsMinScaleIncrement(scale, overviewScale);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 6309cac..7631df4 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -512,6 +512,11 @@
     private AbsListView.PerformClick mPerformClick;
 
     /**
+     * Delayed action for touch mode.
+     */
+    private Runnable mTouchModeReset;
+
+    /**
      * This view is in transcript mode -- it shows the bottom of the list when the data
      * changes
      */
@@ -733,16 +738,6 @@
         boolean smoothScrollbar = a.getBoolean(R.styleable.AbsListView_smoothScrollbar, true);
         setSmoothScrollbarEnabled(smoothScrollbar);
 
-        final int adapterId = a.getResourceId(R.styleable.AbsListView_adapter, 0);
-        if (adapterId != 0) {
-            final Context c = context;
-            post(new Runnable() {
-                public void run() {
-                    setAdapter(Adapters.loadAdapter(c, adapterId));
-                }
-            });
-        }
-
         setChoiceMode(a.getInt(R.styleable.AbsListView_choiceMode, CHOICE_MODE_NONE));
         setFastScrollAlwaysVisible(
                 a.getBoolean(R.styleable.AbsListView_fastScrollAlwaysVisible, false));
@@ -1475,8 +1470,16 @@
             ss.position = getSelectedItemPosition();
             ss.firstId = INVALID_POSITION;
         } else {
-            if (haveChildren) {
-                // Remember the position of the first child
+            if (haveChildren && mFirstPosition > 0) {
+                // Remember the position of the first child.
+                // We only do this if we are not currently at the top of
+                // the list, for two reasons:
+                // (1) The list may be in the process of becoming empty, in
+                // which case mItemCount may not be 0, but if we try to
+                // ask for any information about position 0 we will crash.
+                // (2) Being "at the top" seems like a special case, anyway,
+                // and the user wouldn't expect to end up somewhere else when
+                // they revisit the list even if its content has changed.
                 View v = getChildAt(0);
                 ss.viewTop = v.getTop();
                 int firstPos = mFirstPosition;
@@ -2314,6 +2317,27 @@
             mFlingStrictSpan.finish();
             mFlingStrictSpan = null;
         }
+
+        if (mFlingRunnable != null) {
+            removeCallbacks(mFlingRunnable);
+        }
+
+        if (mPositionScroller != null) {
+            mPositionScroller.stop();
+        }
+
+        if (mClearScrollingCache != null) {
+            removeCallbacks(mClearScrollingCache);
+        }
+
+        if (mPerformClick != null) {
+            removeCallbacks(mPerformClick);
+        }
+
+        if (mTouchModeReset != null) {
+            removeCallbacks(mTouchModeReset);
+            mTouchModeReset = null;
+        }
     }
 
     @Override
@@ -2329,6 +2353,9 @@
                 // let the fling runnable report it's new state which
                 // should be idle
                 mFlingRunnable.endFling();
+                if (mPositionScroller != null) {
+                    mPositionScroller.stop();
+                }
                 if (mScrollY != 0) {
                     mScrollY = 0;
                     finishGlows();
@@ -2400,7 +2427,6 @@
     }
 
     private class PerformClick extends WindowRunnnable implements Runnable {
-        View mChild;
         int mClickMotionPosition;
 
         public void run() {
@@ -2413,7 +2439,8 @@
             if (adapter != null && mItemCount > 0 &&
                     motionPosition != INVALID_POSITION &&
                     motionPosition < adapter.getCount() && sameWindow()) {
-                performItemClick(mChild, motionPosition, adapter.getItemId(motionPosition));
+                performItemClick(getChildAt(motionPosition - mFirstPosition), motionPosition,
+                        adapter.getItemId(motionPosition));
             }
         }
     }
@@ -2696,6 +2723,9 @@
                 if (mFlingRunnable != null) {
                     mFlingRunnable.endFling();
                 }
+                if (mPositionScroller != null) {
+                    mPositionScroller.stop();
+                }
 
                 if (mScrollY != 0) {
                     mScrollY = 0;
@@ -2736,6 +2766,9 @@
             switch (mTouchMode) {
             case TOUCH_MODE_OVERFLING: {
                 mFlingRunnable.endFling();
+                if (mPositionScroller != null) {
+                    mPositionScroller.stop();
+                }
                 mTouchMode = TOUCH_MODE_OVERSCROLL;
                 mMotionY = mLastY = (int) ev.getY();
                 mMotionCorrection = 0;
@@ -2986,7 +3019,6 @@
                     }
 
                     final AbsListView.PerformClick performClick = mPerformClick;
-                    performClick.mChild = child;
                     performClick.mClickMotionPosition = motionPosition;
                     performClick.rememberWindowAttachCount();
 
@@ -3012,23 +3044,29 @@
                                     ((TransitionDrawable) d).resetTransition();
                                 }
                             }
-                            postDelayed(new Runnable() {
+                            if (mTouchModeReset != null) {
+                                removeCallbacks(mTouchModeReset);
+                            }
+                            mTouchModeReset = new Runnable() {
+                                @Override
                                 public void run() {
                                     mTouchMode = TOUCH_MODE_REST;
                                     child.setPressed(false);
                                     setPressed(false);
                                     if (!mDataChanged) {
-                                        post(performClick);
+                                        performClick.run();
                                     }
                                 }
-                            }, ViewConfiguration.getPressedStateDuration());
+                            };
+                            postDelayed(mTouchModeReset,
+                                    ViewConfiguration.getPressedStateDuration());
                         } else {
                             mTouchMode = TOUCH_MODE_REST;
                             updateSelectorState();
                         }
                         return true;
                     } else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
-                        post(performClick);
+                        performClick.run();
                     }
                 }
                 mTouchMode = TOUCH_MODE_REST;
@@ -3073,6 +3111,9 @@
                             if (mFlingRunnable != null) {
                                 mFlingRunnable.endFling();
                             }
+                            if (mPositionScroller != null) {
+                                mPositionScroller.stop();
+                            }
                         }
                     }
                 } else {
@@ -3479,6 +3520,11 @@
                 } else {
                     mEdgeGlowBottom.onAbsorb(vel);
                 }
+            } else {
+                mTouchMode = TOUCH_MODE_REST;
+                if (mPositionScroller != null) {
+                    mPositionScroller.stop();
+                }
             }
             invalidate();
             post(this);
@@ -3497,9 +3543,6 @@
 
             removeCallbacks(this);
             removeCallbacks(mCheckFlywheel);
-            if (mPositionScroller != null) {
-                removeCallbacks(mPositionScroller);
-            }
 
             reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
             clearScrollingCache();
@@ -3650,6 +3693,8 @@
         }
 
         void start(int position) {
+            stop();
+
             final int firstPos = mFirstPosition;
             final int lastPos = firstPos + getChildCount() - 1;
 
@@ -3678,6 +3723,8 @@
         }
 
         void start(int position, int boundPosition) {
+            stop();
+
             if (boundPosition == INVALID_POSITION) {
                 start(position);
                 return;
@@ -3741,6 +3788,8 @@
         }
 
         void startWithOffset(int position, int offset, int duration) {
+            stop();
+
             mTargetPos = position;
             mOffsetFromTop = offset;
             mBoundPos = INVALID_POSITION;
@@ -3918,11 +3967,22 @@
                 final int position = mTargetPos;
                 final int lastPos = firstPos + childCount - 1;
 
+                int viewTravelCount = 0;
                 if (position < firstPos) {
-                    smoothScrollBy(-getHeight(), mScrollDuration);
+                    viewTravelCount = firstPos - position + 1;
+                } else if (position > lastPos) {
+                    viewTravelCount = position - lastPos;
+                }
+
+                // Estimate how many screens we should travel
+                final float screenTravelCount = (float) viewTravelCount / childCount;
+
+                final float modifier = Math.min(Math.abs(screenTravelCount), 1.f);
+                if (position < firstPos) {
+                    smoothScrollBy((int) (-getHeight() * modifier), mScrollDuration);
                     post(this);
                 } else if (position > lastPos) {
-                    smoothScrollBy(getHeight(), mScrollDuration);
+                    smoothScrollBy((int) (getHeight() * modifier), mScrollDuration);
                     post(this);
                 } else {
                     // On-screen, just scroll.
@@ -4038,12 +4098,25 @@
         if (mFlingRunnable == null) {
             mFlingRunnable = new FlingRunnable();
         }
+
         // No sense starting to scroll if we're not going anywhere
-        if (distance != 0) {
+        final int firstPos = mFirstPosition;
+        final int childCount = getChildCount();
+        final int lastPos = firstPos + childCount;
+        final int topLimit = getPaddingTop();
+        final int bottomLimit = getHeight() - getPaddingBottom();
+
+        if (distance == 0 || mItemCount == 0 || childCount == 0 ||
+                (firstPos == 0 && getChildAt(0).getTop() == topLimit && distance < 0) ||
+                (lastPos == mItemCount - 1 &&
+                        getChildAt(childCount - 1).getBottom() == bottomLimit && distance > 0)) {
+            mFlingRunnable.endFling();
+            if (mPositionScroller != null) {
+                mPositionScroller.stop();
+            }
+        } else {
             reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
             mFlingRunnable.startScroll(distance, duration);
-        } else {
-            mFlingRunnable.endFling();
         }
     }
 
@@ -4178,7 +4251,8 @@
             return incrementalDeltaY != 0;
         }
 
-        if (firstPosition + childCount == mItemCount && lastBottom <= end &&
+        if (firstPosition + childCount == mItemCount &&
+                lastBottom <= getHeight() - listPadding.bottom &&
                 incrementalDeltaY <= 0) {
             // Don't need to move views up if the bottom of the last position
             // is already visible
@@ -4382,6 +4456,18 @@
         requestLayout();
         invalidate();
     }
+    
+    /**
+     * If there is a selection returns true.
+     * Otherwise resurrects the selection and returns false.
+     */
+    boolean ensureSelectionOnMovementKey() {
+        if (mSelectedPosition < 0) {
+            resurrectSelection();
+            return false;
+        }
+        return true;
+    }
 
     /**
      * Makes the item at the supplied position selected.
@@ -4477,7 +4563,9 @@
 
         mResurrectToPosition = INVALID_POSITION;
         removeCallbacks(mFlingRunnable);
-        removeCallbacks(mPositionScroller);
+        if (mPositionScroller != null) {
+            mPositionScroller.stop();
+        }
         mTouchMode = TOUCH_MODE_REST;
         clearScrollingCache();
         mSpecificTop = selectedTop;
@@ -4718,9 +4806,17 @@
             dX = dest.left + dest.width() / 2;
             dY = dest.bottom;
             break;
+        case View.FOCUS_FORWARD:
+        case View.FOCUS_BACKWARD:
+            sX = source.right + source.width() / 2;
+            sY = source.top + source.height() / 2;
+            dX = dest.left + dest.width() / 2;
+            dY = dest.top + dest.height() / 2;
+            break;
         default:
             throw new IllegalArgumentException("direction must be one of "
-                    + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
+                    + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, "
+                    + "FOCUS_FORWARD, FOCUS_BACKWARD}.");
         }
         int deltaX = dX - sX;
         int deltaY = dY - sY;
@@ -4760,7 +4856,10 @@
             if (mFiltered && mPopup != null && mPopup.isShowing()) {
                 if (event.getAction() == KeyEvent.ACTION_DOWN
                         && event.getRepeatCount() == 0) {
-                    getKeyDispatcherState().startTracking(event, this);
+                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    if (state != null) {
+                        state.startTracking(event, this);
+                    }
                     handled = true;
                 } else if (event.getAction() == KeyEvent.ACTION_UP
                         && event.isTracking() && !event.isCanceled()) {
@@ -5184,6 +5283,8 @@
     public void onRemoteAdapterConnected() {
         if (mRemoteAdapter != mAdapter) {
             setAdapter(mRemoteAdapter);
+        } else if (mRemoteAdapter != null) {
+            mRemoteAdapter.superNotifyDataSetChanged();
         }
     }
 
@@ -5191,10 +5292,11 @@
      * Called back when the adapter disconnects from the RemoteViewsService.
      */
     public void onRemoteAdapterDisconnected() {
-        if (mRemoteAdapter == mAdapter) {
-            mRemoteAdapter = null;
-            setAdapter(null);
-        }
+        // If the remote adapter disconnects, we keep it around
+        // since the currently displayed items are still cached.
+        // Further, we want the service to eventually reconnect
+        // when necessary, as triggered by this view requesting
+        // items from the Adapter.
     }
 
     /**
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index 162b030..c27082f 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -787,6 +787,7 @@
         // We do the former in case mAdapter is null, and hence setDisplayedChild won't
         // set mWhichChild
         mWhichChild = ss.whichChild;
+
         setDisplayedChild(mWhichChild);
     }
 
@@ -964,6 +965,8 @@
     public void onRemoteAdapterConnected() {
         if (mRemoteViewsAdapter != mAdapter) {
             setAdapter(mRemoteViewsAdapter);
+        } else if (mRemoteViewsAdapter != null) {
+            mRemoteViewsAdapter.superNotifyDataSetChanged();
         }
     }
 
@@ -971,10 +974,11 @@
      * Called back when the adapter disconnects from the RemoteViewsService.
      */
     public void onRemoteAdapterDisconnected() {
-        if (mRemoteViewsAdapter != mAdapter) {
-            mRemoteViewsAdapter = null;
-            setAdapter(mRemoteViewsAdapter);
-        }
+        // If the remote adapter disconnects, we keep it around
+        // since the currently displayed items are still cached.
+        // Further, we want the service to eventually reconnect
+        // when necessary, as triggered by this view requesting
+        // items from the Adapter.
     }
 
     public void advance() {
@@ -983,4 +987,10 @@
 
     public void willBeAdvancedByHost() {
     }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        mAdapter = null;
+        super.onDetachedFromWindow();
+    }
 }
diff --git a/core/java/android/widget/Adapters.java b/core/java/android/widget/Adapters.java
deleted file mode 100644
index a71d4ab..0000000
--- a/core/java/android/widget/Adapters.java
+++ /dev/null
@@ -1,1233 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.database.Cursor;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.util.AttributeSet;
-import android.util.Xml;
-import android.view.View;
-
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/**
- * <p>This class can be used to load {@link android.widget.Adapter adapters} defined in
- * XML resources. XML-defined adapters can be used to easily create adapters in your
- * own application or to pass adapters to other processes.</p>
- * 
- * <h2>Types of adapters</h2>
- * <p>Adapters defined using XML resources can only be one of the following supported
- * types. Arbitrary adapters are not supported to guarantee the safety of the loaded
- * code when adapters are loaded across packages.</p>
- * <ul>
- *  <li><a href="#xml-cursor-adapter">Cursor adapter</a>: a cursor adapter can be used
- *  to display the content of a cursor, most often coming from a content provider</li>
- * </ul>
- * <p>The complete XML format definition of each adapter type is available below.</p>
- * 
- * <a name="xml-cursor-adapter"></a>
- * <h2>Cursor adapter</h2>
- * <p>A cursor adapter XML definition starts with the
- * <a href="#xml-cursor-adapter-tag"><code>&lt;cursor-adapter /&gt;</code></a>
- * tag and may contain one or more instances of the following tags:</p>
- * <ul>
- *  <li><a href="#xml-cursor-adapter-select-tag"><code>&lt;select /&gt;</code></a></li>
- *  <li><a href="#xml-cursor-adapter-bind-tag"><code>&lt;bind /&gt;</code></a></li>
- * </ul>
- * 
- * <a name="xml-cursor-adapter-tag"></a>
- * <h3>&lt;cursor-adapter /&gt;</h3>
- * <p>The <code>&lt;cursor-adapter /&gt;</code> element defines the beginning of the
- * document and supports the following attributes:</p>
- * <ul>
- *  <li><code>android:layout</code>: Reference to the XML layout to be inflated for
- *  each item of the adapter. This attribute is mandatory.</li>
- *  <li><code>android:selection</code>: Selection expression, used when the
- *  <code>android:uri</code> attribute is defined or when the adapter is loaded with
- *  {@link android.widget.Adapters#loadCursorAdapter(android.content.Context, int, String, Object[])}.
- *  This attribute is optional.</li>
- *  <li><code>android:sortOrder</code>: Sort expression, used when the
- *  <code>android:uri</code> attribute is defined or when the adapter is loaded with
- *  {@link android.widget.Adapters#loadCursorAdapter(android.content.Context, int, String, Object[])}.
- *  This attribute is optional.</li>
- *  <li><code>android:uri</code>: URI of the content provider to query to retrieve a cursor.
- *  Specifying this attribute is equivalent to calling
- *  {@link android.widget.Adapters#loadCursorAdapter(android.content.Context, int, String, Object[])}.
- *  If you call this method, the value of the XML attribute is ignored. This attribute is
- *  optional.</li>
- * </ul>
- * <p>In addition, you can specify one or more instances of
- * <a href="#xml-cursor-adapter-select-tag"><code>&lt;select /&gt;</code></a> and
- * <a href="#xml-cursor-adapter-bind-tag"><code>&lt;bind /&gt;</code></a> tags as children
- * of <code>&lt;cursor-adapter /&gt;</code>.</p>
- * 
- * <a name="xml-cursor-adapter-select-tag"></a>
- * <h3>&lt;select /&gt;</h3>
- * <p>The <code>&lt;select /&gt;</code> tag is used to select columns from the cursor
- * when doing the query. This can be very useful when using transformations in the
- * <code>&lt;bind /&gt;</code> elements. It can also be very useful if you are providing
- * your own <a href="#xml-cursor-adapter-bind-data-types">binder</a> or
- * <a href="#xml-cursor-adapter-bind-data-types">transformation</a> classes.
- * <code>&lt;select /&gt;</code> elements are ignored if you supply the cursor yourself.</p>
- * <p>The <code>&lt;select /&gt;</code> supports the following attributes:</p>
- * <ul>
- *  <li><code>android:column</code>: Name of the column to select in the cursor during the
- *  query operation</li>
- * </ul>
- * <p><strong>Note:</strong> The column named <code>_id</code> is always implicitly
- * selected.</p>
- * 
- * <a name="xml-cursor-adapter-bind-tag"></a>
- * <h3>&lt;bind /&gt;</h3>
- * <p>The <code>&lt;bind /&gt;</code> tag is used to bind a column from the cursor to
- * a {@link android.view.View}. A column bound using this tag is automatically selected
- * during the query and a matching
- * <a href="#xml-cursor-adapter-select-tag"><code>&lt;select /&gt;</code> tag is therefore
- * not required.</p>
- * 
- * <p>Each binding is declared as a one to one matching but
- * custom binder classes or special
- * <a href="#xml-cursor-adapter-bind-data-transformation">data transformations</a> can
- * allow you to bind several columns to a single view. In this case you must use the
- * <a href="#xml-cursor-adapter-select-tag"><code>&lt;select /&gt;</code> tag to make
- * sure any required column is part of the query.</p>
- * 
- * <p>The <code>&lt;bind /&gt;</code> tag supports the following attributes:</p>
- * <ul>
- *  <li><code>android:from</code>: The name of the column to bind from.
- *  This attribute is mandatory. Note that <code>@</code> which are not used to reference resources
- *  should be backslash protected as in <code>\@</code>.</li>
- *  <li><code>android:to</code>: The id of the view to bind to. This attribute is mandatory.</li>
- *  <li><code>android:as</code>: The <a href="#xml-cursor-adapter-bind-data-types">data type</a>
- *  of the binding. This attribute is mandatory.</li>
- * </ul>
- * 
- * <p>In addition, a <code>&lt;bind /&gt;</code> can contain zero or more instances of
- * <a href="#xml-cursor-adapter-bind-data-transformation">data transformations</a> children
- * tags.</p>
- *
- * <a name="xml-cursor-adapter-bind-data-types"></a>
- * <h4>Binding data types</h4>
- * <p>For a binding to occur the data type of the bound column/view pair must be specified.
- * The following data types are currently supported:</p>
- * <ul>
- *  <li><code>string</code>: The content of the column is interpreted as a string and must be
- *  bound to a {@link android.widget.TextView}</li>
- *  <li><code>image</code>: The content of the column is interpreted as a blob describing an
- *  image and must be bound to an {@link android.widget.ImageView}</li>
- *  <li><code>image-uri</code>: The content of the column is interpreted as a URI to an image
- *  and must be bound to an {@link android.widget.ImageView}</li>
- *  <li><code>drawable</code>: The content of the column is interpreted as a resource id to a
- *  drawable and must be bound to an {@link android.widget.ImageView}</li>
- *  <li><code>tag</code>: The content of the column is interpreted as a string and will be set as
- *  the tag (using {@link View#setTag(Object)} of the associated View. This can be used to
- *  associate meta-data to your view, that can be used for instance by a listener.</li>
- *  <li>A fully qualified class name: The name of a class corresponding to an implementation of
- *  {@link android.widget.Adapters.CursorBinder}. Cursor binders can be used to provide
- *  bindings not supported by default. Custom binders cannot be used with
- *  {@link android.content.Context#isRestricted() restricted contexts}, for instance in an
- *  application widget</li>
- * </ul>
- * 
- * <a name="xml-cursor-adapter-bind-transformation"></a>
- * <h4>Binding transformations</h4>
- * <p>When defining a data binding you can specify an optional transformation by using one
- * of the following tags as a child of a <code>&lt;bind /&gt;</code> elements:</p>
- * <ul>
- *  <li><code>&lt;map /&gt;</code>: Maps a constant string to a string or a resource. Use
- *  one instance of this tag per value you want to map</li>
- *  <li><code>&lt;transform /&gt;</code>: Transforms a column's value using an expression
- *  or an instance of {@link android.widget.Adapters.CursorTransformation}</li>
- * </ul>
- * <p>While several <code>&lt;map /&gt;</code> tags can be used at the same time, you cannot
- * mix <code>&lt;map /&gt;</code> and <code>&lt;transform /&gt;</code> tags. If several
- * <code>&lt;transform /&gt;</code> tags are specified, only the last one is retained.</p>
- * 
- * <a name="xml-cursor-adapter-bind-transformation-map" />
- * <p><strong>&lt;map /&gt;</strong></p>
- * <p>A map element simply specifies a value to match from and a value to match to. When
- * a column's value equals the value to match from, it is replaced with the value to match
- * to. The following attributes are supported:</p>
- * <ul>
- *  <li><code>android:fromValue</code>: The value to match from. This attribute is mandatory</li>
- *  <li><code>android:toValue</code>: The value to match to. This value can be either a string
- *  or a resource identifier. This value is interpreted as a resource identifier when the
- *  data binding is of type <code>drawable</code>. This attribute is mandatory</li>
- * </ul>
- * 
- * <a name="xml-cursor-adapter-bind-transformation-transform"></a>
- * <p><strong>&lt;transform /&gt;</strong></p>
- * <p>A simple transform that occurs either by calling a specified class or by performing
- * simple text substitution. The following attributes are supported:</p>
- * <ul>
- *  <li><code>android:withExpression</code>: The transformation expression. The expression is
- *  a string containing column names surrounded with curly braces { and }. During the
- *  transformation each column name is replaced by its value. All columns must have been
- *  selected in the query. An example of expression is <code>"First name: {first_name},
- *  last name: {last_name}"</code>. This attribute is mandatory
- *  if <code>android:withClass</code> is not specified and ignored if <code>android:withClass</code>
- *  is specified</li>
- *  <li><code>android:withClass</code>: A fully qualified class name corresponding to an
- *  implementation of {@link android.widget.Adapters.CursorTransformation}. Custom
- *  transformations cannot be used with
- *  {@link android.content.Context#isRestricted() restricted contexts}, for instance in
- *  an app widget This attribute is mandatory if <code>android:withExpression</code> is
- *  not specified</li>
- * </ul>
- * 
- * <h3>Example</h3>
- * <p>The following example defines a cursor adapter that queries all the contacts with
- * a phone number using the contacts content provider. Each contact is displayed with
- * its display name, its favorite status and its photo. To display photos, a custom data
- * binder is declared:</p>
- * 
- * <pre class="prettyprint">
- * &lt;cursor-adapter xmlns:android="http://schemas.android.com/apk/res/android"
- *     android:uri="content://com.android.contacts/contacts"
- *     android:selection="has_phone_number=1"
- *     android:layout="@layout/contact_item"&gt;
- *
- *     &lt;bind android:from="display_name" android:to="@id/name" android:as="string" /&gt;
- *     &lt;bind android:from="starred" android:to="@id/star" android:as="drawable"&gt;
- *         &lt;map android:fromValue="0" android:toValue="@android:drawable/star_big_off" /&gt;
- *         &lt;map android:fromValue="1" android:toValue="@android:drawable/star_big_on" /&gt;
- *     &lt;/bind&gt;
- *     &lt;bind android:from="_id" android:to="@id/name"
- *              android:as="com.google.android.test.adapters.ContactPhotoBinder" /&gt;
- *
- * &lt;/cursor-adapter&gt;
- * </pre>
- * 
- * <h3>Related APIs</h3>
- * <ul>
- *  <li>{@link android.widget.Adapters#loadAdapter(android.content.Context, int, Object[])}</li>
- *  <li>{@link android.widget.Adapters#loadCursorAdapter(android.content.Context, int, android.database.Cursor, Object[])}</li>
- *  <li>{@link android.widget.Adapters#loadCursorAdapter(android.content.Context, int, String, Object[])}</li>
- *  <li>{@link android.widget.Adapters.CursorBinder}</li>
- *  <li>{@link android.widget.Adapters.CursorTransformation}</li>
- *  <li>{@link android.widget.CursorAdapter}</li>
- * </ul>
- * 
- * @see android.widget.Adapter
- * @see android.content.ContentProvider
- * 
- * @attr ref android.R.styleable#CursorAdapter_layout 
- * @attr ref android.R.styleable#CursorAdapter_selection 
- * @attr ref android.R.styleable#CursorAdapter_sortOrder 
- * @attr ref android.R.styleable#CursorAdapter_uri 
- * @attr ref android.R.styleable#CursorAdapter_BindItem_as 
- * @attr ref android.R.styleable#CursorAdapter_BindItem_from 
- * @attr ref android.R.styleable#CursorAdapter_BindItem_to
- * @attr ref android.R.styleable#CursorAdapter_MapItem_fromValue 
- * @attr ref android.R.styleable#CursorAdapter_MapItem_toValue 
- * @attr ref android.R.styleable#CursorAdapter_SelectItem_column 
- * @attr ref android.R.styleable#CursorAdapter_TransformItem_withClass 
- * @attr ref android.R.styleable#CursorAdapter_TransformItem_withExpression 
- */
-@SuppressWarnings({"JavadocReference"})
-public class Adapters {
-    private static final String ADAPTER_CURSOR = "cursor-adapter";
-
-    /**
-     * <p>Interface used to bind a {@link android.database.Cursor} column to a View. This
-     * interface can be used to provide bindings for data types not supported by the
-     * standard implementation of {@link android.widget.Adapters}.</p>
-     * 
-     * <p>A binder is provided with a cursor transformation which may or may not be used
-     * to transform the value retrieved from the cursor. The transformation is guaranteed
-     * to never be null so it's always safe to apply the transformation.</p>
-     * 
-     * <p>The binder is associated with a Context but can be re-used with multiple cursors.
-     * As such, the implementation should make no assumption about the Cursor in use.</p>
-     *
-     * @see android.view.View 
-     * @see android.database.Cursor
-     * @see android.widget.Adapters.CursorTransformation
-     */
-    public static abstract class CursorBinder {
-        /**
-         * <p>The context associated with this binder.</p>
-         */
-        protected final Context mContext;
-
-        /**
-         * <p>The transformation associated with this binder. This transformation is never
-         * null and may or may not be applied to the Cursor data during the
-         * {@link #bind(android.view.View, android.database.Cursor, int)} operation.</p>
-         * 
-         * @see #bind(android.view.View, android.database.Cursor, int) 
-         */
-        protected final CursorTransformation mTransformation;
-
-        /**
-         * <p>Creates a new Cursor binder.</p> 
-         * 
-         * @param context The context associated with this binder.
-         * @param transformation The transformation associated with this binder. This
-         *        transformation may or may not be applied by the binder and is guaranteed
-         *        to not be null.
-         */
-        public CursorBinder(Context context, CursorTransformation transformation) {
-            mContext = context;
-            mTransformation = transformation;
-        }
-
-        /**
-         * <p>Binds the specified Cursor column to the supplied View. The binding operation
-         * can query other Cursor columns as needed. During the binding operation, values
-         * retrieved from the Cursor may or may not be transformed using this binder's
-         * cursor transformation.</p>
-         * 
-         * @param view The view to bind data to.
-         * @param cursor The cursor to bind data from.
-         * @param columnIndex The column index in the cursor where the data to bind resides.
-         * 
-         * @see #mTransformation
-         * 
-         * @return True if the column was successfully bound to the View, false otherwise.
-         */
-        public abstract boolean bind(View view, Cursor cursor, int columnIndex);
-    }
-
-    /**
-     * <p>Interface used to transform data coming out of a {@link android.database.Cursor}
-     * before it is bound to a {@link android.view.View}.</p>
-     * 
-     * <p>Transformations are used to transform text-based data (in the form of a String),
-     * or to transform data into a resource identifier. A default implementation is provided
-     * to generate resource identifiers.</p>
-     * 
-     * @see android.database.Cursor
-     * @see android.widget.Adapters.CursorBinder
-     */
-    public static abstract class CursorTransformation {
-        /**
-         * <p>The context associated with this transformation.</p>
-         */
-        protected final Context mContext;
-
-        /**
-         * <p>Creates a new Cursor transformation.</p>
-         * 
-         * @param context The context associated with this transformation.
-         */
-        public CursorTransformation(Context context) {
-            mContext = context;
-        }
-
-        /**
-         * <p>Transforms the specified Cursor column into a String. The transformation
-         * can simply return the content of the column as a String (this is known
-         * as the identity transformation) or manipulate the content. For instance,
-         * a transformation can perform text substitutions or concatenate other
-         * columns with the specified column.</p>
-         * 
-         * @param cursor The cursor that contains the data to transform. 
-         * @param columnIndex The index of the column to transform.
-         * 
-         * @return A String containing the transformed value of the column.
-         */
-        public abstract String transform(Cursor cursor, int columnIndex);
-
-        /**
-         * <p>Transforms the specified Cursor column into a resource identifier.
-         * The default implementation simply interprets the content of the column
-         * as an integer.</p>
-         * 
-         * @param cursor The cursor that contains the data to transform. 
-         * @param columnIndex The index of the column to transform.
-         * 
-         * @return A resource identifier.
-         */
-        public int transformToResource(Cursor cursor, int columnIndex) {
-            return cursor.getInt(columnIndex);
-        }        
-    }
-
-    /**
-     * <p>Loads the {@link android.widget.CursorAdapter} defined in the specified
-     * XML resource. The content of the adapter is loaded from the content provider
-     * identified by the supplied URI.</p>
-     * 
-     * <p><strong>Note:</strong> If the supplied {@link android.content.Context} is
-     * an {@link android.app.Activity}, the cursor returned by the content provider
-     * will be automatically managed. Otherwise, you are responsible for managing the
-     * cursor yourself.</p>
-     * 
-     * <p>The format of the XML definition of the cursor adapter is documented at
-     * the top of this page.</p>
-     * 
-     * @param context The context to load the XML resource from.
-     * @param id The identifier of the XML resource declaring the adapter.
-     * @param uri The URI of the content provider.
-     * @param parameters Optional parameters to pass to the CursorAdapter, used
-     *        to substitute values in the selection expression.
-     * 
-     * @return A {@link android.widget.CursorAdapter}
-     * 
-     * @throws IllegalArgumentException If the XML resource does not contain
-     *         a valid &lt;cursor-adapter /&gt; definition.
-     * 
-     * @see android.content.ContentProvider
-     * @see android.widget.CursorAdapter
-     * @see #loadAdapter(android.content.Context, int, Object[]) 
-     */
-    public static CursorAdapter loadCursorAdapter(Context context, int id, String uri,
-            Object... parameters) {
-
-        XmlCursorAdapter adapter = (XmlCursorAdapter) loadAdapter(context, id, ADAPTER_CURSOR,
-                parameters);
-
-        if (uri != null) {
-            adapter.setUri(uri);
-        }
-        adapter.load();
-
-        return adapter;
-    }
-
-    /**
-     * <p>Loads the {@link android.widget.CursorAdapter} defined in the specified
-     * XML resource. The content of the adapter is loaded from the specified cursor.
-     * You are responsible for managing the supplied cursor.</p>
-     * 
-     * <p>The format of the XML definition of the cursor adapter is documented at
-     * the top of this page.</p>
-     * 
-     * @param context The context to load the XML resource from.
-     * @param id The identifier of the XML resource declaring the adapter.
-     * @param cursor The cursor containing the data for the adapter.
-     * @param parameters Optional parameters to pass to the CursorAdapter, used
-     *        to substitute values in the selection expression.
-     * 
-     * @return A {@link android.widget.CursorAdapter}
-     * 
-     * @throws IllegalArgumentException If the XML resource does not contain
-     *         a valid &lt;cursor-adapter /&gt; definition.
-     * 
-     * @see android.content.ContentProvider
-     * @see android.widget.CursorAdapter
-     * @see android.database.Cursor
-     * @see #loadAdapter(android.content.Context, int, Object[]) 
-     */
-    public static CursorAdapter loadCursorAdapter(Context context, int id, Cursor cursor,
-            Object... parameters) {
-
-        XmlCursorAdapter adapter = (XmlCursorAdapter) loadAdapter(context, id, ADAPTER_CURSOR,
-                parameters);
-
-        if (cursor != null) {
-            adapter.changeCursor(cursor);
-        }
-
-        return adapter;
-    }
-
-    /**
-     * <p>Loads the adapter defined in the specified XML resource. The XML definition of
-     * the adapter must follow the format definition of one of the supported adapter
-     * types described at the top of this page.</p>
-     * 
-     * <p><strong>Note:</strong> If the loaded adapter is a {@link android.widget.CursorAdapter}
-     * and the supplied {@link android.content.Context} is an {@link android.app.Activity},
-     * the cursor returned by the content provider will be automatically managed. Otherwise,
-     * you are responsible for managing the cursor yourself.</p>
-     * 
-     * @param context The context to load the XML resource from.
-     * @param id The identifier of the XML resource declaring the adapter.
-     * @param parameters Optional parameters to pass to the adapter.
-     *  
-     * @return An adapter instance.
-     * 
-     * @see #loadCursorAdapter(android.content.Context, int, android.database.Cursor, Object[]) 
-     * @see #loadCursorAdapter(android.content.Context, int, String, Object[]) 
-     */
-    public static BaseAdapter loadAdapter(Context context, int id, Object... parameters) {
-        final BaseAdapter adapter = loadAdapter(context, id, null, parameters);
-        if (adapter instanceof ManagedAdapter) {
-            ((ManagedAdapter) adapter).load();
-        }
-        return adapter;
-    }
-
-    /**
-     * Loads an adapter from the specified XML resource. The optional assertName can
-     * be used to exit early if the adapter defined in the XML resource is not of the
-     * expected type.
-     * 
-     * @param context The context to associate with the adapter.
-     * @param id The resource id of the XML document defining the adapter.
-     * @param assertName The mandatory name of the adapter in the XML document.
-     *        Ignored if null.
-     * @param parameters Optional parameters passed to the adapter.
-     * 
-     * @return An instance of {@link android.widget.BaseAdapter}.
-     */
-    private static BaseAdapter loadAdapter(Context context, int id, String assertName,
-            Object... parameters) {
-
-        XmlResourceParser parser = null;
-        try {
-            parser = context.getResources().getXml(id);
-            return createAdapterFromXml(context, parser, Xml.asAttributeSet(parser),
-                    id, parameters, assertName);
-        } catch (XmlPullParserException ex) {
-            Resources.NotFoundException rnf = new Resources.NotFoundException(
-                    "Can't load adapter resource ID " +
-                    context.getResources().getResourceEntryName(id));
-            rnf.initCause(ex);
-            throw rnf;
-        } catch (IOException ex) {
-            Resources.NotFoundException rnf = new Resources.NotFoundException(
-                    "Can't load adapter resource ID " +
-                    context.getResources().getResourceEntryName(id));
-            rnf.initCause(ex);
-            throw rnf;
-        } finally {
-            if (parser != null) parser.close();
-        }
-    }
-
-    /**
-     * Generates an adapter using the specified XML parser. This method is responsible
-     * for choosing the type of the adapter to create based on the content of the
-     * XML parser.
-     * 
-     * This method will generate an {@link IllegalArgumentException} if
-     * <code>assertName</code> is not null and does not match the root tag of the XML
-     * document. 
-     */
-    private static BaseAdapter createAdapterFromXml(Context c,
-            XmlPullParser parser, AttributeSet attrs, int id, Object[] parameters,
-            String assertName) throws XmlPullParserException, IOException {
-
-        BaseAdapter adapter = null;
-
-        // Make sure we are on a start tag.
-        int type;
-        int depth = parser.getDepth();
-
-        while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) &&
-                type != XmlPullParser.END_DOCUMENT) {
-
-            if (type != XmlPullParser.START_TAG) {
-                continue;
-            }
-
-            String name = parser.getName();
-            if (assertName != null && !assertName.equals(name)) {
-                throw new IllegalArgumentException("The adapter defined in " +
-                        c.getResources().getResourceEntryName(id) + " must be a <" +
-                        assertName + " />");
-            }
-
-            if (ADAPTER_CURSOR.equals(name)) {
-                adapter = createCursorAdapter(c, parser, attrs, id, parameters);
-            } else {
-                throw new IllegalArgumentException("Unknown adapter name " + parser.getName() +
-                        " in " + c.getResources().getResourceEntryName(id));
-            }
-        }
-
-        return adapter;
-
-    }
-
-    /**
-     * Creates an XmlCursorAdapter using an XmlCursorAdapterParser.
-     */
-    private static XmlCursorAdapter createCursorAdapter(Context c, XmlPullParser parser,
-            AttributeSet attrs, int id, Object[] parameters)
-            throws IOException, XmlPullParserException {
-
-        return new XmlCursorAdapterParser(c, parser, attrs, id).parse(parameters);
-    }
-
-    /**
-     * Parser that can generate XmlCursorAdapter instances. This parser is responsible for
-     * handling all the attributes and child nodes for a &lt;cursor-adapter /&gt;.
-     */
-    private static class XmlCursorAdapterParser {
-        private static final String ADAPTER_CURSOR_BIND = "bind";
-        private static final String ADAPTER_CURSOR_SELECT = "select";
-        private static final String ADAPTER_CURSOR_AS_STRING = "string";
-        private static final String ADAPTER_CURSOR_AS_IMAGE = "image";
-        private static final String ADAPTER_CURSOR_AS_TAG = "tag";
-        private static final String ADAPTER_CURSOR_AS_IMAGE_URI = "image-uri";
-        private static final String ADAPTER_CURSOR_AS_DRAWABLE = "drawable";
-        private static final String ADAPTER_CURSOR_MAP = "map";
-        private static final String ADAPTER_CURSOR_TRANSFORM = "transform";
-
-        private final Context mContext;
-        private final XmlPullParser mParser;
-        private final AttributeSet mAttrs;
-        private final int mId;
-
-        private final HashMap<String, CursorBinder> mBinders;
-        private final ArrayList<String> mFrom;
-        private final ArrayList<Integer> mTo;
-        private final CursorTransformation mIdentity;
-        private final Resources mResources;
-
-        public XmlCursorAdapterParser(Context c, XmlPullParser parser, AttributeSet attrs, int id) {
-            mContext = c;
-            mParser = parser;
-            mAttrs = attrs;
-            mId = id;
-
-            mResources = mContext.getResources();
-            mBinders = new HashMap<String, CursorBinder>();
-            mFrom = new ArrayList<String>();
-            mTo = new ArrayList<Integer>();
-            mIdentity = new IdentityTransformation(mContext);            
-        }
-
-        public XmlCursorAdapter parse(Object[] parameters)
-               throws IOException, XmlPullParserException {
-
-            Resources resources = mResources;
-            TypedArray a = resources.obtainAttributes(mAttrs, android.R.styleable.CursorAdapter);
-
-            String uri = a.getString(android.R.styleable.CursorAdapter_uri);
-            String selection = a.getString(android.R.styleable.CursorAdapter_selection);
-            String sortOrder = a.getString(android.R.styleable.CursorAdapter_sortOrder);
-            int layout = a.getResourceId(android.R.styleable.CursorAdapter_layout, 0);
-            if (layout == 0) {
-                throw new IllegalArgumentException("The layout specified in " +
-                        resources.getResourceEntryName(mId) + " does not exist");
-            }
-
-            a.recycle();
-
-            XmlPullParser parser = mParser;
-            int type;
-            int depth = parser.getDepth();
-
-            while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) &&
-                    type != XmlPullParser.END_DOCUMENT) {
-
-                if (type != XmlPullParser.START_TAG) {
-                    continue;
-                }
-
-                String name = parser.getName();
-
-                if (ADAPTER_CURSOR_BIND.equals(name)) {
-                    parseBindTag();
-                } else if (ADAPTER_CURSOR_SELECT.equals(name)) {
-                    parseSelectTag();
-                } else {
-                    throw new RuntimeException("Unknown tag name " + parser.getName() + " in " +
-                            resources.getResourceEntryName(mId));
-                }
-            }
-
-            String[] fromArray = mFrom.toArray(new String[mFrom.size()]);
-            int[] toArray = new int[mTo.size()];
-            for (int i = 0; i < toArray.length; i++) {
-                toArray[i] = mTo.get(i);
-            }
-
-            String[] selectionArgs = null;
-            if (parameters != null) {
-                selectionArgs = new String[parameters.length];
-                for (int i = 0; i < selectionArgs.length; i++) {
-                    selectionArgs[i] = (String) parameters[i];
-                }
-            }
-
-            return new XmlCursorAdapter(mContext, layout, uri, fromArray, toArray, selection,
-                    selectionArgs, sortOrder, mBinders);
-        }
-
-        private void parseSelectTag() {
-            TypedArray a = mResources.obtainAttributes(mAttrs,
-                    android.R.styleable.CursorAdapter_SelectItem);
-
-            String fromName = a.getString(android.R.styleable.CursorAdapter_SelectItem_column);
-            if (fromName == null) {
-                throw new IllegalArgumentException("A select item in " +
-                        mResources.getResourceEntryName(mId) +
-                        " does not have a 'column' attribute");
-            }
-
-            a.recycle();
-
-            mFrom.add(fromName);
-            mTo.add(View.NO_ID);
-        }
-
-        private void parseBindTag() throws IOException, XmlPullParserException {
-            Resources resources = mResources;
-            TypedArray a = resources.obtainAttributes(mAttrs,
-                    android.R.styleable.CursorAdapter_BindItem);
-
-            String fromName = a.getString(android.R.styleable.CursorAdapter_BindItem_from);
-            if (fromName == null) {
-                throw new IllegalArgumentException("A bind item in " +
-                        resources.getResourceEntryName(mId) + " does not have a 'from' attribute");
-            }
-
-            int toName = a.getResourceId(android.R.styleable.CursorAdapter_BindItem_to, 0);
-            if (toName == 0) {
-                throw new IllegalArgumentException("A bind item in " +
-                        resources.getResourceEntryName(mId) + " does not have a 'to' attribute");
-            }
-
-            String asType = a.getString(android.R.styleable.CursorAdapter_BindItem_as);
-            if (asType == null) {
-                throw new IllegalArgumentException("A bind item in " +
-                        resources.getResourceEntryName(mId) + " does not have an 'as' attribute");
-            }
-
-            mFrom.add(fromName);
-            mTo.add(toName);
-            mBinders.put(fromName, findBinder(asType));
-
-            a.recycle();
-        }
-
-        private CursorBinder findBinder(String type) throws IOException, XmlPullParserException {
-            final XmlPullParser parser = mParser;
-            final Context context = mContext;
-            CursorTransformation transformation = mIdentity;
-
-            int tagType;
-            int depth = parser.getDepth();
-
-            final boolean isDrawable = ADAPTER_CURSOR_AS_DRAWABLE.equals(type);            
-
-            while (((tagType = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
-                    && tagType != XmlPullParser.END_DOCUMENT) {
-
-                if (tagType != XmlPullParser.START_TAG) {
-                    continue;
-                }
-
-                String name = parser.getName();
-
-                if (ADAPTER_CURSOR_TRANSFORM.equals(name)) {
-                    transformation = findTransformation();
-                } else if (ADAPTER_CURSOR_MAP.equals(name)) {
-                    if (!(transformation instanceof MapTransformation)) {
-                        transformation = new MapTransformation(context);
-                    }
-                    findMap(((MapTransformation) transformation), isDrawable);
-                } else {
-                    throw new RuntimeException("Unknown tag name " + parser.getName() + " in " +
-                            context.getResources().getResourceEntryName(mId));
-                }
-            }
-
-            if (ADAPTER_CURSOR_AS_STRING.equals(type)) {
-                return new StringBinder(context, transformation);
-            } else if (ADAPTER_CURSOR_AS_TAG.equals(type)) {
-                return new TagBinder(context, transformation);
-            } else if (ADAPTER_CURSOR_AS_IMAGE.equals(type)) {
-                return new ImageBinder(context, transformation);            
-            } else if (ADAPTER_CURSOR_AS_IMAGE_URI.equals(type)) {
-                return new ImageUriBinder(context, transformation);
-            } else if (isDrawable) {
-                return new DrawableBinder(context, transformation);
-            } else {
-                return createBinder(type, transformation);
-            }
-        }
-
-        private CursorBinder createBinder(String type, CursorTransformation transformation) {
-            if (mContext.isRestricted()) return null;
-
-            try {
-                final Class<?> klass = Class.forName(type, true, mContext.getClassLoader());
-                if (CursorBinder.class.isAssignableFrom(klass)) {
-                    final Constructor<?> c = klass.getDeclaredConstructor(
-                            Context.class, CursorTransformation.class);
-                    return (CursorBinder) c.newInstance(mContext, transformation);
-                }
-            } catch (ClassNotFoundException e) {
-                throw new IllegalArgumentException("Cannot instanciate binder type in " +
-                        mContext.getResources().getResourceEntryName(mId) + ": " + type, e);
-            } catch (NoSuchMethodException e) {
-                throw new IllegalArgumentException("Cannot instanciate binder type in " +
-                        mContext.getResources().getResourceEntryName(mId) + ": " + type, e);
-            } catch (InvocationTargetException e) {
-                throw new IllegalArgumentException("Cannot instanciate binder type in " +
-                        mContext.getResources().getResourceEntryName(mId) + ": " + type, e);
-            } catch (InstantiationException e) {
-                throw new IllegalArgumentException("Cannot instanciate binder type in " +
-                        mContext.getResources().getResourceEntryName(mId) + ": " + type, e);
-            } catch (IllegalAccessException e) {
-                throw new IllegalArgumentException("Cannot instanciate binder type in " +
-                        mContext.getResources().getResourceEntryName(mId) + ": " + type, e);
-            }
-
-            return null;
-        }
-
-        private void findMap(MapTransformation transformation, boolean drawable) {
-            Resources resources = mResources;
-
-            TypedArray a = resources.obtainAttributes(mAttrs,
-                    android.R.styleable.CursorAdapter_MapItem);
-
-            String from = a.getString(android.R.styleable.CursorAdapter_MapItem_fromValue);
-            if (from == null) {
-                throw new IllegalArgumentException("A map item in " +
-                        resources.getResourceEntryName(mId) +
-                        " does not have a 'fromValue' attribute");
-            }
-
-            if (!drawable) {
-                String to = a.getString(android.R.styleable.CursorAdapter_MapItem_toValue);
-                if (to == null) {
-                    throw new IllegalArgumentException("A map item in " +
-                            resources.getResourceEntryName(mId) +
-                            " does not have a 'toValue' attribute");
-                }
-                transformation.addStringMapping(from, to);
-            } else {
-                int to = a.getResourceId(android.R.styleable.CursorAdapter_MapItem_toValue, 0);
-                if (to == 0) {
-                    throw new IllegalArgumentException("A map item in " +
-                            resources.getResourceEntryName(mId) +
-                            " does not have a 'toValue' attribute");
-                }
-                transformation.addResourceMapping(from, to);
-            }
-
-            a.recycle();
-        }
-
-        private CursorTransformation findTransformation() {
-            Resources resources = mResources;
-            CursorTransformation transformation = null;
-            TypedArray a = resources.obtainAttributes(mAttrs,
-                    android.R.styleable.CursorAdapter_TransformItem);
-
-            String className = a.getString(android.R.styleable.CursorAdapter_TransformItem_withClass);
-            if (className == null) {
-                String expression = a.getString(
-                        android.R.styleable.CursorAdapter_TransformItem_withExpression);
-                transformation = createExpressionTransformation(expression);
-            } else if (!mContext.isRestricted()) {
-                try {
-                    final Class<?> klas = Class.forName(className, true, mContext.getClassLoader());
-                    if (CursorTransformation.class.isAssignableFrom(klas)) {
-                        final Constructor<?> c = klas.getDeclaredConstructor(Context.class);
-                        transformation = (CursorTransformation) c.newInstance(mContext);
-                    }
-                } catch (ClassNotFoundException e) {
-                    throw new IllegalArgumentException("Cannot instanciate transform type in " +
-                           mContext.getResources().getResourceEntryName(mId) + ": " + className, e);
-                } catch (NoSuchMethodException e) {
-                    throw new IllegalArgumentException("Cannot instanciate transform type in " +
-                           mContext.getResources().getResourceEntryName(mId) + ": " + className, e);
-                } catch (InvocationTargetException e) {
-                    throw new IllegalArgumentException("Cannot instanciate transform type in " +
-                           mContext.getResources().getResourceEntryName(mId) + ": " + className, e);
-                } catch (InstantiationException e) {
-                    throw new IllegalArgumentException("Cannot instanciate transform type in " +
-                           mContext.getResources().getResourceEntryName(mId) + ": " + className, e);
-                } catch (IllegalAccessException e) {
-                    throw new IllegalArgumentException("Cannot instanciate transform type in " +
-                           mContext.getResources().getResourceEntryName(mId) + ": " + className, e);
-                }
-            }
-
-            a.recycle();
-
-            if (transformation == null) {
-                throw new IllegalArgumentException("A transform item in " +
-                    resources.getResourceEntryName(mId) + " must have a 'withClass' or " +
-                    "'withExpression' attribute");
-            }
-
-            return transformation;
-        }
-
-        private CursorTransformation createExpressionTransformation(String expression) {
-            return new ExpressionTransformation(mContext, expression);
-        }
-    }
-
-    /**
-     * Interface used by adapters that require to be loaded after creation.
-     */
-    private static interface ManagedAdapter {
-        /**
-         * Loads the content of the adapter, asynchronously.
-         */
-        void load();
-    }
-
-    /**
-     * Implementation of a Cursor adapter defined in XML. This class is a thin wrapper
-     * of a SimpleCursorAdapter. The main difference is the ability to handle CursorBinders.
-     */
-    private static class XmlCursorAdapter extends SimpleCursorAdapter implements ManagedAdapter {
-        private String mUri;
-        private final String mSelection;
-        private final String[] mSelectionArgs;
-        private final String mSortOrder;
-        private final String[] mColumns;
-        private final CursorBinder[] mBinders;
-        private AsyncTask<Void,Void,Cursor> mLoadTask;
-
-        XmlCursorAdapter(Context context, int layout, String uri, String[] from, int[] to,
-                String selection, String[] selectionArgs, String sortOrder,
-                HashMap<String, CursorBinder> binders) {
-
-            super(context, layout, null, from, to);
-            mContext = context;
-            mUri = uri;
-            mSelection = selection;
-            mSelectionArgs = selectionArgs;
-            mSortOrder = sortOrder;
-            mColumns = new String[from.length + 1];
-            // This is mandatory in CursorAdapter
-            mColumns[0] = "_id";
-            System.arraycopy(from, 0, mColumns, 1, from.length);
-
-            CursorBinder basic = new StringBinder(context, new IdentityTransformation(context));
-            final int count = from.length;
-            mBinders = new CursorBinder[count];
-
-            for (int i = 0; i < count; i++) {
-                CursorBinder binder = binders.get(from[i]);
-                if (binder == null) binder = basic;
-                mBinders[i] = binder;
-            }
-        }
-
-        @Override
-        public void bindView(View view, Context context, Cursor cursor) {
-            final int count = mTo.length;
-            final int[] from = mFrom;
-            final int[] to = mTo;
-            final CursorBinder[] binders = mBinders;
-
-            for (int i = 0; i < count; i++) {
-                final View v = view.findViewById(to[i]);
-                if (v != null) {
-                    binders[i].bind(v, cursor, from[i]);
-                }
-            }
-        }
-
-        public void load() {
-            if (mUri != null) {
-                mLoadTask = new QueryTask().execute();
-            }
-        }
-
-        void setUri(String uri) {
-            mUri = uri;
-        }
-
-        @Override
-        public void changeCursor(Cursor c) {
-            if (mLoadTask != null && mLoadTask.getStatus() != QueryTask.Status.FINISHED) {
-                mLoadTask.cancel(true);
-                mLoadTask = null;
-            }
-            super.changeCursor(c);
-        }
-
-        class QueryTask extends AsyncTask<Void, Void, Cursor> {
-            @Override
-            protected Cursor doInBackground(Void... params) {
-                if (mContext instanceof Activity) {
-                    return ((Activity) mContext).managedQuery(
-                            Uri.parse(mUri), mColumns, mSelection, mSelectionArgs, mSortOrder);
-                } else {
-                    return mContext.getContentResolver().query(
-                            Uri.parse(mUri), mColumns, mSelection, mSelectionArgs, mSortOrder);
-                }
-            }
-
-            @Override
-            protected void onPostExecute(Cursor cursor) {
-                if (!isCancelled()) {
-                    XmlCursorAdapter.super.changeCursor(cursor);
-                }
-            }
-        }
-    }
-
-    /**
-     * Identity transformation, returns the content of the specified column as a String,
-     * without performing any manipulation. This is used when no transformation is specified.
-     */
-    private static class IdentityTransformation extends CursorTransformation {
-        public IdentityTransformation(Context context) {
-            super(context);
-        }
-
-        @Override
-        public String transform(Cursor cursor, int columnIndex) {
-            return cursor.getString(columnIndex);
-        }
-    }
-
-    /**
-     * An expression transformation is a simple template based replacement utility.
-     * In an expression, each segment of the form <code>{([^}]+)}</code> is replaced
-     * with the value of the column of name $1.
-     */
-    private static class ExpressionTransformation extends CursorTransformation {
-        private final ExpressionNode mFirstNode = new ConstantExpressionNode("");
-        private final StringBuilder mBuilder = new StringBuilder();
-
-        public ExpressionTransformation(Context context, String expression) {
-            super(context);
-
-            parse(expression);
-        }
-
-        private void parse(String expression) {
-            ExpressionNode node = mFirstNode;
-            int segmentStart;
-            int count = expression.length();
-
-            for (int i = 0; i < count; i++) {
-                char c = expression.charAt(i);
-                // Start a column name segment
-                segmentStart = i;
-                if (c == '{') {
-                    while (i < count && (c = expression.charAt(i)) != '}') {
-                        i++;
-                    }
-                    // We've reached the end, but the expression didn't close
-                    if (c != '}') {
-                        throw new IllegalStateException("The transform expression contains a " +
-                                "non-closed column name: " +
-                                expression.substring(segmentStart + 1, i));
-                    }
-                    node.next = new ColumnExpressionNode(expression.substring(segmentStart + 1, i));
-                } else {
-                    while (i < count && (c = expression.charAt(i)) != '{') {
-                        i++;
-                    }
-                    node.next = new ConstantExpressionNode(expression.substring(segmentStart, i));
-                    // Rewind if we've reached a column expression
-                    if (c == '{') i--;
-                }
-                node = node.next;
-            }
-        }
-
-        @Override
-        public String transform(Cursor cursor, int columnIndex) {
-            final StringBuilder builder = mBuilder;
-            builder.delete(0, builder.length());
-
-            ExpressionNode node = mFirstNode;
-            // Skip the first node
-            while ((node = node.next) != null) {
-                builder.append(node.asString(cursor));
-            }
-
-            return builder.toString();
-        }
-
-        static abstract class ExpressionNode {
-            public ExpressionNode next;
-
-            public abstract String asString(Cursor cursor);
-        }
-
-        static class ConstantExpressionNode extends ExpressionNode {
-            private final String mConstant;
-
-            ConstantExpressionNode(String constant) {
-                mConstant = constant;
-            }
-
-            @Override
-            public String asString(Cursor cursor) {
-                return mConstant;
-            }
-        }
-
-        static class ColumnExpressionNode extends ExpressionNode {
-            private final String mColumnName;
-            private Cursor mSignature;
-            private int mColumnIndex = -1;
-
-            ColumnExpressionNode(String columnName) {
-                mColumnName = columnName;
-            }
-
-            @Override
-            public String asString(Cursor cursor) {
-                if (cursor != mSignature || mColumnIndex == -1) {
-                    mColumnIndex = cursor.getColumnIndex(mColumnName);
-                    mSignature = cursor;
-                }
-
-                return cursor.getString(mColumnIndex);
-            }
-        }
-    }
-
-    /**
-     * A map transformation offers a simple mapping between specified String values
-     * to Strings or integers.
-     */
-    private static class MapTransformation extends CursorTransformation {
-        private final HashMap<String, String> mStringMappings;
-        private final HashMap<String, Integer> mResourceMappings;
-
-        public MapTransformation(Context context) {
-            super(context);
-            mStringMappings = new HashMap<String, String>();
-            mResourceMappings = new HashMap<String, Integer>();
-        }
-
-        void addStringMapping(String from, String to) {
-            mStringMappings.put(from, to);
-        }
-
-        void addResourceMapping(String from, int to) {
-            mResourceMappings.put(from, to);
-        }
-
-        @Override
-        public String transform(Cursor cursor, int columnIndex) {
-            final String value = cursor.getString(columnIndex);
-            final String transformed = mStringMappings.get(value);
-            return transformed == null ? value : transformed;
-        }
-
-        @Override
-        public int transformToResource(Cursor cursor, int columnIndex) {
-            final String value = cursor.getString(columnIndex);
-            final Integer transformed = mResourceMappings.get(value);
-            try {
-                return transformed == null ? Integer.parseInt(value) : transformed;
-            } catch (NumberFormatException e) {
-                return 0;
-            }
-        }
-    }
-
-    /**
-     * Binds a String to a TextView.
-     */
-    private static class StringBinder extends CursorBinder {
-        public StringBinder(Context context, CursorTransformation transformation) {
-            super(context, transformation);
-        }
-
-        @Override
-        public boolean bind(View view, Cursor cursor, int columnIndex) {
-            if (view instanceof TextView) {
-                final String text = mTransformation.transform(cursor, columnIndex);
-                ((TextView) view).setText(text);
-                return true;
-            }
-            return false;
-        }
-    }
-
-    /**
-     * Binds an image blob to an ImageView.
-     */
-    private static class ImageBinder extends CursorBinder {
-        public ImageBinder(Context context, CursorTransformation transformation) {
-            super(context, transformation);
-        }
-
-        @Override
-        public boolean bind(View view, Cursor cursor, int columnIndex) {
-            if (view instanceof ImageView) {
-                final byte[] data = cursor.getBlob(columnIndex);
-                ((ImageView) view).setImageBitmap(BitmapFactory.decodeByteArray(data, 0,
-                        data.length));
-                return true;
-            }
-            return false;
-        }
-    }
-
-    private static class TagBinder extends CursorBinder {
-        public TagBinder(Context context, CursorTransformation transformation) {
-            super(context, transformation);
-        }
-
-        @Override
-        public boolean bind(View view, Cursor cursor, int columnIndex) {
-            final String text = mTransformation.transform(cursor, columnIndex);
-            view.setTag(text);
-            return true;
-        }
-    }
-
-    /**
-     * Binds an image URI to an ImageView.
-     */
-    private static class ImageUriBinder extends CursorBinder {
-        public ImageUriBinder(Context context, CursorTransformation transformation) {
-            super(context, transformation);
-        }
-
-        @Override
-        public boolean bind(View view, Cursor cursor, int columnIndex) {
-            if (view instanceof ImageView) {
-                ((ImageView) view).setImageURI(Uri.parse(
-                        mTransformation.transform(cursor, columnIndex)));
-                return true;
-            }
-            return false;
-        }
-    }
-
-    /**
-     * Binds a drawable resource identifier to an ImageView.
-     */
-    private static class DrawableBinder extends CursorBinder {
-        public DrawableBinder(Context context, CursorTransformation transformation) {
-            super(context, transformation);
-        }
-
-        @Override
-        public boolean bind(View view, Cursor cursor, int columnIndex) {
-            if (view instanceof ImageView) {
-                final int resource = mTransformation.transformToResource(cursor, columnIndex);
-                if (resource == 0) return false;
-
-                ((ImageView) view).setImageResource(resource);
-                return true;
-            }
-            return false;
-        }
-    }
-}
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index e07befa..4d8d21f 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -607,10 +607,16 @@
             // special case for the back key, we do not even try to send it
             // to the drop down list but instead, consume it immediately
             if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
-                getKeyDispatcherState().startTracking(event, this);
+                KeyEvent.DispatcherState state = getKeyDispatcherState();
+                if (state != null) {
+                    state.startTracking(event, this);
+                }
                 return true;
             } else if (event.getAction() == KeyEvent.ACTION_UP) {
-                getKeyDispatcherState().handleUpEvent(event);
+                KeyEvent.DispatcherState state = getKeyDispatcherState();
+                if (state != null) {
+                    state.handleUpEvent(event);
+                }
                 if (event.isTracking() && !event.isCanceled()) {
                     dismissDropDown();
                     return true;
@@ -630,7 +636,10 @@
             // from the drop down as its content
             case KeyEvent.KEYCODE_ENTER:
             case KeyEvent.KEYCODE_DPAD_CENTER:
-                performCompletion();
+            case KeyEvent.KEYCODE_TAB:
+                if (event.hasNoModifiers()) {
+                    performCompletion();
+                }
                 return true;
             }
         }
@@ -646,7 +655,9 @@
         if (!isPopupShowing()) {
             switch(keyCode) {
             case KeyEvent.KEYCODE_DPAD_DOWN:
-                performValidation();
+                if (event.hasNoModifiers()) {
+                    performValidation();
+                }
             }
         }
 
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
new file mode 100644
index 0000000..7ef61a8
--- /dev/null
+++ b/core/java/android/widget/CalendarView.java
@@ -0,0 +1,1398 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.widget;
+
+import com.android.internal.R;
+
+import android.annotation.Widget;
+import android.app.Service;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.Style;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.text.format.DateFormat;
+import android.text.format.DateUtils;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.GestureDetector;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView.OnScrollListener;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import libcore.icu.LocaleData;
+
+/**
+ * This class is a calendar widget for displaying and selecting dates. The range
+ * of dates supported by this calendar is configurable. A user can select a date
+ * by taping on it and can scroll and fling the calendar to a desired date.
+ *
+ * @attr ref android.R.styleable#CalendarView_showWeekNumber
+ * @attr ref android.R.styleable#CalendarView_firstDayOfWeek
+ * @attr ref android.R.styleable#CalendarView_minDate
+ * @attr ref android.R.styleable#CalendarView_maxDate
+ * @attr ref android.R.styleable#CalendarView_shownWeekCount
+ * @attr ref android.R.styleable#CalendarView_selectedWeekBackgroundColor
+ * @attr ref android.R.styleable#CalendarView_focusedMonthDateColor
+ * @attr ref android.R.styleable#CalendarView_unfocusedMonthDateColor
+ * @attr ref android.R.styleable#CalendarView_weekNumberColor
+ * @attr ref android.R.styleable#CalendarView_weekSeparatorLineColor
+ * @attr ref android.R.styleable#CalendarView_selectedDateVerticalBar
+ * @attr ref android.R.styleable#CalendarView_weekDayTextAppearance
+ * @attr ref android.R.styleable#CalendarView_dateTextAppearance
+ */
+@Widget
+public class CalendarView extends FrameLayout {
+
+    /**
+     * Tag for logging.
+     */
+    private static final String LOG_TAG = CalendarView.class.getSimpleName();
+
+    /**
+     * Default value whether to show week number.
+     */
+    private static final boolean DEFAULT_SHOW_WEEK_NUMBER = true;
+
+    /**
+     * The number of milliseconds in a day.e
+     */
+    private static final long MILLIS_IN_DAY = 86400000L;
+
+    /**
+     * The number of day in a week.
+     */
+    private static final int DAYS_PER_WEEK = 7;
+
+    /**
+     * The number of milliseconds in a week.
+     */
+    private static final long MILLIS_IN_WEEK = DAYS_PER_WEEK * MILLIS_IN_DAY;
+
+    /**
+     * Affects when the month selection will change while scrolling upe
+     */
+    private static final int SCROLL_HYST_WEEKS = 2;
+
+    /**
+     * How long the GoTo fling animation should last.
+     */
+    private static final int GOTO_SCROLL_DURATION = 1000;
+
+    /**
+     * The duration of the adjustment upon a user scroll in milliseconds.
+     */
+    private static final int ADJUSTMENT_SCROLL_DURATION = 500;
+
+    /**
+     * How long to wait after receiving an onScrollStateChanged notification
+     * before acting on it.
+     */
+    private static final int SCROLL_CHANGE_DELAY = 40;
+
+    /**
+     * String for formatting the month name in the title text view.
+     */
+    private static final String FORMAT_MONTH_NAME = "MMMM, yyyy";
+
+    /**
+     * String for parsing dates.
+     */
+    private static final String DATE_FORMAT = "MM/dd/yyyy";
+
+    /**
+     * The default minimal date.
+     */
+    private static final String DEFAULT_MIN_DATE = "01/01/1900";
+
+    /**
+     * The default maximal date.
+     */
+    private static final String DEFAULT_MAX_DATE = "01/01/2100";
+
+    private static final int DEFAULT_SHOWN_WEEK_COUNT = 6;
+
+    private static final int DEFAULT_DATE_TEXT_SIZE = 14;
+
+    private static final int UNSCALED_SELECTED_DATE_VERTICAL_BAR_WIDTH = 6;
+
+    private static final int UNSCALED_WEEK_MIN_VISIBLE_HEIGHT = 12;
+
+    private static final int UNSCALED_LIST_SCROLL_TOP_OFFSET = 2;
+
+    private static final int UNSCALED_BOTTOM_BUFFER = 20;
+
+    private static final int UNSCALED_WEEK_SEPARATOR_LINE_WIDTH = 1;
+
+    private static final int DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID = -1;
+
+    private final int mWeekSeperatorLineWidth;
+
+    private final int mDateTextSize;
+
+    private final Drawable mSelectedDateVerticalBar;
+
+    private final int mSelectedDateVerticalBarWidth;
+
+    private final int mSelectedWeekBackgroundColor;
+
+    private final int mFocusedMonthDateColor;
+
+    private final int mUnfocusedMonthDateColor;
+
+    private final int mWeekSeparatorLineColor;
+
+    private final int mWeekNumberColor;
+
+    /**
+     * The top offset of the weeks list.
+     */
+    private int mListScrollTopOffset = 2;
+
+    /**
+     * The visible height of a week view.
+     */
+    private int mWeekMinVisibleHeight = 12;
+
+    /**
+     * The visible height of a week view.
+     */
+    private int mBottomBuffer = 20;
+
+    /**
+     * The number of shown weeks.
+     */
+    private int mShownWeekCount;
+
+    /**
+     * Flag whether to show the week number.
+     */
+    private boolean mShowWeekNumber;
+
+    /**
+     * The number of day per week to be shown.
+     */
+    private int mDaysPerWeek = 7;
+
+    /**
+     * The friction of the week list while flinging.
+     */
+    private float mFriction = .05f;
+
+    /**
+     * Scale for adjusting velocity of the week list while flinging.
+     */
+    private float mVelocityScale = 0.333f;
+
+    /**
+     * The adapter for the weeks list.
+     */
+    private WeeksAdapter mAdapter;
+
+    /**
+     * The weeks list.
+     */
+    private ListView mListView;
+
+    /**
+     * The name of the month to display.
+     */
+    private TextView mMonthName;
+
+    /**
+     * The header with week day names.
+     */
+    private ViewGroup mDayNamesHeader;
+
+    /**
+     * Cached labels for the week names header.
+     */
+    private String[] mDayLabels;
+
+    /**
+     * Temporary instance to avoid multiple instantiations.
+     */
+    private Calendar mTempDate = Calendar.getInstance();
+
+    /**
+     * The first day of the week.
+     */
+    private int mFirstDayOfWeek;
+
+    /**
+     * The first day of the focused month.
+     */
+    private Calendar mFirstDayOfMonth = Calendar.getInstance();
+
+    /**
+     * Which month should be displayed/highlighted [0-11].
+     */
+    private int mCurrentMonthDisplayed;
+
+    /**
+     * Used for tracking during a scroll.
+     */
+    private long mPreviousScrollPosition;
+
+    /**
+     * Used for tracking which direction the view is scrolling.
+     */
+    private boolean mIsScrollingUp = false;
+
+    /**
+     * The previous scroll state of the weeks ListView.
+     */
+    private int mPreviousScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+    /**
+     * The current scroll state of the weeks ListView.
+     */
+    private int mCurrentScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+    /**
+     * Listener for changes in the selected day.
+     */
+    private OnDateChangeListener mOnDateChangeListener;
+
+    /**
+     * Command for adjusting the position after a scroll/fling.
+     */
+    private ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable();
+
+    /**
+     * The start date of the range supported by this picker.
+     */
+    private Calendar mMinDate = Calendar.getInstance();
+
+    /**
+     * The end date of the range supported by this picker.
+     */
+    private Calendar mMaxDate = Calendar.getInstance();
+
+    /**
+     * Date format for parsing dates.
+     */
+    private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
+
+    /**
+     * The callback used to indicate the user changes the date.
+     */
+    public interface OnDateChangeListener {
+
+        /**
+         * Called upon change of the selected day.
+         *
+         * @param view The view associated with this listener.
+         * @param year The year that was set.
+         * @param month The month that was set [0-11].
+         * @param dayOfMonth The day of the month that was set.
+         */
+        public void onSelectedDayChange(CalendarView view, int year, int month, int dayOfMonth);
+    }
+
+    public CalendarView(Context context) {
+        this(context, null);
+    }
+
+    public CalendarView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CalendarView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, 0);
+
+        TypedValue calendarViewStyle = new TypedValue();
+        context.getTheme().resolveAttribute(R.attr.calendarViewStyle, calendarViewStyle, true);
+        TypedArray attributesArray = context.obtainStyledAttributes(calendarViewStyle.resourceId,
+                R.styleable.CalendarView);
+        mShowWeekNumber = attributesArray.getBoolean(R.styleable.CalendarView_showWeekNumber,
+                DEFAULT_SHOW_WEEK_NUMBER);
+        mFirstDayOfWeek = attributesArray.getInt(R.styleable.CalendarView_firstDayOfWeek,
+                LocaleData.get(Locale.getDefault()).firstDayOfWeek);
+        String minDate = attributesArray.getString(R.styleable.CalendarView_minDate);
+        if (TextUtils.isEmpty(minDate) || !parseDate(minDate, mMinDate)) {
+            parseDate(DEFAULT_MIN_DATE, mMinDate);
+        }
+        String maxDate = attributesArray.getString(R.styleable.CalendarView_maxDate);
+        if (TextUtils.isEmpty(maxDate) || !parseDate(maxDate, mMaxDate)) {
+            parseDate(DEFAULT_MAX_DATE, mMaxDate);
+        }
+        mShownWeekCount = attributesArray.getInt(R.styleable.CalendarView_shownWeekCount,
+                DEFAULT_SHOWN_WEEK_COUNT);
+        mSelectedWeekBackgroundColor = attributesArray.getColor(
+                R.styleable.CalendarView_selectedWeekBackgroundColor, 0);
+        mFocusedMonthDateColor = attributesArray.getColor(
+                R.styleable.CalendarView_focusedMonthDateColor, 0);
+        mUnfocusedMonthDateColor = attributesArray.getColor(
+                R.styleable.CalendarView_unfocusedMonthDateColor, 0);
+        mWeekSeparatorLineColor = attributesArray.getColor(
+                R.styleable.CalendarView_weekSeparatorLineColor, 0);
+        mWeekNumberColor = attributesArray.getColor(R.styleable.CalendarView_weekNumberColor, 0);
+        mSelectedDateVerticalBar = attributesArray.getDrawable(
+                R.styleable.CalendarView_selectedDateVerticalBar);
+
+        int dateTextAppearanceResId= attributesArray.getResourceId(
+                R.styleable.CalendarView_dateTextAppearance, R.style.TextAppearance_Small);
+        TypedArray dateTextAppearance = context.obtainStyledAttributes(dateTextAppearanceResId,
+                com.android.internal.R.styleable.TextAppearance);
+        mDateTextSize = dateTextAppearance.getDimensionPixelSize(
+                R.styleable.TextAppearance_textSize, DEFAULT_DATE_TEXT_SIZE);
+
+        int weekDayTextAppearanceResId = attributesArray.getResourceId(
+                R.styleable.CalendarView_weekDayTextAppearance,
+                DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID);
+        attributesArray.recycle();
+
+        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+        mWeekMinVisibleHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                UNSCALED_WEEK_MIN_VISIBLE_HEIGHT, displayMetrics);
+        mListScrollTopOffset = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                UNSCALED_LIST_SCROLL_TOP_OFFSET, displayMetrics);
+        mBottomBuffer = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                UNSCALED_BOTTOM_BUFFER, displayMetrics);
+        mSelectedDateVerticalBarWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                UNSCALED_SELECTED_DATE_VERTICAL_BAR_WIDTH, displayMetrics);
+        mWeekSeperatorLineWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                UNSCALED_WEEK_SEPARATOR_LINE_WIDTH, displayMetrics);
+
+        LayoutInflater layoutInflater = (LayoutInflater) mContext
+                .getSystemService(Service.LAYOUT_INFLATER_SERVICE);
+        View content = layoutInflater.inflate(R.layout.calendar_view, null, false);
+        addView(content);
+
+        mListView = (ListView) findViewById(R.id.list);
+        mDayNamesHeader = (ViewGroup) content.findViewById(com.android.internal.R.id.day_names);
+        mMonthName = (TextView) content.findViewById(com.android.internal.R.id.month_name);
+
+        setUpHeader(weekDayTextAppearanceResId);
+        setUpListView();
+        setUpAdapter();
+
+        // go to today now
+        mTempDate.setTimeInMillis(System.currentTimeMillis());
+        goTo(mTempDate, false, true, true);
+        invalidate();
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        mListView.setEnabled(enabled);
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return mListView.isEnabled();
+    }
+
+    /**
+     * Gets the minimal date supported by this {@link CalendarView} in milliseconds
+     * since January 1, 1970 00:00:00 in {@link TimeZone#getDefault()} time
+     * zone.
+     * <p>
+     * Note: The default minimal date is 01/01/1900.
+     * <p>
+     *
+     * @return The minimal supported date.
+     */
+    public long getMinDate() {
+        return mMinDate.getTimeInMillis();
+    }
+
+    /**
+     * Sets the minimal date supported by this {@link CalendarView} in milliseconds
+     * since January 1, 1970 00:00:00 in {@link TimeZone#getDefault()} time
+     * zone.
+     *
+     * @param minDate The minimal supported date.
+     */
+    public void setMinDate(long minDate) {
+        mTempDate.setTimeInMillis(minDate);
+        if (isSameDate(mTempDate, mMinDate)) {
+            return;
+        }
+        mMinDate.setTimeInMillis(minDate);
+        // reinitialize the adapter since its range depends on min date
+        mAdapter.init();
+        Calendar date = mAdapter.mSelectedDate;
+        if (date.before(mMinDate)) {
+            setDate(mMinDate.getTimeInMillis());
+        } else {
+            // we go to the current date to force the ListView to query its
+            // adapter for the shown views since we have changed the adapter
+            // range and the base from which the later calculates item indices
+            // note that calling setDate will not work since the date is the same
+            goTo(date, false, true, false);
+        }
+    }
+
+    /**
+     * Gets the maximal date supported by this {@link CalendarView} in milliseconds
+     * since January 1, 1970 00:00:00 in {@link TimeZone#getDefault()} time
+     * zone.
+     * <p>
+     * Note: The default maximal date is 01/01/2100.
+     * <p>
+     *
+     * @return The maximal supported date.
+     */
+    public long getMaxDate() {
+        return mMaxDate.getTimeInMillis();
+    }
+
+    /**
+     * Sets the maximal date supported by this {@link CalendarView} in milliseconds
+     * since January 1, 1970 00:00:00 in {@link TimeZone#getDefault()} time
+     * zone.
+     *
+     * @param maxDate The maximal supported date.
+     */
+    public void setMaxDate(long maxDate) {
+        mTempDate.setTimeInMillis(maxDate);
+        if (isSameDate(mTempDate, mMaxDate)) {
+            return;
+        }
+        mMaxDate.setTimeInMillis(maxDate);
+        // reinitialize the adapter since its range depends on max date
+        mAdapter.init();
+        Calendar date = mAdapter.mSelectedDate;
+        if (date.after(mMaxDate)) {
+            setDate(mMaxDate.getTimeInMillis());
+        } else {
+            // we go to the current date to force the ListView to query its
+            // adapter for the shown views since we have changed the adapter
+            // range and the base from which the later calculates item indices
+            // note that calling setDate will not work since the date is the same
+            goTo(date, false, true, false);
+        }
+    }
+
+    /**
+     * Sets whether to show the week number.
+     *
+     * @param showWeekNumber True to show the week number.
+     */
+    public void setShowWeekNumber(boolean showWeekNumber) {
+        if (mShowWeekNumber == showWeekNumber) {
+            return;
+        }
+        mShowWeekNumber = showWeekNumber;
+        mAdapter.notifyDataSetChanged();
+        setUpHeader(DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID);
+    }
+
+    /**
+     * Gets whether to show the week number.
+     *
+     * @return True if showing the week number.
+     */
+    public boolean getShowWeekNumber() {
+        return mShowWeekNumber;
+    }
+
+    /**
+     * Gets the first day of week.
+     *
+     * @return The first day of the week conforming to the {@link CalendarView}
+     *         APIs.
+     * @see Calendar#MONDAY
+     * @see Calendar#TUESDAY
+     * @see Calendar#WEDNESDAY
+     * @see Calendar#THURSDAY
+     * @see Calendar#FRIDAY
+     * @see Calendar#SATURDAY
+     * @see Calendar#SUNDAY
+     */
+    public int getFirstDayOfWeek() {
+        return mFirstDayOfWeek;
+    }
+
+    /**
+     * Sets the first day of week.
+     *
+     * @param firstDayOfWeek The first day of the week conforming to the
+     *            {@link CalendarView} APIs.
+     * @see Calendar#MONDAY
+     * @see Calendar#TUESDAY
+     * @see Calendar#WEDNESDAY
+     * @see Calendar#THURSDAY
+     * @see Calendar#FRIDAY
+     * @see Calendar#SATURDAY
+     * @see Calendar#SUNDAY
+     */
+    public void setFirstDayOfWeek(int firstDayOfWeek) {
+        if (mFirstDayOfWeek == firstDayOfWeek) {
+            return;
+        }
+        mFirstDayOfWeek = firstDayOfWeek;
+        mAdapter.init();
+        mAdapter.notifyDataSetChanged();
+        setUpHeader(DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID);
+    }
+
+    /**
+     * Sets the listener to be notified upon selected date change.
+     *
+     * @param listener The listener to be notified.
+     */
+    public void setOnDateChangeListener(OnDateChangeListener listener) {
+        mOnDateChangeListener = listener;
+    }
+
+    /**
+     * Gets the selected date in milliseconds since January 1, 1970 00:00:00 in
+     * {@link TimeZone#getDefault()} time zone.
+     *
+     * @return The selected date.
+     */
+    public long getDate() {
+        return mAdapter.mSelectedDate.getTimeInMillis();
+    }
+
+    /**
+     * Sets the selected date in milliseconds since January 1, 1970 00:00:00 in
+     * {@link TimeZone#getDefault()} time zone.
+     *
+     * @param date The selected date.
+     *
+     * @throws IllegalArgumentException of the provided date is before the
+     *        minimal or after the maximal date.
+     *
+     * @see #setDate(long, boolean, boolean)
+     * @see #setMinDate(long)
+     * @see #setMaxDate(long)
+     */
+    public void setDate(long date) {
+        setDate(date, false, false);
+    }
+
+    /**
+     * Sets the selected date in milliseconds since January 1, 1970 00:00:00 in
+     * {@link TimeZone#getDefault()} time zone.
+     *
+     * @param date The date.
+     * @param animate Whether to animate the scroll to the current date.
+     * @param center Whether to center the current date even if it is already visible.
+     *
+     * @throws IllegalArgumentException of the provided date is before the
+     *        minimal or after the maximal date.
+     *
+     * @see #setMinDate(long)
+     * @see #setMaxDate(long)
+     */
+    public void setDate(long date, boolean animate, boolean center) {
+        mTempDate.setTimeInMillis(date);
+        if (isSameDate(mTempDate, mAdapter.mSelectedDate)) {
+            return;
+        }
+        goTo(mTempDate, animate, true, center);
+    }
+
+    /**
+     * @return True if the <code>firstDate</code> is the same as the <code>
+     * secondDate</code>.
+     */
+    private boolean isSameDate(Calendar firstDate, Calendar secondDate) {
+        return (firstDate.get(Calendar.DAY_OF_YEAR) == secondDate.get(Calendar.DAY_OF_YEAR)
+                && firstDate.get(Calendar.YEAR) == secondDate.get(Calendar.YEAR));
+    }
+
+    /**
+     * Creates a new adapter if necessary and sets up its parameters.
+     */
+    private void setUpAdapter() {
+        if (mAdapter == null) {
+            mAdapter = new WeeksAdapter(getContext());
+            mAdapter.registerDataSetObserver(new DataSetObserver() {
+                @Override
+                public void onChanged() {
+                    if (mOnDateChangeListener != null) {
+                        Calendar selectedDay = mAdapter.getSelectedDay();
+                        mOnDateChangeListener.onSelectedDayChange(CalendarView.this,
+                                selectedDay.get(Calendar.YEAR),
+                                selectedDay.get(Calendar.MONTH),
+                                selectedDay.get(Calendar.DAY_OF_MONTH));
+                    }
+                }
+            });
+            mListView.setAdapter(mAdapter);
+        }
+
+        // refresh the view with the new parameters
+        mAdapter.notifyDataSetChanged();
+    }
+
+    /**
+     * Sets up the strings to be used by the header.
+     */
+    private void setUpHeader(int weekDayTextAppearanceResId) {
+        mDayLabels = new String[mDaysPerWeek];
+        for (int i = mFirstDayOfWeek, count = mFirstDayOfWeek + mDaysPerWeek; i < count; i++) {
+            int calendarDay = (i > Calendar.SATURDAY) ? i - Calendar.SATURDAY : i;
+            mDayLabels[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay,
+                    DateUtils.LENGTH_SHORTEST);
+        }
+
+        TextView label = (TextView) mDayNamesHeader.getChildAt(0);
+        if (mShowWeekNumber) {
+            label.setVisibility(View.VISIBLE);
+        } else {
+            label.setVisibility(View.GONE);
+        }
+        for (int i = 1, count = mDayNamesHeader.getChildCount(); i < count; i++) {
+            label = (TextView) mDayNamesHeader.getChildAt(i);
+            if (weekDayTextAppearanceResId > -1) {
+                label.setTextAppearance(mContext, weekDayTextAppearanceResId);
+            }
+            if (i < mDaysPerWeek + 1) {
+                label.setText(mDayLabels[i - 1]);
+                label.setVisibility(View.VISIBLE);
+            } else {
+                label.setVisibility(View.GONE);
+            }
+        }
+        mDayNamesHeader.invalidate();
+    }
+
+    /**
+     * Sets all the required fields for the list view.
+     */
+    private void setUpListView() {
+        // Configure the listview
+        mListView.setDivider(null);
+        mListView.setItemsCanFocus(true);
+        mListView.setVerticalScrollBarEnabled(false);
+        mListView.setOnScrollListener(new OnScrollListener() {
+            public void onScrollStateChanged(AbsListView view, int scrollState) {
+                CalendarView.this.onScrollStateChanged(view, scrollState);
+            }
+
+            public void onScroll(
+                    AbsListView view, int firstVisibleItem, int visibleItemCount,
+                    int totalItemCount) {
+                CalendarView.this.onScroll(view, firstVisibleItem, visibleItemCount,
+                        totalItemCount);
+            }
+        });
+        // Make the scrolling behavior nicer
+        mListView.setFriction(mFriction);
+        mListView.setVelocityScale(mVelocityScale);
+    }
+
+    /**
+     * This moves to the specified time in the view. If the time is not already
+     * in range it will move the list so that the first of the month containing
+     * the time is at the top of the view. If the new time is already in view
+     * the list will not be scrolled unless forceScroll is true. This time may
+     * optionally be highlighted as selected as well.
+     *
+     * @param date The time to move to.
+     * @param animate Whether to scroll to the given time or just redraw at the
+     *            new location.
+     * @param setSelected Whether to set the given time as selected.
+     * @param forceScroll Whether to recenter even if the time is already
+     *            visible.
+     *
+     * @throws IllegalArgumentException of the provided date is before the
+     *        range start of after the range end.
+     */
+    private void goTo(Calendar date, boolean animate, boolean setSelected, boolean forceScroll) {
+        if (date.before(mMinDate) || date.after(mMaxDate)) {
+            throw new IllegalArgumentException("Time not between " + mMinDate.getTime()
+                    + " and " + mMaxDate.getTime());
+        }
+        // Find the first and last entirely visible weeks
+        int firstFullyVisiblePosition = mListView.getFirstVisiblePosition();
+        View firstChild = mListView.getChildAt(0);
+        if (firstChild != null && firstChild.getTop() < 0) {
+            firstFullyVisiblePosition++;
+        }
+        int lastFullyVisiblePosition = firstFullyVisiblePosition + mShownWeekCount - 1;
+        if (firstChild != null && firstChild.getTop() > mBottomBuffer) {
+            lastFullyVisiblePosition--;
+        }
+        if (setSelected) {
+            mAdapter.setSelectedDay(date);
+        }
+        // Get the week we're going to
+        int position = getWeeksSinceMinDate(date);
+
+        // Check if the selected day is now outside of our visible range
+        // and if so scroll to the month that contains it
+        if (position < firstFullyVisiblePosition || position > lastFullyVisiblePosition
+                || forceScroll) {
+            mFirstDayOfMonth.setTimeInMillis(date.getTimeInMillis());
+            mFirstDayOfMonth.set(Calendar.DAY_OF_MONTH, 1);
+
+            setMonthDisplayed(mFirstDayOfMonth);
+            position = getWeeksSinceMinDate(mFirstDayOfMonth);
+
+            mPreviousScrollState = OnScrollListener.SCROLL_STATE_FLING;
+            if (animate) {
+                mListView.smoothScrollToPositionFromTop(position, mListScrollTopOffset,
+                        GOTO_SCROLL_DURATION);
+            } else {
+                mListView.setSelectionFromTop(position, mListScrollTopOffset);
+                // Perform any after scroll operations that are needed
+                onScrollStateChanged(mListView, OnScrollListener.SCROLL_STATE_IDLE);
+            }
+        } else if (setSelected) {
+            // Otherwise just set the selection
+            setMonthDisplayed(date);
+        }
+    }
+
+    /**
+     * Parses the given <code>date</code> and in case of success sets
+     * the result to the <code>outDate</code>.
+     *
+     * @return True if the date was parsed.
+     */
+    private boolean parseDate(String date, Calendar outDate) {
+        try {
+            outDate.setTime(mDateFormat.parse(date));
+            return true;
+        } catch (ParseException e) {
+            Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT);
+            return false;
+        }
+    }
+
+    /**
+     * Called when a <code>view</code> transitions to a new <code>scrollState
+     * </code>.
+     */
+    private void onScrollStateChanged(AbsListView view, int scrollState) {
+        mScrollStateChangedRunnable.doScrollStateChange(view, scrollState);
+    }
+
+    /**
+     * Updates the title and selected month if the <code>view</code> has moved to a new
+     * month.
+     */
+    private void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+            int totalItemCount) {
+        WeekView child = (WeekView) view.getChildAt(0);
+        if (child == null) {
+            return;
+        }
+
+        // Figure out where we are
+        long currScroll = view.getFirstVisiblePosition() * child.getHeight() - child.getBottom();
+
+        // If we have moved since our last call update the direction
+        if (currScroll < mPreviousScrollPosition) {
+            mIsScrollingUp = true;
+        } else if (currScroll > mPreviousScrollPosition) {
+            mIsScrollingUp = false;
+        } else {
+            return;
+        }
+
+        // Use some hysteresis for checking which month to highlight. This
+        // causes the month to transition when two full weeks of a month are
+        // visible when scrolling up, and when the first day in a month reaches
+        // the top of the screen when scrolling down.
+        int offset = child.getBottom() < mWeekMinVisibleHeight ? 1 : 0;
+        if (mIsScrollingUp) {
+            child = (WeekView) view.getChildAt(SCROLL_HYST_WEEKS + offset);
+        } else if (offset != 0) {
+            child = (WeekView) view.getChildAt(offset);
+        }
+
+        // Find out which month we're moving into
+        int month;
+        if (mIsScrollingUp) {
+            month = child.getMonthOfFirstWeekDay();
+        } else {
+            month = child.getMonthOfLastWeekDay();
+        }
+
+        // And how it relates to our current highlighted month
+        int monthDiff;
+        if (mCurrentMonthDisplayed == 11 && month == 0) {
+            monthDiff = 1;
+        } else if (mCurrentMonthDisplayed == 0 && month == 11) {
+            monthDiff = -1;
+        } else {
+            monthDiff = month - mCurrentMonthDisplayed;
+        }
+
+        // Only switch months if we're scrolling away from the currently
+        // selected month
+        if ((!mIsScrollingUp && monthDiff > 0) || (mIsScrollingUp && monthDiff < 0)) {
+            Calendar firstDay = child.getFirstDay();
+            if (mIsScrollingUp) {
+                firstDay.add(Calendar.DAY_OF_MONTH, -DAYS_PER_WEEK);
+            } else {
+                firstDay.add(Calendar.DAY_OF_MONTH, DAYS_PER_WEEK);
+            }
+            setMonthDisplayed(firstDay);
+        }
+        mPreviousScrollPosition = currScroll;
+        mPreviousScrollState = mCurrentScrollState;
+    }
+
+    /**
+     * Sets the month displayed at the top of this view based on time. Override
+     * to add custom events when the title is changed.
+     *
+     * @param calendar A day in the new focus month.
+     */
+    private void setMonthDisplayed(Calendar calendar) {
+        mMonthName.setText(DateFormat.format(FORMAT_MONTH_NAME, calendar));
+        mMonthName.invalidate();
+        mCurrentMonthDisplayed = calendar.get(Calendar.MONTH);
+        mAdapter.setFocusMonth(mCurrentMonthDisplayed);
+        // TODO Send Accessibility Event
+    }
+
+    /**
+     * @return Returns the number of weeks between the current <code>date</code>
+     *         and the <code>mMinDate</code>.
+     */
+    private int getWeeksSinceMinDate(Calendar date) {
+        if (date.before(mMinDate)) {
+            throw new IllegalArgumentException("fromDate: " + mMinDate.getTime()
+                    + " does not precede toDate: " + date.getTime());
+        }
+        int fromDateDayOfWeek = mMinDate.get(Calendar.DAY_OF_WEEK);
+        long diff = (fromDateDayOfWeek - mFirstDayOfWeek) * MILLIS_IN_DAY;
+        long refDay = mMinDate.getTimeInMillis() - diff;
+        return (int) ((date.getTimeInMillis() - refDay) / MILLIS_IN_WEEK);
+    }
+
+    /**
+     * Command responsible for acting upon scroll state changes.
+     */
+    private class ScrollStateRunnable implements Runnable {
+        private AbsListView mView;
+
+        private int mNewState;
+
+        /**
+         * Sets up the runnable with a short delay in case the scroll state
+         * immediately changes again.
+         *
+         * @param view The list view that changed state
+         * @param scrollState The new state it changed to
+         */
+        public void doScrollStateChange(AbsListView view, int scrollState) {
+            mView = view;
+            mNewState = scrollState;
+            removeCallbacks(this);
+            postDelayed(this, SCROLL_CHANGE_DELAY);
+        }
+
+        public void run() {
+            mCurrentScrollState = mNewState;
+            // Fix the position after a scroll or a fling ends
+            if (mNewState == OnScrollListener.SCROLL_STATE_IDLE
+                    && mPreviousScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
+                View child = mView.getChildAt(0);
+                if (child == null) {
+                    // The view is no longer visible, just return
+                    return;
+                }
+                int dist = child.getBottom() - mListScrollTopOffset;
+                if (dist > mListScrollTopOffset) {
+                    if (mIsScrollingUp) {
+                        mView.smoothScrollBy(dist - child.getHeight(), ADJUSTMENT_SCROLL_DURATION);
+                    } else {
+                        mView.smoothScrollBy(dist, ADJUSTMENT_SCROLL_DURATION);
+                    }
+                }
+            }
+            mPreviousScrollState = mNewState;
+        }
+    }
+
+    /**
+     * <p>
+     * This is a specialized adapter for creating a list of weeks with
+     * selectable days. It can be configured to display the week number, start
+     * the week on a given day, show a reduced number of days, or display an
+     * arbitrary number of weeks at a time.
+     * </p>
+     */
+    private class WeeksAdapter extends BaseAdapter implements OnTouchListener {
+
+        private int mSelectedWeek;
+
+        private GestureDetector mGestureDetector;
+
+        private int mFocusedMonth;
+
+        private final Calendar mSelectedDate = Calendar.getInstance();
+
+        private int mTotalWeekCount;
+
+        public WeeksAdapter(Context context) {
+            mContext = context;
+            mGestureDetector = new GestureDetector(mContext, new CalendarGestureListener());
+            init();
+        }
+
+        /**
+         * Set up the gesture detector and selected time
+         */
+        private void init() {
+            mSelectedWeek = getWeeksSinceMinDate(mSelectedDate);
+            mTotalWeekCount = getWeeksSinceMinDate(mMaxDate);
+            if (mMinDate.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek
+                || mMaxDate.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek) {
+                mTotalWeekCount++;
+            }
+        }
+
+        /**
+         * Updates the selected day and related parameters.
+         *
+         * @param selectedDay The time to highlight
+         */
+        public void setSelectedDay(Calendar selectedDay) {
+            if (selectedDay.get(Calendar.DAY_OF_YEAR) == mSelectedDate.get(Calendar.DAY_OF_YEAR)
+                    && selectedDay.get(Calendar.YEAR) == mSelectedDate.get(Calendar.YEAR)) {
+                return;
+            }
+            mSelectedDate.setTimeInMillis(selectedDay.getTimeInMillis());
+            mSelectedWeek = getWeeksSinceMinDate(mSelectedDate);
+            mFocusedMonth = mSelectedDate.get(Calendar.MONTH);
+            notifyDataSetChanged();
+        }
+
+        /**
+         * @return The selected day of month.
+         */
+        public Calendar getSelectedDay() {
+            return mSelectedDate;
+        }
+
+        @Override
+        public int getCount() {
+            return mTotalWeekCount;
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return null;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            WeekView weekView = null;
+            if (convertView != null) {
+                weekView = (WeekView) convertView;
+            } else {
+                weekView = new WeekView(mContext);
+                android.widget.AbsListView.LayoutParams params =
+                    new android.widget.AbsListView.LayoutParams(LayoutParams.WRAP_CONTENT,
+                            LayoutParams.WRAP_CONTENT);
+                weekView.setLayoutParams(params);
+                weekView.setClickable(true);
+                weekView.setOnTouchListener(this);
+            }
+
+            int selectedWeekDay = (mSelectedWeek == position) ? mSelectedDate.get(
+                    Calendar.DAY_OF_WEEK) : -1;
+            weekView.init(position, selectedWeekDay, mFocusedMonth);
+
+            return weekView;
+        }
+
+        /**
+         * Changes which month is in focus and updates the view.
+         *
+         * @param month The month to show as in focus [0-11]
+         */
+        public void setFocusMonth(int month) {
+            if (mFocusedMonth == month) {
+                return;
+            }
+            mFocusedMonth = month;
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public boolean onTouch(View v, MotionEvent event) {
+            if (mListView.isEnabled() && mGestureDetector.onTouchEvent(event)) {
+                WeekView weekView = (WeekView) v;
+                weekView.getDayFromLocation(event.getX(), mTempDate);
+                // it is possible that the touched day is outside the valid range
+                // we draw whole weeks but range end can fall not on the week end
+                if (mTempDate.before(mMinDate) || mTempDate.after(mMaxDate)) {
+                    return true;
+                }
+                onDateTapped(mTempDate);
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Maintains the same hour/min/sec but moves the day to the tapped day.
+         *
+         * @param day The day that was tapped
+         */
+        private void onDateTapped(Calendar day) {
+            setSelectedDay(day);
+            setMonthDisplayed(day);
+        }
+
+        /**
+         * This is here so we can identify single tap events and set the
+         * selected day correctly
+         */
+        class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener {
+            @Override
+            public boolean onSingleTapUp(MotionEvent e) {
+                return true;
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * This is a dynamic view for drawing a single week. It can be configured to
+     * display the week number, start the week on a given day, or show a reduced
+     * number of days. It is intended for use as a single view within a
+     * ListView. See {@link WeeksAdapter} for usage.
+     * </p>
+     */
+    private class WeekView extends View {
+
+        private final Rect mTempRect = new Rect();
+
+        private final Paint mDrawPaint = new Paint();
+
+        private final Paint mMonthNumDrawPaint = new Paint();
+
+        // Cache the number strings so we don't have to recompute them each time
+        private String[] mDayNumbers;
+
+        // Quick lookup for checking which days are in the focus month
+        private boolean[] mFocusDay;
+
+        // The first day displayed by this item
+        private Calendar mFirstDay;
+
+        // The month of the first day in this week
+        private int mMonthOfFirstWeekDay = -1;
+
+        // The month of the last day in this week
+        private int mLastWeekDayMonth = -1;
+
+        // The position of this week, equivalent to weeks since the week of Jan
+        // 1st, 1900
+        private int mWeek = -1;
+
+        // Quick reference to the width of this view, matches parent
+        private int mWidth;
+
+        // The height this view should draw at in pixels, set by height param
+        private int mHeight;
+
+        // If this view contains the selected day
+        private boolean mHasSelectedDay = false;
+
+        // Which day is selected [0-6] or -1 if no day is selected
+        private int mSelectedDay = -1;
+
+        // The number of days + a spot for week number if it is displayed
+        private int mNumCells;
+
+        // The left edge of the selected day
+        private int mSelectedLeft = -1;
+
+        // The right edge of the selected day
+        private int mSelectedRight = -1;
+
+        public WeekView(Context context) {
+            super(context);
+
+            mHeight = (mListView.getHeight() - mListView.getPaddingTop() - mListView
+                    .getPaddingBottom()) / mShownWeekCount;
+
+            // Sets up any standard paints that will be used
+            setPaintProperties();
+        }
+
+        /**
+         * Initializes this week view.
+         *
+         * @param weekNumber The number of the week this view represents. The
+         *            week number is a zero based index of the weeks since
+         *            {@link CalendarView#getMinDate()}.
+         * @param selectedWeekDay The selected day of the week from 0 to 6, -1 if no
+         *            selected day.
+         * @param focusedMonth The month that is currently in focus i.e.
+         *            highlighted.
+         */
+        public void init(int weekNumber, int selectedWeekDay, int focusedMonth) {
+            mSelectedDay = selectedWeekDay;
+            mHasSelectedDay = mSelectedDay != -1;
+            mNumCells = mShowWeekNumber ? mDaysPerWeek + 1 : mDaysPerWeek;
+            mWeek = weekNumber;
+            mTempDate.setTimeInMillis(mMinDate.getTimeInMillis());
+            mTempDate.add(Calendar.WEEK_OF_YEAR, mWeek);
+            mTempDate.setFirstDayOfWeek(mFirstDayOfWeek);
+
+            // Allocate space for caching the day numbers and focus values
+            mDayNumbers = new String[mNumCells];
+            mFocusDay = new boolean[mNumCells];
+
+            // If we're showing the week number calculate it based on Monday
+            int i = 0;
+            if (mShowWeekNumber) {
+                mDayNumbers[0] = Integer.toString(mTempDate.get(Calendar.WEEK_OF_YEAR));
+                i++;
+            }
+
+            // Now adjust our starting day based on the start day of the week
+            int diff = mFirstDayOfWeek - mTempDate.get(Calendar.DAY_OF_WEEK);
+            mTempDate.add(Calendar.DAY_OF_MONTH, diff);
+
+            mFirstDay = (Calendar) mTempDate.clone();
+            mMonthOfFirstWeekDay = mTempDate.get(Calendar.MONTH);
+
+            for (; i < mNumCells; i++) {
+                mFocusDay[i] = (mTempDate.get(Calendar.MONTH) == focusedMonth);
+                // do not draw dates outside the valid range to avoid user confusion
+                if (mTempDate.before(mMinDate) || mTempDate.after(mMaxDate)) {
+                    mDayNumbers[i] = "";
+                } else {
+                    mDayNumbers[i] = Integer.toString(mTempDate.get(Calendar.DAY_OF_MONTH));
+                }
+                mTempDate.add(Calendar.DAY_OF_MONTH, 1);
+            }
+            // We do one extra add at the end of the loop, if that pushed us to
+            // new month undo it
+            if (mTempDate.get(Calendar.DAY_OF_MONTH) == 1) {
+                mTempDate.add(Calendar.DAY_OF_MONTH, -1);
+            }
+            mLastWeekDayMonth = mTempDate.get(Calendar.MONTH);
+
+            updateSelectionPositions();
+        }
+
+        /**
+         * Sets up the text and style properties for painting.
+         */
+        private void setPaintProperties() {
+            mDrawPaint.setFakeBoldText(false);
+            mDrawPaint.setAntiAlias(true);
+            mDrawPaint.setTextSize(mDateTextSize);
+            mDrawPaint.setStyle(Style.FILL);
+
+            mMonthNumDrawPaint.setFakeBoldText(true);
+            mMonthNumDrawPaint.setAntiAlias(true);
+            mMonthNumDrawPaint.setTextSize(mDateTextSize);
+            mMonthNumDrawPaint.setColor(mFocusedMonthDateColor);
+            mMonthNumDrawPaint.setStyle(Style.FILL);
+            mMonthNumDrawPaint.setTextAlign(Align.CENTER);
+        }
+
+        /**
+         * Returns the month of the first day in this week.
+         *
+         * @return The month the first day of this view is in.
+         */
+        public int getMonthOfFirstWeekDay() {
+            return mMonthOfFirstWeekDay;
+        }
+
+        /**
+         * Returns the month of the last day in this week
+         *
+         * @return The month the last day of this view is in
+         */
+        public int getMonthOfLastWeekDay() {
+            return mLastWeekDayMonth;
+        }
+
+        /**
+         * Returns the first day in this view.
+         *
+         * @return The first day in the view.
+         */
+        public Calendar getFirstDay() {
+            return mFirstDay;
+        }
+
+        /**
+         * Calculates the day that the given x position is in, accounting for
+         * week number. Returns a Time referencing that day or null if
+         *
+         * @param x The x position of the touch eventy
+         */
+        public void getDayFromLocation(float x, Calendar outCalendar) {
+            int dayStart = mShowWeekNumber ? mWidth / mNumCells : 0;
+            if (x < dayStart || x > mWidth) {
+                outCalendar.clear();
+                return;
+            }
+            // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels
+            int dayPosition = (int) ((x - dayStart) * mDaysPerWeek
+                    / (mWidth - dayStart));
+            outCalendar.setTimeInMillis(mFirstDay.getTimeInMillis());
+            outCalendar.add(Calendar.DAY_OF_MONTH, dayPosition);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            drawBackground(canvas);
+            drawWeekNumbers(canvas);
+            drawWeekSeparators(canvas);
+            drawSelectedDateVerticalBars(canvas);
+        }
+
+        /**
+         * This draws the selection highlight if a day is selected in this week.
+         *
+         * @param canvas The canvas to draw on
+         */
+        private void drawBackground(Canvas canvas) {
+            if (!mHasSelectedDay) {
+                return;
+            }
+            mDrawPaint.setColor(mSelectedWeekBackgroundColor);
+
+            mTempRect.top = mWeekSeperatorLineWidth;
+            mTempRect.bottom = mHeight;
+            mTempRect.left = mShowWeekNumber ? mWidth / mNumCells : 0;
+            mTempRect.right = mSelectedLeft - 2;
+            canvas.drawRect(mTempRect, mDrawPaint);
+
+            mTempRect.left = mSelectedRight + 3;
+            mTempRect.right = mWidth;
+            canvas.drawRect(mTempRect, mDrawPaint);
+        }
+
+        /**
+         * Draws the week and month day numbers for this week.
+         *
+         * @param canvas The canvas to draw on
+         */
+        private void drawWeekNumbers(Canvas canvas) {
+            float textHeight = mDrawPaint.getTextSize();
+            int y = (int) ((mHeight + textHeight) / 2) - mWeekSeperatorLineWidth;
+            int nDays = mNumCells;
+
+            mDrawPaint.setTextAlign(Align.CENTER);
+            int i = 0;
+            int divisor = 2 * nDays;
+            if (mShowWeekNumber) {
+                mDrawPaint.setColor(mWeekNumberColor);
+                int x = mWidth / divisor;
+                canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
+                i++;
+            }
+            for (; i < nDays; i++) {
+                mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
+                        : mUnfocusedMonthDateColor);
+                int x = (2 * i + 1) * mWidth / divisor;
+                canvas.drawText(mDayNumbers[i], x, y, mMonthNumDrawPaint);
+            }
+        }
+
+        /**
+         * Draws a horizontal line for separating the weeks.
+         *
+         * @param canvas The canvas to draw on.
+         */
+        private void drawWeekSeparators(Canvas canvas) {
+            // If it is the topmost fully visible child do not draw separator line
+            int firstFullyVisiblePosition = mListView.getFirstVisiblePosition();
+            if (mListView.getChildAt(0).getTop() < 0) {
+                firstFullyVisiblePosition++;
+            }
+            if (firstFullyVisiblePosition == mWeek) {
+                return;
+            }
+            mDrawPaint.setColor(mWeekSeparatorLineColor);
+            mDrawPaint.setStrokeWidth(mWeekSeperatorLineWidth);
+            float x = mShowWeekNumber ? mWidth / mNumCells : 0;
+            canvas.drawLine(x, 0, mWidth, 0, mDrawPaint);
+        }
+
+        /**
+         * Draws the selected date bars if this week has a selected day.
+         *
+         * @param canvas The canvas to draw on
+         */
+        private void drawSelectedDateVerticalBars(Canvas canvas) {
+            if (!mHasSelectedDay) {
+                return;
+            }
+            mSelectedDateVerticalBar.setBounds(mSelectedLeft - mSelectedDateVerticalBarWidth / 2,
+                    mWeekSeperatorLineWidth,
+                    mSelectedLeft + mSelectedDateVerticalBarWidth / 2, mHeight);
+            mSelectedDateVerticalBar.draw(canvas);
+            mSelectedDateVerticalBar.setBounds(mSelectedRight - mSelectedDateVerticalBarWidth / 2,
+                    mWeekSeperatorLineWidth,
+                    mSelectedRight + mSelectedDateVerticalBarWidth / 2, mHeight);
+            mSelectedDateVerticalBar.draw(canvas);
+        }
+
+        @Override
+        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+            mWidth = w;
+            updateSelectionPositions();
+        }
+
+        /**
+         * This calculates the positions for the selected day lines.
+         */
+        private void updateSelectionPositions() {
+            if (mHasSelectedDay) {
+                int selectedPosition = mSelectedDay - mFirstDayOfWeek;
+                if (selectedPosition < 0) {
+                    selectedPosition += 7;
+                }
+                if (mShowWeekNumber) {
+                    selectedPosition++;
+                }
+                mSelectedLeft = selectedPosition * mWidth / mNumCells;
+                mSelectedRight = (selectedPosition + 1) * mWidth / mNumCells;
+            }
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mHeight);
+        }
+    }
+}
diff --git a/core/java/android/widget/CursorAdapter.java b/core/java/android/widget/CursorAdapter.java
index 4cf8785..516162a 100644
--- a/core/java/android/widget/CursorAdapter.java
+++ b/core/java/android/widget/CursorAdapter.java
@@ -67,7 +67,7 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
-    protected DataSetObserver mDataSetObserver = new MyDataSetObserver();
+    protected DataSetObserver mDataSetObserver;
     /**
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
@@ -81,54 +81,81 @@
 
     /**
      * If set the adapter will call requery() on the cursor whenever a content change
-     * notification is delivered. Implies {@link #FLAG_REGISTER_CONTENT_OBSERVER}
+     * notification is delivered. Implies {@link #FLAG_REGISTER_CONTENT_OBSERVER}.
+     *
+     * @deprecated This option is discouraged, as it results in Cursor queries
+     * being performed on the application's UI thread and thus can cause poor
+     * responsiveness or even Application Not Responding errors.  As an alternative,
+     * use {@link android.app.LoaderManager} with a {@link android.content.CursorLoader}.
      */
+    @Deprecated
     public static final int FLAG_AUTO_REQUERY = 0x01;
 
     /**
      * If set the adapter will register a content observer on the cursor and will call
-     * {@link #onContentChanged()} when a notification comes in.
+     * {@link #onContentChanged()} when a notification comes in.  Be careful when
+     * using this flag: you will need to unset the current Cursor from the adapter
+     * to avoid leaks due to its registered observers.  This flag is not needed
+     * when using a CursorAdapter with a
+     * {@link android.content.CursorLoader}.
      */
     public static final int FLAG_REGISTER_CONTENT_OBSERVER = 0x02;
 
     /**
-     * Constructor. The adapter will call requery() on the cursor whenever
-     * it changes so that the most recent data is always displayed.
+     * Constructor that always enables auto-requery.
+     *
+     * @deprecated This option is discouraged, as it results in Cursor queries
+     * being performed on the application's UI thread and thus can cause poor
+     * responsiveness or even Application Not Responding errors.  As an alternative,
+     * use {@link android.app.LoaderManager} with a {@link android.content.CursorLoader}.
      *
      * @param c The cursor from which to get the data.
      * @param context The context
      */
+    @Deprecated
     public CursorAdapter(Context context, Cursor c) {
         init(context, c, FLAG_AUTO_REQUERY);
     }
 
     /**
-     * Constructor
+     * Constructor that allows control over auto-requery.  It is recommended
+     * you not use this, but instead {@link #CursorAdapter(Context, Cursor, int)}.
+     * When using this constructor, {@link #FLAG_REGISTER_CONTENT_OBSERVER}
+     * will always be set.
+     *
      * @param c The cursor from which to get the data.
      * @param context The context
      * @param autoRequery If true the adapter will call requery() on the
      *                    cursor whenever it changes so the most recent
-     *                    data is always displayed.
+     *                    data is always displayed.  Using true here is discouraged.
      */
     public CursorAdapter(Context context, Cursor c, boolean autoRequery) {
         init(context, c, autoRequery ? FLAG_AUTO_REQUERY : FLAG_REGISTER_CONTENT_OBSERVER);
     }
 
     /**
-     * Constructor
+     * Recommended constructor.
+     *
      * @param c The cursor from which to get the data.
      * @param context The context
-     * @param flags flags used to determine the behavior of the adapter
+     * @param flags Flags used to determine the behavior of the adapter; may
+     * be any combination of {@link #FLAG_AUTO_REQUERY} and
+     * {@link #FLAG_REGISTER_CONTENT_OBSERVER}.
      */
     public CursorAdapter(Context context, Cursor c, int flags) {
         init(context, c, flags);
     }
 
+    /**
+     * @deprecated Don't use this, use the normal constructor.  This will
+     * be removed in the future.
+     */
+    @Deprecated
     protected void init(Context context, Cursor c, boolean autoRequery) {
         init(context, c, autoRequery ? FLAG_AUTO_REQUERY : FLAG_REGISTER_CONTENT_OBSERVER);
     }
 
-    protected void init(Context context, Cursor c, int flags) {
+    void init(Context context, Cursor c, int flags) {
         if ((flags & FLAG_AUTO_REQUERY) == FLAG_AUTO_REQUERY) {
             flags |= FLAG_REGISTER_CONTENT_OBSERVER;
             mAutoRequery = true;
@@ -142,13 +169,15 @@
         mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1;
         if ((flags & FLAG_REGISTER_CONTENT_OBSERVER) == FLAG_REGISTER_CONTENT_OBSERVER) {
             mChangeObserver = new ChangeObserver();
+            mDataSetObserver = new MyDataSetObserver();
         } else {
             mChangeObserver = null;
+            mDataSetObserver = null;
         }
 
         if (cursorPresent) {
             if (mChangeObserver != null) c.registerContentObserver(mChangeObserver);
-            c.registerDataSetObserver(mDataSetObserver);
+            if (mDataSetObserver != null) c.registerDataSetObserver(mDataSetObserver);
         }
     }
 
@@ -275,22 +304,39 @@
      * Change the underlying cursor to a new cursor. If there is an existing cursor it will be
      * closed.
      * 
-     * @param cursor the new cursor to be used
+     * @param cursor The new cursor to be used
      */
     public void changeCursor(Cursor cursor) {
-        if (cursor == mCursor) {
-            return;
+        Cursor old = swapCursor(cursor);
+        if (old != null) {
+            old.close();
         }
-        if (mCursor != null) {
-            if (mChangeObserver != null) mCursor.unregisterContentObserver(mChangeObserver);
-            mCursor.unregisterDataSetObserver(mDataSetObserver);
-            mCursor.close();
+    }
+
+    /**
+     * Swap in a new Cursor, returning the old Cursor.  Unlike
+     * {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em>
+     * closed.
+     *
+     * @param newCursor The new cursor to be used.
+     * @return Returns the previously set Cursor, or null if there wasa not one.
+     * If the given new Cursor is the same instance is the previously set
+     * Cursor, null is also returned.
+     */
+    public Cursor swapCursor(Cursor newCursor) {
+        if (newCursor == mCursor) {
+            return null;
         }
-        mCursor = cursor;
-        if (cursor != null) {
-            if (mChangeObserver != null) cursor.registerContentObserver(mChangeObserver);
-            cursor.registerDataSetObserver(mDataSetObserver);
-            mRowIDColumn = cursor.getColumnIndexOrThrow("_id");
+        Cursor oldCursor = mCursor;
+        if (oldCursor != null) {
+            if (mChangeObserver != null) oldCursor.unregisterContentObserver(mChangeObserver);
+            if (mDataSetObserver != null) oldCursor.unregisterDataSetObserver(mDataSetObserver);
+        }
+        mCursor = newCursor;
+        if (newCursor != null) {
+            if (mChangeObserver != null) newCursor.registerContentObserver(mChangeObserver);
+            if (mDataSetObserver != null) newCursor.registerDataSetObserver(mDataSetObserver);
+            mRowIDColumn = newCursor.getColumnIndexOrThrow("_id");
             mDataValid = true;
             // notify the observers about the new cursor
             notifyDataSetChanged();
@@ -300,6 +346,7 @@
             // notify the observers about the lack of a data set
             notifyDataSetInvalidated();
         }
+        return oldCursor;
     }
 
     /**
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index e98c0bd..dbcf1e9 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -23,56 +23,98 @@
 import android.content.res.TypedArray;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 import android.text.format.DateFormat;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
-import android.widget.NumberPicker.OnChangeListener;
+import android.widget.NumberPicker.OnValueChangedListener;
 
+import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Locale;
+import java.util.TimeZone;
 
 /**
- * A view for selecting a month / year / day based on a calendar like layout.
+ * This class is a widget for selecting a date. The date can be selected by a
+ * year, month, and day spinners or a {@link CalendarView}. The set of spinners
+ * and the calendar view are automatically synchronized. The client can
+ * customize whether only the spinners, or only the calendar view, or both to be
+ * displayed. Also the minimal and maximal date from which dates to be selected
+ * can be customized.
  * <p>
  * See the <a href="{@docRoot}
  * resources/tutorials/views/hello-datepicker.html">Date Picker tutorial</a>.
  * </p>
+ * <p>
  * For a dialog using this view, see {@link android.app.DatePickerDialog}.
+ * </p>
+ *
+ * @attr ref android.R.styleable#DatePicker_startYear
+ * @attr ref android.R.styleable#DatePicker_endYear
+ * @attr ref android.R.styleable#DatePicker_maxDate
+ * @attr ref android.R.styleable#DatePicker_minDate
+ * @attr ref android.R.styleable#DatePicker_spinnersShown
+ * @attr ref android.R.styleable#DatePicker_calendarViewShown
  */
 @Widget
 public class DatePicker extends FrameLayout {
 
+    private static final String LOG_TAG = DatePicker.class.getSimpleName();
+
+    private static final String DATE_FORMAT = "MM/dd/yyyy";
+
     private static final int DEFAULT_START_YEAR = 1900;
 
     private static final int DEFAULT_END_YEAR = 2100;
 
-    private final NumberPicker mDayPicker;
+    private static final boolean DEFAULT_CALENDAR_VIEW_SHOWN = true;
 
-    private final NumberPicker mMonthPicker;
+    private static final boolean DEFAULT_SPINNERS_SHOWN = true;
 
-    private final NumberPicker mYearPicker;
+    private static final boolean DEFAULT_ENABLED_STATE = true;
 
-    private final DayPicker mMiniMonthDayPicker;
+    private final NumberPicker mDaySpinner;
+
+    private final LinearLayout mSpinners;
+
+    private final NumberPicker mMonthSpinner;
+
+    private final NumberPicker mYearSpinner;
+
+    private final CalendarView mCalendarView;
 
     private OnDateChangedListener mOnDateChangedListener;
 
     private Locale mMonthLocale;
 
-    private final Calendar mTempCalendar = Calendar.getInstance();
+    private final Calendar mTempDate = Calendar.getInstance();
 
-    private final int mNumberOfMonths = mTempCalendar.getActualMaximum(Calendar.MONTH) + 1;
+    private final int mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
 
     private final String[] mShortMonths = new String[mNumberOfMonths];
 
+    private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
+
+    private final Calendar mMinDate = Calendar.getInstance();
+
+    private final Calendar mMaxDate = Calendar.getInstance();
+
+    private final Calendar mCurrentDate = Calendar.getInstance();
+
+    private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
+
     /**
-     * The callback used to indicate the user changes the date.
+     * The callback used to indicate the user changes\d the date.
      */
     public interface OnDateChangedListener {
 
         /**
+         * Called upon a date change.
+         *
          * @param view The view associated with this listener.
          * @param year The year that was set.
          * @param monthOfYear The month that was set (0-11) for compatibility
@@ -93,74 +135,227 @@
     public DatePicker(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
+        TypedArray attributesArray = context.obtainStyledAttributes(attrs, R.styleable.DatePicker);
+        boolean spinnersShown = attributesArray.getBoolean(R.styleable.DatePicker_spinnersShown,
+                DEFAULT_SPINNERS_SHOWN);
+        boolean calendarViewShown = attributesArray.getBoolean(
+                R.styleable.DatePicker_calendarViewShown, DEFAULT_CALENDAR_VIEW_SHOWN);
+        int startYear = attributesArray
+                .getInt(R.styleable.DatePicker_startYear, DEFAULT_START_YEAR);
+        int endYear = attributesArray.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
+        String minDate = attributesArray.getString(R.styleable.DatePicker_minDate);
+        String maxDate = attributesArray.getString(R.styleable.DatePicker_maxDate);
+        attributesArray.recycle();
+
         LayoutInflater inflater = (LayoutInflater) context
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         inflater.inflate(R.layout.date_picker, this, true);
 
-        OnChangeListener onChangeListener = new OnChangeListener() {
-            public void onChange(NumberPicker picker, int oldVal, int newVal) {
-                updateDateUnchecked(mYearPicker.getCurrent(), mMonthPicker.getCurrent(),
-                        mDayPicker.getCurrent());
+        OnValueChangedListener onChangeListener = new OnValueChangedListener() {
+            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
+                updateDate(mYearSpinner.getValue(), mMonthSpinner.getValue(), mDaySpinner
+                        .getValue());
             }
         };
 
-        // day
-        mDayPicker = (NumberPicker) findViewById(R.id.day);
-        mDayPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
-        mDayPicker.setOnLongPressUpdateInterval(100);
-        mDayPicker.setOnChangeListener(onChangeListener);
+        mSpinners = (LinearLayout) findViewById(R.id.pickers);
 
-        // month
-        mMonthPicker = (NumberPicker) findViewById(R.id.month);
-        mMonthPicker.setRange(0, mNumberOfMonths - 1, getShortMonths());
-        mMonthPicker.setOnLongPressUpdateInterval(200);
-        mMonthPicker.setOnChangeListener(onChangeListener);
-
-        // year
-        mYearPicker = (NumberPicker) findViewById(R.id.year);
-        mYearPicker.setOnLongPressUpdateInterval(100);
-        mYearPicker.setOnChangeListener(onChangeListener);
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker);
-        int mStartYear = a.getInt(R.styleable.DatePicker_startYear, DEFAULT_START_YEAR);
-        int mEndYear = a.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
-        mYearPicker.setRange(mStartYear, mEndYear);
-        a.recycle();
-
-        // mini-month day-picker
-        mMiniMonthDayPicker = (DayPicker) findViewById(R.id.mini_month_day_picker);
-        mTempCalendar.clear();
-        mTempCalendar.set(mStartYear, 0, 1);
-        Calendar endRangeDate = (Calendar) mTempCalendar.clone();
-        endRangeDate.set(mEndYear, 11, 31);
-        mMiniMonthDayPicker.setRange(mTempCalendar, endRangeDate);
-        mMiniMonthDayPicker.setOnDateChangeListener(new DayPicker.OnSelectedDayChangeListener() {
-            public void onSelectedDayChange(DayPicker view, int year, int month, int monthDay) {
-                updateDateUnchecked(year, month, monthDay);
+        // calendar view day-picker
+        mCalendarView = (CalendarView) findViewById(R.id.calendar_view);
+        mCalendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
+            public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) {
+                updateDate(year, month, monthDay);
             }
         });
-        
-        // initialize to current date
-        mTempCalendar.setTimeInMillis(System.currentTimeMillis());
-        init(mTempCalendar.get(Calendar.YEAR), mTempCalendar.get(Calendar.MONTH),
-                mTempCalendar.get(Calendar.DAY_OF_MONTH), null);
 
-        // re-order the number pickers to match the current date format
-        reorderPickers();
+        // day
+        mDaySpinner = (NumberPicker) findViewById(R.id.day);
+        mDaySpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+        mDaySpinner.setOnLongPressUpdateInterval(100);
+        mDaySpinner.setOnValueChangedListener(onChangeListener);
+
+        // month
+        mMonthSpinner = (NumberPicker) findViewById(R.id.month);
+        mMonthSpinner.setMinValue(0);
+        mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
+        mMonthSpinner.setDisplayedValues(getShortMonths());
+        mMonthSpinner.setOnLongPressUpdateInterval(200);
+        mMonthSpinner.setOnValueChangedListener(onChangeListener);
+
+        // year
+        mYearSpinner = (NumberPicker) findViewById(R.id.year);
+        mYearSpinner.setOnLongPressUpdateInterval(100);
+        mYearSpinner.setOnValueChangedListener(onChangeListener);
+
+        // show only what the user required but make sure we
+        // show something and the spinners have higher priority
+        if (!spinnersShown && !calendarViewShown) {
+            setSpinnersShown(true);
+        } else {
+            setSpinnersShown(spinnersShown);
+            setCalendarViewShown(calendarViewShown);
+
+            // set the min date giving priority of the minDate over startYear
+            mTempDate.clear();
+            if (!TextUtils.isEmpty(minDate)) {
+                if (!parseDate(minDate, mTempDate)) {
+                    mTempDate.set(startYear, 0, 1);
+                }
+            } else {
+                mTempDate.set(startYear, 0, 1);
+            }
+            mMinDate.clear();
+            setMinDate(mTempDate.getTimeInMillis());
+
+            // set the max date giving priority of the minDate over startYear
+            mTempDate.clear();
+            if (!TextUtils.isEmpty(maxDate)) {
+                if (!parseDate(maxDate, mTempDate)) {
+                    mTempDate.set(endYear, 11, 31);
+                }
+            } else {
+                mTempDate.set(endYear, 11, 31);
+            }
+            mMaxDate.clear();
+            setMaxDate(mTempDate.getTimeInMillis());
+
+            // initialize to current date
+            mCurrentDate.setTimeInMillis(System.currentTimeMillis());
+            init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), mCurrentDate
+                    .get(Calendar.DAY_OF_MONTH), null);
+        }
+
+        // re-order the number spinners to match the current date format
+        reorderSpinners();
+    }
+
+    /**
+     * Gets the minimal date supported by this {@link DatePicker} in
+     * milliseconds since January 1, 1970 00:00:00 in
+     * {@link TimeZone#getDefault()} time zone.
+     * <p>
+     * Note: The default minimal date is 01/01/1900.
+     * <p>
+     *
+     * @return The minimal supported date.
+     */
+    public long getMinDate() {
+        return mCalendarView.getMinDate();
+    }
+
+    /**
+     * Sets the minimal date supported by this {@link NumberPicker} in
+     * milliseconds since January 1, 1970 00:00:00 in
+     * {@link TimeZone#getDefault()} time zone.
+     *
+     * @param minDate The minimal supported date.
+     */
+    public void setMinDate(long minDate) {
+        mTempDate.setTimeInMillis(minDate);
+        if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
+                && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
+            return;
+        }
+        mMinDate.setTimeInMillis(minDate);
+        mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
+        mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
+        mCalendarView.setMinDate(minDate);
+        updateSpinners(mYearSpinner.getValue(), mMonthSpinner.getValue(), mDaySpinner.getValue());
+    }
+
+    /**
+     * Gets the maximal date supported by this {@link DatePicker} in
+     * milliseconds since January 1, 1970 00:00:00 in
+     * {@link TimeZone#getDefault()} time zone.
+     * <p>
+     * Note: The default maximal date is 12/31/2100.
+     * <p>
+     *
+     * @return The maximal supported date.
+     */
+    public long getMaxDate() {
+        return mCalendarView.getMaxDate();
+    }
+
+    /**
+     * Sets the maximal date supported by this {@link DatePicker} in
+     * milliseconds since January 1, 1970 00:00:00 in
+     * {@link TimeZone#getDefault()} time zone.
+     *
+     * @param maxDate The maximal supported date.
+     */
+    public void setMaxDate(long maxDate) {
+        mTempDate.setTimeInMillis(maxDate);
+        if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
+                && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+            return;
+        }
+        mMaxDate.setTimeInMillis(maxDate);
+        mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
+        mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
+        mCalendarView.setMaxDate(maxDate);
+        updateSpinners(mYearSpinner.getValue(), mMonthSpinner.getValue(), mDaySpinner.getValue());
     }
 
     @Override
     public void setEnabled(boolean enabled) {
+        if (mIsEnabled == enabled) {
+            return;
+        }
         super.setEnabled(enabled);
-        mDayPicker.setEnabled(enabled);
-        mMonthPicker.setEnabled(enabled);
-        mYearPicker.setEnabled(enabled);
-        mMiniMonthDayPicker.setEnabled(enabled);
+        mDaySpinner.setEnabled(enabled);
+        mMonthSpinner.setEnabled(enabled);
+        mYearSpinner.setEnabled(enabled);
+        mCalendarView.setEnabled(enabled);
+        mIsEnabled = enabled;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return mIsEnabled;
     }
 
     /**
-     * Reorders the pickers according to the date format in the current locale.
+     * Gets whether the {@link CalendarView} is shown.
+     *
+     * @return True if the calendar view is shown.
      */
-    private void reorderPickers() {
+    public boolean getCalendarViewShown() {
+        return mCalendarView.isShown();
+    }
+
+    /**
+     * Sets whether the {@link CalendarView} is shown.
+     *
+     * @param shown True if the calendar view is to be shown.
+     */
+    public void setCalendarViewShown(boolean shown) {
+        mCalendarView.setVisibility(shown ? VISIBLE : GONE);
+    }
+
+    /**
+     * Gets whether the spinners are shown.
+     *
+     * @return True if the spinners are shown.
+     */
+    public boolean getSpinnersShown() {
+        return mSpinners.isShown();
+    }
+
+    /**
+     * Sets whether the spinners are shown.
+     *
+     * @param shown True if the spinners are to be shown.
+     */
+    public void setSpinnersShown(boolean shown) {
+        mSpinners.setVisibility(shown ? VISIBLE : GONE);
+    }
+
+    /**
+     * Reorders the spinners according to the date format in the current
+     * {@link Locale}.
+     */
+    private void reorderSpinners() {
         java.text.DateFormat format;
         String order;
 
@@ -185,10 +380,10 @@
         }
 
         /*
-         * Remove the 3 pickers from their parent and then add them back in the
+         * Remove the 3 spinners from their parent and then add them back in the
          * required order.
          */
-        LinearLayout parent = (LinearLayout) findViewById(R.id.pickers);
+        LinearLayout parent = mSpinners;
         parent.removeAllViews();
 
         boolean quoted = false;
@@ -203,13 +398,13 @@
 
             if (!quoted) {
                 if (c == DateFormat.DATE && !didDay) {
-                    parent.addView(mDayPicker);
+                    parent.addView(mDaySpinner);
                     didDay = true;
                 } else if ((c == DateFormat.MONTH || c == 'L') && !didMonth) {
-                    parent.addView(mMonthPicker);
+                    parent.addView(mMonthSpinner);
                     didMonth = true;
                 } else if (c == DateFormat.YEAR && !didYear) {
-                    parent.addView(mYearPicker);
+                    parent.addView(mYearSpinner);
                     didYear = true;
                 }
             }
@@ -217,13 +412,13 @@
 
         // Shouldn't happen, but just in case.
         if (!didMonth) {
-            parent.addView(mMonthPicker);
+            parent.addView(mMonthSpinner);
         }
         if (!didDay) {
-            parent.addView(mDayPicker);
+            parent.addView(mDaySpinner);
         }
         if (!didYear) {
-            parent.addView(mYearPicker);
+            parent.addView(mYearSpinner);
         }
     }
 
@@ -235,10 +430,12 @@
      * @param dayOfMonth The day of the month.
      */
     public void updateDate(int year, int month, int dayOfMonth) {
-        if (mYearPicker.getCurrent() != year
-                || mDayPicker.getCurrent() != dayOfMonth
-                || mMonthPicker.getCurrent() != month) {
-            updateDateUnchecked(year, month, dayOfMonth);
+        if (mCurrentDate.get(Calendar.YEAR) != year
+                || mCurrentDate.get(Calendar.MONTH) != dayOfMonth
+                || mCurrentDate.get(Calendar.DAY_OF_MONTH) != month) {
+            updateSpinners(year, month, dayOfMonth);
+            updateCalendarView();
+            notifyDateChanged();
         }
     }
 
@@ -251,20 +448,20 @@
     @Override
     protected Parcelable onSaveInstanceState() {
         Parcelable superState = super.onSaveInstanceState();
-        return new SavedState(superState, mYearPicker.getCurrent(), mMonthPicker.getCurrent(),
-                mDayPicker.getCurrent());
+        return new SavedState(superState, mYearSpinner.getValue(), mMonthSpinner.getValue(),
+                mDaySpinner.getValue());
     }
 
     @Override
     protected void onRestoreInstanceState(Parcelable state) {
         SavedState ss = (SavedState) state;
         super.onRestoreInstanceState(ss.getSuperState());
-        updatePickers(ss.mYear, ss.mMonth, ss.mDay);
+        updateSpinners(ss.mYear, ss.mMonth, ss.mDay);
     }
 
     /**
      * Initialize the state. If the provided values designate an inconsistent
-     * date the values are normalized before updating the pickers.
+     * date the values are normalized before updating the spinners.
      *
      * @param year The initial year.
      * @param monthOfYear The initial month <strong>starting from zero</strong>.
@@ -274,21 +471,25 @@
      */
     public void init(int year, int monthOfYear, int dayOfMonth,
             OnDateChangedListener onDateChangedListener) {
-        mOnDateChangedListener = onDateChangedListener;
         updateDate(year, monthOfYear, dayOfMonth);
+        // register the callback after updating the date
+        mOnDateChangedListener = onDateChangedListener;
     }
 
     /**
-     * Updates the current date.
+     * Parses the given <code>date</code> and in case of success sets the result
+     * to the <code>outDate</code>.
      *
-     * @param year The year.
-     * @param month The month which is <strong>starting from zero</strong>.
-     * @param dayOfMonth The day of the month.
+     * @return True if the date was parsed.
      */
-    private void updateDateUnchecked(int year, int month, int dayOfMonth) {
-        updatePickers(year, month, dayOfMonth);
-        updateMiniMonth();
-        notifyDateChanged();
+    private boolean parseDate(String date, Calendar outDate) {
+        try {
+            outDate.setTime(mDateFormat.parse(date));
+            return true;
+        } catch (ParseException e) {
+            Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT);
+            return false;
+        }
     }
 
     /**
@@ -309,33 +510,81 @@
     }
 
     /**
-     * Updates the pickers with the given <code>year</code>, <code>month</code>,
-     * and <code>dayOfMonth</code>. If the provided values designate an inconsistent
-     * date the values are normalized before updating the pickers.
+     * Updates the spinners with the given <code>year</code>, <code>month</code>
+     * , and <code>dayOfMonth</code>. If the provided values designate an
+     * inconsistent date the values are normalized before updating the spinners.
      */
-    private void updatePickers(int year, int month, int dayOfMonth) {
-        // larger fields are not updated and the day is adjusted without wrapping
-        mTempCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
-        mTempCalendar.roll(Calendar.MONTH, month - mTempCalendar.get(Calendar.MONTH));
-        mTempCalendar.roll(Calendar.YEAR, year - mTempCalendar.get(Calendar.YEAR));
+    private void updateSpinners(int year, int month, int dayOfMonth) {
+        // compute the deltas before modifying the current date
+        int deltaMonths = getDelataMonth(month);
+        int deltaDays = getDelataDayOfMonth(dayOfMonth);
+        mCurrentDate.set(Calendar.YEAR, year);
+        mCurrentDate.add(Calendar.MONTH, deltaMonths);
+        mCurrentDate.add(Calendar.DAY_OF_MONTH, deltaDays);
 
-        mYearPicker.setCurrent(mTempCalendar.get(Calendar.YEAR));
-        mMonthPicker.setCurrent(mTempCalendar.get(Calendar.MONTH));
-        mDayPicker.setRange(1, mTempCalendar.getActualMaximum(Calendar.DAY_OF_MONTH));
-        mDayPicker.setCurrent(mTempCalendar.get(Calendar.DAY_OF_MONTH));
+        if (mCurrentDate.before(mMinDate)) {
+            mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
+        } else if (mCurrentDate.after(mMaxDate)) {
+            mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
+        }
+
+        mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
+        mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
+        mDaySpinner.setMinValue(1);
+        mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
+        mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
     }
 
     /**
-     * Updates the mini-month with the given year, month, and day selected by the
-     * number pickers.
+     * @return The delta days of moth from the current date and the given
+     *         <code>dayOfMonth</code>.
      */
-    private void updateMiniMonth() {
-        Calendar selectedDay = mMiniMonthDayPicker.getSelectedDay();
-        if (selectedDay.get(Calendar.YEAR) != mYearPicker.getCurrent()
-                || selectedDay.get(Calendar.MONTH) != mMonthPicker.getCurrent()
-                || selectedDay.get(Calendar.DAY_OF_MONTH) != mDayPicker.getCurrent()) {
-            mMiniMonthDayPicker.goTo(mYearPicker.getCurrent(), mMonthPicker.getCurrent(),
-                    mDayPicker.getCurrent(), false, true, false);
+    private int getDelataDayOfMonth(int dayOfMonth) {
+        int prevDayOfMonth = mCurrentDate.get(Calendar.DAY_OF_MONTH);
+        if (prevDayOfMonth == dayOfMonth) {
+            return 0;
+        }
+        int maxDayOfMonth = mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH);
+        if (dayOfMonth == 1 && prevDayOfMonth == maxDayOfMonth) {
+            return 1;
+        }
+        if (dayOfMonth == maxDayOfMonth && prevDayOfMonth == 1) {
+            return -1;
+        }
+        return dayOfMonth - prevDayOfMonth;
+    }
+
+    /**
+     * @return The delta months from the current date and the given
+     *         <code>month</code>.
+     */
+    private int getDelataMonth(int month) {
+        int prevMonth = mCurrentDate.get(Calendar.MONTH);
+        if (prevMonth == month) {
+            return 0;
+        }
+        if (month == 0 && prevMonth == 11) {
+            return 1;
+        }
+        if (month == 11 && prevMonth == 0) {
+            return -1;
+        }
+        return month - prevMonth;
+    }
+
+    /**
+     * Updates the calendar view with the given year, month, and day selected by
+     * the number spinners.
+     */
+    private void updateCalendarView() {
+        mTempDate.setTimeInMillis(mCalendarView.getDate());
+        if (mTempDate.get(Calendar.YEAR) != mYearSpinner.getValue()
+                || mTempDate.get(Calendar.MONTH) != mMonthSpinner.getValue()
+                || mTempDate.get(Calendar.DAY_OF_MONTH) != mDaySpinner.getValue()) {
+            mTempDate.clear();
+            mTempDate.set(mYearSpinner.getValue(), mMonthSpinner.getValue(),
+                    mDaySpinner.getValue());
+            mCalendarView.setDate(mTempDate.getTimeInMillis(), false, false);
         }
     }
 
@@ -343,21 +592,21 @@
      * @return The selected year.
      */
     public int getYear() {
-        return mYearPicker.getCurrent();
+        return mYearSpinner.getValue();
     }
 
     /**
      * @return The selected month.
      */
     public int getMonth() {
-        return mMonthPicker.getCurrent();
+        return mMonthSpinner.getValue();
     }
 
     /**
      * @return The selected day of month.
      */
     public int getDayOfMonth() {
-        return mDayPicker.getCurrent();
+        return mDaySpinner.getValue();
     }
 
     /**
@@ -365,8 +614,8 @@
      */
     private void notifyDateChanged() {
         if (mOnDateChangedListener != null) {
-            mOnDateChangedListener.onDateChanged(DatePicker.this, mYearPicker.getCurrent(),
-                    mMonthPicker.getCurrent(), mDayPicker.getCurrent());
+            mOnDateChangedListener.onDateChanged(DatePicker.this, mYearSpinner.getValue(),
+                    mMonthSpinner.getValue(), mDaySpinner.getValue());
         }
     }
 
diff --git a/core/java/android/widget/DayPicker.java b/core/java/android/widget/DayPicker.java
deleted file mode 100644
index cdf51f7..0000000
--- a/core/java/android/widget/DayPicker.java
+++ /dev/null
@@ -1,1498 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import com.android.internal.R;
-
-import android.app.Service;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.database.DataSetObserver;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.Paint.Style;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.text.format.DateFormat;
-import android.text.format.DateUtils;
-import android.text.format.Time;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.view.GestureDetector;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AbsListView.OnScrollListener;
-
-import java.security.InvalidParameterException;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.Locale;
-
-import libcore.icu.LocaleData;
-
-/**
- * Displays a day picker in the form of a calendar. The calendar
- * is represented as a list where each row depicts a week. Each week is
- * composed of items that are selectable days.
- */
-public class DayPicker extends FrameLayout {
-
-    /**
-     * The number of milliseconds in a day.
-     *
-     * @hide
-     */
-    protected static final long MILLIS_IN_DAY = 86400000L;
-
-    /**
-     * The number of day in a week.
-     *
-     * @hide
-     */
-    protected static final int DAYS_PER_WEEK = 7;
-
-    /**
-     * The number of milliseconds in a week.
-     *
-     * @hide
-     */
-    protected static final long MILLIS_IN_WEEK = DAYS_PER_WEEK * MILLIS_IN_DAY;
-
-    /**
-     * Affects when the month selection will change while scrolling up
-     *
-     * @hide
-     */ 
-    protected static final int SCROLL_HYST_WEEKS = 2;
-
-    /**
-     * How long the GoTo fling animation should last.
-     *
-     * @hide
-     */
-    protected static final int GOTO_SCROLL_DURATION = 1000;
-
-    /**
-     * The duration of the adjustment upon a user scroll in milliseconds.
-     *
-     * @hide
-     */
-    protected static final int ADJUSTMENT_SCROLL_DURATION = 500;
-
-    /**
-     * How long to wait after receiving an onScrollStateChanged notification
-     * before acting on it.
-     *
-     * @hide
-     */
-    protected static final int SCROLL_CHANGE_DELAY = 40;
-
-    /**
-     * The scale used to compensate for different screen density.
-     *
-     * @hide
-     */
-    protected static float sScale;
-
-    /**
-     * The top offset of the weeks list.
-     *
-     * @hide
-     */
-    protected static int mListTopOffset = 2;
-
-    /**
-     * The visible height of a week view.
-     *
-     * @hide
-     */
-    protected int mWeekMinVisibleHeight = 12;
-
-
-    /**
-     * The visible height of a week view.
-     *
-     * @hide
-     */
-    protected int mBottomBuffer = 20;
-
-    /**
-     * The number of shown weeks.
-     *
-     * @hide
-     */
-    protected int mShownWeekCount = 6;
-
-    /**
-     * Flag whether to show the week number.
-     *
-     * @hide
-     */
-    protected boolean mShowWeekNumber = true;
-
-    /**
-     * The number of day per week to be shown
-     *
-     * @hide
-     */
-    protected int mDaysPerWeek = 7;
-
-    /**
-     * The friction of the week list while flinging.
-     *
-     * @hide
-     */
-    protected float mFriction = .05f;
-
-    /**
-     * Scale for adjusting velocity of the week list while flinging.
-     *
-     * @hide
-     */
-    protected float mVelocityScale = 0.333f;
-
-    /**
-     * The adapter for the weeks list.
-     *
-     * @hide
-     */
-    protected WeeksAdapter mAdapter;
-
-    /**
-     * The weeks list.
-     *
-     * @hide
-     */
-    protected ListView mListView;
-
-    /**
-     * The name of the month to display.
-     *
-     * @hide
-     */
-    protected TextView mMonthName;
-
-    /**
-     * The header with week day names.
-     *
-     * @hide
-     */
-    protected ViewGroup mDayNamesHeader;
-
-    /**
-     * Cached labels for the week names header.
-     *
-     * @hide
-     */
-    protected String[] mDayLabels;
-
-    /**
-     * Temporary instance to avoid multiple instantiations.
-     *
-     * @hide
-     */
-    protected Calendar mTempCalendar = Calendar.getInstance();
-
-    /**
-     * The first day of the week based on the current locale.
-     *
-     * @hide
-     */
-    protected int mFirstDayOfWeek = LocaleData.get(Locale.getDefault()).firstDayOfWeek;
-
-    /**
-     * The first day of the focused month.
-     *
-     * @hide
-     */
-    protected Calendar mFirstDayOfMonth = Calendar.getInstance();
-
-    /**
-     * Which month should be displayed/highlighted [0-11]
-     *
-     * @hide
-     */
-    protected int mCurrentMonthDisplayed;
-
-    /**
-     * Used for tracking during a scroll.
-     *
-     * @hide
-     */
-    protected long mPreviousScrollPosition;
-
-    /**
-     * Used for tracking which direction the view is scrolling.
-     *
-     * @hide
-     */
-    protected boolean mIsScrollingUp = false;
-
-    /**
-     * The previous scroll state of the weeks ListView.
-     *
-     * @hide
-     */
-    protected int mPreviousScrollState = OnScrollListener.SCROLL_STATE_IDLE;
-
-    /**
-     * The current scroll state of the weeks ListView.
-     *
-     * @hide
-     */
-    protected int mCurrentScrollState = OnScrollListener.SCROLL_STATE_IDLE;
-
-    /**
-     * Listener for changes in the selected day.
-     *
-     * @hide
-     */
-    protected OnSelectedDayChangeListener mOnChangeListener;
-
-    /**
-     * Command for adjusting the position after a scroll/fling.
-     *
-     * @hide
-     */
-    protected ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable();
-
-    /**
-     * The start date of the range supported by this picker.
-     *
-     * @hide
-     */
-    protected Calendar mRangeStartDate = Calendar.getInstance();
-
-    /**
-     * The end date of the range supported by this picker.
-     *
-     * @hide
-     */
-    protected Calendar mRangeEndDate = Calendar.getInstance();
-
-    /**
-     * String for formatting the month name in the title text view.
-     *
-     * @hide
-     */
-    protected String mMonthNameFormatSrting = "MMMM, yyyy";
-
-    /**
-     * The callback used to indicate the user changes the date.
-     */
-    public interface OnSelectedDayChangeListener {
-
-        /**
-         * Called upon change of the selected day.
-         *
-         * @param view The view associated with this listener.
-         * @param year The year that was set.
-         * @param month The month that was set [0-11].
-         * @param dayOfMonth The day of the month that was set.
-         */
-        public void onSelectedDayChange(DayPicker view, int year, int month, int dayOfMonth);
-    }
-
-    public DayPicker(Context context) {
-        this(context, null);
-    }
-
-    public DayPicker(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public DayPicker(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, 0);
-
-        LayoutInflater layoutInflater = (LayoutInflater) mContext
-                .getSystemService(Service.LAYOUT_INFLATER_SERVICE);
-        View content = layoutInflater.inflate(R.layout.day_picker, null, false);
-        addView(content);
-
-        mListView = (ListView) findViewById(R.id.list);
-        mDayNamesHeader = (ViewGroup) content.findViewById(com.android.internal.R.id.day_names);
-        mMonthName = (TextView) content.findViewById(com.android.internal.R.id.month_name);
-
-        // Adjust sizes for screen density
-        if (sScale == 0) {
-            sScale = mContext.getResources().getDisplayMetrics().density;
-            if (sScale != 1) {
-                mWeekMinVisibleHeight *= sScale;
-                mBottomBuffer *= sScale;
-                mListTopOffset *= sScale;
-            }
-        }
-
-        // set default range
-        mRangeStartDate.clear();
-        mRangeStartDate.set(1900, 0, 1);
-        mRangeEndDate.clear();
-        mRangeEndDate.set(2100, 0, 1);
-
-        setUpHeader();
-        updateHeader();
-        setUpListView();
-        setUpAdapter();
-
-        // go to today now
-        mTempCalendar.setTimeInMillis(System.currentTimeMillis());
-        goTo(mTempCalendar, false, true, true);
-        invalidate();
-    }
-
-    /**
-     * Sets the range supported by this day picker. This is the picker will not
-     * support dates before <code>startRangeDate</code> and <code>endRangeDate
-     * </code>.
-     *
-     * @param startRangeDate The start date.
-     * @param endRangeDate The end date.
-     */
-    public void setRange(Calendar startRangeDate, Calendar endRangeDate) {
-        boolean doSetupAdapter = false;
-        if (mRangeStartDate.get(Calendar.DAY_OF_YEAR) != startRangeDate.get(Calendar.DAY_OF_YEAR)
-                || mRangeStartDate.get(Calendar.YEAR) != startRangeDate.get(Calendar.YEAR)) {
-            mRangeStartDate.setTimeInMillis(startRangeDate.getTimeInMillis());
-            mRangeStartDate.setTimeZone(startRangeDate.getTimeZone());
-            doSetupAdapter = true;
-        }
-        if (mRangeEndDate.get(Calendar.DAY_OF_YEAR) != endRangeDate.get(Calendar.DAY_OF_YEAR)
-                || mRangeEndDate.get(Calendar.YEAR) != endRangeDate.get(Calendar.YEAR)) {
-            mRangeEndDate.setTimeInMillis(endRangeDate.getTimeInMillis());
-            mRangeEndDate.setTimeZone(endRangeDate.getTimeZone());
-            doSetupAdapter = true;
-            
-        }
-        if (doSetupAdapter) {
-            setUpAdapter();
-        }
-    }
-
-    /**
-     * Sets the listener to be notified upon day selection changes.
-     *
-     * @param listener The listener to be called back.
-     */
-    public void setOnDateChangeListener(OnSelectedDayChangeListener listener) {
-        mOnChangeListener = listener;
-    }
-
-    /**
-     * Gets the selected day.
-     *
-     * @return The selected day.
-     */
-    public Calendar getSelectedDay() {
-        return (Calendar) mAdapter.mSelectedDay.clone();
-    }
-
-    /**
-     * Sets the selected day. This is equivalent to a call to
-     * {@link #goTo(Calendar, boolean, boolean, boolean)} with
-     * the arguments <code>selectedDay</code>, <code>false</code>,
-     * <code>true</code>, <code>false</code> respectively.
-     *
-     * @param selectedDay The selected day.
-     */
-    public void setSelectedDay(Calendar selectedDay) {
-        goTo(selectedDay, false, true, false);
-    }
-
-    /**
-     * Creates a new adapter if necessary and sets up its parameters. Override
-     * this method to provide a custom adapter.
-     *
-     * @hide
-     */
-    protected void setUpAdapter() {
-        if (mAdapter == null) {
-            mAdapter = new WeeksAdapter(getContext());
-            mAdapter.registerDataSetObserver(new DataSetObserver() {
-                @Override
-                public void onChanged() {
-                    if (mOnChangeListener != null) {
-                        Calendar selectedDay = mAdapter.getSelectedDay();
-                        mOnChangeListener.onSelectedDayChange(DayPicker.this,
-                                selectedDay.get(Calendar.YEAR),
-                                selectedDay.get(Calendar.MONTH),
-                                selectedDay.get(Calendar.DAY_OF_MONTH));
-                    }
-                }
-            });
-            mListView.setAdapter(mAdapter);
-        }
-
-        // refresh the view with the new parameters
-        mAdapter.notifyDataSetChanged();
-    }
-
-    /**
-     * Sets up the strings to be used by the header. Override this method to use
-     * different strings or modify the view params.
-     *
-     * @hide
-     */
-    protected void setUpHeader() {
-        mDayLabels = new String[mDaysPerWeek];
-        for (int i = mFirstDayOfWeek, count = mFirstDayOfWeek + mDaysPerWeek; i < count; i++) {
-            int calendarDay = (i < mDaysPerWeek) ? i : 1; // Calendar.MONDAY is
-            // 1
-            mDayLabels[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay,
-                    DateUtils.LENGTH_SHORTEST);
-        }
-    }
-
-    /**
-     * Sets all the required fields for the list view. Override this method to
-     * set a different list view behavior.
-     *
-     * @hide
-     */
-    protected void setUpListView() {
-        // Configure the listview
-        mListView.setDivider(null);
-        mListView.setItemsCanFocus(true);
-        mListView.setVerticalScrollBarEnabled(false);
-        mListView.setOnScrollListener(new OnScrollListener() {
-            public void onScrollStateChanged(AbsListView view, int scrollState) {
-                DayPicker.this.onScrollStateChanged(view, scrollState);
-            }
-
-            public void onScroll(
-                    AbsListView view, int firstVisibleItem, int visibleItemCount,
-                    int totalItemCount) {
-                DayPicker.this.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
-            }
-        });
-        // Make the scrolling behavior nicer
-        mListView.setFriction(mFriction);
-        mListView.setVelocityScale(mVelocityScale);
-    }
-
-    /**
-     * Fixes the day names header to provide correct spacing and updates the
-     * label text. Override this to set up a custom header.
-     *
-     * @hide
-     */
-    protected void updateHeader() {
-        TextView label = (TextView) mDayNamesHeader.getChildAt(0);
-        if (mShowWeekNumber) {
-            label.setVisibility(View.VISIBLE);
-        } else {
-            label.setVisibility(View.GONE);
-        }
-        for (int i = 1, count = mDayNamesHeader.getChildCount(); i < count; i++) {
-            label = (TextView) mDayNamesHeader.getChildAt(i);
-            if (i < mDaysPerWeek + 1) {
-                label.setText(mDayLabels[i - 1]);
-                label.setVisibility(View.VISIBLE);
-            } else {
-                label.setVisibility(View.GONE);
-            }
-        }
-        mDayNamesHeader.invalidate();
-    }
-
-    /**
-     * This moves to the specified time in the view. If the time is not already
-     * in range it will move the list so that the first of the month containing
-     * the time is at the top of the view. If the new time is already in view
-     * the list will not be scrolled unless forceScroll is true. This time may
-     * optionally be highlighted as selected as well.
-     *
-     * @param year The year to move to.
-     * @param month The month to move to <strong>starting from zero<strong>.
-     * @param dayOfMonth The month day to move to.
-     * @param animate Whether to scroll to the given time or just redraw at the
-     *            new location.
-     * @param setSelected Whether to set the given time as selected
-     * @param forceScroll Whether to recenter even if the time is already
-     *            visible.
-     *
-     * @throws IllegalArgumentException of the provided date is before the
-     *        range start of after the range end.
-     *
-     * @see #setRange(Calendar, Calendar)
-     */
-    public void goTo(int year, int month, int dayOfMonth, boolean animate, boolean setSelected,
-            boolean forceScroll) {
-        mTempCalendar.clear();
-        mTempCalendar.set(year, month, dayOfMonth);
-        goTo(mTempCalendar, animate, setSelected, forceScroll);
-    }
-
-    /**
-     * This moves to the specified time in the view. If the time is not already
-     * in range it will move the list so that the first of the month containing
-     * the time is at the top of the view. If the new time is already in view
-     * the list will not be scrolled unless forceScroll is true. This time may
-     * optionally be highlighted as selected as well.
-     *
-     * @param date The time to move to.
-     * @param animate Whether to scroll to the given time or just redraw at the
-     *            new location.
-     * @param setSelected Whether to set the given time as selected.
-     * @param forceScroll Whether to recenter even if the time is already
-     *            visible.
-     *
-     * @throws IllegalArgumentException of the provided date is before the
-     *        range start of after the range end.
-     *
-     * @see #setRange(Calendar, Calendar)
-     */
-    public void goTo(Calendar date, boolean animate, boolean setSelected, boolean forceScroll) {
-        if (date.before(mRangeStartDate) || date.after(mRangeEndDate)) { 
-            throw new IllegalArgumentException("Time not between " + mRangeStartDate.getTime()
-                    + " and " + mRangeEndDate.getTime());
-        }
-        // Find the first and last entirely visible weeks
-        int firstFullyVisiblePosition = mListView.getFirstVisiblePosition();
-        View firstChild = mListView.getChildAt(0);
-        if (firstChild != null && firstChild.getTop() < 0) {
-            firstFullyVisiblePosition++;
-        }
-        int lastFullyVisiblePosition = firstFullyVisiblePosition + mShownWeekCount - 1;
-        if (firstChild != null && firstChild.getTop() > mBottomBuffer) {
-            lastFullyVisiblePosition--;
-        }
-        if (setSelected) {
-            mAdapter.setSelectedDay(date);
-        }
-        // Get the week we're going to
-        int position = getWeeksDelta(date);
-
-        // Check if the selected day is now outside of our visible range
-        // and if so scroll to the month that contains it
-        if (position < firstFullyVisiblePosition || position > lastFullyVisiblePosition
-                || forceScroll) {
-            mFirstDayOfMonth.setTimeInMillis(date.getTimeInMillis());
-            mFirstDayOfMonth.setTimeZone(date.getTimeZone());
-            mFirstDayOfMonth.set(Calendar.DAY_OF_MONTH, 1);
-
-            setMonthDisplayed(mFirstDayOfMonth);
-            position = getWeeksDelta(mFirstDayOfMonth);
-
-            mPreviousScrollState = OnScrollListener.SCROLL_STATE_FLING;
-            if (animate) {
-                mListView.smoothScrollToPositionFromTop(position, mListTopOffset,
-                        GOTO_SCROLL_DURATION);
-            } else {
-                mListView.setSelectionFromTop(position, mListTopOffset);
-                // Perform any after scroll operations that are needed
-                onScrollStateChanged(mListView, OnScrollListener.SCROLL_STATE_IDLE);
-            }
-        } else if (setSelected) {
-            // Otherwise just set the selection
-            setMonthDisplayed(date);
-        }
-    }
-
-    /**
-     * Called when a <code>view</code> transitions to a new <code>scrollState
-     * </code>.
-     *
-     * @hide
-     */
-    protected void onScrollStateChanged(AbsListView view, int scrollState) {
-        mScrollStateChangedRunnable.doScrollStateChange(view, scrollState);
-    }
-
-    /**
-     * Updates the title and selected month if the <code>view</code> has moved to a new
-     * month.
-     *
-     * @hide
-     */
-    protected void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
-            int totalItemCount) {
-        WeekView child = (WeekView) view.getChildAt(0);
-        if (child == null) {
-            return;
-        }
-
-        // Figure out where we are
-        int offset = child.getBottom() < mWeekMinVisibleHeight ? 1 : 0;
-        long currScroll = view.getFirstVisiblePosition() * child.getHeight() - child.getBottom();
-
-        // If we have moved since our last call update the direction
-        if (currScroll < mPreviousScrollPosition) {
-            mIsScrollingUp = true;
-        } else if (currScroll > mPreviousScrollPosition) {
-            mIsScrollingUp = false;
-        } else {
-            return;
-        }
-
-        // Use some hysteresis for checking which month to highlight. This
-        // causes the month to transition when two full weeks of a month are
-        // visible when scrolling up, and when the first day in a month reaches
-        // the top of the screen when scrolling down.
-        if (mIsScrollingUp) {
-            child = (WeekView) view.getChildAt(SCROLL_HYST_WEEKS + offset);
-        } else if (offset != 0) {
-            child = (WeekView) view.getChildAt(offset);
-        }
-
-        // Find out which month we're moving into
-        int month;
-        if (mIsScrollingUp) {
-            month = child.getMonthOfFirstWeekDay();
-        } else {
-            month = child.getMonthOfLastWeekDay();
-        }
-
-        // And how it relates to our current highlighted month
-        int monthDiff;
-        if (mCurrentMonthDisplayed == 11 && month == 0) {
-            monthDiff = 1;
-        } else if (mCurrentMonthDisplayed == 0 && month == 11) {
-            monthDiff = -1;
-        } else {
-            monthDiff = month - mCurrentMonthDisplayed;
-        }
-
-        // Only switch months if we're scrolling away from the currently
-        // selected month
-        if ((!mIsScrollingUp && monthDiff > 0) || (mIsScrollingUp && monthDiff < 0)) {
-            Calendar firstDay = child.getFirstDay();
-            if (mIsScrollingUp) {
-                firstDay.add(Calendar.DAY_OF_MONTH, -DAYS_PER_WEEK);
-            } else {
-                firstDay.add(Calendar.DAY_OF_MONTH, DAYS_PER_WEEK);
-            }
-            setMonthDisplayed(firstDay);
-        }
-        mPreviousScrollPosition = currScroll;
-        mPreviousScrollState = mCurrentScrollState;
-    }
-
-    /**
-     * Sets the month displayed at the top of this view based on time. Override
-     * to add custom events when the title is changed.
-     *
-     * @param calendar A day in the new focus month.
-     *
-     * @hide
-     */
-    protected void setMonthDisplayed(Calendar calendar) {
-        mMonthName.setText(DateFormat.format(mMonthNameFormatSrting, calendar));
-        mMonthName.invalidate();
-        mCurrentMonthDisplayed = calendar.get(Calendar.MONTH);
-        mAdapter.setFocusMonth(mCurrentMonthDisplayed);
-        // TODO Send Accessibility Event
-    }
-
-    /**
-     * @return Returns the number of weeks between the current week day of the
-     *         <code>fromDate</code> and the first day of week of
-     *         <code>toDate</code>.
-     *
-     * @hide
-     */
-    protected int getWeeksDelta(Calendar toDate) {
-        if (toDate.before(mRangeStartDate)) {
-            throw new IllegalArgumentException("fromDate: " + mRangeStartDate.getTime()
-                    + " does not precede toDate: " + toDate.getTime());
-        }
-        int fromDateDayOfWeek = mRangeStartDate.get(Calendar.DAY_OF_WEEK);
-        long diff = (fromDateDayOfWeek - toDate.getFirstDayOfWeek()) * MILLIS_IN_DAY;
-        if (diff < 0) {
-            diff = diff + MILLIS_IN_WEEK;
-        }
-        long refDay = mRangeStartDate.getTimeInMillis() - diff;
-        return (int) ((toDate.getTimeInMillis() - refDay) / MILLIS_IN_WEEK);
-    }
-
-    /**
-     * Command responsible for acting upon scroll state changes.
-     *
-     * @hide
-     */
-    protected class ScrollStateRunnable implements Runnable {
-        private AbsListView mView;
-
-        private int mNewState;
-
-        /**
-         * Sets up the runnable with a short delay in case the scroll state
-         * immediately changes again.
-         *
-         * @param view The list view that changed state
-         * @param scrollState The new state it changed to
-         */
-        public void doScrollStateChange(AbsListView view, int scrollState) {
-            removeCallbacks(this);
-            mView = view;
-            mNewState = scrollState;
-            removeCallbacks(this);
-            postDelayed(this, SCROLL_CHANGE_DELAY);
-        }
-
-        public void run() {
-            mCurrentScrollState = mNewState;
-            // Fix the position after a scroll or a fling ends
-            if (mNewState == OnScrollListener.SCROLL_STATE_IDLE
-                    && mPreviousScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
-                mPreviousScrollState = mNewState;
-                View child = mView.getChildAt(0);
-                if (child == null) {
-                    // The view is no longer visible, just return
-                    return;
-                }
-                int dist = child.getBottom() - mListTopOffset;
-                if (dist > mListTopOffset) {
-                    if (mIsScrollingUp) {
-                        mView.smoothScrollBy(dist - child.getHeight(), ADJUSTMENT_SCROLL_DURATION);
-                    } else {
-                        mView.smoothScrollBy(dist, ADJUSTMENT_SCROLL_DURATION);
-                    }
-                }
-            } else {
-                mPreviousScrollState = mNewState;
-            }
-        }
-    }
-
-    /**
-     * <p>
-     * This is a specialized adapter for creating a list of weeks with
-     * selectable days. It can be configured to display the week number, start
-     * the week on a given day, show a reduced number of days, or display an
-     * arbitrary number of weeks at a time.
-     * </p>
-     *
-     * @hide
-     */
-    public class WeeksAdapter extends BaseAdapter implements OnTouchListener {
-
-        /**
-         * The default maximum year supported by the Date Time Picker.
-         */
-        public static final int DEFAULT_MAX_CALENDAR_YEAR = 2100;
-
-        /**
-         * The default minimum year supported by the Date Time Picker.
-         */
-        public static final int DEFAULT_MIN_CALENDAR_YEAR = 1900;
-
-        /**
-         * The number of weeks to display at a time.
-         */
-        public static final String WEEK_PARAMS_NUM_WEEKS = "num_weeks";
-
-        /**
-         * Which month should be in focus currently.
-         */
-        public static final String WEEK_PARAMS_FOCUS_MONTH = "focus_month";
-
-        /**
-         * Whether the week number should be shown. Non-zero to show them.
-         */
-        public static final String WEEK_PARAMS_SHOW_WEEK = "week_numbers";
-
-        /**
-         * Which day the week should start on. {@link Time#SUNDAY} through
-         * {@link Time#SATURDAY}.
-         */
-        public static final String WEEK_PARAMS_WEEK_START = "week_start";
-
-        /**
-         * The year of the highlighted day.
-         */
-        public static final String WEEK_PARAMS_YEAR = "selected_year";
-
-        /**
-         * The month of the highlighted day.
-         */
-        public static final String WEEK_PARAMS_MONTH = "selected_month";
-
-        /**
-         * The year of the highlighted day.
-         */
-        public static final String WEEK_PARAMS_DAY_OF_MONTH = "selected_day_of_month";
-
-        /**
-         * The start date of the supported interval.
-         */
-        public static final String WEEK_PARAMS_START_DATE_RANGE_MILLIS = "start_date_gange_millis";
-
-        /**
-         * The end date of the supported interval.
-         */
-        public static final String WEEK_PARAMS_END_DATE_RANGE_MILLIS = "end_date_gange_millis";
-
-        /**
-         * How many days of the week to display [1-7].
-         */
-        public static final String WEEK_PARAMS_DAYS_PER_WEEK = "days_per_week";
-
-        protected int WEEK_7_OVERHANG_HEIGHT = 7;
-
-        protected int mSelectedWeek;
-
-        protected GestureDetector mGestureDetector;
-
-        protected int mFocusMonth = 0;
-
-        private final Calendar mSelectedDay = Calendar.getInstance();
-
-        private int mTotalWeekCount = -1;
-
-        public WeeksAdapter(Context context) {
-            mContext = context;
-
-            if (sScale == 0) {
-                sScale = context.getResources().getDisplayMetrics().density;
-                if (sScale != 1) {
-                    WEEK_7_OVERHANG_HEIGHT *= sScale;
-                }
-            }
-            init();
-        }
-
-        /**
-         * Set up the gesture detector and selected time
-         */
-        protected void init() {
-            mGestureDetector = new GestureDetector(mContext, new CalendarGestureListener());
-            mSelectedWeek = getWeeksDelta(mSelectedDay);
-            mTotalWeekCount = getWeeksDelta(mRangeEndDate);
-        }
-
-        /**
-         * Updates the selected day and related parameters.
-         * 
-         * @param selectedDay The time to highlight
-         */
-        public void setSelectedDay(Calendar selectedDay) {
-            if (selectedDay.get(Calendar.DAY_OF_YEAR) == mSelectedDay.get(Calendar.DAY_OF_YEAR)
-                    && selectedDay.get(Calendar.YEAR) == mSelectedDay.get(Calendar.YEAR)) {
-                return;
-            }
-            mSelectedDay.setTimeInMillis(selectedDay.getTimeInMillis());
-            mSelectedDay.setTimeZone(selectedDay.getTimeZone());
-            mSelectedWeek = getWeeksDelta(mSelectedDay);
-            mFocusMonth = mSelectedDay.get(Calendar.MONTH);
-            notifyDataSetChanged();
-            invalidate();  // Test
-        }
-
-        /**
-         * @return The selected day of month.
-         */
-        public Calendar getSelectedDay() {
-            return mSelectedDay;
-        }
-
-        /**
-         * updates any config options that may have changed and refreshes the
-         * view
-         */
-        public void refresh() {
-            notifyDataSetChanged();
-        }
-
-        @Override
-        public int getCount() {
-            return mTotalWeekCount;
-        }
-
-        @Override
-        public Object getItem(int position) {
-            return null;
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            WeekView v;
-            HashMap<String, Object> drawingParams = null;
-            if (convertView != null) {
-                v = (WeekView) convertView;
-                // We store the drawing parameters in the view so it can be
-                // recycled
-                drawingParams = (HashMap<String, Object>) v.getTag();
-            } else {
-                v = getNewView();
-                // Set up the new view
-                android.widget.AbsListView.LayoutParams params =
-                    new android.widget.AbsListView.LayoutParams(
-                        LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
-                v.setLayoutParams(params);
-                v.setClickable(true);
-                v.setOnTouchListener(this);
-
-                drawingParams = new HashMap<String, Object>();
-            }
-
-            // pass in all the view parameters
-            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_SHOW_WK_NUM,
-                    mShowWeekNumber ? 1 : 0);
-            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_WEEK_START, mFirstDayOfWeek);
-            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_NUM_DAYS, mDaysPerWeek);
-            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_WEEK, position);
-            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_FOCUS_MONTH, mFocusMonth);
-            putDrawingParementer(drawingParams, WeekView.VIEW_PARAMS_SELECTED_DAY,
-                    (mSelectedWeek == position) ? mSelectedDay.get(Calendar.DAY_OF_WEEK) : -1);
-            v.setWeekParams(drawingParams);
-
-            return v;
-        }
-
-        /**
-         * Puts the given <code>value</code> for the drawing
-         * <code>parameter</code> in the <code>drawingParams</code>.
-         */
-        private void putDrawingParementer(HashMap<String, Object> drawingParams, String parameter,
-                int value) {
-            int[] valueArray = (int[]) drawingParams.get(parameter);
-            if (valueArray == null) {
-                valueArray = new int[1];
-                drawingParams.put(parameter, valueArray);
-            }
-            valueArray[0] = value;
-        }
-
-        /**
-         * Creates a new WeekView and returns it. Override this to customize the
-         * view creation.
-         *
-         * @return A new WeekView
-         */
-        protected WeekView getNewView() {
-            return new WeekView(mContext);
-        }
-
-        /**
-         * Changes which month is in focus and updates the view.
-         *
-         * @param month The month to show as in focus [0-11]
-         */
-        public void setFocusMonth(int month) {
-            if (mFocusMonth == month) {
-                return;
-            }
-            mFocusMonth = month;
-            notifyDataSetChanged();
-        }
-
-        @Override
-        public boolean onTouch(View v, MotionEvent event) {
-            if (mGestureDetector.onTouchEvent(event)) {
-                WeekView weekView = (WeekView) v;
-                weekView.getDayFromLocation(event.getX(), mTempCalendar);
-                if (mTempCalendar.get(Calendar.YEAR) != 0) {
-                    onDayTapped(mTempCalendar);
-                }
-                return true;
-            }
-            return false;
-        }
-
-        /**
-         * Maintains the same hour/min/sec but moves the day to the tapped day.
-         * 
-         * @param day The day that was tapped
-         */
-        protected void onDayTapped(Calendar day) {
-            setSelectedDay(day);
-        }
-
-        /**
-         * This is here so we can identify single tap events and set the
-         * selected day correctly
-         */
-        protected class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener {
-            @Override
-            public boolean onSingleTapUp(MotionEvent e) {
-                return true;
-            }
-        }
-    }
-
-    /**
-     * <p>
-     * This is a dynamic view for drawing a single week. It can be configured to
-     * display the week number, start the week on a given day, or show a reduced
-     * number of days. It is intended for use as a single view within a
-     * ListView. See {@link WeeksAdapter} for usage.
-     * </p>
-     *
-     * @hide
-     */
-    public class WeekView extends View {
-
-        /*
-         * These params can be passed into the view to control how it appears.
-         * {@link #VIEW_PARAMS_WEEK} is the only required field, though the
-         * default values are unlikely to fit most layouts correctly.
-         */
-
-        /**
-         * This sets the height of this week in pixels
-         */
-        public static final String VIEW_PARAMS_HEIGHT = "height";
-
-        /**
-         * This specifies the position (or weeks since the epoch) of this week.
-         */
-        public static final String VIEW_PARAMS_WEEK = "week";
-
-        /**
-         * This sets one of the days in this view as selected
-         * {@link Time#SUNDAY} through {@link Time#SATURDAY}.
-         */
-        public static final String VIEW_PARAMS_SELECTED_DAY = "selected_day";
-
-        /**
-         * Which day the week should start on. {@link Time#SUNDAY} through
-         * {@link Time#SATURDAY}.
-         */
-        public static final String VIEW_PARAMS_WEEK_START = "week_start";
-
-        /**
-         * How many days to display at a time. Days will be displayed starting
-         * with {@link #mFirstDay}.
-         */
-        public static final String VIEW_PARAMS_NUM_DAYS = "num_days";
-
-        /**
-         * Which month is currently in focus, as defined by {@link Time#month}
-         * [0-11].
-         */
-        public static final String VIEW_PARAMS_FOCUS_MONTH = "focus_month";
-
-        /**
-         * If this month should display week numbers. false if 0, true
-         * otherwise.
-         */
-        public static final String VIEW_PARAMS_SHOW_WK_NUM = "show_wk_num";
-
-        protected static final int DEFAULT_SHOW_WK_NUM = 0;
-
-        protected final int mWeekSeperatorWidth;
-
-        protected final int mNumberTextSize;
-
-        protected final int mWeekDayPadding;
-
-        protected final Rect mTempRect = new Rect();
-
-        protected final Paint mDrawPaint = new Paint();
-
-        protected final Paint mMonthNumDrawPaint = new Paint();
-
-        protected final Drawable mSelectedDayLine;
-
-        protected final int mSelectedDayLineWidth;
-
-        protected final int mSelectionBackgroundColor;
-
-        protected final int mFocusedMonthDateColor;
-
-        protected final int mOtherMonthDateColor;
-
-        protected final int mGridLinesColor;
-
-        protected final int mWeekNumberColor;
-
-        protected final int mFirstDayOfweek;
-
-        // Cache the number strings so we don't have to recompute them each time
-        protected String[] mDayNumbers;
-
-        // Quick lookup for checking which days are in the focus month
-        protected boolean[] mFocusDay;
-
-        // The first day displayed by this item
-        protected Calendar mFirstDay;
-
-        // The month of the first day in this week
-        protected int mMonthOfFirstWeekDay = -1;
-
-        // The month of the last day in this week
-        protected int mLastWeekDayMonth = -1;
-
-        // The position of this week, equivalent to weeks since the week of Jan
-        // 1st, 1900
-        protected int mWeek = -1;
-
-        // Quick reference to the width of this view, matches parent
-        protected int mWidth;
-
-        // The height this view should draw at in pixels, set by height param
-        protected int mHeight;
-
-        // If this view contains the selected day
-        protected boolean mHasSelectedDay = false;
-
-        // Which day is selected [0-6] or -1 if no day is selected
-        protected int mSelectedDay = -1;
-
-        // How many days to display
-        protected int mWeekDayCount;
-
-        // The number of days + a spot for week number if it is displayed
-        protected int mNumCells;
-
-        // The left edge of the selected day
-        protected int mSelectedLeft = -1;
-
-        // The right edge of the selected day
-        protected int mSelectedRight = -1;
-
-        public WeekView(Context context) {
-            super(context);
-
-            TypedValue outTypedValue = new TypedValue();
-            context.getTheme().resolveAttribute(R.attr.dayPickerWeekViewStyle, outTypedValue, true);
-            TypedArray attributesArray = context.obtainStyledAttributes(outTypedValue.resourceId,
-                    R.styleable.DayPickerWeekView);
-            mHeight = attributesArray.getDimensionPixelSize(R.styleable.DayPickerWeekView_height,
-                    26);
-            mNumberTextSize = attributesArray.getDimensionPixelSize(
-                    R.styleable.DayPickerWeekView_textSize, 14);
-            mFirstDayOfweek = attributesArray.getInt(R.styleable.DayPickerWeekView_weekStartDay,
-                    Calendar.SUNDAY);
-            mNumCells = mWeekDayCount = attributesArray.getInt(
-                    R.styleable.DayPickerWeekView_weekDayCount, 7);
-            mShowWeekNumber = attributesArray.getBoolean(R.styleable.DayPickerWeekView_weekDayCount,
-                    true);
-            mWeekSeperatorWidth = attributesArray.getDimensionPixelSize(
-                    R.styleable.DayPickerWeekView_weekSeperatorWidth, 1);
-            mWeekDayPadding = attributesArray.getDimensionPixelSize(
-                    R.styleable.DayPickerWeekView_weekDayPadding, 0);
-            mSelectionBackgroundColor = attributesArray.getColor(
-                    R.styleable.DayPickerWeekView_selectionBackgroundColor, 0);
-            mFocusedMonthDateColor = attributesArray.getColor(
-                    R.styleable.DayPickerWeekView_focusedMonthDateColor, 0);
-            mOtherMonthDateColor = attributesArray.getColor(
-                    R.styleable.DayPickerWeekView_otherMonthDateColor, 0);
-            mGridLinesColor = attributesArray.getColor(
-                    R.styleable.DayPickerWeekView_gridLinesColor, 0);
-            mWeekNumberColor = attributesArray.getColor(
-                    R.styleable.DayPickerWeekView_weekNumberColor, 0);
-            mSelectedDayLine = attributesArray
-                    .getDrawable(R.styleable.DayPickerWeekView_selectedDayLine);
-            mSelectedDayLineWidth = attributesArray.getDimensionPixelSize(
-                    R.styleable.DayPickerWeekView_selectedDayLineWidth, 6);
-            attributesArray.recycle();
-
-            // Sets up any standard paints that will be used
-            setPaintProperties();
-        }
-
-        /**
-         * Sets all the parameters for displaying this week. The only required
-         * parameter is the week number. Other parameters have a default value
-         * and will only update if a new value is included, except for focus
-         * month, which will always default to no focus month if no value is
-         * passed in. See {@link #VIEW_PARAMS_HEIGHT} for more info on
-         * parameters.
-         *
-         * @param params A map of the new parameters, see
-         *            {@link #VIEW_PARAMS_HEIGHT}
-         */
-        public void setWeekParams(HashMap<String, Object> params) {
-            if (!params.containsKey(VIEW_PARAMS_WEEK)) {
-                throw new InvalidParameterException(
-                        "You must specify the week number for this view");
-            }
-            setTag(params);
-            // We keep the current value for any params not present
-            if (params.containsKey(VIEW_PARAMS_HEIGHT)) {
-                mHeight = ((int[]) params.get(VIEW_PARAMS_HEIGHT))[0];
-            }
-            if (params.containsKey(VIEW_PARAMS_SELECTED_DAY)) {
-                mSelectedDay = ((int[]) params.get(VIEW_PARAMS_SELECTED_DAY))[0];
-            }
-            mHasSelectedDay = mSelectedDay != -1;
-            if (params.containsKey(VIEW_PARAMS_NUM_DAYS)) {
-                mWeekDayCount = ((int[]) params.get(VIEW_PARAMS_NUM_DAYS))[0];
-            }
-            if (params.containsKey(VIEW_PARAMS_SHOW_WK_NUM)) {
-                if (((int[]) params.get(VIEW_PARAMS_SHOW_WK_NUM))[0] != 0) {
-                    mNumCells = mWeekDayCount + 1;
-                    mShowWeekNumber = true;
-                } else {
-                    mShowWeekNumber = false;
-                }
-            } else {
-                mNumCells = mShowWeekNumber ? mWeekDayCount + 1 : mWeekDayCount;
-            }
-            mWeek = ((int[]) params.get(VIEW_PARAMS_WEEK))[0];
-            mTempCalendar.clear();
-            mTempCalendar.set(1900, 0, 1);
-            mTempCalendar.add(Calendar.WEEK_OF_YEAR, mWeek);
-            if (params.containsKey(VIEW_PARAMS_WEEK_START)) {
-                mTempCalendar.setFirstDayOfWeek(((int[]) params.get(VIEW_PARAMS_WEEK_START))[0]);
-            } else {
-                mTempCalendar.setFirstDayOfWeek(Calendar.SUNDAY);
-            }
-
-            // Allocate space for caching the day numbers and focus values
-            mDayNumbers = new String[mNumCells];
-            mFocusDay = new boolean[mNumCells];
-
-            // If we're showing the week number calculate it based on Monday
-            int i = 0;
-            if (mShowWeekNumber) {
-                mDayNumbers[0] = Integer.toString(mTempCalendar.get(Calendar.WEEK_OF_YEAR));
-                i++;
-            }
-
-            // Now adjust our starting day based on the start day of the week
-            int diff = mTempCalendar.getFirstDayOfWeek() - mTempCalendar.get(Calendar.DAY_OF_WEEK);
-            mTempCalendar.add(Calendar.DAY_OF_MONTH, diff);
-
-            mFirstDay = (Calendar) mTempCalendar.clone();
-
-            mMonthOfFirstWeekDay = mTempCalendar.get(Calendar.MONTH);
-
-            int focusMonth = params.containsKey(VIEW_PARAMS_FOCUS_MONTH) ? ((int[]) params
-                    .get(VIEW_PARAMS_FOCUS_MONTH))[0] : -1;
-
-            for (; i < mNumCells; i++) {
-                mFocusDay[i] = (mTempCalendar.get(Calendar.MONTH) == focusMonth);
-                mDayNumbers[i] = Integer.toString(mTempCalendar.get(Calendar.DAY_OF_MONTH));
-                mTempCalendar.add(Calendar.DAY_OF_MONTH, 1);
-            }
-            // We do one extra add at the end of the loop, if that pushed us to
-            // new month undo it
-            if (mTempCalendar.get(Calendar.DAY_OF_MONTH) == 1) {
-                mTempCalendar.add(Calendar.DAY_OF_MONTH, -1);
-            }
-            mLastWeekDayMonth = mTempCalendar.get(Calendar.MONTH);
-
-            updateSelectionPositions();
-        }
-
-        /**
-         * Sets up the text and style properties for painting. Override this if
-         * you want to use a different paint.
-         */
-        protected void setPaintProperties() {
-            mDrawPaint.setFakeBoldText(false);
-            mDrawPaint.setAntiAlias(true);
-            mDrawPaint.setTextSize(mNumberTextSize);
-            mDrawPaint.setStyle(Style.FILL);
-
-            mMonthNumDrawPaint.setFakeBoldText(true);
-            mMonthNumDrawPaint.setAntiAlias(true);
-            mMonthNumDrawPaint.setTextSize(mNumberTextSize);
-            mMonthNumDrawPaint.setColor(mFocusedMonthDateColor);
-            mMonthNumDrawPaint.setStyle(Style.FILL);
-            mMonthNumDrawPaint.setTextAlign(Align.CENTER);
-        }
-
-        /**
-         * Returns the month of the first day in this week.
-         *
-         * @return The month the first day of this view is in.
-         */
-        public int getMonthOfFirstWeekDay() {
-            return mMonthOfFirstWeekDay;
-        }
-
-        /**
-         * Returns the month of the last day in this week
-         *
-         * @return The month the last day of this view is in
-         */
-        public int getMonthOfLastWeekDay() {
-            return mLastWeekDayMonth;
-        }
-
-        /**
-         * Returns the first day in this view.
-         *
-         * @return The first day in the view.
-         */
-        public Calendar getFirstDay() {
-            return mFirstDay;
-        }
-
-        /**
-         * Returns the number of days this view will display.
-         */
-        public int getNumDays() {
-            return mWeekDayCount;
-        }
-
-        /**
-         * Calculates the day that the given x position is in, accounting for
-         * week number. Returns a Time referencing that day or null if
-         *
-         * @param x The x position of the touch eventy
-         */
-        public void getDayFromLocation(float x, Calendar outCalendar) {
-            int dayStart = mShowWeekNumber ? (mWidth - mWeekDayPadding * 2) / mNumCells
-                    + mWeekDayPadding : mWeekDayPadding;
-            if (x < dayStart || x > mWidth - mWeekDayPadding) {
-                outCalendar.set(0, 0, 0, 0, 0, 0);
-                return;
-            }
-            // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels
-            int dayPosition = (int) ((x - dayStart) * mWeekDayCount
-                    / (mWidth - dayStart - mWeekDayPadding));
-            outCalendar.setTimeZone(mFirstDay.getTimeZone());
-            outCalendar.setTimeInMillis(mFirstDay.getTimeInMillis());
-            outCalendar.add(Calendar.DAY_OF_MONTH, dayPosition);
-        }
-
-        @Override
-        protected void onDraw(Canvas canvas) {
-            drawBackground(canvas);
-            drawWeekNums(canvas);
-            drawDaySeparators(canvas);
-            drawSelectedDayLines(canvas);
-        }
-
-        /**
-         * This draws the selection highlight if a day is selected in this week.
-         * Override this method if you wish to have a different background
-         * drawn.
-         *
-         * @param canvas The canvas to draw on
-         */
-        protected void drawBackground(Canvas canvas) {
-            if (!mHasSelectedDay) {
-                return;
-            }
-            mDrawPaint.setColor(mSelectionBackgroundColor);
-
-            mTempRect.top = mWeekSeperatorWidth;
-            mTempRect.bottom = mHeight;
-            mTempRect.left = mShowWeekNumber ? mWeekDayPadding + (mWidth - mWeekDayPadding * 2)
-                    / mNumCells : mWeekDayPadding;
-            mTempRect.right = mSelectedLeft - 2;
-            canvas.drawRect(mTempRect, mDrawPaint);
-
-            mTempRect.left = mSelectedRight + 3;
-            mTempRect.right = mWidth - mWeekDayPadding;
-            canvas.drawRect(mTempRect, mDrawPaint);
-        }
-
-        /**
-         * Draws the week and month day numbers for this week. Override this
-         * method if you need different placement.
-         *
-         * @param canvas The canvas to draw on
-         */
-        protected void drawWeekNums(Canvas canvas) {
-            float textHeight = mDrawPaint.getTextSize();
-            int y = (int) ((mHeight + textHeight) / 2) - mWeekSeperatorWidth;
-            int nDays = mNumCells;
-
-            mDrawPaint.setTextAlign(Align.CENTER);
-            int i = 0;
-            int divisor = 2 * nDays;
-            if (mShowWeekNumber) {
-                mDrawPaint.setColor(mWeekNumberColor);
-                int x = (mWidth - mWeekDayPadding * 2) / divisor + mWeekDayPadding;
-                canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
-                i++;
-            }
-            for (; i < nDays; i++) {
-                mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
-                        : mOtherMonthDateColor);
-                int x = (2 * i + 1) * (mWidth - mWeekDayPadding * 2) / divisor + mWeekDayPadding;
-                canvas.drawText(mDayNumbers[i], x, y, mMonthNumDrawPaint);
-            }
-        }
-
-        /**
-         * Draws a horizontal line for separating the weeks. Override this
-         * method if you want custom separators.
-         *
-         * @param canvas The canvas to draw on.
-         */
-        protected void drawDaySeparators(Canvas canvas) {
-            // If it is the topmost fully visible child do not draw separator line
-            int firstFullyVisiblePosition = mListView.getFirstVisiblePosition();
-            if (mListView.getChildAt(0).getTop() < 0) {
-                firstFullyVisiblePosition++;
-            }
-            if (firstFullyVisiblePosition == mWeek) {
-                return;
-            }
-            mDrawPaint.setColor(mGridLinesColor);
-            mDrawPaint.setStrokeWidth(mWeekSeperatorWidth);
-            float x = mShowWeekNumber ? mWeekDayPadding + (mWidth - mWeekDayPadding * 2) / mNumCells
-                    : mWeekDayPadding;
-            canvas.drawLine(x, 0, mWidth - mWeekDayPadding, 0, mDrawPaint);
-        }
-
-        /**
-         * Draws the selected day lines if this week has a selected day.
-         *
-         * @param canvas The canvas to draw on
-         */
-        protected void drawSelectedDayLines(Canvas canvas) {
-            if (!mHasSelectedDay) {
-                return;
-            }
-            mSelectedDayLine.setBounds(mSelectedLeft - mSelectedDayLineWidth / 2,
-                    mWeekSeperatorWidth,
-                    mSelectedLeft + mSelectedDayLineWidth / 2, mHeight);
-            mSelectedDayLine.draw(canvas);
-            mSelectedDayLine.setBounds(mSelectedRight - mSelectedDayLineWidth / 2,
-                    mWeekSeperatorWidth,
-                    mSelectedRight + mSelectedDayLineWidth / 2, mHeight);
-            mSelectedDayLine.draw(canvas);
-        }
-
-        @Override
-        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-            mWidth = w;
-            updateSelectionPositions();
-        }
-
-        /**
-         * This calculates the positions for the selected day lines.
-         */
-        protected void updateSelectionPositions() {
-            if (mHasSelectedDay) {
-                int selectedPosition = mSelectedDay - mTempCalendar.getFirstDayOfWeek();
-                if (selectedPosition < 0) {
-                    selectedPosition += 7;
-                }
-                if (mShowWeekNumber) {
-                    selectedPosition++;
-                }
-                mSelectedLeft = selectedPosition * (mWidth - mWeekDayPadding * 2) / mNumCells
-                        + mWeekDayPadding;
-                mSelectedRight = (selectedPosition + 1) * (mWidth - mWeekDayPadding * 2) / mNumCells
-                        + mWeekDayPadding;
-            }
-        }
-
-        @Override
-        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mHeight);
-        }
-    }
-}
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 6ff671a..dfa94c7 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -57,7 +56,7 @@
     private static final int[] DEFAULT_STATES = new int[0];
 
     private static final int[] ATTRS = new int[] {
-        android.R.attr.textColorPrimary,
+        android.R.attr.fastScrollTextColor,
         android.R.attr.fastScrollThumbDrawable,
         android.R.attr.fastScrollTrackDrawable,
         android.R.attr.fastScrollPreviewBackgroundLeft,
@@ -65,7 +64,7 @@
         android.R.attr.fastScrollOverlayPosition
     };
 
-    private static final int PRIMARY_TEXT_COLOR = 0;
+    private static final int TEXT_COLOR = 0;
     private static final int THUMB_DRAWABLE = 1;
     private static final int TRACK_DRAWABLE = 2;
     private static final int PREVIEW_BACKGROUND_LEFT = 3;
@@ -248,7 +247,7 @@
         mPaint.setTextAlign(Paint.Align.CENTER);
         mPaint.setTextSize(mOverlaySize / 2);
 
-        ColorStateList textColor = ta.getColorStateList(PRIMARY_TEXT_COLOR);
+        ColorStateList textColor = ta.getColorStateList(TEXT_COLOR);
         int textColorNormal = textColor.getDefaultColor();
         mPaint.setColor(textColorNormal);
         mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
@@ -407,7 +406,10 @@
         // Are there enough pages to require fast scroll? Recompute only if total count changes
         if (mItemCount != totalItemCount && visibleItemCount > 0) {
             mItemCount = totalItemCount;
-            mLongList = mAlwaysShow || mItemCount / visibleItemCount >= MIN_PAGES;
+            mLongList = mItemCount / visibleItemCount >= MIN_PAGES;
+        }
+        if (mAlwaysShow) {
+            mLongList = true;
         }
         if (!mLongList) {
             if (mState != STATE_NONE) {
@@ -416,8 +418,8 @@
             return;
         }
         if (totalItemCount - visibleItemCount > 0 && mState != STATE_DRAGGING ) {
-            mThumbY = ((mList.getHeight() - mThumbH) * firstVisibleItem) 
-                    / (totalItemCount - visibleItemCount);
+            mThumbY = getThumbPositionForListPosition(firstVisibleItem, visibleItemCount,
+                    totalItemCount);
             if (mChangedBounds) {
                 resetThumbPos();
                 mChangedBounds = false;
@@ -579,6 +581,49 @@
         }
     }
 
+    private int getThumbPositionForListPosition(int firstVisibleItem, int visibleItemCount,
+            int totalItemCount) {
+        if (mSectionIndexer == null) {
+            getSectionsFromIndexer();
+        }
+        if (mSectionIndexer == null) {
+            return ((mList.getHeight() - mThumbH) * firstVisibleItem)
+                    / (totalItemCount - visibleItemCount);
+        }
+
+        firstVisibleItem -= mListOffset;
+        if (firstVisibleItem < 0) {
+            return 0;
+        }
+        totalItemCount -= mListOffset;
+
+        final int trackHeight = mList.getHeight() - mThumbH;
+
+        final int section = mSectionIndexer.getSectionForPosition(firstVisibleItem);
+        final int sectionPos = mSectionIndexer.getPositionForSection(section);
+        final int nextSectionPos = mSectionIndexer.getPositionForSection(section + 1);
+        final int sectionCount = mSectionIndexer.getSections().length;
+        final int positionsInSection = nextSectionPos - sectionPos;
+
+        final View child = mList.getChildAt(0);
+        final float incrementalPos = child == null ? 0 : firstVisibleItem +
+                (float) (mList.getPaddingTop() - child.getTop()) / child.getHeight();
+        final float posWithinSection = (incrementalPos - sectionPos) / positionsInSection;
+        int result = (int) ((section + posWithinSection) / sectionCount * trackHeight);
+
+        // Fake out the scrollbar for the last item. Since the section indexer won't
+        // ever actually move the list in this end space, make scrolling across the last item
+        // account for whatever space is remaining.
+        if (firstVisibleItem > 0 && firstVisibleItem + visibleItemCount == totalItemCount) {
+            final View lastChild = mList.getChildAt(visibleItemCount - 1);
+            final float lastItemVisible = (float) (mList.getHeight() - mList.getPaddingBottom()
+                    - lastChild.getTop()) / lastChild.getHeight();
+            result += (trackHeight - result) * lastItemVisible;
+        }
+
+        return result;
+    }
+
     private void cancelFling() {
         // Cancel the list fling
         MotionEvent cancelFling = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 26e191d..f659ead 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -29,6 +29,8 @@
 import android.view.Gravity;
 import android.widget.RemoteViews.RemoteView;
 
+import java.util.ArrayList;
+
 
 /**
  * FrameLayout is designed to block out an area on the screen to display
@@ -46,6 +48,8 @@
  */
 @RemoteView
 public class FrameLayout extends ViewGroup {
+    private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.LEFT;
+
     @ViewDebug.ExportedProperty(category = "measurement")
     boolean mMeasureAllChildren = false;
 
@@ -76,8 +80,8 @@
 
     boolean mForegroundBoundsChanged = false;
     
-    private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.LEFT;
-
+    private final ArrayList<View> mMatchParentChildren = new ArrayList<View>(1);
+    
     public FrameLayout(Context context) {
         super(context);
     }
@@ -246,20 +250,33 @@
      */
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int count = getChildCount();
+        int count = getChildCount();
+
+        final boolean measureMatchParentChildren =
+                MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
+                MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
+        mMatchParentChildren.clear();
 
         int maxHeight = 0;
         int maxWidth = 0;
         int childState = 0;
 
-        // Find rightmost and bottommost child
         for (int i = 0; i < count; i++) {
             final View child = getChildAt(i);
             if (mMeasureAllChildren || child.getVisibility() != GONE) {
                 measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
-                maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
-                maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                maxWidth = Math.max(maxWidth,
+                        child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
+                maxHeight = Math.max(maxHeight,
+                        child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
                 childState = combineMeasuredStates(childState, child.getMeasuredState());
+                if (measureMatchParentChildren) {
+                    if (lp.width == LayoutParams.MATCH_PARENT ||
+                            lp.height == LayoutParams.MATCH_PARENT) {
+                        mMatchParentChildren.add(child);
+                    }
+                }
             }
         }
 
@@ -280,7 +297,40 @@
 
         setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
                 resolveSizeAndState(maxHeight, heightMeasureSpec,
-                        childState<<MEASURED_HEIGHT_STATE_SHIFT));
+                        childState << MEASURED_HEIGHT_STATE_SHIFT));
+
+        count = mMatchParentChildren.size();
+        if (count > 1) {
+            for (int i = 0; i < count; i++) {
+                final View child = mMatchParentChildren.get(i);
+
+                final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
+                int childWidthMeasureSpec;
+                int childHeightMeasureSpec;
+                
+                if (lp.width == LayoutParams.MATCH_PARENT) {
+                    childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth() -
+                            mPaddingLeft - mPaddingRight - lp.leftMargin - lp.rightMargin,
+                            MeasureSpec.EXACTLY);
+                } else {
+                    childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
+                            mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin,
+                            lp.width);
+                }
+                
+                if (lp.height == LayoutParams.MATCH_PARENT) {
+                    childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight() -
+                            mPaddingTop - mPaddingBottom - lp.topMargin - lp.bottomMargin,
+                            MeasureSpec.EXACTLY);
+                } else {
+                    childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
+                            mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin,
+                            lp.height);
+                }
+
+                child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+            }
+        }
     }
  
     /**
@@ -306,8 +356,8 @@
                 final int width = child.getMeasuredWidth();
                 final int height = child.getMeasuredHeight();
 
-                int childLeft = parentLeft;
-                int childTop = parentTop;
+                int childLeft;
+                int childTop;
 
                 int gravity = lp.gravity;
                 if (gravity == -1) {
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index df01da7..c7addcc 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1483,61 +1483,95 @@
         int action = event.getAction();
 
         if (action != KeyEvent.ACTION_UP) {
-            if (mSelectedPosition < 0) {
-                switch (keyCode) {
-                    case KeyEvent.KEYCODE_DPAD_UP:
-                    case KeyEvent.KEYCODE_DPAD_DOWN:
-                    case KeyEvent.KEYCODE_DPAD_LEFT:
-                    case KeyEvent.KEYCODE_DPAD_RIGHT:
-                    case KeyEvent.KEYCODE_DPAD_CENTER:
-                    case KeyEvent.KEYCODE_SPACE:
-                    case KeyEvent.KEYCODE_ENTER:
-                        resurrectSelection();
-                        return true;
-                }
-            }
-
             switch (keyCode) {
                 case KeyEvent.KEYCODE_DPAD_LEFT:
-                    handled = arrowScroll(FOCUS_LEFT);
+                    if (event.hasNoModifiers()) {
+                        handled = ensureSelectionOnMovementKey() && arrowScroll(FOCUS_LEFT);
+                    }
                     break;
 
                 case KeyEvent.KEYCODE_DPAD_RIGHT:
-                    handled = arrowScroll(FOCUS_RIGHT);
+                    if (event.hasNoModifiers()) {
+                        handled = ensureSelectionOnMovementKey() && arrowScroll(FOCUS_RIGHT);
+                    }
                     break;
 
                 case KeyEvent.KEYCODE_DPAD_UP:
-                    if (!event.isAltPressed()) {
-                        handled = arrowScroll(FOCUS_UP);
-
-                    } else {
-                        handled = fullScroll(FOCUS_UP);
+                    if (event.hasNoModifiers()) {
+                        handled = ensureSelectionOnMovementKey() && arrowScroll(FOCUS_UP);
+                    } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                        handled = ensureSelectionOnMovementKey() && fullScroll(FOCUS_UP);
                     }
                     break;
 
                 case KeyEvent.KEYCODE_DPAD_DOWN:
-                    if (!event.isAltPressed()) {
-                        handled = arrowScroll(FOCUS_DOWN);
-                    } else {
-                        handled = fullScroll(FOCUS_DOWN);
+                    if (event.hasNoModifiers()) {
+                        handled = ensureSelectionOnMovementKey() && arrowScroll(FOCUS_DOWN);
+                    } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                        handled = ensureSelectionOnMovementKey() && fullScroll(FOCUS_DOWN);
                     }
                     break;
 
                 case KeyEvent.KEYCODE_DPAD_CENTER:
                 case KeyEvent.KEYCODE_ENTER: {
-                    if (getChildCount() > 0 && event.getRepeatCount() == 0) {
+                    if (event.hasNoModifiers()
+                            && event.getRepeatCount() == 0 && getChildCount() > 0) {
+                        ensureSelectionOnMovementKey();
                         keyPressed();
                     }
-
                     return true;
                 }
 
                 case KeyEvent.KEYCODE_SPACE:
                     if (mPopup == null || !mPopup.isShowing()) {
-                        if (!event.isShiftPressed()) {
-                            handled = pageScroll(FOCUS_DOWN);
-                        } else {
-                            handled = pageScroll(FOCUS_UP);
+                        if (event.hasNoModifiers()) {
+                            handled = ensureSelectionOnMovementKey() && pageScroll(FOCUS_DOWN);
+                        } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
+                            handled = ensureSelectionOnMovementKey() && pageScroll(FOCUS_UP);
+                        }
+                    }
+                    break;
+
+                case KeyEvent.KEYCODE_PAGE_UP:
+                    if (event.hasNoModifiers()) {
+                        handled = ensureSelectionOnMovementKey() && pageScroll(FOCUS_UP);
+                    } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                        handled = ensureSelectionOnMovementKey() && fullScroll(FOCUS_UP);
+                    }
+                    break;
+
+                case KeyEvent.KEYCODE_PAGE_DOWN:
+                    if (event.hasNoModifiers()) {
+                        handled = ensureSelectionOnMovementKey() && pageScroll(FOCUS_DOWN);
+                    } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                        handled = ensureSelectionOnMovementKey() && fullScroll(FOCUS_DOWN);
+                    }
+                    break;
+
+                case KeyEvent.KEYCODE_MOVE_HOME:
+                    if (event.hasNoModifiers()) {
+                        handled = ensureSelectionOnMovementKey() && fullScroll(FOCUS_UP);
+                    }
+                    break;
+
+                case KeyEvent.KEYCODE_MOVE_END:
+                    if (event.hasNoModifiers()) {
+                        handled = ensureSelectionOnMovementKey() && fullScroll(FOCUS_DOWN);
+                    }
+                    break;
+
+                case KeyEvent.KEYCODE_TAB:
+                    // XXX Sometimes it is useful to be able to TAB through the items in
+                    //     a GridView sequentially.  Unfortunately this can create an
+                    //     asymmetry in TAB navigation order unless the list selection
+                    //     always reverts to the top or bottom when receiving TAB focus from
+                    //     another widget.  Leaving this behavior disabled for now but
+                    //     perhaps it should be configurable (and more comprehensive).
+                    if (false) {
+                        if (event.hasNoModifiers()) {
+                            handled = ensureSelectionOnMovementKey() && sequenceScroll(FOCUS_FORWARD);
+                        } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
+                            handled = ensureSelectionOnMovementKey() && sequenceScroll(FOCUS_BACKWARD);
                         }
                     }
                     break;
@@ -1686,6 +1720,64 @@
         return moved;
     }
 
+    /**
+     * Goes to the next or previous item according to the order set by the
+     * adapter.
+     */
+    boolean sequenceScroll(int direction) {
+        int selectedPosition = mSelectedPosition;
+        int numColumns = mNumColumns;
+        int count = mItemCount;
+
+        int startOfRow;
+        int endOfRow;
+        if (!mStackFromBottom) {
+            startOfRow = (selectedPosition / numColumns) * numColumns;
+            endOfRow = Math.min(startOfRow + numColumns - 1, count - 1);
+        } else {
+            int invertedSelection = count - 1 - selectedPosition;
+            endOfRow = count - 1 - (invertedSelection / numColumns) * numColumns;
+            startOfRow = Math.max(0, endOfRow - numColumns + 1);
+        }
+
+        boolean moved = false;
+        boolean showScroll = false;
+        switch (direction) {
+            case FOCUS_FORWARD:
+                if (selectedPosition < count - 1) {
+                    // Move to the next item.
+                    mLayoutMode = LAYOUT_MOVE_SELECTION;
+                    setSelectionInt(selectedPosition + 1);
+                    moved = true;
+                    // Show the scrollbar only if changing rows.
+                    showScroll = selectedPosition == endOfRow;
+                }
+                break;
+
+            case FOCUS_BACKWARD:
+                if (selectedPosition > 0) {
+                    // Move to the previous item.
+                    mLayoutMode = LAYOUT_MOVE_SELECTION;
+                    setSelectionInt(selectedPosition - 1);
+                    moved = true;
+                    // Show the scrollbar only if changing rows.
+                    showScroll = selectedPosition == startOfRow;
+                }
+                break;
+        }
+
+        if (moved) {
+            playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
+            invokeOnItemScrollListener();
+        }
+
+        if (showScroll) {
+            awakenScrollBars();
+        }
+
+        return moved;
+    }
+
     @Override
     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
         super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
@@ -1729,7 +1821,7 @@
      * change is coming from?
      * @param childIndex The index to check.
      * @param direction The direction, one of
-     *        {FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}
+     *        {FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, FOCUS_BACKWARD}
      * @return Whether childIndex is a candidate.
      */
     private boolean isCandidateSelection(int childIndex, int direction) {
@@ -1761,9 +1853,16 @@
             case View.FOCUS_UP:
                 // coming from bottom, need to be in last row
                 return rowEnd == count - 1;
+            case View.FOCUS_FORWARD:
+                // coming from top-left, need to be first in top row
+                return childIndex == rowStart && rowStart == 0;
+            case View.FOCUS_BACKWARD:
+                // coming from bottom-right, need to be last in bottom row
+                return childIndex == rowEnd && rowEnd == count - 1;
             default:
                 throw new IllegalArgumentException("direction must be one of "
-                        + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
+                        + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, "
+                        + "FOCUS_FORWARD, FOCUS_BACKWARD}.");
         }
     }
 
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 50867b9..f6b1dbc 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.view.ViewDebug;
 import com.android.internal.R;
 
 import android.util.AttributeSet;
@@ -115,6 +116,7 @@
      * When set to true, the scroll view measure its child to make it fill the currently
      * visible area.
      */
+    @ViewDebug.ExportedProperty(category = "layout")
     private boolean mFillViewport;
 
     /**
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 9c483ee..444a163d 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -440,7 +440,8 @@
     public void setContentWidth(int width) {
         Drawable popupBackground = mPopup.getBackground();
         if (popupBackground != null) {
-            mDropDownWidth = popupBackground.getIntrinsicWidth() + width;
+            popupBackground.getPadding(mTempRect);
+            mDropDownWidth = mTempRect.left + mTempRect.right + width;
         }
     }
 
@@ -914,10 +915,16 @@
             // to the drop down list but instead, consume it immediately
             final View anchorView = mDropDownAnchorView;
             if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
-                anchorView.getKeyDispatcherState().startTracking(event, this);
+                KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
+                if (state != null) {
+                    state.startTracking(event, this);
+                }
                 return true;
             } else if (event.getAction() == KeyEvent.ACTION_UP) {
-                anchorView.getKeyDispatcherState().handleUpEvent(event);
+                KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
+                if (state != null) {
+                    state.handleUpEvent(event);
+                }
                 if (event.isTracking() && !event.isCanceled()) {
                     dismiss();
                     return true;
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 3703846..796af55 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import com.android.internal.R;
+import com.android.internal.util.Predicate;
 import com.google.android.collect.Lists;
 
 import android.content.Context;
@@ -103,7 +104,7 @@
 
     Drawable mDivider;
     int mDividerHeight;
-    
+
     Drawable mOverScrollHeader;
     Drawable mOverScrollFooter;
 
@@ -1535,7 +1536,6 @@
             // reset the focus restoration
             View focusLayoutRestoreDirectChild = null;
 
-
             // Don't put header or footer views into the Recycler. Those are
             // already cached in mHeaderViews;
             if (dataChanged) {
@@ -2078,51 +2078,47 @@
         int action = event.getAction();
 
         if (action != KeyEvent.ACTION_UP) {
-            if (mSelectedPosition < 0) {
-                switch (keyCode) {
-                case KeyEvent.KEYCODE_DPAD_UP:
-                case KeyEvent.KEYCODE_DPAD_DOWN:
-                case KeyEvent.KEYCODE_DPAD_CENTER:
-                case KeyEvent.KEYCODE_ENTER:
-                case KeyEvent.KEYCODE_SPACE:
-                    if (resurrectSelection()) {
-                        return true;
-                    }
-                }
-            }
             switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_UP:
-                if (!event.isAltPressed()) {
-                    while (count > 0) {
-                        handled = arrowScroll(FOCUS_UP);
-                        count--;
+                if (event.hasNoModifiers()) {
+                    if (ensureSelectionOnMovementKey()) {
+                        while (count-- > 0) {
+                            handled |= arrowScroll(FOCUS_UP);
+                        }
                     }
-                } else {
-                    handled = fullScroll(FOCUS_UP);
+                } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                    handled = ensureSelectionOnMovementKey() && fullScroll(FOCUS_UP);
                 }
                 break;
 
             case KeyEvent.KEYCODE_DPAD_DOWN:
-                if (!event.isAltPressed()) {
-                    while (count > 0) {
-                        handled = arrowScroll(FOCUS_DOWN);
-                        count--;
+                if (event.hasNoModifiers()) {
+                    if (ensureSelectionOnMovementKey()) {
+                        while (count-- > 0) {
+                            handled |= arrowScroll(FOCUS_DOWN);
+                        }
                     }
-                } else {
-                    handled = fullScroll(FOCUS_DOWN);
+                } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                    handled = ensureSelectionOnMovementKey() && fullScroll(FOCUS_DOWN);
                 }
                 break;
 
             case KeyEvent.KEYCODE_DPAD_LEFT:
-                handled = handleHorizontalFocusWithinListItem(View.FOCUS_LEFT);
+                if (event.hasNoModifiers()) {
+                    handled = handleHorizontalFocusWithinListItem(View.FOCUS_LEFT);
+                }
                 break;
+
             case KeyEvent.KEYCODE_DPAD_RIGHT:
-                handled = handleHorizontalFocusWithinListItem(View.FOCUS_RIGHT);
+                if (event.hasNoModifiers()) {
+                    handled = handleHorizontalFocusWithinListItem(View.FOCUS_RIGHT);
+                }
                 break;
 
             case KeyEvent.KEYCODE_DPAD_CENTER:
             case KeyEvent.KEYCODE_ENTER:
                 if (mItemCount > 0 && event.getRepeatCount() == 0) {
+                    ensureSelectionOnMovementKey();
                     keyPressed();
                 }
                 handled = true;
@@ -2130,14 +2126,58 @@
 
             case KeyEvent.KEYCODE_SPACE:
                 if (mPopup == null || !mPopup.isShowing()) {
-                    if (!event.isShiftPressed()) {
-                        pageScroll(FOCUS_DOWN);
-                    } else {
-                        pageScroll(FOCUS_UP);
+                    if (event.hasNoModifiers()) {
+                        handled = ensureSelectionOnMovementKey() && pageScroll(FOCUS_DOWN);
+                    } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
+                        handled = ensureSelectionOnMovementKey() && pageScroll(FOCUS_UP);
                     }
                     handled = true;
                 }
                 break;
+
+            case KeyEvent.KEYCODE_PAGE_UP:
+                if (event.hasNoModifiers()) {
+                    handled = ensureSelectionOnMovementKey() && pageScroll(FOCUS_UP);
+                } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                    handled = ensureSelectionOnMovementKey() && fullScroll(FOCUS_UP);
+                }
+                break;
+
+            case KeyEvent.KEYCODE_PAGE_DOWN:
+                if (event.hasNoModifiers()) {
+                    handled = ensureSelectionOnMovementKey() && pageScroll(FOCUS_DOWN);
+                } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                    handled = ensureSelectionOnMovementKey() && fullScroll(FOCUS_DOWN);
+                }
+                break;
+
+            case KeyEvent.KEYCODE_MOVE_HOME:
+                if (event.hasNoModifiers()) {
+                    handled = ensureSelectionOnMovementKey() && fullScroll(FOCUS_UP);
+                }
+                break;
+
+            case KeyEvent.KEYCODE_MOVE_END:
+                if (event.hasNoModifiers()) {
+                    handled = ensureSelectionOnMovementKey() && fullScroll(FOCUS_DOWN);
+                }
+                break;
+
+            case KeyEvent.KEYCODE_TAB:
+                // XXX Sometimes it is useful to be able to TAB through the items in
+                //     a ListView sequentially.  Unfortunately this can create an
+                //     asymmetry in TAB navigation order unless the list selection
+                //     always reverts to the top or bottom when receiving TAB focus from
+                //     another widget.  Leaving this behavior disabled for now but
+                //     perhaps it should be configurable (and more comprehensive).
+                if (false) {
+                    if (event.hasNoModifiers()) {
+                        handled = ensureSelectionOnMovementKey() && arrowScroll(FOCUS_DOWN);
+                    } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
+                        handled = ensureSelectionOnMovementKey() && arrowScroll(FOCUS_UP);
+                    }
+                }
+                break;
             }
         }
 
@@ -3053,7 +3093,14 @@
             }
             final Paint paint = mDividerPaint;
 
-            final int listBottom = mBottom - mTop - mListPadding.bottom + mScrollY;
+            int effectivePaddingTop = 0;
+            int effectivePaddingBottom = 0;
+            if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
+                effectivePaddingTop = mListPadding.top;
+                effectivePaddingBottom = mListPadding.bottom;
+            }
+
+            final int listBottom = mBottom - mTop - effectivePaddingBottom + mScrollY;
             if (!mStackFromBottom) {
                 int bottom = 0;
                 
@@ -3104,7 +3151,7 @@
                 }
             } else {
                 int top;
-                int listTop = mListPadding.top;
+                int listTop = effectivePaddingTop;
 
                 final int scrollY = mScrollY;
 
@@ -3402,7 +3449,7 @@
     }
 
     /* (non-Javadoc)
-     * @see android.view.View#findViewWithTag(String)
+     * @see android.view.View#findViewWithTag(Object)
      * First look in our children, then in any header and footer views that may be scrolled off.
      */
     @Override
@@ -3410,12 +3457,12 @@
         View v;
         v = super.findViewWithTagTraversal(tag);
         if (v == null) {
-            v = findViewTagInHeadersOrFooters(mHeaderViewInfos, tag);
+            v = findViewWithTagInHeadersOrFooters(mHeaderViewInfos, tag);
             if (v != null) {
                 return v;
             }
 
-            v = findViewTagInHeadersOrFooters(mFooterViewInfos, tag);
+            v = findViewWithTagInHeadersOrFooters(mFooterViewInfos, tag);
             if (v != null) {
                 return v;
             }
@@ -3427,7 +3474,7 @@
      *
      * Look in the passed in list of headers or footers for the view with the tag.
      */
-    View findViewTagInHeadersOrFooters(ArrayList<FixedViewInfo> where, Object tag) {
+    View findViewWithTagInHeadersOrFooters(ArrayList<FixedViewInfo> where, Object tag) {
         if (where != null) {
             int len = where.size();
             View v;
@@ -3447,6 +3494,55 @@
         return null;
     }
 
+    /**
+     * @hide
+     * @see android.view.View#findViewByPredicate(Predicate)
+     * First look in our children, then in any header and footer views that may be scrolled off.
+     */
+    @Override
+    protected View findViewByPredicateTraversal(Predicate<View> predicate) {
+        View v;
+        v = super.findViewByPredicateTraversal(predicate);
+        if (v == null) {
+            v = findViewByPredicateInHeadersOrFooters(mHeaderViewInfos, predicate);
+            if (v != null) {
+                return v;
+            }
+
+            v = findViewByPredicateInHeadersOrFooters(mFooterViewInfos, predicate);
+            if (v != null) {
+                return v;
+            }
+        }
+        return v;
+    }
+
+    /* (non-Javadoc)
+     *
+     * Look in the passed in list of headers or footers for the first view that matches
+     * the predicate.
+     */
+    View findViewByPredicateInHeadersOrFooters(ArrayList<FixedViewInfo> where,
+            Predicate<View> predicate) {
+        if (where != null) {
+            int len = where.size();
+            View v;
+
+            for (int i = 0; i < len; i++) {
+                v = where.get(i).view;
+
+                if (!v.isRootNamespace()) {
+                    v = v.findViewByPredicate(predicate);
+
+                    if (v != null) {
+                        return v;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         if (mItemsCanFocus && ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 7b35b51..ba46a3f 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -30,8 +30,8 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
-import android.graphics.Paint.Align;
 import android.graphics.Rect;
+import android.graphics.Paint.Align;
 import android.text.InputFilter;
 import android.text.InputType;
 import android.text.Spanned;
@@ -41,11 +41,11 @@
 import android.util.SparseArray;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
-import android.view.LayoutInflater.Filter;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewConfiguration;
+import android.view.LayoutInflater.Filter;
 import android.view.animation.OvershootInterpolator;
 import android.view.inputmethod.InputMethodManager;
 
@@ -62,11 +62,18 @@
  * <p>
  * For an example of using this widget, see {@link android.widget.TimePicker}.
  * </p>
+ *
+ * @attr ref android.R.styleable#NumberPicker_solidColor
  */
 @Widget
 public class NumberPicker extends LinearLayout {
 
     /**
+     * The default update interval during long press.
+     */
+    private static final long DEFAULT_LONG_PRESS_UPDATE_INTERVAL = 300;
+
+    /**
      * The index of the middle selector item.
      */
     private static final int SELECTOR_MIDDLE_ITEM_INDEX = 2;
@@ -115,6 +122,8 @@
      * strings like "01". Keeping a static formatter etc. is the most efficient
      * way to do this; it avoids creating temporary objects on every call to
      * format().
+     *
+     * @hide
      */
     public static final NumberPicker.Formatter TWO_DIGIT_FORMATTER = new NumberPicker.Formatter() {
         final StringBuilder mBuilder = new StringBuilder();
@@ -123,7 +132,7 @@
 
         final Object[] mArgs = new Object[1];
 
-        public String toString(int value) {
+        public String format(int value) {
             mArgs[0] = value;
             mBuilder.delete(0, mBuilder.length());
             mFmt.format("%02d", mArgs);
@@ -159,22 +168,22 @@
     /**
      * Lower value of the range of numbers allowed for the NumberPicker
      */
-    private int mStart;
+    private int mMinValue;
 
     /**
      * Upper value of the range of numbers allowed for the NumberPicker
      */
-    private int mEnd;
+    private int mMaxValue;
 
     /**
      * Current value of this NumberPicker
      */
-    private int mCurrent;
+    private int mValue;
 
     /**
      * Listener to be notified upon current value change.
      */
-    private OnChangeListener mOnChangeListener;
+    private OnValueChangedListener mOnValueChangedListener;
 
     /**
      * Listener to be notified upon scroll state change.
@@ -189,7 +198,7 @@
     /**
      * The speed for updating the value form long press.
      */
-    private long mLongPressUpdateInterval = 300;
+    private long mLongPressUpdateInterval = DEFAULT_LONG_PRESS_UPDATE_INTERVAL;
 
     /**
      * Cache for the string representation of selector indices.
@@ -308,7 +317,7 @@
     /**
      * Flag whether the selector should wrap around.
      */
-    private boolean mWrapSelector;
+    private boolean mWrapSelectorWheel;
 
     /**
      * The back ground color used to optimize scroller fading.
@@ -326,9 +335,10 @@
     private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;
 
     /**
-     * The callback interface used to indicate the number value has changed.
+     * Interface to listen for changes of the current value.
      */
-    public interface OnChangeListener {
+    public interface OnValueChangedListener {
+
         /**
          * Called upon a change of the current value.
          *
@@ -336,11 +346,11 @@
          * @param oldVal The previous value.
          * @param newVal The new value.
          */
-        void onChange(NumberPicker picker, int oldVal, int newVal);
+        void onValueChange(NumberPicker picker, int oldVal, int newVal);
     }
 
     /**
-     * Interface for listening to the picker scroll state.
+     * Interface to listen for the picker scroll state.
      */
     public interface OnScrollListener {
 
@@ -360,27 +370,29 @@
         public static int SCROLL_STATE_FLING = 2;
 
         /**
-         * Callback method to be invoked while the number picker is being scrolled.
+         * Callback invoked while the number picker scroll state has changed.
          *
-         * @param view The view whose scroll state is being reported
-         * @param scrollState The current scroll state. One of {@link #SCROLL_STATE_IDLE},
-         * {@link #SCROLL_STATE_TOUCH_SCROLL} or {@link #SCROLL_STATE_IDLE}.
+         * @param view The view whose scroll state is being reported.
+         * @param scrollState The current scroll state. One of
+         *            {@link #SCROLL_STATE_IDLE},
+         *            {@link #SCROLL_STATE_TOUCH_SCROLL} or
+         *            {@link #SCROLL_STATE_IDLE}.
          */
         public void onScrollStateChange(NumberPicker view, int scrollState);
     }
 
     /**
-     * Interface used to format the number into a string for presentation.
+     * Interface used to format current value into a string for presentation.
      */
     public interface Formatter {
 
         /**
-         * Formats a string representation of the current index.
+         * Formats a string representation of the current value.
          *
          * @param value The currently selected value.
          * @return A formatted string representation.
          */
-        public String toString(int value);
+        public String format(int value);
     }
 
     /**
@@ -436,9 +448,9 @@
             public void onClick(View v) {
                 mInputText.clearFocus();
                 if (v.getId() == R.id.increment) {
-                    changeCurrent(mCurrent + 1);
+                    changeCurrent(mValue + 1);
                 } else {
-                    changeCurrent(mCurrent - 1);
+                    changeCurrent(mValue - 1);
                 }
             }
         };
@@ -466,7 +478,7 @@
         mDecrementButton.setOnLongClickListener(onLongClickListener);
 
         // input text
-        mInputText = (EditText) findViewById(R.id.timepicker_input);
+        mInputText = (EditText) findViewById(R.id.numberpicker_input);
         mInputText.setOnFocusChangeListener(new OnFocusChangeListener() {
             public void onFocusChange(View v, boolean hasFocus) {
                 if (!hasFocus) {
@@ -534,7 +546,7 @@
         });
 
         // create the fling and adjust scrollers
-        mFlingScroller = new Scroller(getContext());
+        mFlingScroller = new Scroller(getContext(), null, true);
         mAdjustScroller = new Scroller(getContext(), new OvershootInterpolator());
 
         updateInputTextView();
@@ -551,6 +563,9 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
+        if (!isEnabled()) {
+            return false;
+        }
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
                 mLastMotionEventY = mLastDownEventY = event.getY();
@@ -594,6 +609,9 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
+        if (!isEnabled()) {
+            return false;
+        }
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
         }
@@ -702,12 +720,6 @@
         }
     }
 
-    /**
-     * Set the enabled state of this view. The interpretation of the enabled
-     * state varies by subclass.
-     *
-     * @param enabled True if this view is enabled, false otherwise.
-     */
     @Override
     public void setEnabled(boolean enabled) {
         super.setEnabled(enabled);
@@ -716,9 +728,6 @@
         mInputText.setEnabled(enabled);
     }
 
-    /**
-     * Scrolls the selector with the given <code>vertical offset</code>.
-     */
     @Override
     public void scrollBy(int x, int y) {
         int[] selectorIndices = getSelectorIndices();
@@ -734,11 +743,13 @@
             mSelectorElementHeight = mTextSize + selectorTextGapHeight;
         }
 
-        if (!mWrapSelector && y > 0 && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mStart) {
+        if (!mWrapSelectorWheel && y > 0
+                && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) {
             mCurrentScrollOffset = mInitialScrollOffset;
             return;
         }
-        if (!mWrapSelector && y < 0 && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mEnd) {
+        if (!mWrapSelectorWheel && y < 0
+                && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) {
             mCurrentScrollOffset = mInitialScrollOffset;
             return;
         }
@@ -747,7 +758,7 @@
             mCurrentScrollOffset -= mSelectorElementHeight;
             decrementSelectorIndices(selectorIndices);
             changeCurrent(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX]);
-            if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mStart) {
+            if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) {
                 mCurrentScrollOffset = mInitialScrollOffset;
             }
         }
@@ -755,7 +766,7 @@
             mCurrentScrollOffset += mSelectorElementHeight;
             incrementScrollSelectorIndices(selectorIndices);
             changeCurrent(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX]);
-            if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mEnd) {
+            if (selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) {
                 mCurrentScrollOffset = mInitialScrollOffset;
             }
         }
@@ -769,16 +780,16 @@
     /**
      * Sets the listener to be notified on change of the current value.
      *
-     * @param onChangeListener The listener.
+     * @param onValueChangedListener The listener.
      */
-    public void setOnChangeListener(OnChangeListener onChangeListener) {
-        mOnChangeListener = onChangeListener;
+    public void setOnValueChangedListener(OnValueChangedListener onValueChangedListener) {
+        mOnValueChangedListener = onValueChangedListener;
     }
 
     /**
      * Set listener to be notified for scroll state changes.
      *
-     * @param onScrollListener the callback, should not be null.
+     * @param onScrollListener The listener.
      */
     public void setOnScrollListener(OnScrollListener onScrollListener) {
         mOnScrollListener = onScrollListener;
@@ -787,164 +798,216 @@
     /**
      * Set the formatter to be used for formatting the current value.
      * <p>
-     * Note: If you have provided alternative values for the selected positons
-     *       this formatter is never invoked.
+     * Note: If you have provided alternative values for the values this
+     * formatter is never invoked.
      * </p>
      *
-     * @param formatter the formatter object. If formatter is null,
-     *            String.valueOf() will be used.
+     * @param formatter The formatter object. If formatter is <code>null</code>,
+     *            {@link String#valueOf(int)} will be used.
      *
-     * @see #setRange(int, int, String[])
+     * @see #setDisplayedValues(String[])
      */
     public void setFormatter(Formatter formatter) {
-        mFormatter = formatter;
-    }
-
-    /**
-     * Set the range of numbers allowed for the number picker. The current value
-     * will be automatically set to the start.
-     *
-     * @param start the start of the range (inclusive)
-     * @param end the end of the range (inclusive)
-     */
-    public void setRange(int start, int end) {
-        setRange(start, end, null);
-    }
-
-    /**
-     * Set the range of numbers allowed for the number picker. The current value
-     * will be automatically set to the start. Also provide a mapping for values
-     * used to display to the user instead of the numbers in the range.
-     *
-     * @param start The start of the range (inclusive).
-     * @param end The end of the range (inclusive).
-     * @param displayedValues The values displayed to the user.
-     */
-    public void setRange(int start, int end, String[] displayedValues) {
-        boolean wrapSelector = (end - start) >= mSelectorIndices.length;
-        setRange(start, end, displayedValues, wrapSelector);
-    }
-
-    /**
-     * Set the range of numbers allowed for the number picker. The current value
-     * will be automatically set to the start. Also provide a mapping for values
-     * used to display to the user.
-     * <p>
-     * Note: The <code>wrapSelectorWheel</code> argument is ignored if the range
-     * (difference between <code>start</code> and <code>end</code>) us less than
-     * five since this is the number of values shown by the selector wheel.
-     * </p>
-     *
-     * @param start the start of the range (inclusive)
-     * @param end the end of the range (inclusive)
-     * @param displayedValues the values displayed to the user.
-     * @param wrapSelectorWheel Whether to wrap the selector wheel.
-     *
-     * @see #setWrapSelectorWheel(boolean)
-     */
-    public void setRange(int start, int end, String[] displayedValues, boolean wrapSelectorWheel) {
-        if (start == mStart && end == mEnd) {
+        if (formatter == mFormatter) {
             return;
         }
-
-        if (start < 0 || end < 0) {
-            throw new IllegalArgumentException("start and end must be > 0");
-        }
-        
-        mDisplayedValues = displayedValues;
-        mStart = start;
-        mEnd = end;
-        mCurrent = start;
-
-        setWrapSelectorWheel(wrapSelectorWheel);
-        updateInputTextView();
-
-        if (displayedValues != null) {
-            // Allow text entry rather than strictly numeric entry.
-            mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT
-                    | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
-        } else {
-            mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
-        }
-
-        resetSelectorIndices();
+        mFormatter = formatter;
+        resetSelectorWheelIndices();
     }
 
     /**
      * Set the current value for the number picker.
+     * <p>
+     * If the argument is less than the {@link NumberPicker#getMinValue()} and
+     * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the
+     * current value is set to the {@link NumberPicker#getMinValue()} value.
+     * </p>
+     * <p>
+     * If the argument is less than the {@link NumberPicker#getMinValue()} and
+     * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the
+     * current value is set to the {@link NumberPicker#getMaxValue()} value.
+     * </p>
+     * <p>
+     * If the argument is less than the {@link NumberPicker#getMaxValue()} and
+     * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the
+     * current value is set to the {@link NumberPicker#getMaxValue()} value.
+     * </p>
+     * <p>
+     * If the argument is less than the {@link NumberPicker#getMaxValue()} and
+     * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the
+     * current value is set to the {@link NumberPicker#getMinValue()} value.
+     * </p>
      *
-     * @param current the current value the start of the range (inclusive)
-     *
-     * @throws IllegalArgumentException when current is not within the range of
-     *             of the number picker.
+     * @param value The current value.
+     * @see #setWrapSelectorWheel(boolean)
+     * @see #setMinValue(int)
+     * @see #setMaxValue(int)
      */
-    public void setCurrent(int current) {
-        if (mCurrent == current) {
+    public void setValue(int value) {
+        if (mValue == value) {
             return;
         }
-        if (current < mStart || current > mEnd) {
-            throw new IllegalArgumentException("current should be >= start and <= end");
+        if (value < mMinValue) {
+            value = mWrapSelectorWheel ? mMaxValue : mMinValue;
         }
-        mCurrent = current;
+        if (value > mMaxValue) {
+            value = mWrapSelectorWheel ? mMinValue : mMaxValue;
+        }
+        mValue = value;
         updateInputTextView();
         updateIncrementAndDecrementButtonsVisibilityState();
     }
 
     /**
-     * Sets whether the selector wheel shown during flinging/scrolling should wrap
-     * around the beginning and end values. By default if the range is more than
-     * five (the number of items shown on the selector wheel) the selector wheel
-     * wrapping is enabled.
+     * Gets whether the selector wheel wraps when reaching the min/max value.
+     *
+     * @return True if the selector wheel wraps.
+     *
+     * @see #getMinValue()
+     * @see #getMaxValue()
+     */
+    public boolean getWrapSelectorWheel() {
+        return mWrapSelectorWheel;
+    }
+
+    /**
+     * Sets whether the selector wheel shown during flinging/scrolling should
+     * wrap around the {@link NumberPicker#getMinValue()} and
+     * {@link NumberPicker#getMaxValue()} values.
+     * <p>
+     * By default if the range (max - min) is more than five (the number of
+     * items shown on the selector wheel) the selector wheel wrapping is
+     * enabled.
+     * </p>
      *
      * @param wrapSelector Whether to wrap.
      */
     public void setWrapSelectorWheel(boolean wrapSelector) {
-        if (wrapSelector && (mEnd - mStart) < mSelectorIndices.length) {
+        if (wrapSelector && (mMaxValue - mMinValue) < mSelectorIndices.length) {
             throw new IllegalStateException("Range less than selector items count.");
         }
-        if (wrapSelector != mWrapSelector) {
+        if (wrapSelector != mWrapSelectorWheel) {
             // force the selector indices array to be reinitialized
             mSelectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] = Integer.MAX_VALUE;
-            mWrapSelector = wrapSelector;
+            mWrapSelectorWheel = wrapSelector;
         }
     }
 
     /**
      * Sets the speed at which the numbers be incremented and decremented when
      * the up and down buttons are long pressed respectively.
+     * <p>
+     * The default value is 300 ms.
+     * </p>
      *
      * @param intervalMillis The speed (in milliseconds) at which the numbers
-     *            will be incremented and decremented (default 300ms).
+     *            will be incremented and decremented.
      */
     public void setOnLongPressUpdateInterval(long intervalMillis) {
         mLongPressUpdateInterval = intervalMillis;
     }
 
     /**
-     * Returns the current value of the NumberPicker.
+     * Returns the value of the picker.
      *
-     * @return the current value.
+     * @return The value.
      */
-    public int getCurrent() {
-        return mCurrent;
+    public int getValue() {
+        return mValue;
     }
 
     /**
-     * Returns the range lower value of the NumberPicker.
+     * Returns the min value of the picker.
      *
-     * @return The lower number of the range.
+     * @return The min value
      */
-    public int getRangeStart() {
-        return mStart;
+    public int getMinValue() {
+        return mMinValue;
     }
 
     /**
-     * Returns the range end value of the NumberPicker.
+     * Sets the min value of the picker.
      *
-     * @return The upper number of the range.
+     * @param minValue The min value.
      */
-    public int getRangeEnd() {
-        return mEnd;
+    public void setMinValue(int minValue) {
+        if (mMinValue == minValue) {
+            return;
+        }
+        if (minValue < 0) {
+            throw new IllegalArgumentException("minValue must be >= 0");
+        }
+        mMinValue = minValue;
+        if (mMinValue > mValue) {
+            mValue = mMinValue;
+        }
+        boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length;
+        setWrapSelectorWheel(wrapSelectorWheel);
+        resetSelectorWheelIndices();
+        updateInputTextView();
+        updateIncrementAndDecrementButtonsVisibilityState();
+    }
+
+    /**
+     * Returns the max value of the picker.
+     *
+     * @return The max value.
+     */
+    public int getMaxValue() {
+        return mMaxValue;
+    }
+
+    /**
+     * Sets the max value of the picker.
+     *
+     * @param maxValue The max value.
+     */
+    public void setMaxValue(int maxValue) {
+        if (mMaxValue == maxValue) {
+            return;
+        }
+        if (maxValue < 0) {
+            throw new IllegalArgumentException("maxValue must be >= 0");
+        }
+        mMaxValue = maxValue;
+        if (mMaxValue < mValue) {
+            mValue = mMaxValue;
+        }
+        boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length;
+        setWrapSelectorWheel(wrapSelectorWheel);
+        resetSelectorWheelIndices();
+        updateInputTextView();
+        updateIncrementAndDecrementButtonsVisibilityState();
+    }
+
+    /**
+     * Gets the values to be displayed instead of string values.
+     *
+     * @return The displayed values.
+     */
+    public String[] getDisplayedValues() {
+        return mDisplayedValues;
+    }
+
+    /**
+     * Sets the values to be displayed.
+     *
+     * @param displayedValues The displayed values.
+     */
+    public void setDisplayedValues(String[] displayedValues) {
+        if (mDisplayedValues == displayedValues) {
+            return;
+        }
+        mDisplayedValues = displayedValues;
+        if (mDisplayedValues != null) {
+            // Allow text entry rather than strictly numeric entry.
+            mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT
+                    | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+        } else {
+            mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
+        }
+        updateInputTextView();
+        resetSelectorWheelIndices();
     }
 
     @Override
@@ -979,10 +1042,7 @@
         // children
         // after we have completed drawing ourselves.
 
-        // Draw the selector wheel if needed
-        if (mDrawSelectorWheel) {
-            super.draw(canvas);
-        }
+        super.draw(canvas);
 
         // Draw our children if we are not showing the selector wheel of fading
         // it out
@@ -1020,7 +1080,7 @@
      * Resets the selector indices and clear the cached
      * string representation of these indices.
      */
-    private void resetSelectorIndices() {
+    private void resetSelectorWheelIndices() {
         mSelectorIndexToStringCache.clear();
         int[] selectorIdices = getSelectorIndices();
         for (int i = 0; i < selectorIdices.length; i++) {
@@ -1037,15 +1097,15 @@
      * @param current the new value of the NumberPicker
      */
     private void changeCurrent(int current) {
-        if (mCurrent == current) {
+        if (mValue == current) {
             return;
         }
         // Wrap around the values if we go past the start or end
-        if (mWrapSelector) {
+        if (mWrapSelectorWheel) {
             current = getWrappedSelectorIndex(current);
         }
-        int previous = mCurrent;
-        setCurrent(current);
+        int previous = mValue;
+        setValue(current);
         notifyChange(previous, current);
     }
 
@@ -1110,7 +1170,7 @@
         mPreviousScrollerY = 0;
         Scroller flingScroller = mFlingScroller;
 
-        if (mWrapSelector) {
+        if (mWrapSelectorWheel) {
             if (velocityY > 0) {
                 flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE);
             } else {
@@ -1118,10 +1178,10 @@
             }
         } else {
             if (velocityY > 0) {
-                int maxY = mTextSize * (mCurrent - mStart);
+                int maxY = mTextSize * (mValue - mMinValue);
                 flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, maxY);
             } else {
-                int startY = mTextSize * (mEnd - mCurrent);
+                int startY = mTextSize * (mMaxValue - mValue);
                 int maxY = startY;
                 flingScroller.fling(0, startY, 0, velocityY, 0, 0, 0, maxY);
             }
@@ -1155,12 +1215,12 @@
      * Updates the visibility state of the increment and decrement buttons.
      */
     private void updateIncrementAndDecrementButtonsVisibilityState() {
-        if (mWrapSelector || mCurrent < mEnd) {
+        if (mWrapSelectorWheel || mValue < mMaxValue) {
             mIncrementButton.setVisibility(VISIBLE);
         } else {
             mIncrementButton.setVisibility(INVISIBLE);
         }
-        if (mWrapSelector || mCurrent > mStart) {
+        if (mWrapSelectorWheel || mValue > mMinValue) {
             mDecrementButton.setVisibility(VISIBLE);
         } else {
             mDecrementButton.setVisibility(INVISIBLE);
@@ -1172,11 +1232,11 @@
      *         the middle one.
      */
     private int[] getSelectorIndices() {
-        int current = getCurrent();
+        int current = getValue();
         if (mSelectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] != current) {
             for (int i = 0; i < mSelectorIndices.length; i++) {
                 int selectorIndex = current + (i - SELECTOR_MIDDLE_ITEM_INDEX);
-                if (mWrapSelector) {
+                if (mWrapSelectorWheel) {
                     selectorIndex = getWrappedSelectorIndex(selectorIndex);
                 }
                 mSelectorIndices[i] = selectorIndex;
@@ -1190,10 +1250,10 @@
      * @return The wrapped index <code>selectorIndex</code> value.
      */
     private int getWrappedSelectorIndex(int selectorIndex) {
-        if (selectorIndex > mEnd) {
-            return mStart + (selectorIndex - mEnd) % (mEnd - mStart);
-        } else if (selectorIndex < mStart) {
-            return mEnd - (mStart - selectorIndex) % (mEnd - mStart);
+        if (selectorIndex > mMaxValue) {
+            return mMinValue + (selectorIndex - mMaxValue) % (mMaxValue - mMinValue) - 1;
+        } else if (selectorIndex < mMinValue) {
+            return mMaxValue - (mMinValue - selectorIndex) % (mMaxValue - mMinValue) + 1;
         }
         return selectorIndex;
     }
@@ -1207,8 +1267,8 @@
             selectorIndices[i] = selectorIndices[i + 1];
         }
         int nextScrollSelectorIndex = selectorIndices[selectorIndices.length - 2] + 1;
-        if (mWrapSelector && nextScrollSelectorIndex > mEnd) {
-            nextScrollSelectorIndex = mStart;
+        if (mWrapSelectorWheel && nextScrollSelectorIndex > mMaxValue) {
+            nextScrollSelectorIndex = mMinValue;
         }
         selectorIndices[selectorIndices.length - 1] = nextScrollSelectorIndex;
         ensureCachedScrollSelectorValue(nextScrollSelectorIndex);
@@ -1223,8 +1283,8 @@
             selectorIndices[i] = selectorIndices[i - 1];
         }
         int nextScrollSelectorIndex = selectorIndices[1] - 1;
-        if (mWrapSelector && nextScrollSelectorIndex < mStart) {
-            nextScrollSelectorIndex = mEnd;
+        if (mWrapSelectorWheel && nextScrollSelectorIndex < mMinValue) {
+            nextScrollSelectorIndex = mMaxValue;
         }
         selectorIndices[0] = nextScrollSelectorIndex;
         ensureCachedScrollSelectorValue(nextScrollSelectorIndex);
@@ -1241,11 +1301,11 @@
         if (scrollSelectorValue != null) {
             return;
         }
-        if (selectorIndex < mStart || selectorIndex > mEnd) {
+        if (selectorIndex < mMinValue || selectorIndex > mMaxValue) {
             scrollSelectorValue = "";
         } else {
             if (mDisplayedValues != null) {
-                int displayedValueIndex = selectorIndex - mStart;
+                int displayedValueIndex = selectorIndex - mMinValue;
                 scrollSelectorValue = mDisplayedValues[displayedValueIndex];
             } else {
                 scrollSelectorValue = formatNumber(selectorIndex);
@@ -1255,7 +1315,7 @@
     }
 
     private String formatNumber(int value) {
-        return (mFormatter != null) ? mFormatter.toString(value) : String.valueOf(value);
+        return (mFormatter != null) ? mFormatter.format(value) : String.valueOf(value);
     }
 
     private void validateInputTextView(View v) {
@@ -1283,9 +1343,9 @@
          * number.
          */
         if (mDisplayedValues == null) {
-            mInputText.setText(formatNumber(mCurrent));
+            mInputText.setText(formatNumber(mValue));
         } else {
-            mInputText.setText(mDisplayedValues[mCurrent - mStart]);
+            mInputText.setText(mDisplayedValues[mValue - mMinValue]);
         }
         mInputText.setSelection(mInputText.getText().length());
     }
@@ -1295,8 +1355,8 @@
      * NumberPicker.
      */
     private void notifyChange(int previous, int current) {
-        if (mOnChangeListener != null) {
-            mOnChangeListener.onChange(this, previous, mCurrent);
+        if (mOnValueChangedListener != null) {
+            mOnValueChangedListener.onValueChange(this, previous, mValue);
         }
     }
 
@@ -1344,7 +1404,7 @@
                 // Don't force the user to type in jan when ja will do
                 value = value.toLowerCase();
                 if (mDisplayedValues[i].toLowerCase().startsWith(value)) {
-                    return mStart + i;
+                    return mMinValue + i;
                 }
             }
 
@@ -1359,7 +1419,7 @@
                 // Ignore as if it's not a number we don't care
             }
         }
-        return mStart;
+        return mMinValue;
     }
 
     /**
@@ -1431,7 +1491,7 @@
                  * allowed. We have to allow less than min as the user might
                  * want to delete some numbers and then type a new number.
                  */
-                if (val > mEnd) {
+                if (val > mMaxValue) {
                     return "";
                 } else {
                     return filtered;
@@ -1476,7 +1536,16 @@
     class AdjustScrollerCommand implements Runnable {
         public void run() {
             mPreviousScrollerY = 0;
+            if (mInitialScrollOffset == mCurrentScrollOffset) {
+                showInputControls();
+                updateInputTextView();
+                return;
+            }
+            // adjust to the closest value
             int deltaY = mInitialScrollOffset - mCurrentScrollOffset;
+            if (Math.abs(deltaY) > mSelectorElementHeight / 2) {
+                deltaY += (deltaY > 0) ? -mSelectorElementHeight : mSelectorElementHeight;
+            }
             float delayCoef = (float) Math.abs(deltaY) / (float) mTextSize;
             int duration = (int) (delayCoef * SELECTOR_ADJUSTMENT_DURATION_MILLIS);
             mAdjustScroller.startScroll(0, 0, 0, deltaY, duration);
@@ -1495,7 +1564,7 @@
         }
 
         public void run() {
-            changeCurrent(mCurrent + mUpdateStep);
+            changeCurrent(mValue + mUpdateStep);
             postDelayed(this, mLongPressUpdateInterval);
         }
     }
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 591a2d4..79d6a81 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -84,7 +84,7 @@
     private View mPopupView;
     private boolean mFocusable;
     private int mInputMethodMode = INPUT_METHOD_FROM_FOCUSABLE;
-    private int mSoftInputMode;
+    private int mSoftInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;
     private boolean mTouchable = true;
     private boolean mOutsideTouchable = false;
     private boolean mClippingEnabled = true;
@@ -1468,12 +1468,17 @@
             if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                 if (event.getAction() == KeyEvent.ACTION_DOWN
                         && event.getRepeatCount() == 0) {
-                    getKeyDispatcherState().startTracking(event, this);
+                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    if (state != null) {
+                        state.startTracking(event, this);
+                    }
                     return true;
-                } else if (event.getAction() == KeyEvent.ACTION_UP
-                        && getKeyDispatcherState().isTracking(event) && !event.isCanceled()) {
-                    dismiss();
-                    return true;
+                } else if (event.getAction() == KeyEvent.ACTION_UP) {
+                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    if (state != null && state.isTracking(event) && !event.isCanceled()) {
+                        dismiss();
+                        return true;
+                    }
                 }
                 return super.dispatchKeyEvent(event);
             } else {
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 5b143fe..ef4e4e0 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -1004,9 +1004,11 @@
 
     @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/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java
index 5598c65..5f3d21f 100644
--- a/core/java/android/widget/QuickContactBadge.java
+++ b/core/java/android/widget/QuickContactBadge.java
@@ -16,24 +16,26 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.content.AsyncQueryHandler;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
 import android.database.Cursor;
+import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Intents;
 import android.provider.ContactsContract.PhoneLookup;
 import android.provider.ContactsContract.QuickContact;
 import android.provider.ContactsContract.RawContacts;
-import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.View.OnClickListener;
-import com.android.internal.R;
 
 /**
  * Widget used to show an image with the standard QuickContact badge
@@ -45,6 +47,7 @@
     private String mContactEmail;
     private String mContactPhone;
     private int mMode;
+    private Drawable mOverlay;
     private QueryHandler mQueryHandler;
     private Drawable mBadgeBackground;
     private Drawable mNoBadgeBackground;
@@ -100,11 +103,25 @@
 
         a.recycle();
 
+        TypedArray styledAttributes = mContext.obtainStyledAttributes(R.styleable.Theme);
+        mOverlay = styledAttributes.getDrawable(com.android.internal.R.styleable.Theme_quickContactBadgeOverlay);
+        styledAttributes.recycle();
+
         init();
 
         mBadgeBackground = getBackground();
     }
 
+    @Override
+    protected void drawableStateChanged() {
+        super.drawableStateChanged();
+        Drawable d = mOverlay;
+        if (d != null && d.isStateful()) {
+            d.setState(getDrawableState());
+            invalidate();
+        }
+    }
+
     private void init() {
         mQueryHandler = new QueryHandler(mContext.getContentResolver());
         setOnClickListener(this);
@@ -118,7 +135,29 @@
     public void setMode(int size) {
         mMode = size;
     }
-    
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+
+        if (mOverlay == null || mOverlay.getIntrinsicWidth() == 0 ||
+                mOverlay.getIntrinsicHeight() == 0) {
+            return; // nothing to draw
+        }
+
+        mOverlay.setBounds(0, 0, getWidth(), getHeight());
+
+        if (mPaddingTop == 0 && mPaddingLeft == 0) {
+            mOverlay.draw(canvas);
+        } else {
+            int saveCount = canvas.getSaveCount();
+            canvas.save();
+            canvas.translate(mPaddingLeft, mPaddingTop);
+            mOverlay.draw(canvas);
+            canvas.restoreToCount(saveCount);
+        }
+    }
+
     /**
      * Resets the contact photo to the default state.
      */
@@ -132,7 +171,8 @@
     /**
      * Assign the contact uri that this QuickContactBadge should be associated
      * with. Note that this is only used for displaying the QuickContact window and
-     * won't bind the contact's photo for you.
+     * won't bind the contact's photo for you. Call {@link #setImageDrawable(Drawable)} to set the
+     * photo.
      *
      * @param contactUri Either a {@link Contacts#CONTENT_URI} or
      *            {@link Contacts#CONTENT_LOOKUP_URI} style URI.
@@ -146,9 +186,12 @@
 
     private void onContactUriChanged() {
         if (mContactUri == null && mContactEmail == null && mContactPhone == null) {
+            // Holo theme has no background on badges. Use a null background.
+            /*
             if (mNoBadgeBackground == null) {
                 mNoBadgeBackground = getResources().getDrawable(R.drawable.quickcontact_nobadge);
             }
+            */
             setBackgroundDrawable(mNoBadgeBackground);
         } else {
             setBackgroundDrawable(mBadgeBackground);
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 52d9c08..df1f4bf 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -148,15 +148,11 @@
             adapter.mMainQueue.removeMessages(0);
             adapter.mWorkerQueue.removeMessages(0);
 
-            // Clear the cache (the meta data will be re-requested on service re-connection)
-            synchronized (adapter.mCache) {
-                adapter.mCache.reset();
-            }
-
             final RemoteAdapterConnectionCallback callback = adapter.mCallback.get();
             if (callback != null) {
                 callback.onRemoteAdapterDisconnected();
             }
+            adapter.mCache.reset();
         }
 
         public IRemoteViewsFactory getRemoteViewsFactory() {
@@ -335,8 +331,8 @@
 
                     // Compose the loading view text
                     TextView loadingTextView = (TextView) mLayoutInflater.inflate(
-				com.android.internal.R.layout.remote_views_adapter_default_loading_view,
-				layout, false);
+                            com.android.internal.R.layout.remote_views_adapter_default_loading_view,
+                            layout, false);
                     loadingTextView.setHeight(mFirstViewHeight);
                     loadingTextView.setTag(new Integer(0));
 
@@ -662,11 +658,9 @@
             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
@@ -880,7 +874,7 @@
         // a chance to update itself and return new meta data associated with the new data.
     }
 
-    private void superNotifyDataSetChanged() {
+    void superNotifyDataSetChanged() {
         super.notifyDataSetChanged();
     }
 
diff --git a/core/java/android/widget/ResourceCursorAdapter.java b/core/java/android/widget/ResourceCursorAdapter.java
index aee411e..7341c2c 100644
--- a/core/java/android/widget/ResourceCursorAdapter.java
+++ b/core/java/android/widget/ResourceCursorAdapter.java
@@ -35,13 +35,19 @@
     private LayoutInflater mInflater;
     
     /**
-     * Constructor.
+     * Constructor the enables auto-requery.
+     *
+     * @deprecated This option is discouraged, as it results in Cursor queries
+     * being performed on the application's UI thread and thus can cause poor
+     * responsiveness or even Application Not Responding errors.  As an alternative,
+     * use {@link android.app.LoaderManager} with a {@link android.content.CursorLoader}.
      *
      * @param context The context where the ListView associated with this adapter is running
      * @param layout resource identifier of a layout file that defines the views
      *            for this list item.  Unless you override them later, this will
      *            define both the item views and the drop down views.
      */
+    @Deprecated
     public ResourceCursorAdapter(Context context, int layout, Cursor c) {
         super(context, c);
         mLayout = mDropDownLayout = layout;
@@ -49,7 +55,11 @@
     }
     
     /**
-     * Constructor.
+     * Constructor with default behavior as per
+     * {@link CursorAdapter#CursorAdapter(Context, Cursor, boolean)}; it is recommended
+     * you not use this, but instead {@link #ResourceCursorAdapter(Context, int, Cursor, int)}.
+     * When using this constructor, {@link #FLAG_REGISTER_CONTENT_OBSERVER}
+     * will always be set.
      *
      * @param context The context where the ListView associated with this adapter is running
      * @param layout resource identifier of a layout file that defines the views
@@ -58,7 +68,7 @@
      * @param c The cursor from which to get the data.
      * @param autoRequery If true the adapter will call requery() on the
      *                    cursor whenever it changes so the most recent
-     *                    data is always displayed.
+     *                    data is always displayed.  Using true here is discouraged.
      */
     public ResourceCursorAdapter(Context context, int layout, Cursor c, boolean autoRequery) {
         super(context, c, autoRequery);
@@ -67,14 +77,15 @@
     }
 
     /**
-     * Constructor.
+     * Standard constructor.
      *
      * @param context The context where the ListView associated with this adapter is running
-     * @param layout resource identifier of a layout file that defines the views
+     * @param layout Resource identifier of a layout file that defines the views
      *            for this list item.  Unless you override them later, this will
      *            define both the item views and the drop down views.
      * @param c The cursor from which to get the data.
-     * @param flags flags used to determine the behavior of the adapter
+     * @param flags Flags used to determine the behavior of the adapter,
+     * as per {@link CursorAdapter#CursorAdapter(Context, Cursor, int)}.
      */
     public ResourceCursorAdapter(Context context, int layout, Cursor c, int flags) {
         super(context, c, flags);
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index f25edd8..8558c70 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.view.ViewDebug;
 import com.android.internal.R;
 
 import android.content.Context;
@@ -110,6 +111,7 @@
      * When set to true, the scroll view measure its child to make it fill the currently
      * visible area.
      */
+    @ViewDebug.ExportedProperty(category = "layout")
     private boolean mFillViewport;
 
     /**
@@ -326,8 +328,8 @@
             if (child.getMeasuredHeight() < height) {
                 final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
 
-                int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, mPaddingLeft
-                        + mPaddingRight, lp.width);
+                int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
+                        mPaddingLeft + mPaddingRight, lp.width);
                 height -= mPaddingTop;
                 height -= mPaddingBottom;
                 int childHeightMeasureSpec =
@@ -1327,7 +1329,7 @@
         mIsLayoutDirty = false;
         // Give a child focus if it needs it
         if (mChildToScrollTo != null && isViewDescendantOf(mChildToScrollTo, this)) {
-                scrollToChild(mChildToScrollTo);
+            scrollToChild(mChildToScrollTo);
         }
         mChildToScrollTo = null;
 
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index e499e54..2c96056 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -18,6 +18,8 @@
 
 import static android.widget.SuggestionsAdapter.getColumnString;
 
+import com.android.internal.R;
+
 import android.app.PendingIntent;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
@@ -44,14 +46,11 @@
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.TextView.OnEditorActionListener;
 
-import com.android.internal.R;
-
 import java.util.WeakHashMap;
 
 /**
@@ -84,7 +83,7 @@
     private CursorAdapter mSuggestionsAdapter;
     private View mSearchButton;
     private View mSubmitButton;
-    private View mCloseButton;
+    private ImageView mCloseButton;
     private View mSearchEditFrame;
     private View mVoiceButton;
     private SearchAutoComplete mQueryTextView;
@@ -189,7 +188,7 @@
 
         mSearchEditFrame = findViewById(R.id.search_edit_frame);
         mSubmitButton = findViewById(R.id.search_go_btn);
-        mCloseButton = findViewById(R.id.search_close_btn);
+        mCloseButton = (ImageView) findViewById(R.id.search_close_btn);
         mVoiceButton = findViewById(R.id.search_voice_btn);
 
         mSearchButton.setOnClickListener(mOnClickListener);
@@ -218,6 +217,10 @@
         if (maxWidth != -1) {
             setMaxWidth(maxWidth);
         }
+        CharSequence queryHint = a.getText(R.styleable.SearchView_queryHint);
+        if (!TextUtils.isEmpty(queryHint)) {
+            setQueryHint(queryHint);
+        }
         a.recycle();
 
         // Save voice intent for later queries/launching
@@ -252,7 +255,9 @@
     @Override
     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
         if (mClearingFocus || isIconified()) return false;
-        return mQueryTextView.requestFocus(direction, previouslyFocusedRect);
+        boolean result = mQueryTextView.requestFocus(direction, previouslyFocusedRect);
+        if (result) updateViewsVisibility(mIconifiedByDefault);
+        return result;
     }
 
     /** @hide */
@@ -263,6 +268,7 @@
         mQueryTextView.clearFocus();
         setImeVisibility(false);
         mClearingFocus = false;
+        updateViewsVisibility(mIconifiedByDefault);
     }
 
     /**
@@ -515,11 +521,21 @@
         mSearchButton.setVisibility(visCollapsed);
         mSubmitButton.setVisibility(mSubmitButtonEnabled && hasText ? visExpanded : GONE);
         mSearchEditFrame.setVisibility(visExpanded);
+        updateCloseButton();
         updateVoiceButton(!hasText);
         requestLayout();
         invalidate();
     }
 
+    private void updateCloseButton() {
+        final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText());
+        // Should we show the close button? It is not shown if there's no focus,
+        // field is not iconified by default and there is no text in it.
+        final boolean showClose = hasText || mIconifiedByDefault || mQueryTextView.hasFocus();
+        mCloseButton.setVisibility(showClose ? VISIBLE : INVISIBLE);
+        mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
+    }
+
     private void setImeVisibility(boolean visible) {
         InputMethodManager imm = (InputMethodManager)
         getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -611,14 +627,16 @@
 
             // If there is text in the query box, handle enter, and action keys
             // The search key is handled by the dialog's onKeyDown().
-            if (!mQueryTextView.isEmpty()) {
-                if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) {
-                    v.cancelLongPress();
+            if (!mQueryTextView.isEmpty() && event.hasNoModifiers()) {
+                if (event.getAction() == KeyEvent.ACTION_UP) {
+                    if (keyCode == KeyEvent.KEYCODE_ENTER) {
+                        v.cancelLongPress();
 
-                    // Launch as a regular search.
-                    launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, mQueryTextView.getText()
-                            .toString());
-                    return true;
+                        // Launch as a regular search.
+                        launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, mQueryTextView.getText()
+                                .toString());
+                        return true;
+                    }
                 }
                 if (event.getAction() == KeyEvent.ACTION_DOWN) {
                     SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
@@ -646,11 +664,11 @@
         if (mSuggestionsAdapter == null) {
             return false;
         }
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-
+        if (event.getAction() == KeyEvent.ACTION_DOWN && event.hasNoModifiers()) {
             // First, check for enter or search (both of which we'll treat as a
             // "click")
-            if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH) {
+            if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH
+                    || keyCode == KeyEvent.KEYCODE_TAB) {
                 int position = mQueryTextView.getListSelection();
                 return onItemClicked(position, KeyEvent.KEYCODE_UNKNOWN, null);
             }
@@ -812,6 +830,7 @@
             invalidate();
         }
         updateVoiceButton(!hasText);
+        updateCloseButton();
         if (mOnQueryChangeListener != null) {
             mOnQueryChangeListener.onQueryTextChanged(newText.toString());
         }
@@ -882,6 +901,10 @@
         }
     }
 
+    void onTextFocusChanged() {
+        updateCloseButton();
+    }
+
     private boolean onItemClicked(int position, int actionKey, String actionMsg) {
         if (mOnSuggestionListener == null
                 || !mOnSuggestionListener.onSuggestionClicked(position)) {
@@ -1283,6 +1306,12 @@
             }
         }
 
+        @Override
+        protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+            super.onFocusChanged(focused, direction, previouslyFocusedRect);
+            mSearchView.onTextFocusChanged();
+        }
+
         /**
          * We override this method so that we can allow a threshold of zero,
          * which ACTV does not.
diff --git a/core/java/android/widget/SimpleCursorAdapter.java b/core/java/android/widget/SimpleCursorAdapter.java
index d1c2270..3d2a252 100644
--- a/core/java/android/widget/SimpleCursorAdapter.java
+++ b/core/java/android/widget/SimpleCursorAdapter.java
@@ -66,7 +66,23 @@
     String[] mOriginalFrom;
 
     /**
-     * Constructor.
+     * Constructor the enables auto-requery.
+     *
+     * @deprecated This option is discouraged, as it results in Cursor queries
+     * being performed on the application's UI thread and thus can cause poor
+     * responsiveness or even Application Not Responding errors.  As an alternative,
+     * use {@link android.app.LoaderManager} with a {@link android.content.CursorLoader}.
+     */
+    @Deprecated
+    public SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
+        super(context, layout, c);
+        mTo = to;
+        mOriginalFrom = from;
+        findColumns(from);
+    }
+
+    /**
+     * Standard constructor.
      * 
      * @param context The context where the ListView associated with this
      *            SimpleListItemFactory is running
@@ -80,9 +96,12 @@
      *            These should all be TextViews. The first N views in this list
      *            are given the values of the first N columns in the from
      *            parameter.  Can be null if the cursor is not available yet.
+     * @param flags Flags used to determine the behavior of the adapter,
+     * as per {@link CursorAdapter#CursorAdapter(Context, Cursor, int)}.
      */
-    public SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
-        super(context, layout, c);
+    public SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from,
+            int[] to, int flags) {
+        super(context, layout, c, flags);
         mTo = to;
         mOriginalFrom = from;
         findColumns(from);
@@ -318,10 +337,11 @@
     }
 
     @Override
-    public void changeCursor(Cursor c) {
-        super.changeCursor(c);
+    public Cursor swapCursor(Cursor c) {
+        Cursor res = super.swapCursor(c);
         // rescan columns in case cursor layout is different
         findColumns(mOriginalFrom);
+        return res;
     }
     
     /**
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index b90837c..0102628 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -24,7 +24,8 @@
 import android.content.res.TypedArray;
 import android.database.DataSetObserver;
 import android.util.AttributeSet;
-import android.view.LayoutInflater;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -43,6 +44,9 @@
 public class Spinner extends AbsSpinner implements OnClickListener {
     private static final String TAG = "Spinner";
     
+    // Only measure this many items to get a decent max width.
+    private static final int MAX_ITEMS_MEASURED = 15;
+
     /**
      * Use a dialog window for selecting spinner options.
      */
@@ -61,6 +65,8 @@
     private SpinnerPopup mPopup;
     private DropDownAdapter mTempAdapter;
 
+    private int mGravity;
+
     /**
      * Construct a new spinner with the given context's theme.
      *
@@ -148,10 +154,7 @@
         }
 
         case MODE_DROPDOWN: {
-            final int hintResource = a.getResourceId(
-                    com.android.internal.R.styleable.Spinner_popupPromptView, 0);
-
-            DropdownPopup popup = new DropdownPopup(context, attrs, defStyle, hintResource);
+            DropdownPopup popup = new DropdownPopup(context, attrs, defStyle);
 
             popup.setWidth(a.getLayoutDimension(
                     com.android.internal.R.styleable.Spinner_dropDownWidth,
@@ -168,6 +171,8 @@
         }
         }
         
+        mGravity = a.getInt(com.android.internal.R.styleable.Spinner_gravity, Gravity.CENTER);
+
         mPopup.setPromptText(a.getString(com.android.internal.R.styleable.Spinner_prompt));
 
         a.recycle();
@@ -179,7 +184,25 @@
             mTempAdapter = null;
         }
     }
-    
+
+    /**
+     * Describes how the selected item view is positioned. Currently only the horizontal component
+     * is used. The default is determined by the current theme.
+     *
+     * @param gravity See {@link android.view.Gravity}
+     *
+     * @attr ref android.R.styleable#Spinner_gravity
+     */
+    public void setGravity(int gravity) {
+        if (mGravity != gravity) {
+            if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
+                gravity |= Gravity.LEFT;
+            }
+            mGravity = gravity;
+            requestLayout();
+        }
+    }
+
     @Override
     public void setAdapter(SpinnerAdapter adapter) {
         super.setAdapter(adapter);
@@ -230,6 +253,17 @@
         throw new RuntimeException("setOnItemClickListener cannot be used with a spinner.");
     }
 
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        if (mPopup != null && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) {
+            final int measuredWidth = getMeasuredWidth();
+            setMeasuredDimension(Math.min(Math.max(measuredWidth, mPopup.measureContentWidth()),
+                    MeasureSpec.getSize(widthMeasureSpec)),
+                    getMeasuredHeight());
+        }
+    }
+
     /**
      * @see android.view.View#onLayout(boolean,int,int,int,int)
      *
@@ -274,11 +308,19 @@
         // Clear out old views
         removeAllViewsInLayout();
 
-        // Make selected view and center it
+        // Make selected view and position it
         mFirstPosition = mSelectedPosition;
         View sel = makeAndAddView(mSelectedPosition);
         int width = sel.getMeasuredWidth();
-        int selectedOffset = childrenLeft + (childrenWidth / 2) - (width / 2);
+        int selectedOffset = childrenLeft;
+        switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+            case Gravity.CENTER_HORIZONTAL:
+                selectedOffset = childrenLeft + (childrenWidth / 2) - (width / 2);
+                break;
+            case Gravity.RIGHT:
+                selectedOffset = childrenLeft + childrenWidth - width;
+                break;
+        }
         sel.offsetLeftAndRight(selectedOffset);
 
         // Flush any cached views that did not get reused above
@@ -537,6 +579,8 @@
          */
         public void setPromptText(CharSequence hintText);
         public CharSequence getHintText();
+
+        public int measureContentWidth();
     }
     
     private class DialogPopup implements SpinnerPopup, DialogInterface.OnClickListener {
@@ -578,19 +622,23 @@
             setSelection(which);
             dismiss();
         }
+
+        public int measureContentWidth() {
+            // Doesn't matter for dialog mode
+            return 0;
+        }
     }
     
     private class DropdownPopup extends ListPopupWindow implements SpinnerPopup {
         private CharSequence mHintText;
-        private TextView mHintView;
-        private int mHintResource;
+        private int mPopupMaxWidth;
         
-        public DropdownPopup(Context context, AttributeSet attrs,
-                int defStyleRes, int hintResource) {
+        public DropdownPopup(Context context, AttributeSet attrs, int defStyleRes) {
             super(context, attrs, 0, defStyleRes);
             
-            mHintResource = hintResource;
-            
+            final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+            mPopupMaxWidth = metrics.widthPixels / 2;
+
             setAnchorView(Spinner.this);
             setModal(true);
             setPromptPosition(POSITION_PROMPT_ABOVE);
@@ -607,24 +655,56 @@
         }
         
         public void setPromptText(CharSequence hintText) {
+            // Hint text is ignored for dropdowns, but maintain it here.
             mHintText = hintText;
-            if (mHintView != null) {
-                mHintView.setText(hintText);
-            }
         }
 
         @Override
         public void show() {
-            if (mHintView == null) {
-                final TextView textView = (TextView) LayoutInflater.from(getContext()).inflate(
-                        mHintResource, null).findViewById(com.android.internal.R.id.text1);
-                textView.setText(mHintText);
-                setPromptView(textView);
-                mHintView = textView;
-            }
+            setWidth(Spinner.this.getWidth());
             super.show();
             getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
             setSelection(Spinner.this.getSelectedItemPosition());
         }
+
+        @Override
+        public int measureContentWidth() {
+            final SpinnerAdapter adapter = getAdapter();
+            if (adapter == null) {
+                return 0;
+            }
+
+            int width = 0;
+            View itemView = null;
+            int itemType = 0;
+            final int widthMeasureSpec =
+                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+            final int heightMeasureSpec =
+                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+
+            // Make sure the number of items we'll measure is capped. If it's a huge data set
+            // with wildly varying sizes, oh well.
+            final int start = Math.max(0, getSelectedItemPosition());
+            final int count = Math.min(adapter.getCount(), start + MAX_ITEMS_MEASURED);
+            for (int i = start; i < count; i++) {
+                final int positionType = adapter.getItemViewType(i);
+                if (positionType != itemType) {
+                    itemType = positionType;
+                    itemView = null;
+                }
+                itemView = adapter.getDropDownView(i, itemView, Spinner.this);
+                if (itemView.getLayoutParams() == null) {
+                    itemView.setLayoutParams(generateDefaultLayoutParams());
+                }
+                itemView.measure(widthMeasureSpec, heightMeasureSpec);
+                width = Math.max(width, itemView.getMeasuredWidth());
+            }
+            return width;
+        }
+
+        private ViewGroup.LayoutParams generateDefaultLayoutParams() {
+            return new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT);
+        }
     }
 }
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 11bdd65..264af71 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -16,13 +16,14 @@
 
 package android.widget;
 
+import java.lang.ref.WeakReference;
+
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BlurMaskFilter;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
@@ -55,6 +56,7 @@
     private static final int DEFAULT_ANIMATION_DURATION = 400;
     private static final int FADE_IN_ANIMATION_DURATION = 800;
     private static final int MINIMUM_ANIMATION_DURATION = 50;
+    private static final int STACK_RELAYOUT_DURATION = 100;
 
     /**
      * Parameters effecting the perspective visuals
@@ -62,6 +64,11 @@
     private static final float PERSPECTIVE_SHIFT_FACTOR_Y = 0.1f;
     private static final float PERSPECTIVE_SHIFT_FACTOR_X = 0.1f;
 
+    private float mPerspectiveShiftX;
+    private float mPerspectiveShiftY;
+    private float mNewPerspectiveShiftX;
+    private float mNewPerspectiveShiftY;
+
     @SuppressWarnings({"FieldCanBeLocal"})
     private static final float PERSPECTIVE_SCALE_FACTOR = 0.f;
 
@@ -187,17 +194,38 @@
     /**
      * Animate the views between different relative indexes within the {@link AdapterViewAnimator}
      */
-    void animateViewForTransition(int fromIndex, int toIndex, View view) {
-        if (fromIndex == -1 && toIndex > 0) {
+    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) {
                 view.setAlpha(0);
             }
+            view.setScaleX(1 - PERSPECTIVE_SCALE_FACTOR);
+            view.setScaleY(1 - PERSPECTIVE_SCALE_FACTOR);
+            view.setTranslationX(mPerspectiveShiftX);
+            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);
@@ -205,75 +233,103 @@
             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(DEFAULT_ANIMATION_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
         if (toIndex != -1) {
-            transformViewAtIndex(toIndex, view);
+            transformViewAtIndex(toIndex, view, true);
         }
     }
 
-    private void transformViewAtIndex(int index, View view) {
-        float maxPerspectiveShiftY = getMeasuredHeight() * PERSPECTIVE_SHIFT_FACTOR_Y;
-        float maxPerspectiveShiftX = getMeasuredWidth() * PERSPECTIVE_SHIFT_FACTOR_X;
+    private void transformViewAtIndex(int index, final View view, boolean animate) {
+        final float maxPerspectiveShiftY = mPerspectiveShiftY;
+        final float maxPerspectiveShiftX = mPerspectiveShiftX;
 
         index = mMaxNumActiveViews - index - 1;
         if (index == mMaxNumActiveViews - 1) index--;
 
         float r = (index * 1.0f) / (mMaxNumActiveViews - 2);
 
-        float scale = 1 - PERSPECTIVE_SCALE_FACTOR * (1 - r);
-        PropertyValuesHolder scalePropX = PropertyValuesHolder.ofFloat("scaleX", scale);
-        PropertyValuesHolder scalePropY = PropertyValuesHolder.ofFloat("scaleY", scale);
+        final float scale = 1 - PERSPECTIVE_SCALE_FACTOR * (1 - r);
 
         int stackDirection = (mStackMode == ITEMS_SLIDE_UP) ? 1 : -1;
         float perspectiveTranslationY = -stackDirection * r * maxPerspectiveShiftY;
         float scaleShiftCorrectionY = stackDirection * (1 - scale) *
                 (getMeasuredHeight() * (1 - PERSPECTIVE_SHIFT_FACTOR_Y) / 2.0f);
-        float transY = perspectiveTranslationY + scaleShiftCorrectionY;
+        final float transY = perspectiveTranslationY + scaleShiftCorrectionY;
 
         float perspectiveTranslationX = (1 - r) * maxPerspectiveShiftX;
         float scaleShiftCorrectionX =  (1 - scale) *
                 (getMeasuredWidth() * (1 - PERSPECTIVE_SHIFT_FACTOR_X) / 2.0f);
-        float transX = perspectiveTranslationX + scaleShiftCorrectionX;
+        final float transX = perspectiveTranslationX + scaleShiftCorrectionX;
 
-        PropertyValuesHolder translationX = PropertyValuesHolder.ofFloat("translationX", transX);
-        PropertyValuesHolder translationY = PropertyValuesHolder.ofFloat("translationY", transY);
+        // 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();
+            }
+        }
 
-        ObjectAnimator pa = ObjectAnimator.ofPropertyValuesHolder(view, scalePropX, scalePropY,
-                translationY, translationX);
-        pa.setDuration(100);
-        pa.start();
+        if (animate) {
+            PropertyValuesHolder translationX = PropertyValuesHolder.ofFloat("translationX", transX);
+            PropertyValuesHolder translationY = PropertyValuesHolder.ofFloat("translationY", transY);
+            PropertyValuesHolder scalePropX = PropertyValuesHolder.ofFloat("scaleX", scale);
+            PropertyValuesHolder scalePropY = PropertyValuesHolder.ofFloat("scaleY", scale);
+
+            ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(view, scalePropX, scalePropY,
+                    translationY, translationX);
+            oa.setDuration(STACK_RELAYOUT_DURATION);
+            view.setTagInternal(com.android.internal.R.id.viewAnimation, 
+                    new WeakReference<ObjectAnimator>(oa));
+            oa.start();
+        } else {
+            view.setTranslationX(transX);
+            view.setTranslationY(transY);
+            view.setScaleX(scale);
+            view.setScaleY(scale);
+        }
     }
 
     private void setupStackSlider(View v, int mode) {
@@ -369,7 +425,7 @@
         for (int i = 0; i < getNumActiveViews(); i++) {
             View v = getViewAtRelativeIndex(i);
             if (v != null) {
-                transformViewAtIndex(i, v);
+                transformViewAtIndex(i, v, false);
             }
         }
     }
@@ -409,6 +465,13 @@
             mSwipeThreshold = Math.round(SWIPE_THRESHOLD_RATIO * mSlideAmount);
             mFirstLayoutHappened = true;
         }
+
+        if (Float.compare(mPerspectiveShiftY, mNewPerspectiveShiftY) != 0 ||
+                Float.compare(mPerspectiveShiftX, mNewPerspectiveShiftX) != 0) {
+            mPerspectiveShiftY = mNewPerspectiveShiftY;
+            mPerspectiveShiftX = mNewPerspectiveShiftX;
+            updateChildTransforms();
+        }
     }
 
     @Override
@@ -746,6 +809,18 @@
 
             int stackDirection = (mStackMode == ITEMS_SLIDE_UP) ? 1 : -1;
 
+            // We need to prevent any clipping issues which may arise by setting a layer type.
+            // This doesn't come for free however, so we only want to enable it when required.
+            if (Float.compare(0f, mYProgress) != 0 && Float.compare(1.0f, mYProgress) != 0) {
+                if (mView.getLayerType() == LAYER_TYPE_NONE) {
+                    mView.setLayerType(LAYER_TYPE_HARDWARE, null);
+                }
+            } else {
+                if (mView.getLayerType() != LAYER_TYPE_NONE) {
+                    mView.setLayerType(LAYER_TYPE_NONE, null);
+                }
+            }
+
             switch (mMode) {
                 case NORMAL_MODE:
                     viewLp.setVerticalOffset(Math.round(-r * stackDirection * mSlideAmount));
@@ -922,15 +997,43 @@
 
     private void measureChildren() {
         final int count = getChildCount();
-        final int childWidth = Math.round(getMeasuredWidth()*(1-PERSPECTIVE_SHIFT_FACTOR_X))
+
+        final int measuredWidth = getMeasuredWidth();
+        final int measuredHeight = getMeasuredHeight();
+
+        final int childWidth = Math.round(measuredWidth*(1-PERSPECTIVE_SHIFT_FACTOR_X))
                 - mPaddingLeft - mPaddingRight;
-        final int childHeight = Math.round(getMeasuredHeight()*(1-PERSPECTIVE_SHIFT_FACTOR_Y))
+        final int childHeight = Math.round(measuredHeight*(1-PERSPECTIVE_SHIFT_FACTOR_Y))
                 - mPaddingTop - mPaddingBottom;
 
+        int maxWidth = 0;
+        int maxHeight = 0;
+
         for (int i = 0; i < count; i++) {
             final View child = getChildAt(i);
-            child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
-                    MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
+            child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.AT_MOST),
+                    MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST));
+
+            if (child != mHighlight && child != mClickFeedback) {
+                final int childMeasuredWidth = child.getMeasuredWidth();
+                final int childMeasuredHeight = child.getMeasuredHeight();
+                if (childMeasuredWidth > maxWidth) {
+                    maxWidth = childMeasuredWidth;
+                }
+                if (childMeasuredHeight > maxHeight) {
+                    maxHeight = childMeasuredHeight;
+                }
+            }
+        }
+
+        mNewPerspectiveShiftX = PERSPECTIVE_SHIFT_FACTOR_X * measuredWidth;
+        mNewPerspectiveShiftY = PERSPECTIVE_SHIFT_FACTOR_Y * measuredHeight;
+        if (maxWidth > 0 && maxWidth < childWidth) {
+            mNewPerspectiveShiftX = measuredWidth - maxWidth;
+        }
+
+        if (maxHeight > 0 && maxHeight < childHeight) {
+            mNewPerspectiveShiftY = measuredHeight - maxHeight;
         }
     }
 
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 8fb6fa3..cd4b732 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -479,9 +479,9 @@
     }
 
     private void animateThumbToCheckedState(boolean newCheckedState) {
-        float targetPos = newCheckedState ? 0 : getThumbScrollRange();
         // TODO animate!
-        mThumbPosition = targetPos;
+        //float targetPos = newCheckedState ? 0 : getThumbScrollRange();
+        //mThumbPosition = targetPos;
         setChecked(newCheckedState);
     }
 
@@ -493,12 +493,15 @@
     public void setChecked(boolean checked) {
         super.setChecked(checked);
         mThumbPosition = checked ? 0 : getThumbScrollRange();
+        invalidate();
     }
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
 
+        mThumbPosition = isChecked() ? 0 : getThumbScrollRange();
+
         int switchRight = getWidth() - getPaddingRight();
         int switchLeft = switchRight - mSwitchWidth;
         int switchTop = 0;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index c7ee57b..623cd41 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -81,6 +81,7 @@
 import android.text.method.TextKeyListener;
 import android.text.method.TimeKeyListener;
 import android.text.method.TransformationMethod;
+import android.text.style.ClickableSpan;
 import android.text.style.ParagraphStyle;
 import android.text.style.URLSpan;
 import android.text.style.UpdateAppearance;
@@ -207,8 +208,7 @@
     static final boolean DEBUG_EXTRACT = false;
     
     private static final int PRIORITY = 100;
-
-    private int mCurrentAlpha = 255;    
+    private int mCurrentAlpha = 255;
 
     final int[] mTempCoords = new int[2];
     Rect mTempRect;
@@ -309,8 +309,6 @@
     int mTextSelectHandleRes;
     int mTextEditPasteWindowLayout;
     int mTextEditNoPasteWindowLayout;
-    Drawable mEditTextMultilineBackground;
-    Drawable mEditTextSingleLineBackground;
 
     Drawable mSelectHandleLeft;
     Drawable mSelectHandleRight;
@@ -320,6 +318,8 @@
     private Callback mCustomSelectionActionModeCallback;
 
     private final int mSquaredTouchSlopDistance;
+    // Set when this TextView gained focus with some text selected. Will start selection mode.
+    private boolean mCreatedWithASelection = false;
 
     /*
      * Kick-start the font cache for the zygote process (to pay the cost of
@@ -762,10 +762,6 @@
                 mTextEditNoPasteWindowLayout = a.getResourceId(attr, 0);
                 break;
 
-            case com.android.internal.R.styleable.TextView_multilineBackground:
-                mEditTextMultilineBackground = a.getDrawable(attr);
-                break;
-
             case com.android.internal.R.styleable.TextView_textIsSelectable:
                 mTextIsSelectable = a.getBoolean(attr, false);
                 break;
@@ -773,7 +769,6 @@
         }
         a.recycle();
 
-        mEditTextSingleLineBackground = getBackground();
         BufferType bufferType = BufferType.EDITABLE;
 
         final int variation =
@@ -782,6 +777,8 @@
                 == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
         final boolean webPasswordInputType = variation
                 == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD);
+        final boolean numberPasswordInputType = variation
+                == (EditorInfo.TYPE_CLASS_NUMBER | EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD);
 
         if (inputMethod != null) {
             Class<?> c;
@@ -864,6 +861,7 @@
             mInputType = EditorInfo.TYPE_NULL;
             mInput = null;
             bufferType = BufferType.SPANNABLE;
+            // Required to request focus while in touch mode.
             setFocusableInTouchMode(true);
             // So that selection can be changed using arrow keys and touch is handled.
             setMovementMethod(ArrowKeyMovementMethod.getInstance());
@@ -898,6 +896,11 @@
                 mInputType = (mInputType & ~(EditorInfo.TYPE_MASK_VARIATION))
                         | EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD;
             }
+        } else if ((mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_NUMBER) {
+            if (numberPasswordInputType) {
+                mInputType = (mInputType & ~(EditorInfo.TYPE_MASK_VARIATION))
+                        | EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD;
+            }
         }
 
         if (selectallonfocus) {
@@ -912,9 +915,9 @@
         setCompoundDrawablePadding(drawablePadding);
 
         // Same as setSingleLine(), but make sure the transformation method and the maximum number
-        // of lines of height (for multi-line only) are unchanged.
+        // of lines of height are unchanged for multi-line TextViews.
         setInputTypeSingleLine(singleLine);
-        applySingleLine(singleLine, false, false);
+        applySingleLine(singleLine, singleLine, singleLine);
 
         if (singleLine && mInput == null && ellipsize < 0) {
                 ellipsize = 3; // END
@@ -944,7 +947,7 @@
         }
         setRawTextSize(textSize);
 
-        if (password || passwordInputType || webPasswordInputType) {
+        if (password || passwordInputType || webPasswordInputType || numberPasswordInputType) {
             setTransformationMethod(PasswordTransformationMethod.getInstance());
             typefaceIndex = MONOSPACE;
         } else if ((mInputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION))
@@ -2748,7 +2751,10 @@
                  */
                 mText = text;
 
-                if (mLinksClickable) {
+                // Do not change the movement method for text that support text selection as it
+                // would prevent an arbitrary cursor displacement.
+                final boolean hasTextSelection = this instanceof EditText || mTextIsSelectable;
+                if (mLinksClickable && !hasTextSelection) {
                     setMovementMethod(LinkMovementMethod.getInstance());
                 }
             }
@@ -3091,7 +3097,9 @@
         return variation
                 == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD)
                 || variation
-                == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD);
+                == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD)
+                || variation
+                == (EditorInfo.TYPE_CLASS_NUMBER | EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD);
     }
 
     private boolean isVisiblePasswordInputType(int inputType) {
@@ -3873,10 +3881,15 @@
         // This has to be checked here since:
         // - onFocusChanged cannot start it when focus is given to a view with selected text (after
         //   a screen rotation) since layout is not yet initialized at that point.
-        // - ExtractEditText does not call onFocus when it is displayed. Fixing this issue would
-        //   allow to test for hasSelection in onFocusChanged, which would trigger a
-        //   startTextSelectionMode here. TODO
-        if (this instanceof ExtractEditText && hasSelection() && hasSelectionController()) {
+        if (mCreatedWithASelection) {
+            startSelectionActionMode();
+            mCreatedWithASelection = false;
+        }
+
+        // Phone specific code (there is no ExtractEditText on tablets).
+        // ExtractEditText does not call onFocus when it is displayed, and mHasSelectionOnFocus can
+        // not be set. Do the test here instead.
+        if (this instanceof ExtractEditText && hasSelection()) {
             startSelectionActionMode();
         }
 
@@ -4052,7 +4065,9 @@
 
     @Override
     protected boolean onSetAlpha(int alpha) {
-        if (mMovement == null && getBackground() == null) {
+        // Alpha is supported if and only if the drawing can be done in one pass.
+        // TODO text with spans with a background color currently do not respect this alpha.
+        if (getBackground() == null) {
             mCurrentAlpha = alpha;
             final Drawables dr = mDrawables;
             if (dr != null) {
@@ -4063,6 +4078,8 @@
             }
             return true;
         }
+
+        mCurrentAlpha = 255;
         return false;
     }
 
@@ -4073,7 +4090,7 @@
      *
      * Use {@link #setTextIsSelectable(boolean)} or the
      * {@link android.R.styleable#TextView_textIsSelectable} XML attribute to make this TextView
-     * selectable (the text is not selectable by default). 
+     * selectable (text is not selectable by default).
      *
      * Note that the content of an EditText is always selectable.
      *
@@ -4088,8 +4105,8 @@
     /**
      * Sets whether or not (default) the content of this view is selectable by the user.
      * 
-     * Note that this methods affect the {@link #setFocusableInTouchMode(boolean)},
-     * {@link #setFocusable(boolean)}, {@link #setClickable(boolean)} and
+     * Note that this methods affect the {@link #setFocusable(boolean)},
+     * {@link #setFocusableInTouchMode(boolean)} {@link #setClickable(boolean)} and
      * {@link #setLongClickable(boolean)} states and you may want to restore these if they were
      * customized.
      *
@@ -4118,7 +4135,15 @@
 
     @Override
     protected int[] onCreateDrawableState(int extraSpace) {
-        final int[] drawableState = super.onCreateDrawableState(extraSpace);
+        final int[] drawableState;
+
+        if (mSingleLine) {
+            drawableState = super.onCreateDrawableState(extraSpace);
+        } else {
+            drawableState = super.onCreateDrawableState(extraSpace + 1);
+            mergeDrawableStates(drawableState, MULTILINE_STATE_SET);
+        }
+
         if (mTextIsSelectable) {
             // Disable pressed state, which was introduced when TextView was made clickable.
             // Prevents text color change.
@@ -4134,6 +4159,7 @@
                 }
             }
         }
+
         return drawableState;
     }
 
@@ -4236,7 +4262,10 @@
         }
 
         mTextPaint.setColor(color);
-        mTextPaint.setAlpha(mCurrentAlpha);
+        if (mCurrentAlpha != 255) {
+            // If set, the alpha will override the color's alpha. Multiply the alphas.
+            mTextPaint.setAlpha((mCurrentAlpha * Color.alpha(color)) / 255);
+        }
         mTextPaint.drawableState = getDrawableState();
 
         canvas.save();
@@ -4314,6 +4343,10 @@
 
                         // XXX should pass to skin instead of drawing directly
                         mHighlightPaint.setColor(cursorcolor);
+                        if (mCurrentAlpha != 255) {
+                            mHighlightPaint.setAlpha(
+                                    (mCurrentAlpha * Color.alpha(cursorcolor)) / 255);
+                        }
                         mHighlightPaint.setStyle(Paint.Style.STROKE);
 
                         highlight = mHighlightPath;
@@ -4327,6 +4360,10 @@
 
                     // XXX should pass to skin instead of drawing directly
                     mHighlightPaint.setColor(mHighlightColor);
+                    if (mCurrentAlpha != 255) {
+                        mHighlightPaint.setAlpha(
+                                (mCurrentAlpha * Color.alpha(mHighlightColor)) / 255);
+                    }
                     mHighlightPaint.setStyle(Paint.Style.FILL);
 
                     highlight = mHighlightPath;
@@ -4582,9 +4619,8 @@
 
         if ((mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) {
             int variation = mInputType & EditorInfo.TYPE_MASK_VARIATION;
-
-            if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS ||
-                variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT) {
+            if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
+                    || variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT) {
                 return true;
             }
         }
@@ -4592,6 +4628,23 @@
         return false;
     }
 
+    /**
+     * Returns true if pressing TAB in this field advances focus instead
+     * of inserting the character.  Insert tabs only in multi-line editors.
+     */
+    private boolean shouldAdvanceFocusOnTab() {
+        if (mInput != null && !mSingleLine) {
+            if ((mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) {
+                int variation = mInputType & EditorInfo.TYPE_MASK_VARIATION;
+                if (variation == EditorInfo.TYPE_TEXT_FLAG_IME_MULTI_LINE
+                        || variation == EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     private int doKeyDown(int keyCode, KeyEvent event, KeyEvent otherEvent) {
         if (!isEnabled()) {
             return 0;
@@ -4600,16 +4653,12 @@
         switch (keyCode) {
             case KeyEvent.KEYCODE_ENTER:
                 mEnterKeyIsDown = true;
-                // If ALT modifier is held, then we always insert a
-                // newline character.
-                if ((event.getMetaState()&KeyEvent.META_ALT_ON) == 0) {
-                    
+                if (event.hasNoModifiers()) {
                     // When mInputContentType is set, we know that we are
                     // running in a "modern" cupcake environment, so don't need
                     // to worry about the application trying to capture
                     // enter key events.
                     if (mInputContentType != null) {
-                        
                         // If there is an action listener, given them a
                         // chance to consume the event.
                         if (mInputContentType.onEditorActionListener != null &&
@@ -4620,12 +4669,15 @@
                             return -1;
                         }
                     }
-                    
+
                     // If our editor should move focus when enter is pressed, or
                     // this is a generated event from an IME action button, then
                     // don't let it be inserted into the text.
-                    if ((event.getFlags()&KeyEvent.FLAG_EDITOR_ACTION) != 0
+                    if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0
                             || shouldAdvanceFocusOnEnter()) {
+                        if (mOnClickListener != null) {
+                            return 0;
+                        }
                         return -1;
                     }
                 }
@@ -4633,8 +4685,18 @@
                 
             case KeyEvent.KEYCODE_DPAD_CENTER:
                 mDPadCenterIsDown = true;
-                if (shouldAdvanceFocusOnEnter()) {
-                    return 0;
+                if (event.hasNoModifiers()) {
+                    if (shouldAdvanceFocusOnEnter()) {
+                        return 0;
+                    }
+                }
+                break;
+
+            case KeyEvent.KEYCODE_TAB:
+                if (event.hasNoModifiers() || event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
+                    if (shouldAdvanceFocusOnTab()) {
+                        return 0;
+                    }
                 }
                 break;
 
@@ -4724,81 +4786,84 @@
         }
 
         hideControllers();
-        stopSelectionActionMode();
 
         switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_CENTER:
                 mDPadCenterIsDown = false;
-                /*
-                 * If there is a click listener, just call through to
-                 * super, which will invoke it.
-                 *
-                 * If there isn't a click listener, try to show the soft
-                 * input method.  (It will also
-                 * call performClick(), but that won't do anything in
-                 * this case.)
-                 */
-                if (mOnClickListener == null) {
-                    if (mMovement != null && mText instanceof Editable
-                            && mLayout != null && onCheckIsTextEditor()) {
-                        InputMethodManager imm = (InputMethodManager)
-                                getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-                        imm.showSoftInput(this, 0);
-                    }
-                }
-                return super.onKeyUp(keyCode, event);
-                
-            case KeyEvent.KEYCODE_ENTER:
-                mEnterKeyIsDown = false;
-                if (mInputContentType != null
-                        && mInputContentType.onEditorActionListener != null
-                        && mInputContentType.enterDown) {
-                    mInputContentType.enterDown = false;
-                    if (mInputContentType.onEditorActionListener.onEditorAction(
-                            this, EditorInfo.IME_NULL, event)) {
-                        return true;
-                    }
-                }
-                
-                if ((event.getFlags()&KeyEvent.FLAG_EDITOR_ACTION) != 0
-                        || shouldAdvanceFocusOnEnter()) {
+                if (event.hasNoModifiers()) {
                     /*
                      * If there is a click listener, just call through to
                      * super, which will invoke it.
                      *
-                     * If there isn't a click listener, try to advance focus,
-                     * but still call through to super, which will reset the
-                     * pressed state and longpress state.  (It will also
+                     * If there isn't a click listener, try to show the soft
+                     * input method.  (It will also
                      * call performClick(), but that won't do anything in
                      * this case.)
                      */
                     if (mOnClickListener == null) {
-                        View v = focusSearch(FOCUS_DOWN);
+                        if (mMovement != null && mText instanceof Editable
+                                && mLayout != null && onCheckIsTextEditor()) {
+                            InputMethodManager imm = (InputMethodManager)
+                                    getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+                            imm.showSoftInput(this, 0);
+                        }
+                    }
+                }
+                return super.onKeyUp(keyCode, event);
 
-                        if (v != null) {
-                            if (!v.requestFocus(FOCUS_DOWN)) {
-                                throw new IllegalStateException("focus search returned a view " +
-                                        "that wasn't able to take focus!");
-                            }
-
-                            /*
-                             * Return true because we handled the key; super
-                             * will return false because there was no click
-                             * listener.
-                             */
-                            super.onKeyUp(keyCode, event);
+            case KeyEvent.KEYCODE_ENTER:
+                mEnterKeyIsDown = false;
+                if (event.hasNoModifiers()) {
+                    if (mInputContentType != null
+                            && mInputContentType.onEditorActionListener != null
+                            && mInputContentType.enterDown) {
+                        mInputContentType.enterDown = false;
+                        if (mInputContentType.onEditorActionListener.onEditorAction(
+                                this, EditorInfo.IME_NULL, event)) {
                             return true;
-                        } else if ((event.getFlags()
-                                & KeyEvent.FLAG_EDITOR_ACTION) != 0) {
-                            // No target for next focus, but make sure the IME
-                            // if this came from it.
-                            InputMethodManager imm = InputMethodManager.peekInstance();
-                            if (imm != null) {
-                                imm.hideSoftInputFromWindow(getWindowToken(), 0);
-                            }
                         }
                     }
 
+                    if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0
+                            || shouldAdvanceFocusOnEnter()) {
+                        /*
+                         * If there is a click listener, just call through to
+                         * super, which will invoke it.
+                         *
+                         * If there isn't a click listener, try to advance focus,
+                         * but still call through to super, which will reset the
+                         * pressed state and longpress state.  (It will also
+                         * call performClick(), but that won't do anything in
+                         * this case.)
+                         */
+                        if (mOnClickListener == null) {
+                            View v = focusSearch(FOCUS_DOWN);
+
+                            if (v != null) {
+                                if (!v.requestFocus(FOCUS_DOWN)) {
+                                    throw new IllegalStateException(
+                                            "focus search returned a view " +
+                                            "that wasn't able to take focus!");
+                                }
+
+                                /*
+                                 * Return true because we handled the key; super
+                                 * will return false because there was no click
+                                 * listener.
+                                 */
+                                super.onKeyUp(keyCode, event);
+                                return true;
+                            } else if ((event.getFlags()
+                                    & KeyEvent.FLAG_EDITOR_ACTION) != 0) {
+                                // No target for next focus, but make sure the IME
+                                // if this came from it.
+                                InputMethodManager imm = InputMethodManager.peekInstance();
+                                if (imm != null) {
+                                    imm.hideSoftInputFromWindow(getWindowToken(), 0);
+                                }
+                            }
+                        }
+                    }
                     return super.onKeyUp(keyCode, event);
                 }
                 break;
@@ -5059,6 +5124,7 @@
         if (mInputMethodState != null) {
             mInputMethodState.mExtracting = req;
         }
+        // This stops a possible text selection mode. Maybe not intended.
         hideControllers();
     }
     
@@ -6338,7 +6404,7 @@
             if (applyTransformation) {
                 setTransformationMethod(SingleLineTransformationMethod.getInstance());
             }
-            setBackgroundDrawable(mEditTextSingleLineBackground);
+            // TODO setState
         } else {
             if (changeMaxLines) {
                 setMaxLines(Integer.MAX_VALUE);
@@ -6347,13 +6413,10 @@
             if (applyTransformation) {
                 setTransformationMethod(null);
             }
-            // mEditTextMultilineBackground is defined and used only in EditText
-            if (mEditTextMultilineBackground != null) {
-                setBackgroundDrawable(mEditTextMultilineBackground);
-            }
+            // TODO setState
         }
     }
-    
+
     /**
      * Causes words in the text that are longer than the view is wide
      * to be ellipsized instead of broken in the middle.  You may also
@@ -6724,7 +6787,7 @@
         sendOnTextChanged(buffer, start, before, after);
         onTextChanged(buffer, start, before, after);
 
-        // Hide the controller if the amount of content changed
+        // Hide the controllers if the amount of content changed
         if (before != after) {
             hideControllers();
         }
@@ -6968,6 +7031,12 @@
             int selStart = getSelectionStart();
             int selEnd = getSelectionEnd();
 
+            // SelectAllOnFocus fields are highlighted and not selected. Do not start text selection
+            // mode for these, unless there was a specific selection already started.
+            final boolean isFocusHighlighted = mSelectAllOnFocus && selStart == 0 &&
+                    selEnd == mText.length();
+            mCreatedWithASelection = mFrozenWithFocus && hasSelection() && !isFocusHighlighted;
+
             if (!mFrozenWithFocus || (selStart < 0 || selEnd < 0)) {
                 // If a tap was used to give focus to that view, move cursor at tap position.
                 // Has to be done before onTakeFocus, which can be overloaded.
@@ -7152,7 +7221,8 @@
                 int end = Math.min(len, mPrevEnd);
                 Selection.setSelection((Spannable)mText, start, end);
 
-                if (hasSelection()) {
+                boolean selectAllGotFocus = mSelectAllOnFocus && mTouchFocusSelected;
+                if (hasSelection() && !selectAllGotFocus) {
                     startSelectionActionMode();
                 }
             }
@@ -7207,6 +7277,19 @@
                 handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
             }
 
+            if (mLinksClickable && mAutoLinkMask != 0 && mTextIsSelectable &&
+                    action == MotionEvent.ACTION_UP && !mIgnoreActionUpEvent && isFocused()) {
+                // The LinkMovementMethod which should handle taps on links has not been installed
+                // to support text selection. We reproduce its behavior here to open links.
+                ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(),
+                        getSelectionEnd(), ClickableSpan.class);
+
+                if (links.length != 0) {
+                    links[0].onClick(this);
+                    handled = true;
+                }
+            }
+
             if (isTextEditable() || mTextIsSelectable) {
                 if (mScrollX != oldScrollX || mScrollY != oldScrollY) {
                     // Hide insertion anchor while scrolling. Leave selection.
@@ -7485,43 +7568,49 @@
 
     @Override
     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
-        switch (keyCode) {
-        case KeyEvent.KEYCODE_A:
-            if (canSelectText()) {
-                return onTextContextMenuItem(ID_SELECT_ALL);
+        final int filteredMetaState = event.getMetaState() & ~KeyEvent.META_CTRL_MASK;
+        if (KeyEvent.metaStateHasNoModifiers(filteredMetaState)) {
+            switch (keyCode) {
+            case KeyEvent.KEYCODE_A:
+                if (canSelectText()) {
+                    return onTextContextMenuItem(ID_SELECT_ALL);
+                }
+                break;
+            case KeyEvent.KEYCODE_X:
+                if (canCut()) {
+                    return onTextContextMenuItem(ID_CUT);
+                }
+                break;
+            case KeyEvent.KEYCODE_C:
+                if (canCopy()) {
+                    return onTextContextMenuItem(ID_COPY);
+                }
+                break;
+            case KeyEvent.KEYCODE_V:
+                if (canPaste()) {
+                    return onTextContextMenuItem(ID_PASTE);
+                }
+                break;
             }
-
-            break;
-
-        case KeyEvent.KEYCODE_X:
-            if (canCut()) {
-                return onTextContextMenuItem(ID_CUT);
-            }
-
-            break;
-
-        case KeyEvent.KEYCODE_C:
-            if (canCopy()) {
-                return onTextContextMenuItem(ID_COPY);
-            }
-
-            break;
-
-        case KeyEvent.KEYCODE_V:
-            if (canPaste()) {
-                return onTextContextMenuItem(ID_PASTE);
-            }
-
-            break;
         }
-
         return super.onKeyShortcut(keyCode, event);
     }
 
+    /**
+     * Unlike {@link #textCanBeSelected()}, this method is based on the <i>current</i> state of the
+     * TextView. {@link #textCanBeSelected()} has to be true (this is one of the conditions to have
+     * a selection controller (see {@link #prepareCursorControllers()}), but this is not sufficient.
+     */
     private boolean canSelectText() {
         return hasSelectionController() && mText.length() != 0;
     }
 
+    /**
+     * Test based on the <i>intrinsic</i> charateristics of the TextView.
+     * The text must be spannable and the movement method must allow for arbitary selection.
+     * 
+     * See also {@link #canSelectText()}.
+     */
     private boolean textCanBeSelected() {
         // prepareCursorController() relies on this method.
         // If you change this condition, make sure prepareCursorController is called anywhere
@@ -7562,14 +7651,13 @@
                 hasPrimaryClip());
     }
 
-    private boolean isWordCharacter(int position) {
-        final char c = mTransformed.charAt(position);
-        final int type = Character.getType(c);
+    private boolean isWordCharacter(int c, int type) {
         return (c == '\'' || c == '"' ||
                 type == Character.UPPERCASE_LETTER ||
                 type == Character.LOWERCASE_LETTER ||
                 type == Character.TITLECASE_LETTER ||
                 type == Character.MODIFIER_LETTER ||
+                type == Character.OTHER_LETTER || // Should handle asian characters
                 type == Character.DECIMAL_DIGIT_NUMBER);
     }
 
@@ -7578,17 +7666,15 @@
      *
      * @param offset An offset in the text.
      * @return The offsets for the start and end of the word located at <code>offset</code>.
-     * The two ints offsets are packed in a long, with the starting offset shifted by 32 bits.
-     * Returns a negative value if no valid word was found.
+     * The two ints offsets are packed in a long using {@link #packRangeInLong(int, int)}.
+     * Returns -1 if no valid word was found.
      */
     private long getWordLimitsAt(int offset) {
         int klass = mInputType & InputType.TYPE_MASK_CLASS;
         int variation = mInputType & InputType.TYPE_MASK_VARIATION;
 
         // Text selection is not permitted in password fields
-        if (variation == InputType.TYPE_TEXT_VARIATION_PASSWORD ||
-                variation == InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD ||
-                variation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
+        if (hasPasswordTransformationMethod()) {
             return -1;
         }
 
@@ -7614,35 +7700,32 @@
         int start = end;
 
         for (; start > 0; start--) {
-            if (start == end) {
+            final char c = mTransformed.charAt(start - 1);
+            final int type = Character.getType(c);
+            if (start == end && type == Character.OTHER_PUNCTUATION) { 
                 // Cases where the text ends with a '.' and we select from the end of the line
                 // (right after the dot), or when we select from the space character in "aaa, bbb".
-                final char c = mTransformed.charAt(start - 1);
-                final int type = Character.getType(c);
-                if (type == Character.OTHER_PUNCTUATION) continue;
+                continue;
+            }              
+            if (type == Character.SURROGATE) { // Two Character codepoint
+                end = start - 1; // Recheck as a pair when scanning forward
+                continue;
             }
-            if (!isWordCharacter(start - 1)) break;
+            if (!isWordCharacter(c, type)) break;
             if ((end - start) > MAX_LENGTH) return -1;
         }
 
         for (; end < len; end++) {
-            if (!isWordCharacter(end)) break;
+            final int c = Character.codePointAt(mTransformed, end);
+            final int type = Character.getType(c);
+            if (!isWordCharacter(c, type)) break;
             if ((end - start) > MAX_LENGTH) return -1;
-        }
-
-        if (start == end) {
-            return -1;
-        }
-
-        boolean hasLetter = false;
-        for (int i = start; i < end; i++) {
-            if (Character.isLetter(mTransformed.charAt(i))) {
-                hasLetter = true;
-                break;
+            if (c > 0xFFFF) { // Two Character codepoint
+                end++;
             }
         }
 
-        if (!hasLetter) {
+        if (start == end) {
             return -1;
         }
 
@@ -7672,14 +7755,45 @@
         }
 
         if (hasPasswordTransformationMethod()) {
-            // selectCurrentWord is not available on a password field and would return an
-            // arbitrary 10-charater selection around pressed position. Select all instead.
-            // Note that cut/copy menu entries are not available for passwords.
-            // This is however useful to delete or paste to replace the entire content.
+            // Always select all on a password field.
+            // Cut/copy menu entries are not available for passwords, but being able to select all
+            // is however useful to delete or paste to replace the entire content.
             selectAll();
             return;
         }
 
+        long lastTouchOffsets = getLastTouchOffsets();
+        final int minOffset = extractRangeStartFromLong(lastTouchOffsets);
+        final int maxOffset = extractRangeEndFromLong(lastTouchOffsets);
+
+        int selectionStart, selectionEnd;
+
+        // If a URLSpan (web address, email, phone...) is found at that position, select it.
+        URLSpan[] urlSpans = ((Spanned) mText).getSpans(minOffset, maxOffset, URLSpan.class);
+        if (urlSpans.length == 1) {
+            URLSpan url = urlSpans[0];
+            selectionStart = ((Spanned) mText).getSpanStart(url);
+            selectionEnd = ((Spanned) mText).getSpanEnd(url);
+        } else {
+            long wordLimits = getWordLimitsAt(minOffset);
+            if (wordLimits >= 0) {
+                selectionStart = extractRangeStartFromLong(wordLimits);
+            } else {
+                selectionStart = Math.max(minOffset - 5, 0);
+            }
+
+            wordLimits = getWordLimitsAt(maxOffset);
+            if (wordLimits >= 0) {
+                selectionEnd = extractRangeEndFromLong(wordLimits);
+            } else {
+                selectionEnd = Math.min(maxOffset + 5, mText.length());
+            }
+        }
+
+        Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
+    }
+
+    private long getLastTouchOffsets() {
         int minOffset, maxOffset;
 
         if (mContextMenuTriggeredByKey) {
@@ -7691,23 +7805,7 @@
             maxOffset = selectionController.getMaxTouchOffset();
         }
 
-        int selectionStart, selectionEnd;
-
-        long wordLimits = getWordLimitsAt(minOffset);
-        if (wordLimits >= 0) {
-            selectionStart = extractRangeStartFromLong(wordLimits);
-        } else {
-            selectionStart = Math.max(minOffset - 5, 0);
-        }
-
-        wordLimits = getWordLimitsAt(maxOffset);
-        if (wordLimits >= 0) {
-            selectionEnd = extractRangeEndFromLong(wordLimits);
-        } else {
-            selectionEnd = Math.min(maxOffset + 5, mText.length());
-        }
-
-        Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
+        return packRangeInLong(minOffset, maxOffset);
     }
 
     @Override
@@ -7752,28 +7850,25 @@
         boolean added = false;
         mContextMenuTriggeredByKey = mDPadCenterIsDown || mEnterKeyIsDown;
         // Problem with context menu on long press: the menu appears while the key in down and when
-        // the key is released, the view does not receive the key_up event. This ensures that the
-        // state is reset whenever the context menu action is displayed.
-        // mContextMenuTriggeredByKey saved that state so that it is available in
-        // onTextContextMenuItem. We cannot simply clear these flags in onTextContextMenuItem since
+        // the key is released, the view does not receive the key_up event.
+        // We need two layers of flags: mDPadCenterIsDown and mEnterKeyIsDown are set in key down/up
+        // events. We cannot simply clear these flags in onTextContextMenuItem since
         // it may not be called (if the user/ discards the context menu with the back key).
+        // We clear these flags here and mContextMenuTriggeredByKey saves that state so that it is
+        // available in onTextContextMenuItem.
         mDPadCenterIsDown = mEnterKeyIsDown = false;
 
         MenuHandler handler = new MenuHandler();
 
-        if (mText instanceof Spanned) {
-            int selStart = getSelectionStart();
-            int selEnd = getSelectionEnd();
+        if (mText instanceof Spanned && hasSelectionController()) {
+            long lastTouchOffset = getLastTouchOffsets();
+            final int selStart = extractRangeStartFromLong(lastTouchOffset);
+            final int selEnd = extractRangeEndFromLong(lastTouchOffset);
 
-            int min = Math.min(selStart, selEnd);
-            int max = Math.max(selStart, selEnd);
-
-            URLSpan[] urls = ((Spanned) mText).getSpans(min, max,
-                                                        URLSpan.class);
-            if (urls.length == 1) {
-                menu.add(0, ID_COPY_URL, 0,
-                         com.android.internal.R.string.copyUrl).
-                            setOnMenuItemClickListener(handler);
+            URLSpan[] urls = ((Spanned) mText).getSpans(selStart, selEnd, URLSpan.class);
+            if (urls.length > 0) {
+                menu.add(0, ID_COPY_URL, 0, com.android.internal.R.string.copyUrl).
+                        setOnMenuItemClickListener(handler);
 
                 added = true;
             }
@@ -7785,7 +7880,7 @@
         // populates the menu AFTER this call.
         if (menu.size() > 0) {
             menu.add(0, ID_SELECTION_MODE, 0, com.android.internal.R.string.selectTextMode).
-            setOnMenuItemClickListener(handler);
+                    setOnMenuItemClickListener(handler);
             added = true;
         }
 
@@ -7820,7 +7915,9 @@
 
     /**
      * Called when a context menu option for the text view is selected.  Currently
-     * this will be {@link android.R.id#copyUrl} or {@link android.R.id#selectTextMode}.
+     * this will be {@link android.R.id#copyUrl}, {@link android.R.id#selectTextMode},
+     * {@link android.R.id#selectAll}, {@link android.R.id#paste}, {@link android.R.id#cut}
+     * or {@link android.R.id#copy}.
      */
     public boolean onTextContextMenuItem(int id) {
         int min = 0;
@@ -7854,88 +7951,123 @@
                         setPrimaryClip(clip);
                     }
                 }
+                stopSelectionActionMode();
                 return true;
 
             case ID_SELECTION_MODE:
-                startSelectionActionMode();
+                if (mSelectionActionMode != null) {
+                    // Selection mode is already started, simply change selected part.
+                    updateSelectedRegion();
+                } else {
+                    startSelectionActionMode();
+                }
                 return true;
-            }
 
+            case ID_SELECT_ALL:
+                selectAll();
+                // Update controller positions after selection change.
+                if (hasSelectionController()) {
+                    getSelectionController().show();
+                }
+                return true;
+
+            case ID_PASTE:
+                paste(min, max);
+                return true;
+
+            case ID_CUT:
+                setPrimaryClip(ClipData.newPlainText(null, null,
+                        mTransformed.subSequence(min, max)));
+                ((Editable) mText).delete(min, max);
+                stopSelectionActionMode();
+                return true;
+
+            case ID_COPY:
+                setPrimaryClip(ClipData.newPlainText(null, null,
+                        mTransformed.subSequence(min, max)));
+                stopSelectionActionMode();
+                return true;
+        }
         return false;
     }
 
     /**
      * Prepare text so that there are not zero or two spaces at beginning and end of region defined
      * by [min, max] when replacing this region by paste.
-     * Note that if there was two spaces (or more) at that position before, they are kept. We just
+     * Note that if there were two spaces (or more) at that position before, they are kept. We just
      * make sure we do not add an extra one from the paste content.
      */
     private long prepareSpacesAroundPaste(int min, int max, CharSequence paste) {
-        // Paste adds/removes spaces before or after insertion as needed.
-        if (paste.length() > 0 && Character.isSpaceChar(paste.charAt(0))) {
-            if (min > 0 && Character.isSpaceChar(mTransformed.charAt(min - 1))) {
-                // Two spaces at beginning of paste: remove one
-                final int originalLength = mText.length();
-                ((Editable) mText).delete(min - 1, min);
-                // Due to filters, there is no guarantee that exactly one character was
-                // removed. Count instead.
-                final int delta = mText.length() - originalLength;
-                min += delta;
-                max += delta;
-            }
-        } else {
-            if (min > 0 && !Character.isSpaceChar(mTransformed.charAt(min - 1))) {
-                // No space at beginning of paste: add one
-                final int originalLength = mText.length();
-                ((Editable) mText).replace(min, min, " ");
-                // Taking possible filters into account as above.
-                final int delta = mText.length() - originalLength;
-                min += delta;
-                max += delta;
-            }
-        }
+        if (paste.length() > 0) {
+            if (min > 0) {
+                final char charBefore = mTransformed.charAt(min - 1);
+                final char charAfter = paste.charAt(0);
 
-        if (paste.length() > 0 && Character.isSpaceChar(paste.charAt(paste.length() - 1))) {
-            if (max < mText.length() && Character.isSpaceChar(mTransformed.charAt(max))) {
-                // Two spaces at end of paste: remove one
-                ((Editable) mText).delete(max, max + 1);
+                if (Character.isSpaceChar(charBefore) && Character.isSpaceChar(charAfter)) {
+                    // Two spaces at beginning of paste: remove one
+                    final int originalLength = mText.length();
+                    ((Editable) mText).delete(min - 1, min);
+                    // Due to filters, there is no guarantee that exactly one character was
+                    // removed: count instead.
+                    final int delta = mText.length() - originalLength;
+                    min += delta;
+                    max += delta;
+                } else if (!Character.isSpaceChar(charBefore) && charBefore != '\n' &&
+                        !Character.isSpaceChar(charAfter) && charAfter != '\n') {
+                    // No space at beginning of paste: add one
+                    final int originalLength = mText.length();
+                    ((Editable) mText).replace(min, min, " ");
+                    // Taking possible filters into account as above.
+                    final int delta = mText.length() - originalLength;
+                    min += delta;
+                    max += delta;
+                }
             }
-        } else {
-            if (max < mText.length() && !Character.isSpaceChar(mTransformed.charAt(max))) {
-                // No space at end of paste: add one
-                ((Editable) mText).replace(max, max, " ");
+
+            if (max < mText.length()) {
+                final char charBefore = paste.charAt(paste.length() - 1);
+                final char charAfter = mTransformed.charAt(max);
+
+                if (Character.isSpaceChar(charBefore) && Character.isSpaceChar(charAfter)) {
+                    // Two spaces at end of paste: remove one
+                    ((Editable) mText).delete(max, max + 1);
+                } else if (!Character.isSpaceChar(charBefore) && charBefore != '\n' &&
+                        !Character.isSpaceChar(charAfter) && charAfter != '\n') {
+                    // No space at end of paste: add one
+                    ((Editable) mText).replace(max, max, " ");
+                }
             }
         }
 
         return packRangeInLong(min, max);
     }
 
-    private DragThumbnailBuilder getTextThumbnailBuilder(CharSequence text) {
-        TextView thumbnail = (TextView) inflate(mContext,
+    private DragShadowBuilder getTextThumbnailBuilder(CharSequence text) {
+        TextView shadowView = (TextView) inflate(mContext,
                 com.android.internal.R.layout.text_drag_thumbnail, null);
 
-        if (thumbnail == null) {
+        if (shadowView == null) {
             throw new IllegalArgumentException("Unable to inflate text drag thumbnail");
         }
 
-        if (text.length() > DRAG_THUMBNAIL_MAX_TEXT_LENGTH) {
-            text = text.subSequence(0, DRAG_THUMBNAIL_MAX_TEXT_LENGTH);
+        if (text.length() > DRAG_SHADOW_MAX_TEXT_LENGTH) {
+            text = text.subSequence(0, DRAG_SHADOW_MAX_TEXT_LENGTH);
         }
-        thumbnail.setText(text);
-        thumbnail.setTextColor(getTextColors());
+        shadowView.setText(text);
+        shadowView.setTextColor(getTextColors());
 
-        thumbnail.setTextAppearance(mContext, R.styleable.Theme_textAppearanceLarge);
-        thumbnail.setGravity(Gravity.CENTER);
+        shadowView.setTextAppearance(mContext, R.styleable.Theme_textAppearanceLarge);
+        shadowView.setGravity(Gravity.CENTER);
 
-        thumbnail.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+        shadowView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                 ViewGroup.LayoutParams.WRAP_CONTENT));
 
         final int size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
-        thumbnail.measure(size, size);
+        shadowView.measure(size, size);
 
-        thumbnail.layout(0, 0, thumbnail.getMeasuredWidth(), thumbnail.getMeasuredHeight());
-        thumbnail.invalidate();
-        return new DragThumbnailBuilder(thumbnail);
+        shadowView.layout(0, 0, shadowView.getMeasuredWidth(), shadowView.getMeasuredHeight());
+        shadowView.invalidate();
+        return new DragShadowBuilder(shadowView);
     }
 
     private static class DragLocalState {
@@ -7956,9 +8088,9 @@
             return true;
         }
 
+        // Long press in empty space moves cursor and shows the Paste affordance if available.
         if (!isPositionOnText(mLastDownPositionX, mLastDownPositionY) &&
                 mInsertionControllerEnabled) {
-            // Long press in empty space moves cursor and shows the Paste affordance if available.
             final int offset = getOffset(mLastDownPositionX, mLastDownPositionY);
             stopSelectionActionMode();
             Selection.setSelection((Spannable)mText, offset);
@@ -7975,17 +8107,17 @@
                 CharSequence selectedText = mTransformed.subSequence(start, end);
                 ClipData data = ClipData.newPlainText(null, null, selectedText);
                 DragLocalState localState = new DragLocalState(this, start, end);
-                startDrag(data, getTextThumbnailBuilder(selectedText), false, localState);
+                startDrag(data, getTextThumbnailBuilder(selectedText), localState, 0);
                 stopSelectionActionMode();
             } else {
-                selectCurrentWord();
-                getSelectionController().show();
+                updateSelectedRegion();
             }
             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
             mDiscardNextActionUp = true;
             return true;
         }
 
+        // Start a new selection
         if (startSelectionActionMode()) {
             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
             mDiscardNextActionUp = true;
@@ -7995,6 +8127,17 @@
         return false;
     }
 
+    /**
+     * When selection mode is already started, this method simply updates the selected part of text
+     * to the text under the finger.
+     */
+    private void updateSelectedRegion() {
+        // Start a new selection at current position, keep selectionAction mode on
+        selectCurrentWord();
+        // Updates handles' positions
+        getSelectionController().show();
+    }
+
     private boolean touchPositionIsInSelection() {
         int selectionStart = getSelectionStart();
         int selectionEnd = getSelectionEnd();
@@ -8060,7 +8203,23 @@
             return false;
         }
 
-        selectCurrentWord();
+        if (!canSelectText() || !requestFocus()) {
+            Log.w(LOG_TAG, "TextView does not support text selection. Action mode cancelled.");
+            return false;
+        }
+
+        if (!hasSelection()) {
+            // If selection mode is started after a device rotation, there is already a selection.
+            selectCurrentWord();
+        }
+
+        if (!mTextIsSelectable) {
+            // Show the IME, except when selection non editable text.
+            final InputMethodManager imm = (InputMethodManager)
+                    getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+            imm.showSoftInput(this, 0, null);
+        }
+
         ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
         mSelectionActionMode = startActionMode(actionModeCallback);
         return mSelectionActionMode != null;
@@ -8083,6 +8242,7 @@
 
     private void stopSelectionActionMode() {
         if (mSelectionActionMode != null) {
+            // This will hide the mSelectionModifierCursorController
             mSelectionActionMode.finish();
         }
     }
@@ -8133,26 +8293,15 @@
 
         @Override
         public boolean onCreateActionMode(ActionMode mode, Menu menu) {
-            if (!hasSelectionController()) {
-                Log.w(LOG_TAG, "TextView has no selection controller. Action mode cancelled.");
-                return false;
-            }
-
-            if (!requestFocus()) {
-                return false;
-            }
-
             TypedArray styledAttributes = mContext.obtainStyledAttributes(R.styleable.Theme);
 
             mode.setTitle(mContext.getString(com.android.internal.R.string.textSelectionCABTitle));
             mode.setSubtitle(null);
 
-            if (canSelectText()) {
-                menu.add(0, ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll).
+            menu.add(0, ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll).
                     setAlphabeticShortcut('a').
                     setShowAsAction(
                             MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-            }
 
             if (canCut()) {
                 menu.add(0, ID_CUT, 0, com.android.internal.R.string.cut).
@@ -8209,49 +8358,7 @@
                  mCustomSelectionActionModeCallback.onActionItemClicked(mode, item)) {
                 return true;
             }
-
-            final int itemId = item.getItemId();
-
-            if (itemId == ID_SELECT_ALL) {
-                selectAll();
-                // Update controller positions after selection change.
-                if (hasSelectionController()) {
-                    getSelectionController().show();
-                }
-                return true;
-            }
-
-            int min = 0;
-            int max = mText.length();
-
-            if (isFocused()) {
-                final int selStart = getSelectionStart();
-                final int selEnd = getSelectionEnd();
-
-                min = Math.max(0, Math.min(selStart, selEnd));
-                max = Math.max(0, Math.max(selStart, selEnd));
-            }
-
-            switch (item.getItemId()) {
-                case ID_PASTE:
-                    paste(min, max);
-                    return true;
-
-                case ID_CUT:
-                    setPrimaryClip(ClipData.newPlainText(null, null,
-                            mTransformed.subSequence(min, max)));
-                    ((Editable) mText).delete(min, max);
-                    stopSelectionActionMode();
-                    return true;
-
-                case ID_COPY:
-                    setPrimaryClip(ClipData.newPlainText(null, null,
-                            mTransformed.subSequence(min, max)));
-                    stopSelectionActionMode();
-                    return true;
-            }
-
-            return false;
+            return onTextContextMenuItem(item.getItemId());
         }
 
         @Override
@@ -8259,8 +8366,12 @@
             if (mCustomSelectionActionModeCallback != null) {
                 mCustomSelectionActionModeCallback.onDestroyActionMode(mode);
             }
-            Selection.setSelection((Spannable) mText, getSelectionStart());
-            hideSelectionModifierCursorController();
+            Selection.setSelection((Spannable) mText, getSelectionEnd());
+
+            if (mSelectionModifierCursorController != null) {
+                mSelectionModifierCursorController.hide();
+            }
+
             mSelectionActionMode = null;
         }
     }
@@ -9076,16 +9187,12 @@
         }
     }
 
-    private void hideSelectionModifierCursorController() {
-        // No need to create the controller to hide it.
-        if (mSelectionModifierCursorController != null) {
-            mSelectionModifierCursorController.hide();
-        }
-    }
-    
+    /**
+     * Hides the insertion controller and stops text selection mode, hiding the selection controller
+     */
     private void hideControllers() {
         hideInsertionPointCursorController();
-        hideSelectionModifierCursorController();
+        stopSelectionActionMode();
     }
 
     /**
@@ -9406,9 +9513,11 @@
     private static final InputFilter[] NO_FILTERS = new InputFilter[0];
     private InputFilter[] mFilters = NO_FILTERS;
     private static final Spanned EMPTY_SPANNED = new SpannedString("");
-    private static int DRAG_THUMBNAIL_MAX_TEXT_LENGTH = 20;
+    private static int DRAG_SHADOW_MAX_TEXT_LENGTH = 20;
     // System wide time for last cut or copy action.
     private static long sLastCutOrCopyTime;
     // Used to highlight a word when it is corrected by the IME
     private CorrectionHighlighter mCorrectionHighlighter;
+    // New state used to change background based on whether this TextView is multiline.
+    private static final int[] MULTILINE_STATE_SET = { R.attr.state_multiline };
 }
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 203b637..8f3442e 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -25,7 +25,7 @@
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.widget.NumberPicker.OnChangeListener;
+import android.widget.NumberPicker.OnValueChangedListener;
 
 import java.text.DateFormatSymbols;
 import java.util.Calendar;
@@ -52,6 +52,8 @@
 @Widget
 public class TimePicker extends FrameLayout {
 
+    private static final boolean DEFAULT_ENABLED_STATE = true;
+
     /**
      * A no-op callback used in the constructor to avoid null checks
      * later in the code.
@@ -68,13 +70,15 @@
     private boolean mIsAm;
 
     // ui components
-    private final NumberPicker mHourPicker;
-    private final NumberPicker mMinutePicker;
-    private final NumberPicker mAmPmPicker;
+    private final NumberPicker mHourSpinner;
+    private final NumberPicker mMinuteSpinner;
+    private final NumberPicker mAmPmSpinner;
     private final TextView mDivider;
 
     private final String[] mAmPmStrings;
 
+    private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
+
     // callbacks
     private OnTimeChangedListener mOnTimeChangedListener;
 
@@ -109,9 +113,9 @@
             true);
 
         // hour
-        mHourPicker = (NumberPicker) findViewById(R.id.hour);
-        mHourPicker.setOnChangeListener(new NumberPicker.OnChangeListener() {
-            public void onChange(NumberPicker spinner, int oldVal, int newVal) {
+        mHourSpinner = (NumberPicker) findViewById(R.id.hour);
+        mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangedListener() {
+            public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
                 mCurrentHour = newVal;
                 if (!mIs24HourView) {
                     // adjust from [1-12] to [0-11] internally, with the times
@@ -133,21 +137,22 @@
         mDivider.setText(R.string.time_picker_separator);
 
         // digits of minute
-        mMinutePicker = (NumberPicker) findViewById(R.id.minute);
-        mMinutePicker.setRange(0, 59);
-        mMinutePicker.setOnLongPressUpdateInterval(100);
-        mMinutePicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
-        mMinutePicker.setOnChangeListener(new NumberPicker.OnChangeListener() {
-            public void onChange(NumberPicker spinner, int oldVal, int newVal) {
+        mMinuteSpinner = (NumberPicker) findViewById(R.id.minute);
+        mMinuteSpinner.setMinValue(0);
+        mMinuteSpinner.setMaxValue(59);
+        mMinuteSpinner.setOnLongPressUpdateInterval(100);
+        mMinuteSpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+        mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangedListener() {
+            public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
                 mCurrentMinute = newVal;
                 onTimeChanged();
             }
         });
 
         // am/pm
-        mAmPmPicker = (NumberPicker) findViewById(R.id.amPm);
-        mAmPmPicker.setOnChangeListener(new OnChangeListener() {
-            public void onChange(NumberPicker picker, int oldVal, int newVal) {
+        mAmPmSpinner = (NumberPicker) findViewById(R.id.amPm);
+        mAmPmSpinner.setOnValueChangedListener(new OnValueChangedListener() {
+            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                 picker.requestFocus();
                 if (mIsAm) {
                     // Currently AM switching to PM
@@ -187,10 +192,20 @@
 
     @Override
     public void setEnabled(boolean enabled) {
+        if (mIsEnabled == enabled) {
+            return;
+        }
         super.setEnabled(enabled);
-        mMinutePicker.setEnabled(enabled);
-        mHourPicker.setEnabled(enabled);
-        mAmPmPicker.setEnabled(enabled);
+        mMinuteSpinner.setEnabled(enabled);
+        mDivider.setEnabled(enabled);
+        mHourSpinner.setEnabled(enabled);
+        mAmPmSpinner.setEnabled(enabled);
+        mIsEnabled = enabled;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return mIsEnabled;
     }
 
     /**
@@ -228,6 +243,7 @@
             dest.writeInt(mMinute);
         }
 
+        @SuppressWarnings("unused")
         public static final Parcelable.Creator<SavedState> CREATOR
                 = new Creator<SavedState>() {
             public SavedState createFromParcel(Parcel in) {
@@ -313,7 +329,7 @@
 
     @Override
     public int getBaseline() {
-        return mHourPicker.getBaseline(); 
+        return mHourSpinner.getBaseline();
     }
 
     /**
@@ -329,22 +345,26 @@
                 currentHour = 12;
             }
         }
-        mHourPicker.setCurrent(currentHour);
+        mHourSpinner.setValue(currentHour);
         mIsAm = mCurrentHour < 12;
-        mAmPmPicker.setCurrent(mIsAm ? Calendar.AM : Calendar.PM);
+        mAmPmSpinner.setValue(mIsAm ? Calendar.AM : Calendar.PM);
         onTimeChanged();
     }
 
     private void configurePickerRanges() {
         if (mIs24HourView) {
-            mHourPicker.setRange(0, 23);
-            mHourPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
-            mAmPmPicker.setVisibility(View.GONE);
+            mHourSpinner.setMinValue(0);
+            mHourSpinner.setMaxValue(23);
+            mHourSpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+            mAmPmSpinner.setVisibility(View.GONE);
         } else {
-            mHourPicker.setRange(1, 12);
-            mHourPicker.setFormatter(null);
-            mAmPmPicker.setVisibility(View.VISIBLE);
-            mAmPmPicker.setRange(0, 1, mAmPmStrings);
+            mHourSpinner.setMinValue(1);
+            mHourSpinner.setMaxValue(12);
+            mHourSpinner.setFormatter(null);
+            mAmPmSpinner.setVisibility(View.VISIBLE);
+            mAmPmSpinner.setMinValue(0);
+            mAmPmSpinner.setMaxValue(1);
+            mAmPmSpinner.setDisplayedValues(mAmPmStrings);
         }
     }
 
@@ -358,7 +378,7 @@
      * Set the state of the spinners appropriate to the current minute.
      */
     private void updateMinuteDisplay() {
-        mMinutePicker.setCurrent(mCurrentMinute);
+        mMinuteSpinner.setValue(mCurrentMinute);
         onTimeChanged();
     }
 }
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 3a58867..4ee3083 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -238,6 +238,36 @@
     }
 
     @Override
+    public void setCustomView(int resId) {
+        setCustomView(LayoutInflater.from(mContext).inflate(resId, mActionView, false));
+    }
+
+    @Override
+    public void setDisplayUseLogoEnabled(boolean useLogo) {
+        setDisplayOptions(useLogo ? DISPLAY_USE_LOGO : 0, DISPLAY_USE_LOGO);
+    }
+
+    @Override
+    public void setDisplayShowHomeEnabled(boolean showHome) {
+        setDisplayOptions(showHome ? DISPLAY_SHOW_HOME : 0, DISPLAY_SHOW_HOME);
+    }
+
+    @Override
+    public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) {
+        setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP : 0, DISPLAY_HOME_AS_UP);
+    }
+
+    @Override
+    public void setDisplayShowTitleEnabled(boolean showTitle) {
+        setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE : 0, DISPLAY_SHOW_TITLE);
+    }
+
+    @Override
+    public void setDisplayShowCustomEnabled(boolean showCustom) {
+        setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM : 0, DISPLAY_SHOW_CUSTOM);
+    }
+
+    @Override
     public void setTitle(int resId) {
         setTitle(mContext.getString(resId));
     }
@@ -505,12 +535,13 @@
         }
         mContainerView.setVisibility(View.VISIBLE);
         mContainerView.setAlpha(0);
-        mContainerView.setTranslationY(-mContainerView.getHeight());
         AnimatorSet anim = new AnimatorSet();
-        AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "translationY", 0))
-            .with(ObjectAnimator.ofFloat(mContainerView, "alpha", 1));
+        AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "alpha", 1));
         if (mContentView != null) {
-            b.with(ObjectAnimator.ofFloat(mContentView, "translationY", -mContainerView.getHeight(), 0));
+            b.with(ObjectAnimator.ofFloat(mContentView, "translationY",
+                    -mContainerView.getHeight(), 0));
+            mContainerView.setTranslationY(-mContainerView.getHeight());
+            b.with(ObjectAnimator.ofFloat(mContainerView, "translationY", 0));
         }
         anim.addListener(mShowListener);
         mCurrentAnim = anim;
@@ -527,11 +558,12 @@
         }
         mContainerView.setAlpha(1);
         AnimatorSet anim = new AnimatorSet();
-        AnimatorSet.Builder b = anim.play(
-                ObjectAnimator.ofFloat(mContainerView, "translationY", -mContainerView.getHeight()))
-            .with(ObjectAnimator.ofFloat(mContainerView, "alpha", 0));
+        AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "alpha", 0));
         if (mContentView != null) {
-            b.with(ObjectAnimator.ofFloat(mContentView, "translationY", 0, -mContainerView.getHeight()));
+            b.with(ObjectAnimator.ofFloat(mContentView, "translationY",
+                    0, -mContainerView.getHeight()));
+            b.with(ObjectAnimator.ofFloat(mContainerView, "translationY",
+                    -mContainerView.getHeight()));
         }
         anim.addListener(mHideListener);
         mCurrentAnim = anim;
@@ -649,12 +681,12 @@
 
         @Override
         public void setTitle(int resId) {
-            setTitle(mActivity.getString(resId));
+            setTitle(mContext.getResources().getString(resId));
         }
 
         @Override
         public void setSubtitle(int resId) {
-            setSubtitle(mActivity.getString(resId));
+            setSubtitle(mContext.getResources().getString(resId));
         }
 
         @Override
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index e384320..a139d31 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -412,9 +412,17 @@
         /* Only display the divider if we have a title and a 
          * custom view or a message.
          */
-        if (hasTitle && ((mMessage != null) || (mView != null))) {
-            View divider = mWindow.findViewById(R.id.titleDivider);
-            divider.setVisibility(View.VISIBLE);
+        if (hasTitle) {
+            View divider = null;
+            if (mMessage != null || mView != null || mListView != null) {
+                divider = mWindow.findViewById(R.id.titleDivider);
+            } else {
+                divider = mWindow.findViewById(R.id.titleDividerTop);
+            }
+
+            if (divider != null) {
+                divider.setVisibility(View.VISIBLE);
+            }
         }
         
         setBackground(topPanel, contentPanel, customPanel, hasButtons, a, hasTitle, buttonPanel);
diff --git a/core/java/com/android/internal/app/HeavyWeightSwitcherActivity.java b/core/java/com/android/internal/app/HeavyWeightSwitcherActivity.java
index 1984167..ef7e651 100644
--- a/core/java/com/android/internal/app/HeavyWeightSwitcherActivity.java
+++ b/core/java/com/android/internal/app/HeavyWeightSwitcherActivity.java
@@ -28,6 +28,7 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.View;
 import android.view.Window;
 import android.view.View.OnClickListener;
@@ -84,8 +85,10 @@
         button = findViewById((R.id.cancel));
         button.setOnClickListener(mCancelListener);
         
+        TypedValue out = new TypedValue();
+        getTheme().resolveAttribute(android.R.attr.alertDialogIcon, out, true);
         getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, 
-                android.R.drawable.ic_dialog_alert);
+                out.resourceId);
     }
 
     void setText(int id, CharSequence text) {
diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index 6f6b40b..e32c62d 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -82,6 +82,11 @@
      * {@link LocaleInfo#label}.
      */
     public static ArrayAdapter<LocaleInfo> constructAdapter(Context context) {
+        return constructAdapter(context, R.layout.locale_picker_item, R.id.locale);
+    }
+
+    public static ArrayAdapter<LocaleInfo> constructAdapter(Context context,
+            int layoutId, int fieldId) {
         final Resources resources = context.getResources();
         final String[] locales = context.getAssets().getLocales();
         final String[] specialLocaleCodes = resources.getStringArray(R.array.special_locale_codes);
@@ -149,8 +154,6 @@
             localeInfos[i] = preprocess[i];
         }
         Arrays.sort(localeInfos);
-        final int layoutId = R.layout.locale_picker_item;
-        final int fieldId = R.id.locale;
         return new ArrayAdapter<LocaleInfo>(context, layoutId, fieldId, localeInfos);
     }
 
diff --git a/core/java/com/android/internal/app/RingtonePickerActivity.java b/core/java/com/android/internal/app/RingtonePickerActivity.java
index 5569ffe..719847e 100644
--- a/core/java/com/android/internal/app/RingtonePickerActivity.java
+++ b/core/java/com/android/internal/app/RingtonePickerActivity.java
@@ -204,7 +204,7 @@
      */
     private int addStaticItem(ListView listView, int textResId) {
         TextView textView = (TextView) getLayoutInflater().inflate(
-                com.android.internal.R.layout.select_dialog_singlechoice, listView, false);
+                com.android.internal.R.layout.select_dialog_singlechoice_holo, listView, false);
         textView.setText(textResId);
         listView.addHeaderView(textView);
         mStaticItemCount++;
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java
index cbdb947..d1c3e64 100644
--- a/core/java/com/android/internal/app/ShutdownThread.java
+++ b/core/java/com/android/internal/app/ShutdownThread.java
@@ -109,7 +109,7 @@
         if (confirm) {
             final CloseDialogReceiver closer = new CloseDialogReceiver(context);
             final AlertDialog dialog = new AlertDialog.Builder(context)
-                    .setIcon(android.R.drawable.ic_dialog_alert)
+                    .setIconAttribute(android.R.attr.alertDialogIcon)
                     .setTitle(com.android.internal.R.string.power_off)
                     .setMessage(resourceId)
                     .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 284df1e..b3b80f6 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -70,7 +70,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 52;
+    private static final int VERSION = 54;
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -237,6 +237,12 @@
     int mDischargeCurrentLevel;
     int mLowDischargeAmountSinceCharge;
     int mHighDischargeAmountSinceCharge;
+    int mDischargeScreenOnUnplugLevel;
+    int mDischargeScreenOffUnplugLevel;
+    int mDischargeAmountScreenOn;
+    int mDischargeAmountScreenOnSinceCharge;
+    int mDischargeAmountScreenOff;
+    int mDischargeAmountScreenOffSinceCharge;
 
     long mLastWriteTime = 0; // Milliseconds
 
@@ -1572,6 +1578,11 @@
             // Fake a wake lock, so we consider the device waked as long
             // as the screen is on.
             noteStartWakeLocked(-1, -1, "dummy", WAKE_TYPE_PARTIAL);
+            
+            // Update discharge amounts.
+            if (mOnBatteryInternal) {
+                updateDischargeScreenLevels(false, true);
+            }
         }
     }
 
@@ -1588,6 +1599,11 @@
             }
 
             noteStopWakeLocked(-1, -1, "dummy", WAKE_TYPE_PARTIAL);
+            
+            // Update discharge amounts.
+            if (mOnBatteryInternal) {
+                updateDischargeScreenLevels(true, false);
+            }
         }
     }
 
@@ -3910,8 +3926,7 @@
         mDischargeStartLevel = 0;
         mDischargeUnplugLevel = 0;
         mDischargeCurrentLevel = 0;
-        mLowDischargeAmountSinceCharge = 0;
-        mHighDischargeAmountSinceCharge = 0;
+        initDischarge();
     }
 
     public BatteryStatsImpl(Parcel p) {
@@ -3982,6 +3997,15 @@
         mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
     }
 
+    void initDischarge() {
+        mLowDischargeAmountSinceCharge = 0;
+        mHighDischargeAmountSinceCharge = 0;
+        mDischargeAmountScreenOn = 0;
+        mDischargeAmountScreenOnSinceCharge = 0;
+        mDischargeAmountScreenOff = 0;
+        mDischargeAmountScreenOffSinceCharge = 0;
+    }
+    
     public void resetAllStatsLocked() {
         mStartCount = 0;
         initTimes();
@@ -4018,12 +4042,34 @@
             mKernelWakelockStats.clear();
         }
         
-        mLowDischargeAmountSinceCharge = 0;
-        mHighDischargeAmountSinceCharge = 0;
+        initDischarge();
 
         clearHistoryLocked();
     }
 
+    void updateDischargeScreenLevels(boolean oldScreenOn, boolean newScreenOn) {
+        if (oldScreenOn) {
+            int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
+            if (diff > 0) {
+                mDischargeAmountScreenOn += diff;
+                mDischargeAmountScreenOnSinceCharge += diff;
+            }
+        } else {
+            int diff = mDischargeScreenOffUnplugLevel - mDischargeCurrentLevel;
+            if (diff > 0) {
+                mDischargeAmountScreenOff += diff;
+                mDischargeAmountScreenOffSinceCharge += diff;
+            }
+        }
+        if (newScreenOn) {
+            mDischargeScreenOnUnplugLevel = mDischargeCurrentLevel;
+            mDischargeScreenOffUnplugLevel = 0;
+        } else {
+            mDischargeScreenOnUnplugLevel = 0;
+            mDischargeScreenOffUnplugLevel = mDischargeCurrentLevel;
+        }
+    }
+    
     void setOnBattery(boolean onBattery, int oldStatus, int level) {
         synchronized(this) {
             boolean doWrite = false;
@@ -4041,7 +4087,7 @@
                 // we have gone through a significant charge (from a very low
                 // level to a now very high level).
                 if (oldStatus == BatteryManager.BATTERY_STATUS_FULL
-                        || level >= 95
+                        || level >= 90
                         || (mDischargeCurrentLevel < 20 && level >= 80)) {
                     doWrite = true;
                     resetAllStatsLocked();
@@ -4058,6 +4104,15 @@
                 mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime);
                 mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime);
                 mDischargeCurrentLevel = mDischargeUnplugLevel = level;
+                if (mScreenOn) {
+                    mDischargeScreenOnUnplugLevel = level;
+                    mDischargeScreenOffUnplugLevel = 0;
+                } else {
+                    mDischargeScreenOnUnplugLevel = 0;
+                    mDischargeScreenOffUnplugLevel = level;
+                }
+                mDischargeAmountScreenOn = 0;
+                mDischargeAmountScreenOff = 0;
                 doUnplugLocked(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
             } else {
                 updateKernelWakelocksLocked();
@@ -4073,6 +4128,7 @@
                     mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
                     mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
                 }
+                updateDischargeScreenLevels(mScreenOn, mScreenOn);
                 doPlugLocked(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime));
             }
             if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
@@ -4361,6 +4417,50 @@
             return val;
         }
     }
+    
+    public int getDischargeAmountScreenOn() {
+        synchronized(this) {
+            int val = mDischargeAmountScreenOn;
+            if (mOnBattery && mScreenOn
+                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
+                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
+            }
+            return val;
+        }
+    }
+
+    public int getDischargeAmountScreenOnSinceCharge() {
+        synchronized(this) {
+            int val = mDischargeAmountScreenOnSinceCharge;
+            if (mOnBattery && mScreenOn
+                    && mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
+                val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
+            }
+            return val;
+        }
+    }
+
+    public int getDischargeAmountScreenOff() {
+        synchronized(this) {
+            int val = mDischargeAmountScreenOff;
+            if (mOnBattery && !mScreenOn
+                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
+                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
+            }
+            return val;
+        }
+    }
+
+    public int getDischargeAmountScreenOffSinceCharge() {
+        synchronized(this) {
+            int val = mDischargeAmountScreenOffSinceCharge;
+            if (mOnBattery && !mScreenOn
+                    && mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
+                val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
+            }
+            return val;
+        }
+    }
 
     @Override
     public int getCpuSpeedSteps() {
@@ -4667,6 +4767,8 @@
         mDischargeCurrentLevel = in.readInt();
         mLowDischargeAmountSinceCharge = in.readInt();
         mHighDischargeAmountSinceCharge = in.readInt();
+        mDischargeAmountScreenOnSinceCharge = in.readInt();
+        mDischargeAmountScreenOffSinceCharge = in.readInt();
 
         mStartCount++;
 
@@ -4862,6 +4964,8 @@
         out.writeInt(mDischargeCurrentLevel);
         out.writeInt(getLowDischargeAmountSinceCharge());
         out.writeInt(getHighDischargeAmountSinceCharge());
+        out.writeInt(getDischargeAmountScreenOnSinceCharge());
+        out.writeInt(getDischargeAmountScreenOffSinceCharge());
         
         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
@@ -5101,6 +5205,10 @@
         mDischargeCurrentLevel = in.readInt();
         mLowDischargeAmountSinceCharge = in.readInt();
         mHighDischargeAmountSinceCharge = in.readInt();
+        mDischargeAmountScreenOn = in.readInt();
+        mDischargeAmountScreenOnSinceCharge = in.readInt();
+        mDischargeAmountScreenOff = in.readInt();
+        mDischargeAmountScreenOffSinceCharge = in.readInt();
         mLastWriteTime = in.readLong();
 
         mMobileDataRx[STATS_LAST] = in.readLong();
@@ -5202,6 +5310,10 @@
         out.writeInt(mDischargeCurrentLevel);
         out.writeInt(mLowDischargeAmountSinceCharge);
         out.writeInt(mHighDischargeAmountSinceCharge);
+        out.writeInt(mDischargeAmountScreenOn);
+        out.writeInt(mDischargeAmountScreenOnSinceCharge);
+        out.writeInt(mDischargeAmountScreenOff);
+        out.writeInt(mDischargeAmountScreenOffSinceCharge);
         out.writeLong(mLastWriteTime);
 
         out.writeLong(getMobileTcpBytesReceived(STATS_SINCE_UNPLUGGED));
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 18e1b45..f58f261 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -24,7 +24,6 @@
 import android.os.Process;
 import android.os.SystemProperties;
 import android.util.Config;
-import android.util.Finalizers;
 import android.util.Log;
 import android.util.Slog;
 
@@ -142,12 +141,6 @@
             Debug.enableEmulatorTraceOutput();
         }
 
-        /**
-         * Initialize the thread used to reclaim resources without
-         * going through finalizers.
-         */
-        Finalizers.init();
-
         initialized = true;
     }
 
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 215809f..b2fbd3a7 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -31,7 +31,8 @@
 interface IInputMethodManager {
     List<InputMethodInfo> getInputMethodList();
     List<InputMethodInfo> getEnabledInputMethodList();
-    List<InputMethodSubtype> getEnabledInputMethodSubtypeList(in InputMethodInfo imi);
+    List<InputMethodSubtype> getEnabledInputMethodSubtypeList(in InputMethodInfo imi,
+            boolean allowsImplicitlySelectedSubtypes);
     // TODO: We should change the return type from List to List<Parcelable>
     // Currently there is a bug that aidl doesn't accept List<Parcelable>
     List getShortcutInputMethodsAndSubtypes();
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index d2851a9..0ef4861 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -231,4 +231,9 @@
     public View getActionView() {
         return null;
     }
+
+    @Override
+    public MenuItem setActionView(int resId) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index d5f69ba..3325df6 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 @@
         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 boolean prefersCondensedTitle() {
-        return false;
+        return true;
     }
 
     public void setCheckable(boolean checkable) {
@@ -106,10 +106,11 @@
         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 871973d..8e491e9 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -20,6 +20,7 @@
 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.View;
@@ -46,9 +47,7 @@
     private boolean mReserveOverflow;
     private OverflowMenuButton mOverflowButton;
     private MenuPopupHelper mOverflowPopup;
-    
-    private float mButtonPaddingLeft;
-    private float mButtonPaddingRight;
+
     private float mDividerPadding;
     
     private Drawable mDivider;
@@ -67,9 +66,10 @@
         }
 
         public void run() {
-            mOverflowPopup = mPopup;
-            mPopup.show();
-            mPostedOpenRunnable = null;
+            if (mPopup.tryShow()) {
+                mOverflowPopup = mPopup;
+                mPostedOpenRunnable = null;
+            }
         }
     }
 
@@ -93,16 +93,9 @@
                 Configuration.SCREENLAYOUT_SIZE_XLARGE;
         
         TypedArray a = context.obtainStyledAttributes(com.android.internal.R.styleable.Theme);
-        final int buttonStyle = a.getResourceId(
-                com.android.internal.R.styleable.Theme_actionButtonStyle, 0);
         mDivider = a.getDrawable(com.android.internal.R.styleable.Theme_dividerVertical);
         a.recycle();
         
-        a = context.obtainStyledAttributes(buttonStyle, com.android.internal.R.styleable.View);
-        mButtonPaddingLeft = a.getDimension(com.android.internal.R.styleable.View_paddingLeft, 0);
-        mButtonPaddingRight = a.getDimension(com.android.internal.R.styleable.View_paddingRight, 0);
-        a.recycle();
-        
         mDividerPadding = DIVIDER_PADDING * res.getDisplayMetrics().density;
 
         setBaselineAligned(false);
@@ -146,6 +139,10 @@
         mReserveOverflow = reserveOverflow;
     }
     
+    public View getOverflowButton() {
+        return mOverflowButton;
+    }
+
     @Override
     protected LayoutParams generateDefaultLayoutParams() {
         LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
@@ -156,6 +153,13 @@
     
     @Override
     protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+        if (p instanceof LayoutParams) {
+            LayoutParams result = new LayoutParams((LayoutParams) p);
+            if (result.gravity <= Gravity.NO_GRAVITY) {
+                result.gravity = Gravity.CENTER_VERTICAL;
+            }
+            return result;
+        }
         return generateDefaultLayoutParams();
     }
 
@@ -182,26 +186,39 @@
         
         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);
-            final View actionView = itemData.getActionView();
+
+            View actionView = itemData.getActionView();
+
             if (actionView != null) {
                 final ViewParent parent = actionView.getParent();
                 if (parent instanceof ViewGroup) {
                     ((ViewGroup) parent).removeView(actionView);
                 }
-                addView(actionView, makeActionViewLayoutParams());
+                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;
@@ -274,11 +291,8 @@
         return params;
     }
 
-    private LayoutParams makeActionViewLayoutParams() {
-        LayoutParams params = generateDefaultLayoutParams();
-        params.leftMargin = (int) mButtonPaddingLeft;
-        params.rightMargin = (int) mButtonPaddingRight;
-        return params;
+    private LayoutParams makeActionViewLayoutParams(View view) {
+        return generateLayoutParams(view.getLayoutParams());
     }
 
     private class OverflowMenuButton extends ImageButton {
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index e155875..02584b6 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 @@
     private Drawable mBackground;
     private int mTextAppearance;
     private Context mTextAppearanceContext;
+    private boolean mPreserveIconSpacing;
     
     private int mMenuType;
     
@@ -57,6 +58,8 @@
         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 void setIcon(Drawable icon) {
-        
-        if (!mItemData.shouldShowIcon(mMenuType)) {
+        final boolean showIcon = mItemData.shouldShowIcon(mMenuType);
+        if (!showIcon && !mPreserveIconSpacing) {
             return;
         }
         
@@ -197,8 +200,8 @@
             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/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index d0faea6..830c2c1 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -353,8 +353,7 @@
         mNonActionItems = new ArrayList<MenuItemImpl>();
         mIsActionItemsStale = true;
         
-        mShortcutsVisible =
-                (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS);
+        setShortcutsVisibleInner(true);
     }
     
     public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) {
@@ -782,14 +781,18 @@
      */
     public void setShortcutsVisible(boolean shortcutsVisible) {
         if (mShortcutsVisible == shortcutsVisible) return;
-        
-        mShortcutsVisible =
-            (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS)
-            && shortcutsVisible;
-        
+
+        setShortcutsVisibleInner(shortcutsVisible);
         refreshShortcuts(mShortcutsVisible, isQwertyMode());
     }
 
+    private void setShortcutsVisibleInner(boolean shortcutsVisible) {
+        mShortcutsVisible = shortcutsVisible
+                && mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS
+                && mResources.getBoolean(
+                        com.android.internal.R.bool.config_showMenuShortcutsWhenKeyboardPresent);
+    }
+
     /**
      * @return Whether shortcuts should be visible on menus.
      */
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index 8eee360..6fbae94 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 boolean shouldShowIcon(int menuType) {
         return menuType == MenuBuilder.TYPE_ICON ||
                 menuType == MenuBuilder.TYPE_ACTION_BUTTON ||
-                menuType == MenuBuilder.TYPE_POPUP ||
                 mMenu.getOptionalIconsVisible();
     }
     
@@ -694,6 +693,13 @@
         return this;
     }
 
+    public MenuItem setActionView(int resId) {
+        LayoutInflater inflater = LayoutInflater.from(mMenu.getContext());
+        ViewGroup parent = (ViewGroup) mMenu.getMenuView(MenuBuilder.TYPE_ACTION_BUTTON, null);
+        setActionView(inflater.inflate(resId, parent, false));
+        return this;
+    }
+
     public View getActionView() {
         return mActionView;
     }
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index a5fd38e..b93fac4 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -68,7 +68,17 @@
         }
     }
 
+    public void setAnchorView(View anchor) {
+        mAnchorView = new WeakReference<View>(anchor);
+    }
+
     public void show() {
+        if (!tryShow()) {
+            throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
+        }
+    }
+
+    public boolean tryShow() {
         mPopup = new ListPopupWindow(mContext, null, com.android.internal.R.attr.popupMenuStyle);
         mPopup.setOnItemClickListener(this);
         mPopup.setOnDismissListener(this);
@@ -92,13 +102,14 @@
             mTreeObserver.addOnGlobalLayoutListener(this);
             mPopup.setAnchorView(anchor);
         } else {
-            throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
+            return false;
         }
 
         mPopup.setContentWidth(Math.min(measureContentWidth(adapter), mPopupMaxWidth));
         mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
         mPopup.show();
         mPopup.getListView().setOnKeyListener(this);
+        return true;
     }
 
     public void dismiss() {
@@ -124,7 +135,7 @@
         if (mOverflowOnly) {
             item = mMenu.getOverflowItem(position);
         } else {
-            item = mMenu.getItem(position);
+            item = mMenu.getVisibleItems().get(position);
         }
         mMenu.performItemAction(item, 0);
         dismiss();
@@ -142,12 +153,18 @@
         // Menus don't tend to be long, so this is more sane than it looks.
         int width = 0;
         View itemView = null;
+        int itemType = 0;
         final int widthMeasureSpec =
             MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
         final int heightMeasureSpec =
             MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
         final int count = adapter.getCount();
         for (int i = 0; i < count; i++) {
+            final int positionType = adapter.getItemViewType(i);
+            if (positionType != itemType) {
+                itemType = positionType;
+                itemView = null;
+            }
             itemView = adapter.getView(i, itemView, null);
             itemView.measure(widthMeasureSpec, heightMeasureSpec);
             width = Math.max(width, itemView.getMeasuredWidth());
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index e520e69..e63a68f 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.widget.FrameLayout;
 
 /**
@@ -39,4 +40,10 @@
         setBackgroundDrawable(a.getDrawable(com.android.internal.R.styleable.ActionBar_background));
         a.recycle();
     }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        super.onTouchEvent(ev);
+        return true;
+    }
 }
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 5ae3616..23f89f1 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -159,7 +159,7 @@
     }
 
     public void initForMode(final ActionMode mode) {
-        if (mAnimationMode == ANIMATE_OUT) {
+        if (mAnimationMode != ANIMATE_IDLE || mAnimateInOnLayout) {
             killMode();
         }
 
@@ -216,6 +216,7 @@
         removeAllViews();
         mCustomView = null;
         mMenuView = null;
+        mAnimateInOnLayout = false;
     }
 
     public boolean showOverflowMenu() {
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index ccec32a..297dde7 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -135,6 +135,9 @@
     public ActionBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
+        // Background is always provided by the container.
+        setBackgroundResource(0);
+
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar);
 
         ApplicationInfo appInfo = context.getApplicationInfo();
@@ -434,7 +437,7 @@
                     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/java/com/android/internal/widget/DigitalClock.java b/core/java/com/android/internal/widget/DigitalClock.java
index 23e2277..bc749d8 100644
--- a/core/java/com/android/internal/widget/DigitalClock.java
+++ b/core/java/com/android/internal/widget/DigitalClock.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.Typeface;
@@ -41,12 +42,16 @@
  */
 public class DigitalClock extends RelativeLayout {
 
+    private static final String SYSTEM = "/system/fonts/";
+    private static final String SYSTEM_FONT_TIME_BACKGROUND = SYSTEM + "AndroidClock.ttf";
+    private static final String SYSTEM_FONT_TIME_FOREGROUND = SYSTEM + "AndroidClock_Highlight.ttf";
     private final static String M12 = "h:mm";
     private final static String M24 = "kk:mm";
 
     private Calendar mCalendar;
     private String mFormat;
-    private TextView mTimeDisplay;
+    private TextView mTimeDisplayBackground;
+    private TextView mTimeDisplayForeground;
     private AmPm mAmPm;
     private ContentObserver mFormatChangeObserver;
     private boolean mLive = true;
@@ -117,9 +122,14 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        mTimeDisplay = (TextView) findViewById(R.id.timeDisplay);
-        mTimeDisplay.setTypeface(Typeface.createFromFile("/system/fonts/Clockopia.ttf"));
-        mAmPm = new AmPm(this, Typeface.createFromFile("/system/fonts/DroidSans-Bold.ttf"));
+        AssetManager assets = mContext.getAssets();
+
+        /* The time display consists of two tones. That's why we have two overlapping text views. */
+        mTimeDisplayBackground = (TextView) findViewById(R.id.timeDisplayBackground);
+        mTimeDisplayBackground.setTypeface(Typeface.createFromFile(SYSTEM_FONT_TIME_BACKGROUND));
+        mTimeDisplayForeground = (TextView) findViewById(R.id.timeDisplayForeground);
+        mTimeDisplayForeground.setTypeface(Typeface.createFromFile(SYSTEM_FONT_TIME_FOREGROUND));
+        mAmPm = new AmPm(this, null);
         mCalendar = Calendar.getInstance();
 
         setDateFormat();
@@ -175,12 +185,13 @@
         }
 
         CharSequence newTime = DateFormat.format(mFormat, mCalendar);
-        mTimeDisplay.setText(newTime);
+        mTimeDisplayBackground.setText(newTime);
+        mTimeDisplayForeground.setText(newTime);
         mAmPm.setIsMorning(mCalendar.get(Calendar.AM_PM) == 0);
     }
 
     private void setDateFormat() {
-        mFormat = android.text.format.DateFormat.is24HourFormat(getContext()) 
+        mFormat = android.text.format.DateFormat.is24HourFormat(getContext())
             ? M24 : M12;
         mAmPm.setShowAmPm(mFormat.equals(M12));
     }
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 12cf853..0b765fd 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -300,6 +300,17 @@
                     mPaint.setARGB(255, pressureLevel, 128, 255 - pressureLevel);
                     drawOval(canvas, ps.mCoords.x, ps.mCoords.y, ps.mCoords.toolMajor,
                             ps.mCoords.toolMinor, ps.mCoords.orientation, mPaint);
+
+                    // Draw the orientation arrow.
+                    mPaint.setARGB(255, pressureLevel, 255, 0);
+                    float orientationVectorX = (float) (Math.sin(-ps.mCoords.orientation)
+                            * ps.mCoords.toolMajor * 0.7);
+                    float orientationVectorY = (float) (Math.cos(-ps.mCoords.orientation)
+                            * ps.mCoords.toolMajor * 0.7);
+                    canvas.drawLine(
+                            ps.mCoords.x - orientationVectorX, ps.mCoords.y - orientationVectorY,
+                            ps.mCoords.x + orientationVectorX, ps.mCoords.y + orientationVectorY,
+                            mPaint);
                 }
             }
         }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 8eeed3d..c635b39 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -111,6 +111,7 @@
 	android/graphics/Rasterizer.cpp \
 	android/graphics/Region.cpp \
 	android/graphics/Shader.cpp \
+	android/graphics/SurfaceTexture.cpp \
 	android/graphics/TextLayout.cpp \
 	android/graphics/Typeface.cpp \
 	android/graphics/Utils.cpp \
@@ -200,7 +201,7 @@
 	libmedia \
 	libwpa_client \
 	libjpeg \
-	libnfc_ndef
+	libnfc_ndef \
 
 ifeq ($(USE_OPENGL_RENDERER),true)
 	LOCAL_SHARED_LIBRARIES += libhwui
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 2dfebe5..d28bdc9 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -77,7 +77,6 @@
 extern int register_android_opengl_jni_GLES20(JNIEnv* env);
 
 extern int register_android_hardware_Camera(JNIEnv *env);
-
 extern int register_android_hardware_SensorManager(JNIEnv *env);
 
 extern int register_android_media_AudioRecord(JNIEnv *env);
@@ -112,6 +111,7 @@
 extern int register_android_graphics_Picture(JNIEnv*);
 extern int register_android_graphics_PorterDuff(JNIEnv* env);
 extern int register_android_graphics_Rasterizer(JNIEnv* env);
+extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
 extern int register_android_graphics_Xfermode(JNIEnv* env);
 extern int register_android_graphics_PixelFormat(JNIEnv* env);
 extern int register_com_android_internal_graphics_NativeUtils(JNIEnv *env);
@@ -1236,6 +1236,7 @@
     REG_JNI(register_android_graphics_Rasterizer),
     REG_JNI(register_android_graphics_Region),
     REG_JNI(register_android_graphics_Shader),
+    REG_JNI(register_android_graphics_SurfaceTexture),
     REG_JNI(register_android_graphics_Typeface),
     REG_JNI(register_android_graphics_Xfermode),
     REG_JNI(register_android_graphics_YuvImage),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 73c9a50..dac748d 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -26,7 +26,6 @@
 jfieldID gOptions_ditherFieldID;
 jfieldID gOptions_purgeableFieldID;
 jfieldID gOptions_shareableFieldID;
-jfieldID gOptions_nativeAllocFieldID;
 jfieldID gOptions_preferQualityOverSpeedFieldID;
 jfieldID gOptions_widthFieldID;
 jfieldID gOptions_heightFieldID;
@@ -155,12 +154,6 @@
             env->GetBooleanField(options, gOptions_justBoundsFieldID);
 }
 
-static bool optionsReportSizeToVM(JNIEnv* env, jobject options) {
-    return NULL == options ||
-            !env->GetBooleanField(options, gOptions_nativeAllocFieldID);
-}
-
-
 static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStream* stream,
                                    int sampleSize, bool ditherImage) {
     SkImageRef* pr;
@@ -188,7 +181,6 @@
     bool doDither = true;
     bool isPurgeable = forcePurgeable ||
                         (allowPurgeable && optionsPurgeable(env, options));
-    bool reportSizeToVM = optionsReportSizeToVM(env, options);
     bool preferQualityOverSpeed = false;
     jobject javaBitmap = NULL;
     
@@ -220,7 +212,7 @@
     decoder->setPreferQualityOverSpeed(preferQualityOverSpeed);
 
     NinePatchPeeker     peeker(decoder);
-    JavaPixelAllocator  javaAllocator(env, reportSizeToVM);
+    JavaPixelAllocator  javaAllocator(env);
     SkBitmap*           bitmap;
     if (javaBitmap == NULL) {
         bitmap = new SkBitmap;
@@ -583,7 +575,6 @@
     gOptions_ditherFieldID = getFieldIDCheck(env, gOptions_class, "inDither", "Z");
     gOptions_purgeableFieldID = getFieldIDCheck(env, gOptions_class, "inPurgeable", "Z");
     gOptions_shareableFieldID = getFieldIDCheck(env, gOptions_class, "inInputShareable", "Z");
-    gOptions_nativeAllocFieldID = getFieldIDCheck(env, gOptions_class, "inNativeAlloc", "Z");
     gOptions_preferQualityOverSpeedFieldID = getFieldIDCheck(env, gOptions_class,
             "inPreferQualityOverSpeed", "Z");
     gOptions_widthFieldID = getFieldIDCheck(env, gOptions_class, "outWidth", "I");
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index c81db82..f89967b 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -81,10 +81,7 @@
 
     JavaPixelAllocator *javaAllocator = new JavaPixelAllocator(env);
     decoder->setAllocator(javaAllocator);
-    JavaMemoryUsageReporter *javaMemoryReporter = new JavaMemoryUsageReporter(env);
-    decoder->setReporter(javaMemoryReporter);
     javaAllocator->unref();
-    javaMemoryReporter->unref();
 
     if (!decoder->buildTileIndex(stream, &width, &height)) {
         char msg[100];
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 5134c24..48ff5ed 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -9,9 +9,6 @@
 #include "SkRegion.h"
 #include <android_runtime/AndroidRuntime.h>
 
-//#define REPORT_SIZE_TO_JVM
-//#define TRACK_LOCK_COUNT
-
 void doThrow(JNIEnv* env, const char* exc, const char* msg) {
     // don't throw a new exception if we already have one pending
     if (env->ExceptionCheck() == JNI_FALSE) {
@@ -186,10 +183,6 @@
 static jfieldID gRegion_nativeInstanceID;
 static jmethodID gRegion_constructorMethodID;
 
-static jobject   gVMRuntime_singleton;
-static jmethodID gVMRuntime_trackExternalAllocationMethodID;
-static jmethodID gVMRuntime_trackExternalFreeMethodID;
-
 ///////////////////////////////////////////////////////////////////////////////
 
 void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, int* B)
@@ -428,10 +421,6 @@
     return env;
 }
 
-#ifdef TRACK_LOCK_COUNT
-    static int gLockCount;
-#endif
-
 ///////////////////////////////////////////////////////////////////////////////
 
 AndroidPixelRef::AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
@@ -539,36 +528,10 @@
     return arrayObj;
 }
 
-bool GraphicsJNI::mallocPixelRef(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable) {
-    Sk64 size64 = bitmap->getSize64();
-    if (size64.isNeg() || !size64.is32()) {
-        doThrow(env, "java/lang/IllegalArgumentException",
-                     "bitmap size exceeds 32bits");
-        return false;
-    }
-
-    size_t size = size64.get32();
-
-    // call the version of malloc that returns null on failure
-    void* addr = sk_malloc_flags(size, 0);
-
-    if (NULL == addr) {
-        return false;
-    }
-
-    SkPixelRef* pr = new AndroidPixelRef(env, addr, size, NULL, ctable);
-    bitmap->setPixelRef(pr)->unref();
-    // since we're already allocated, we lockPixels right away
-    // HeapAllocator behaves this way too
-    bitmap->lockPixels();
-    return true;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
-JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env, bool allocateInJavaHeap)
-    : fAllocateInJavaHeap(allocateInJavaHeap),
-      fStorageObj(NULL),
+JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env)
+    : fStorageObj(NULL),
       fAllocCount(0) {
     if (env->GetJavaVM(&fVM) != JNI_OK) {
         SkDebugf("------ [%p] env->GetJavaVM failed\n", env);
@@ -585,49 +548,9 @@
         SkDebugf("WARNING: One-shot allocator has already allocated (alloc count = %d)\n", fAllocCount);
 //        sk_throw();
     }
-
-    if (fAllocateInJavaHeap) {
-        fStorageObj = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable);
-        fAllocCount += 1;
-        return fStorageObj != NULL;
-    }
-    return GraphicsJNI::mallocPixelRef(env, bitmap, ctable);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-JavaMemoryUsageReporter::JavaMemoryUsageReporter(JNIEnv* env)
-    : fTotalSize(0) {
-    if (env->GetJavaVM(&fVM) != JNI_OK) {
-        SkDebugf("------ [%p] env->GetJavaVM failed\n", env);
-        sk_throw();
-    }
-}
-
-JavaMemoryUsageReporter::~JavaMemoryUsageReporter() {
-    JNIEnv* env = vm2env(fVM);
-    jlong jtotalSize = fTotalSize;
-    env->CallVoidMethod(gVMRuntime_singleton,
-            gVMRuntime_trackExternalFreeMethodID,
-            jtotalSize);
-}
-
-bool JavaMemoryUsageReporter::reportMemory(size_t memorySize) {
-    jlong jsize = memorySize;  // the VM wants longs for the size
-    JNIEnv* env = vm2env(fVM);
-    bool r = env->CallBooleanMethod(gVMRuntime_singleton,
-            gVMRuntime_trackExternalAllocationMethodID,
-            jsize);
-    if (GraphicsJNI::hasException(env)) {
-        return false;
-    }
-    if (!r) {
-        LOGE("VM won't let us allocate %zd bytes\n", memorySize);
-        doThrowOOME(env, "bitmap size exceeds VM budget");
-        return false;
-    }
-    fTotalSize += memorySize;
-    return true;
+    fStorageObj = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable);
+    fAllocCount += 1;
+    return fStorageObj != NULL;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -716,21 +639,5 @@
     gRegion_constructorMethodID = env->GetMethodID(gRegion_class, "<init>",
         "(II)V");
     
-    // Get the VMRuntime class.
-    c = env->FindClass("dalvik/system/VMRuntime");
-    SkASSERT(c);
-    // Look up VMRuntime.getRuntime().
-    m = env->GetStaticMethodID(c, "getRuntime", "()Ldalvik/system/VMRuntime;");
-    SkASSERT(m);
-    // Call VMRuntime.getRuntime() and hold onto its result.
-    gVMRuntime_singleton = env->CallStaticObjectMethod(c, m);
-    SkASSERT(gVMRuntime_singleton);
-    gVMRuntime_singleton = (jobject)env->NewGlobalRef(gVMRuntime_singleton);
-    // Look up the VMRuntime methods we'll be using.
-    gVMRuntime_trackExternalAllocationMethodID =
-                        env->GetMethodID(c, "trackExternalAllocation", "(J)Z");
-    gVMRuntime_trackExternalFreeMethodID =
-                            env->GetMethodID(c, "trackExternalFree", "(J)V");
-
     return 0;
 }
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index a71ce83..d678a5d 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -65,12 +65,6 @@
     static jbyteArray allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
                                      SkColorTable* ctable);
 
-    /** Set a pixelref for the bitmap (needs setConfig to already be called)
-        Returns true on success. If it returns false, then it failed, and the
-        appropriate exception will have been raised.
-    */
-    static bool mallocPixelRef(JNIEnv*, SkBitmap*, SkColorTable* ctable);
-
     /** Copy the colors in colors[] to the bitmap, convert to the correct
         format along the way.
     */
@@ -141,7 +135,7 @@
  */
 class JavaPixelAllocator : public SkBitmap::Allocator {
 public:
-    JavaPixelAllocator(JNIEnv* env, bool allocateInJavaHeap=true);
+    JavaPixelAllocator(JNIEnv* env);
     // overrides
     virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
     
@@ -169,18 +163,6 @@
     int fAllocCount;
 };
 
-class JavaMemoryUsageReporter : public SkVMMemoryReporter {
-public:
-    JavaMemoryUsageReporter(JNIEnv* env);
-    virtual ~JavaMemoryUsageReporter();
-    // overrides
-    virtual bool reportMemory(size_t memorySize);
-
-private:
-    JavaVM* fVM;
-    size_t fTotalSize;
-};
-
 enum JNIAccess {
     kRO_JNIAccess,
     kRW_JNIAccess
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 4be1321..3efc41d 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -64,11 +64,6 @@
 #endif
 }
 
-static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, SkMatrix* matrix)
-{
-    return shader ? shader->getLocalMatrix(matrix) : false;
-}
- 
 static void Shader_setLocalMatrix(JNIEnv* env, jobject o, SkShader* shader, SkiaShader* skiaShader,
         const SkMatrix* matrix)
 {
@@ -471,7 +466,6 @@
 
 static JNINativeMethod gShaderMethods[] = {
     { "nativeDestructor",        "(II)V",    (void*)Shader_destructor        },
-    { "nativeGetLocalMatrix",    "(II)Z",    (void*)Shader_getLocalMatrix    },
     { "nativeSetLocalMatrix",    "(III)V",   (void*)Shader_setLocalMatrix    }
 };
 
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
new file mode 100644
index 0000000..c1229f3
--- /dev/null
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceTexture"
+
+#include <stdio.h>
+
+#include <gui/SurfaceTexture.h>
+
+#include <android_runtime/AndroidRuntime.h>
+
+#include <utils/Log.h>
+#include <utils/misc.h>
+
+#include "android/graphics/GraphicsJNI.h"
+#include "jni.h"
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+static const char* const OutOfResourcesException =
+    "android/graphics/SurfaceTexture$OutOfResourcesException";
+
+struct st_t {
+    jfieldID surfaceTexture;
+};
+static st_t st;
+
+// ----------------------------------------------------------------------------
+
+static void setSurfaceTexture(JNIEnv* env, jobject clazz,
+        const sp<SurfaceTexture>& surfaceTexture)
+{
+    SurfaceTexture* const p =
+        (SurfaceTexture*)env->GetIntField(clazz, st.surfaceTexture);
+    if (surfaceTexture.get()) {
+        surfaceTexture->incStrong(clazz);
+    }
+    if (p) {
+        p->decStrong(clazz);
+    }
+    env->SetIntField(clazz, st.surfaceTexture, (int)surfaceTexture.get());
+}
+
+sp<SurfaceTexture> getSurfaceTexture(JNIEnv* env, jobject clazz)
+{
+    sp<SurfaceTexture> surfaceTexture(
+        (SurfaceTexture*)env->GetIntField(clazz, st.surfaceTexture));
+    return surfaceTexture;
+}
+
+// ----------------------------------------------------------------------------
+
+static void SurfaceTexture_init(JNIEnv* env, jobject clazz, jint texName)
+{
+    sp<SurfaceTexture> surfaceTexture(new SurfaceTexture(texName));
+
+    if (surfaceTexture == 0) {
+        doThrow(env, OutOfResourcesException);
+        return;
+    }
+    setSurfaceTexture(env, clazz, surfaceTexture);
+}
+
+static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject clazz)
+{
+    sp<SurfaceTexture> surfaceTexture(getSurfaceTexture(env, clazz));
+    surfaceTexture->updateTexImage();
+}
+
+static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject clazz,
+        jfloatArray jmtx)
+{
+    sp<SurfaceTexture> surfaceTexture(getSurfaceTexture(env, clazz));
+    float* mtx = env->GetFloatArrayElements(jmtx, NULL);
+    surfaceTexture->getTransformMatrix(mtx);
+    env->ReleaseFloatArrayElements(jmtx, mtx, 0);
+}
+
+// ----------------------------------------------------------------------------
+
+const char* const kSurfaceTextureClassPathName = "android/graphics/SurfaceTexture";
+static void nativeClassInit(JNIEnv* env, jclass clazz);
+
+static JNINativeMethod gSurfaceTextureMethods[] = {
+    {"nativeClassInit",     "()V",  (void*)nativeClassInit },
+    {"init",                "(I)V", (void*)SurfaceTexture_init },
+    {"updateTexImage",      "()V",  (void*)SurfaceTexture_updateTexImage },
+    {"getTransformMatrixImpl", "([F)V",  (void*)SurfaceTexture_getTransformMatrix },
+};
+
+static void nativeClassInit(JNIEnv* env, jclass clazz)
+{
+    st.surfaceTexture = env->GetFieldID(clazz,
+            ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I");
+}
+
+int register_android_graphics_SurfaceTexture(JNIEnv* env)
+{
+    int err = 0;
+    err = AndroidRuntime::registerNativeMethods(env, kSurfaceTextureClassPathName,
+            gSurfaceTextureMethods, NELEM(gSurfaceTextureMethods));
+    return err;
+}
+
+} // namespace android
diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp
index fad9539..a428151 100644
--- a/core/jni/android_database_CursorWindow.cpp
+++ b/core/jni/android_database_CursorWindow.cpp
@@ -50,52 +50,47 @@
     return GET_WINDOW(env, javaWindow);
 }
 
-static void native_init_empty(JNIEnv * env, jobject object, jboolean localOnly)
+static jint native_init_empty(JNIEnv * env, jobject object, jint cursorWindowSize,
+        jboolean localOnly)
 {
     uint8_t * data;
     size_t size;
     CursorWindow * window;
 
-    window = new CursorWindow(MAX_WINDOW_SIZE);
+    window = new CursorWindow(cursorWindowSize);
     if (!window) {
-        jniThrowException(env, "java/lang/RuntimeException", "No memory for native window object");
-        return;
+        return 1;
     }
-
     if (!window->initBuffer(localOnly)) {
-        jniThrowException(env, "java/lang/RuntimeException",
-                "Memory couldn't be allocated for 1MB CursorWindow object.");
         delete window;
-        return;
+        return 1;
     }
 
-LOG_WINDOW("native_init_empty: window = %p", window);
+    LOG_WINDOW("native_init_empty: window = %p", window);
     SET_WINDOW(env, object, window);
+    return 0;
 }
 
-static void native_init_memory(JNIEnv * env, jobject object, jobject memObj)
+static jint native_init_memory(JNIEnv * env, jobject object, jobject memObj)
 {
     sp<IMemory> memory = interface_cast<IMemory>(ibinderForJavaObject(env, memObj));
     if (memory == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException", "Couldn't get native binder");
-        return;
+        return 1;
     }
 
     CursorWindow * window = new CursorWindow();
     if (!window) {
-        jniThrowException(env, "java/lang/RuntimeException",
-                "CursorWindow of size 1MB couldn't be created. No memory?");
-        return;
+        return 1;
     }
     if (!window->setMemory(memory)) {
-        jniThrowException(env, "java/lang/RuntimeException",
-                "Memory couldn't be initialized for 1MB CursorWindow object.");
         delete window;
-        return;
+        return 1;
     }
 
-LOG_WINDOW("native_init_memory: numRows = %d, numColumns = %d, window = %p", window->getNumRows(), window->getNumColumns(), window);
+    LOG_WINDOW("native_init_memory: numRows = %d, numColumns = %d, window = %p", window->getNumRows(), window->getNumColumns(), window);
     SET_WINDOW(env, object, window);
+    return 0;
 }
 
 static jobject native_getBinder(JNIEnv * env, jobject object)
@@ -614,8 +609,8 @@
 static JNINativeMethod sMethods[] =
 {
      /* name, signature, funcPtr */
-    {"native_init", "(Z)V", (void *)native_init_empty},
-    {"native_init", "(Landroid/os/IBinder;)V", (void *)native_init_memory},
+    {"native_init", "(IZ)I", (void *)native_init_empty},
+    {"native_init", "(Landroid/os/IBinder;)I", (void *)native_init_memory},
     {"native_getBinder", "()Landroid/os/IBinder;", (void *)native_getBinder},
     {"native_clear", "()V", (void *)native_clear},
     {"close_native", "()V", (void *)native_close},
diff --git a/core/jni/android_database_SQLiteDatabase.cpp b/core/jni/android_database_SQLiteDatabase.cpp
index 7aeed98..a5878a9 100644
--- a/core/jni/android_database_SQLiteDatabase.cpp
+++ b/core/jni/android_database_SQLiteDatabase.cpp
@@ -46,7 +46,6 @@
 
 #define UTF16_STORAGE 0
 #define INVALID_VERSION -1
-#define SQLITE_SOFT_HEAP_LIMIT (4 * 1024 * 1024)
 #define ANDROID_TABLE "android_metadata"
 /* uncomment the next line to force-enable logging of all statements */
 // #define DB_LOG_STATEMENTS
@@ -66,6 +65,7 @@
 static jfieldID offset_db_handle;
 static jmethodID method_custom_function_callback;
 static jclass string_class = NULL;
+static jint sSqliteSoftHeapLimit = 0;
 
 static char *createStr(const char *path, short extra) {
     int len = strlen(path) + extra;
@@ -129,7 +129,7 @@
     // The soft heap limit prevents the page cache allocations from growing
     // beyond the given limit, no matter what the max page cache sizes are
     // set to. The limit does not, as of 3.5.0, affect any other allocations.
-    sqlite3_soft_heap_limit(SQLITE_SOFT_HEAP_LIMIT);
+    sqlite3_soft_heap_limit(sSqliteSoftHeapLimit);
 
     // Set the default busy handler to retry for 1000ms and then return SQLITE_BUSY
     err = sqlite3_busy_timeout(handle, 1000 /* ms */);
@@ -379,10 +379,14 @@
     if (meta != NULL) sqlite3_free_table(meta);
 }
 
+static void native_setSqliteSoftHeapLimit(JNIEnv* env, jobject clazz, jint limit) {
+    sSqliteSoftHeapLimit = limit;
+}
+
 static jint native_releaseMemory(JNIEnv *env, jobject clazz)
 {
     // Attempt to release as much memory from the
-    return sqlite3_release_memory(SQLITE_SOFT_HEAP_LIMIT);
+    return sqlite3_release_memory(sSqliteSoftHeapLimit);
 }
 
 static void native_finalize(JNIEnv* env, jobject object, jint statementId)
@@ -466,6 +470,7 @@
     {"enableSqlProfiling", "(Ljava/lang/String;S)V", (void *)enableSqlProfiling},
     {"native_setLocale", "(Ljava/lang/String;I)V", (void *)native_setLocale},
     {"native_getDbLookaside", "()I", (void *)native_getDbLookaside},
+    {"native_setSqliteSoftHeapLimit", "(I)V", (void *)native_setSqliteSoftHeapLimit},
     {"releaseMemory", "()I", (void *)native_releaseMemory},
     {"native_finalize", "(I)V", (void *)native_finalize},
     {"native_addCustomFunction",
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 10fe583..9f70509 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -25,6 +25,7 @@
 
 #include <utils/Vector.h>
 
+#include <gui/SurfaceTexture.h>
 #include <surfaceflinger/Surface.h>
 #include <camera/Camera.h>
 #include <binder/IMemory.h>
@@ -34,6 +35,7 @@
 struct fields_t {
     jfieldID    context;
     jfieldID    surface;
+    jfieldID    surfaceTexture;
     jfieldID    facing;
     jfieldID    orientation;
     jmethodID   post_event;
@@ -393,6 +395,24 @@
     }
 }
 
+static void android_hardware_Camera_setPreviewTexture(JNIEnv *env,
+        jobject thiz, jobject jSurfaceTexture)
+{
+    LOGV("setPreviewTexture");
+    sp<Camera> camera = get_native_camera(env, thiz, NULL);
+    if (camera == 0) return;
+
+    sp<SurfaceTexture> surfaceTexture = NULL;
+    if (jSurfaceTexture != NULL) {
+        surfaceTexture = reinterpret_cast<SurfaceTexture*>(env->GetIntField(
+                jSurfaceTexture, fields.surfaceTexture));
+    }
+    if (camera->setPreviewTexture(surfaceTexture) != NO_ERROR) {
+        jniThrowException(env, "java/io/IOException",
+                "setPreviewTexture failed");
+    }
+}
+
 static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz)
 {
     LOGV("startPreview");
@@ -603,6 +623,9 @@
   { "setPreviewDisplay",
     "(Landroid/view/Surface;)V",
     (void *)android_hardware_Camera_setPreviewDisplay },
+  { "setPreviewTexture",
+    "(Landroid/graphics/SurfaceTexture;)V",
+    (void *)android_hardware_Camera_setPreviewTexture },
   { "startPreview",
     "()V",
     (void *)android_hardware_Camera_startPreview },
@@ -688,6 +711,8 @@
     field fields_to_find[] = {
         { "android/hardware/Camera", "mNativeContext",   "I", &fields.context },
         { "android/view/Surface",    ANDROID_VIEW_SURFACE_JNI_ID, "I", &fields.surface },
+        { "android/graphics/SurfaceTexture",
+          ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I", &fields.surfaceTexture },
         { "android/hardware/Camera$CameraInfo", "facing",   "I", &fields.facing },
         { "android/hardware/Camera$CameraInfo", "orientation",   "I", &fields.orientation },
     };
@@ -708,4 +733,3 @@
     return AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera",
                                               camMethods, NELEM(camMethods));
 }
-
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index b9ae526..2c39871 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -1154,7 +1154,7 @@
 }
 
 static jboolean connectPanDeviceNative(JNIEnv *env, jobject object, jstring path,
-                                       jstring srcRole, jstring dstRole) {
+                                       jstring dstRole) {
     LOGV(__FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     LOGE("connectPanDeviceNative");
@@ -1165,7 +1165,6 @@
 
     if (nat && eventLoopNat) {
         const char *c_path = env->GetStringUTFChars(path, NULL);
-        const char *src = env->GetStringUTFChars(srcRole, NULL);
         const char *dst = env->GetStringUTFChars(dstRole, NULL);
 
         int len = env->GetStringLength(path) + 1;
@@ -1175,12 +1174,10 @@
         bool ret = dbus_func_args_async(env, nat->conn, -1,onPanDeviceConnectionResult,
                                     context_path, eventLoopNat, c_path,
                                     DBUS_NETWORK_IFACE, "Connect",
-                                    DBUS_TYPE_STRING, &src,
                                     DBUS_TYPE_STRING, &dst,
                                     DBUS_TYPE_INVALID);
 
         env->ReleaseStringUTFChars(path, c_path);
-        env->ReleaseStringUTFChars(srcRole, src);
         env->ReleaseStringUTFChars(dstRole, dst);
         return ret ? JNI_TRUE : JNI_FALSE;
     }
@@ -1274,7 +1271,7 @@
 
     {"setBluetoothTetheringNative", "(ZLjava/lang/String;Ljava/lang/String;)Z",
               (void *)setBluetoothTetheringNative},
-    {"connectPanDeviceNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
+    {"connectPanDeviceNative", "(Ljava/lang/String;Ljava/lang/String;)Z",
               (void *)connectPanDeviceNative},
     {"disconnectPanDeviceNative", "(Ljava/lang/String;)Z", (void *)disconnectPanDeviceNative},
 };
diff --git a/core/jni/android_view_Display.cpp b/core/jni/android_view_Display.cpp
index 2e160ae..ac8835a 100644
--- a/core/jni/android_view_Display.cpp
+++ b/core/jni/android_view_Display.cpp
@@ -17,6 +17,8 @@
 #include <stdio.h>
 #include <assert.h>
 
+#include <cutils/properties.h>
+
 #include <surfaceflinger/SurfaceComposerClient.h>
 #include <ui/PixelFormat.h>
 #include <ui/DisplayInfo.h>
@@ -24,6 +26,7 @@
 #include "jni.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
+#include <utils/Log.h>
 
 // ----------------------------------------------------------------------------
 
@@ -41,6 +44,9 @@
 };
 static offsets_t offsets;
 
+static int gOldSize = -1;
+static int gNewSize = -1;
+
 static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
 {
     jclass npeClazz = env->FindClass(exc);
@@ -69,14 +75,16 @@
         JNIEnv* env, jobject clazz)
 {
     DisplayID dpy = env->GetIntField(clazz, offsets.display);
-    return SurfaceComposerClient::getDisplayWidth(dpy);
+    jint w = SurfaceComposerClient::getDisplayWidth(dpy);
+    return w == gOldSize ? gNewSize : w;
 }
 
 static jint android_view_Display_getHeight(
         JNIEnv* env, jobject clazz)
 {
     DisplayID dpy = env->GetIntField(clazz, offsets.display);
-    return SurfaceComposerClient::getDisplayHeight(dpy);
+    int h = SurfaceComposerClient::getDisplayHeight(dpy);
+    return h == gOldSize ? gNewSize : h;
 }
 
 static jint android_view_Display_getOrientation(
@@ -92,6 +100,13 @@
     return SurfaceComposerClient::getNumberOfDisplays();
 }
 
+static jint android_view_Display_unmapDisplaySize(
+        JNIEnv* env, jclass clazz, jint newSize)
+{
+    if (newSize == gNewSize) return gOldSize;
+    return newSize;
+}
+
 // ----------------------------------------------------------------------------
 
 const char* const kClassPathName = "android/view/Display";
@@ -110,7 +125,9 @@
     {   "getHeight", "()I",
             (void*)android_view_Display_getHeight },
     {   "getOrientation", "()I",
-            (void*)android_view_Display_getOrientation }
+            (void*)android_view_Display_getOrientation },
+    {   "unmapDisplaySize", "(I)I",
+            (void*)android_view_Display_unmapDisplaySize }
 };
 
 void nativeClassInit(JNIEnv* env, jclass clazz)
@@ -125,6 +142,16 @@
 
 int register_android_view_Display(JNIEnv* env)
 {
+    char buf[PROPERTY_VALUE_MAX];
+    int len = property_get("persist.demo.screensizehack", buf, "");
+    if (len > 0) {
+        int temp1, temp2;
+        if (sscanf(buf, "%d=%d", &temp1, &temp2) == 2) {
+            gOldSize = temp1;
+            gNewSize = temp2;
+        }
+    }
+
     return AndroidRuntime::registerNativeMethods(env,
             kClassPathName, gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index c3d3572..40cec3e 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -32,6 +32,7 @@
 #include <SkXfermode.h>
 
 #include <DisplayListRenderer.h>
+#include <LayerRenderer.h>
 #include <OpenGLDebugRenderer.h>
 #include <OpenGLRenderer.h>
 #include <SkiaShader.h>
@@ -77,7 +78,7 @@
 // Constructors
 // ----------------------------------------------------------------------------
 
-static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject canvas) {
+static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
     RENDERER_LOGD("Create OpenGLRenderer");
 #if PROFILE_RENDERER
     return new OpenGLDebugRenderer;
@@ -417,16 +418,21 @@
 // Display lists
 // ----------------------------------------------------------------------------
 
-static OpenGLRenderer* android_view_GLES20Canvas_createDisplayListRenderer(
-        JNIEnv* env, jobject canvas) {
-    return new DisplayListRenderer;
-}
-
-static DisplayList* android_view_GLES20Canvas_createDisplayList(JNIEnv* env,
+static DisplayList* android_view_GLES20Canvas_getDisplayList(JNIEnv* env,
         jobject canvas, DisplayListRenderer* renderer) {
     return renderer->getDisplayList();
 }
 
+static OpenGLRenderer* android_view_GLES20Canvas_getDisplayListRenderer(JNIEnv* env,
+        jobject clazz, DisplayListRenderer* renderer) {
+    if (renderer == NULL) {
+        renderer = new DisplayListRenderer;
+    } else {
+        renderer->reset();
+    }
+    return renderer;
+}
+
 static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env,
         jobject clazz, DisplayList* displayList) {
     delete displayList;
@@ -437,6 +443,66 @@
     renderer->drawDisplayList(displayList);
 }
 
+// ----------------------------------------------------------------------------
+// Layers
+// ----------------------------------------------------------------------------
+
+static void android_view_GLES20Canvas_interrupt(JNIEnv* env, jobject canvas,
+        OpenGLRenderer* renderer) {
+    renderer->interrupt();
+}
+
+static void android_view_GLES20Canvas_resume(JNIEnv* env, jobject canvas,
+        OpenGLRenderer* renderer) {
+    renderer->resume();
+}
+
+static OpenGLRenderer* android_view_GLES20Canvas_createLayerRenderer(JNIEnv* env,
+        jobject clazz, Layer* layer) {
+    if (layer) {
+        return new LayerRenderer(layer);
+    }
+    return NULL;
+}
+
+static Layer* android_view_GLES20Canvas_createLayer(JNIEnv* env, jobject clazz,
+        jint width, jint height, jboolean isOpaque, jintArray layerInfo) {
+    Layer* layer = LayerRenderer::createLayer(width, height, isOpaque);
+
+    if (layer) {
+        jint* storage = env->GetIntArrayElements(layerInfo, NULL);
+        storage[0] = layer->width;
+        storage[1] = layer->height;
+        env->ReleaseIntArrayElements(layerInfo, storage, 0);
+    }
+
+    return layer;
+}
+
+static void android_view_GLES20Canvas_resizeLayer(JNIEnv* env, jobject clazz,
+        Layer* layer, jint width, jint height, jintArray layerInfo) {
+    LayerRenderer::resizeLayer(layer, width, height);
+
+    jint* storage = env->GetIntArrayElements(layerInfo, NULL);
+    storage[0] = layer->width;
+    storage[1] = layer->height;
+    env->ReleaseIntArrayElements(layerInfo, storage, 0);
+}
+
+static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, Layer* layer) {
+    LayerRenderer::destroyLayer(layer);
+}
+
+static void android_view_GLES20Canvas_destroyLayerDeferred(JNIEnv* env,
+        jobject clazz, Layer* layer) {
+    LayerRenderer::destroyLayerDeferred(layer);
+}
+
+static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject canvas,
+        OpenGLRenderer* renderer, Layer* layer, jfloat x, jfloat y, SkPaint* paint) {
+    renderer->drawLayer(layer, x, y, paint);
+}
+
 #endif // USE_OPENGL_RENDERER
 
 // ----------------------------------------------------------------------------
@@ -517,10 +583,20 @@
     { "nGetClipBounds",     "(ILandroid/graphics/Rect;)Z",
             (void*) android_view_GLES20Canvas_getClipBounds },
 
-    { "nCreateDisplayListRenderer", "()I",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
-    { "nCreateDisplayList",  "(I)I",           (void*) android_view_GLES20Canvas_createDisplayList },
-    { "nDestroyDisplayList", "(I)V",           (void*) android_view_GLES20Canvas_destroyDisplayList },
-    { "nDrawDisplayList",    "(II)V",          (void*) android_view_GLES20Canvas_drawDisplayList },
+    { "nGetDisplayList",         "(I)I",       (void*) android_view_GLES20Canvas_getDisplayList },
+    { "nDestroyDisplayList",     "(I)V",       (void*) android_view_GLES20Canvas_destroyDisplayList },
+    { "nGetDisplayListRenderer", "(I)I",       (void*) android_view_GLES20Canvas_getDisplayListRenderer },
+    { "nDrawDisplayList",        "(II)V",      (void*) android_view_GLES20Canvas_drawDisplayList },
+
+    { "nInterrupt",              "(I)V",       (void*) android_view_GLES20Canvas_interrupt },
+    { "nResume",                 "(I)V",       (void*) android_view_GLES20Canvas_resume },
+
+    { "nCreateLayerRenderer",    "(I)I",       (void*) android_view_GLES20Canvas_createLayerRenderer },
+    { "nCreateLayer",            "(IIZ[I)I",   (void*) android_view_GLES20Canvas_createLayer },
+    { "nResizeLayer",            "(III[I)V" ,  (void*) android_view_GLES20Canvas_resizeLayer },
+    { "nDestroyLayer",           "(I)V",       (void*) android_view_GLES20Canvas_destroyLayer },
+    { "nDestroyLayerDeferred",   "(I)V",       (void*) android_view_GLES20Canvas_destroyLayerDeferred },
+    { "nDrawLayer",              "(IIFFI)V",   (void*) android_view_GLES20Canvas_drawLayer },
 
 #endif
 };
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index ada4dd3..52e8f42 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -45,14 +45,10 @@
 static jint com_android_internal_os_ZygoteInit_setreuid(
     JNIEnv* env, jobject clazz, jint ruid, jint euid)
 {
-    int err;
-
-    errno = 0;
-    err = setreuid(ruid, euid);
-
-    //LOGI("setreuid(%d,%d) err %d errno %d", ruid, euid, err, errno);
-
-    return errno;
+    if (setreuid(ruid, euid) < 0) {
+        return errno;
+    }
+    return 0;
 }
 
 /*
@@ -62,14 +58,10 @@
 static jint com_android_internal_os_ZygoteInit_setregid(
     JNIEnv* env, jobject clazz, jint rgid, jint egid)
 {
-    int err;
-
-    errno = 0;
-    err = setregid(rgid, egid);
-
-    //LOGI("setregid(%d,%d) err %d errno %d", rgid, egid, err, errno);
-
-    return errno;
+    if (setregid(rgid, egid) < 0) {
+        return errno;
+    }
+    return 0;
 }
 
 /*
@@ -79,13 +71,10 @@
 static jint com_android_internal_os_ZygoteInit_setpgid(
     JNIEnv* env, jobject clazz, jint pid, jint pgid)
 {
-    int err;
-
-    errno = 0;
-
-    err = setpgid(pid, pgid);
-
-    return errno;
+    if (setpgid(pid, pgid) < 0) {
+        return errno;
+    }
+    return 0;
 }
 
 /*
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 92b50c7..41c911a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -85,8 +85,6 @@
     <protected-broadcast android:name="android.hardware.action.USB_CONNECTED" />
     <protected-broadcast android:name="android.hardware.action.USB_DISCONNECTED" />
     <protected-broadcast android:name="android.hardware.action.USB_STATE" />
-    <protected-broadcast android:name="android.hardware.action.USB_CAMERA_ATTACHED" />
-    <protected-broadcast android:name="android.hardware.action.USB_CAMERA_DETACHED" />
 
     <protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
     <protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
@@ -472,6 +470,15 @@
         android:label="@string/permlab_accessUsb"
         android:description="@string/permdesc_accessUsb" />
 
+    <!-- Allows an application to access the MTP USB kernel driver.
+         For use only by the device side MTP implementation.
+         @hide -->
+    <permission android:name="android.permission.ACCESS_MTP"
+        android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
+        android:protectionLevel="signatureOrSystem"
+        android:label="@string/permlab_accessMtp"
+        android:description="@string/permdesc_accessMtp" />
+
     <!-- Allows access to hardware peripherals.  Intended only for hardware testing -->
     <permission android:name="android.permission.HARDWARE_TEST"
         android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
@@ -533,13 +540,6 @@
         android:description="@string/permdesc_sdcardWrite"
         android:protectionLevel="dangerous" />
 
-    <!-- Allows an application to write to internal media storage -->
-    <permission android:name="android.permission.WRITE_MEDIA_STORAGE"
-        android:permissionGroup="android.permission-group.STORAGE"
-        android:label="@string/permlab_mediaStorageWrite"
-        android:description="@string/permdesc_mediaStorageWrite"
-        android:protectionLevel="signatureOrSystem" />
-
     <!-- ============================================ -->
     <!-- Permissions for low-level system interaction -->
     <!-- ============================================ -->
@@ -1335,6 +1335,11 @@
                 android:exported="true">
         </activity>
 
+        <activity android:name="android.content.SyncActivityTooManyDeletes"
+               android:theme="@android:style/Theme.Holo.Dialog"
+               android:label="@string/sync_too_many_deletes">
+        </activity>
+
         <activity android:name="com.android.server.ShutdownActivity"
             android:permission="android.permission.SHUTDOWN"
             android:excludeFromRecents="true">
diff --git a/core/res/assets/webkit/youtube.html b/core/res/assets/webkit/youtube.html
index 289f8cf..d808bcf 100644
--- a/core/res/assets/webkit/youtube.html
+++ b/core/res/assets/webkit/youtube.html
@@ -38,19 +38,29 @@
                 // All images are loaded, so display them.
                 // (Note that the images are loaded from javascript, so might load
                 // after document.onload fires)
-                ctx.drawImage(background, 0, 0, width, height);
+
                 playWidth = play.width;
                 playHeight = play.height;
                 logoWidth = logo.width;
                 logoHeight = logo.height;
                 var ratio = 1;
                 // If the page is smaller than it 'should' be in either dimension
-                // we scale the play button and logo according to the dimension that
-                // has been shrunk the most.
+                // we scale the background, play button and logo according to the
+                // dimension that has been shrunk the most.
                 if (width / height > defWidth / defHeight && height < defHeight) {
                     ratio = height / defHeight;
+                    // Stretch the background in this dimension only.
+                    backgroundHeight = background.height / ratio;
+                    ctx.drawImage(background, 0, 0, background.width, background.height,
+                        0, (height - backgroundHeight) / 2, width, backgroundHeight);
                 } else if (width / height < defWidth / defHeight && width < defWidth) {
                     ratio = width / defWidth;
+                    backgroundWidth = background.width / ratio;
+                    ctx.drawImage(background, 0, 0, background.width, background.height,
+                        (width - backgroundWidth) / 2, 0, backgroundWidth, height);
+                } else {
+                    // In this case stretch the background in both dimensions to fill the space.
+                    ctx.drawImage(background, 0, 0, width, height);
                 }
                 playWidth *= ratio;
                 playHeight *= ratio;
diff --git a/core/res/res/anim/activity_close_enter.xml b/core/res/res/anim/activity_close_enter.xml
index 69437b8..d525127 100644
--- a/core/res/res/anim/activity_close_enter.xml
+++ b/core/res/res/anim/activity_close_enter.xml
@@ -23,9 +23,9 @@
     <scale android:fromXScale="0.975" android:toXScale="1.0"
             android:fromYScale="0.975" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_activityDefaultDur" />
     <alpha android:fromAlpha=".75" android:toAlpha="1.0"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:duration="@android:integer/config_activityDefaultDur"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/activity_close_exit.xml b/core/res/res/anim/activity_close_exit.xml
index c73bc3a..ab7adcb 100644
--- a/core/res/res/anim/activity_close_exit.xml
+++ b/core/res/res/anim/activity_close_exit.xml
@@ -23,9 +23,9 @@
     <scale android:fromXScale="1.0" android:toXScale="1.075"
             android:fromYScale="1.0" android:toYScale="1.075"
             android:pivotX="50%p" android:pivotY="50%p"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_activityDefaultDur" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:duration="@android:integer/config_activityDefaultDur"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/activity_open_enter.xml b/core/res/res/anim/activity_open_enter.xml
index 7b6a7f0..90f8520 100644
--- a/core/res/res/anim/activity_open_enter.xml
+++ b/core/res/res/anim/activity_open_enter.xml
@@ -23,9 +23,9 @@
     <scale android:fromXScale="1.125" android:toXScale="1.0"
             android:fromYScale="1.125" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_activityDefaultDur" />
     <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:duration="@android:integer/config_activityDefaultDur"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/activity_open_exit.xml b/core/res/res/anim/activity_open_exit.xml
index b07ab2b..30a1dec 100644
--- a/core/res/res/anim/activity_open_exit.xml
+++ b/core/res/res/anim/activity_open_exit.xml
@@ -23,9 +23,9 @@
     <scale android:fromXScale="1.0" android:toXScale="0.975"
             android:fromYScale="1.0" android:toYScale="0.975"
             android:pivotX="50%p" android:pivotY="50%p"
-            android:interpolator="@anim/linear_interpolator"
+            android:interpolator="@interpolator/linear"
             android:duration="@android:integer/config_activityDefaultDur" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0.75"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:duration="@android:integer/config_activityDefaultDur"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/animator_fade_in.xml b/core/res/res/anim/animator_fade_in.xml
deleted file mode 100644
index 2a28b4d..0000000
--- a/core/res/res/anim/animator_fade_in.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@anim/accelerate_interpolator"
-    android:valueFrom="0"
-    android:valueTo="1"
-    android:propertyName="alpha"
-    android:duration="@android:integer/config_mediumAnimTime"
-/>
diff --git a/core/res/res/anim/animator_fade_out.xml b/core/res/res/anim/animator_fade_out.xml
deleted file mode 100644
index 4db6591..0000000
--- a/core/res/res/anim/animator_fade_out.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@anim/accelerate_interpolator"
-    android:valueFrom="1.0"
-    android:valueTo="0.0"
-    android:propertyName="alpha"
-    android:duration="@android:integer/config_mediumAnimTime"
-/>
diff --git a/core/res/res/anim/app_starting_exit.xml b/core/res/res/anim/app_starting_exit.xml
index 0675575..6c255d0 100644
--- a/core/res/res/anim/app_starting_exit.xml
+++ b/core/res/res/anim/app_starting_exit.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator">
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/decelerate_quad">
 	<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="@android:integer/config_mediumAnimTime" />
 </set>
 
diff --git a/core/res/res/anim/dialog_enter.xml b/core/res/res/anim/dialog_enter.xml
index 82bfdf6..8c67eee 100644
--- a/core/res/res/anim/dialog_enter.xml
+++ b/core/res/res/anim/dialog_enter.xml
@@ -22,9 +22,9 @@
     <scale android:fromXScale="0.9" android:toXScale="1.0"
            android:fromYScale="0.9" android:toYScale="1.0"
            android:pivotX="50%" android:pivotY="50%"
-			android:interpolator="@anim/decelerate_quint_interpolator"
+			android:interpolator="@interpolator/decelerate_quint"
            android:duration="@android:integer/config_activityDefaultDur" />
     <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
-			android:interpolator="@anim/decelerate_cubic_interpolator"
+			android:interpolator="@interpolator/decelerate_cubic"
             android:duration="@android:integer/config_activityShortDur" />
 </set>
diff --git a/core/res/res/anim/dialog_exit.xml b/core/res/res/anim/dialog_exit.xml
index 829c619..b040d76 100644
--- a/core/res/res/anim/dialog_exit.xml
+++ b/core/res/res/anim/dialog_exit.xml
@@ -22,9 +22,9 @@
     <scale android:fromXScale="1.0" android:toXScale="0.9"
            	android:fromYScale="1.0" android:toYScale="0.9"
            	android:pivotX="50%" android:pivotY="50%"
-			android:interpolator="@anim/decelerate_quint_interpolator"
+			android:interpolator="@interpolator/decelerate_quint"
            	android:duration="@android:integer/config_activityDefaultDur" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-			android:interpolator="@anim/decelerate_cubic_interpolator"
+			android:interpolator="@interpolator/decelerate_cubic"
             android:duration="@android:integer/config_activityShortDur"/>
 </set>
diff --git a/core/res/res/anim/fade_in.xml b/core/res/res/anim/fade_in.xml
index 57310d9..03e76a5 100644
--- a/core/res/res/anim/fade_in.xml
+++ b/core/res/res/anim/fade_in.xml
@@ -19,6 +19,6 @@
 -->
 
 <alpha xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/decelerate_interpolator"
+        android:interpolator="@interpolator/decelerate_quad"
         android:fromAlpha="0.0" android:toAlpha="1.0"
         android:duration="@android:integer/config_longAnimTime" />
diff --git a/core/res/res/anim/fade_out.xml b/core/res/res/anim/fade_out.xml
index dc76276..e5dfb96 100644
--- a/core/res/res/anim/fade_out.xml
+++ b/core/res/res/anim/fade_out.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator" 
+<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/accelerate_quad" 
     android:fromAlpha="1.0"
     android:toAlpha="0.0"
     android:duration="@android:integer/config_mediumAnimTime" 
diff --git a/core/res/res/anim/fragment_close_enter.xml b/core/res/res/anim/fragment_close_enter.xml
deleted file mode 100644
index eaa192f..0000000
--- a/core/res/res/anim/fragment_close_enter.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License. 
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="normal">
-    <objectAnimator
-        android:interpolator="@anim/decelerate_quint_interpolator"
-        android:valueFrom="0.975" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="scaleY"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@anim/decelerate_quint_interpolator"
-        android:valueFrom="0.975" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="scaleX"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@anim/decelerate_cubic_interpolator"
-        android:valueFrom="0.0" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_close_exit.xml b/core/res/res/anim/fragment_close_exit.xml
deleted file mode 100644
index 8851e3a..0000000
--- a/core/res/res/anim/fragment_close_exit.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License. 
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="top">
-    <objectAnimator
-        android:interpolator="@anim/decelerate_quint_interpolator"
-        android:valueFrom="1.0" android:valueTo="1.075"
-        android:valueType="floatType"
-        android:propertyName="scaleY"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@anim/decelerate_quint_interpolator"
-        android:valueFrom="1.0" android:valueTo="1.075"
-        android:valueType="floatType"
-        android:propertyName="scaleX"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@anim/decelerate_cubic_interpolator"
-        android:valueFrom="1.0" android:valueTo="0.0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_next_enter.xml b/core/res/res/anim/fragment_next_enter.xml
deleted file mode 100644
index 63d3a45..0000000
--- a/core/res/res/anim/fragment_next_enter.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="top">
-    <objectAnimator
-        android:interpolator="@anim/decelerate_cubic_interpolator"
-        android:valueFrom="0"
-        android:valueTo="1"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_next_exit.xml b/core/res/res/anim/fragment_next_exit.xml
deleted file mode 100644
index 91e5786..0000000
--- a/core/res/res/anim/fragment_next_exit.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="normal">
-    <objectAnimator
-        android:interpolator="@anim/decelerate_cubic_interpolator"
-        android:valueFrom="1"
-        android:valueTo="0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityShortDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_open_enter.xml b/core/res/res/anim/fragment_open_enter.xml
deleted file mode 100644
index bac75a5..0000000
--- a/core/res/res/anim/fragment_open_enter.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License. 
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-    <objectAnimator
-        android:interpolator="@anim/decelerate_quint_interpolator"
-        android:valueFrom="1.125" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="scaleY"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@anim/decelerate_quint_interpolator"
-        android:valueFrom="1.125" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="scaleX"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@anim/decelerate_cubic_interpolator"
-        android:valueFrom="0.0" android:valueTo="1.0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_open_exit.xml b/core/res/res/anim/fragment_open_exit.xml
deleted file mode 100644
index 57f1f9f..0000000
--- a/core/res/res/anim/fragment_open_exit.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License. 
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-    <objectAnimator
-        android:interpolator="@anim/linear_interpolator"
-        android:valueFrom="1.0" android:valueTo="0.975"
-        android:valueType="floatType"
-        android:propertyName="scaleY"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@anim/linear_interpolator"
-        android:valueFrom="1.0" android:valueTo="0.975"
-        android:valueType="floatType"
-        android:propertyName="scaleX"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-    <objectAnimator
-        android:interpolator="@anim/decelerate_cubic_interpolator"
-        android:valueFrom="1.0" android:valueTo="0.0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_prev_enter.xml b/core/res/res/anim/fragment_prev_enter.xml
deleted file mode 100644
index 63d3a45..0000000
--- a/core/res/res/anim/fragment_prev_enter.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="top">
-    <objectAnimator
-        android:interpolator="@anim/decelerate_cubic_interpolator"
-        android:valueFrom="0"
-        android:valueTo="1"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityDefaultDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/fragment_prev_exit.xml b/core/res/res/anim/fragment_prev_exit.xml
deleted file mode 100644
index 91e5786..0000000
--- a/core/res/res/anim/fragment_prev_exit.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-	android:zAdjustment="normal">
-    <objectAnimator
-        android:interpolator="@anim/decelerate_cubic_interpolator"
-        android:valueFrom="1"
-        android:valueTo="0"
-        android:valueType="floatType"
-        android:propertyName="alpha"
-        android:duration="@android:integer/config_activityShortDur"/>
-</set>
\ No newline at end of file
diff --git a/core/res/res/anim/grow_fade_in.xml b/core/res/res/anim/grow_fade_in.xml
index 9180438..f121a8a 100644
--- a/core/res/res/anim/grow_fade_in.xml
+++ b/core/res/res/anim/grow_fade_in.xml
@@ -19,12 +19,12 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
-    <scale 	android:interpolator="@anim/decelerate_quint_interpolator"
+    <scale 	android:interpolator="@interpolator/decelerate_quint"
 	 	   	android:fromXScale="0.9" android:toXScale="1.0"
            	android:fromYScale="0.9" android:toYScale="1.0"
            	android:pivotX="50%" android:pivotY="0%"
            	android:duration="@android:integer/config_activityDefaultDur" />
-    <alpha 	android:interpolator="@anim/decelerate_cubic_interpolator"
+    <alpha 	android:interpolator="@interpolator/decelerate_cubic"
             android:fromAlpha="0.0" android:toAlpha="1.0"
             android:duration="@android:integer/config_activityShortDur" />
 </set>
diff --git a/core/res/res/anim/grow_fade_in_center.xml b/core/res/res/anim/grow_fade_in_center.xml
index 09370e6..972101b2 100644
--- a/core/res/res/anim/grow_fade_in_center.xml
+++ b/core/res/res/anim/grow_fade_in_center.xml
@@ -19,12 +19,12 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
-    <scale 	android:interpolator="@anim/decelerate_quint_interpolator"
+    <scale 	android:interpolator="@interpolator/decelerate_quint"
 	 	   	android:fromXScale="0.9" android:toXScale="1.0"
            	android:fromYScale="0.9" android:toYScale="1.0"
            	android:pivotX="50%" android:pivotY="50%"
            	android:duration="@android:integer/config_activityDefaultDur" />
-    <alpha 	android:interpolator="@anim/decelerate_cubic_interpolator"
+    <alpha 	android:interpolator="@interpolator/decelerate_cubic"
             android:fromAlpha="0.0" android:toAlpha="1.0"
             android:duration="@android:integer/config_activityShortDur" />
 </set>
diff --git a/core/res/res/anim/grow_fade_in_from_bottom.xml b/core/res/res/anim/grow_fade_in_from_bottom.xml
index d1488e9..4ca11b86 100644
--- a/core/res/res/anim/grow_fade_in_from_bottom.xml
+++ b/core/res/res/anim/grow_fade_in_from_bottom.xml
@@ -19,12 +19,12 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
-    <scale 	android:interpolator="@anim/decelerate_quint_interpolator"
+    <scale 	android:interpolator="@interpolator/decelerate_quint"
 	 	   	android:fromXScale="0.9" android:toXScale="1.0"
            	android:fromYScale="0.9" android:toYScale="1.0"
            	android:pivotX="50%" android:pivotY="100%"
            	android:duration="@android:integer/config_activityDefaultDur" />
-    <alpha 	android:interpolator="@anim/decelerate_cubic_interpolator"
+    <alpha 	android:interpolator="@interpolator/decelerate_cubic"
             android:fromAlpha="0.0" android:toAlpha="1.0"
             android:duration="@android:integer/config_activityShortDur" />
 </set>
diff --git a/core/res/res/anim/input_method_enter.xml b/core/res/res/anim/input_method_enter.xml
index e02b310..df9310a 100644
--- a/core/res/res/anim/input_method_enter.xml
+++ b/core/res/res/anim/input_method_enter.xml
@@ -21,9 +21,9 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
 		android:shareInterpolator="false">
     <translate android:fromYDelta="10%" android:toYDelta="0"
-	        android:interpolator="@anim/decelerate_quint_interpolator"
+	        android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_shortAnimTime"/>
     <alpha android:fromAlpha="0.5" android:toAlpha="1.0"
-			android:interpolator="@anim/decelerate_cubic_interpolator"
+			android:interpolator="@interpolator/decelerate_cubic"
             android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/input_method_exit.xml b/core/res/res/anim/input_method_exit.xml
index e155f97..e87352f 100644
--- a/core/res/res/anim/input_method_exit.xml
+++ b/core/res/res/anim/input_method_exit.xml
@@ -20,9 +20,9 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
 	android:shareInterpolator="false">
     <translate android:fromYDelta="0" android:toYDelta="10%"
-			android:interpolator="@anim/accelerate_quint_interpolator"
+			android:interpolator="@interpolator/accelerate_quint"
             android:duration="@android:integer/config_shortAnimTime"/>
     <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-			android:interpolator="@anim/accelerate_cubic_interpolator"
+			android:interpolator="@interpolator/accelerate_cubic"
             android:duration="@android:integer/config_shortAnimTime"/>
 </set>
diff --git a/core/res/res/anim/input_method_extract_enter.xml b/core/res/res/anim/input_method_extract_enter.xml
index 96b049f..c475b83 100644
--- a/core/res/res/anim/input_method_extract_enter.xml
+++ b/core/res/res/anim/input_method_extract_enter.xml
@@ -19,6 +19,6 @@
 -->
 
 <alpha xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/decelerate_interpolator"
+        android:interpolator="@interpolator/decelerate_quad"
         android:fromAlpha="0.0" android:toAlpha="1.0"
         android:duration="@android:integer/config_shortAnimTime" />
diff --git a/core/res/res/anim/input_method_extract_exit.xml b/core/res/res/anim/input_method_extract_exit.xml
index 26db13f..8aedb14 100644
--- a/core/res/res/anim/input_method_extract_exit.xml
+++ b/core/res/res/anim/input_method_extract_exit.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator" 
+<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/accelerate_quad" 
     android:fromAlpha="1.0"
     android:toAlpha="0.0"
     android:duration="@android:integer/config_shortAnimTime" 
diff --git a/core/res/res/anim/input_method_fancy_enter.xml b/core/res/res/anim/input_method_fancy_enter.xml
index c6949b3..046f41b 100644
--- a/core/res/res/anim/input_method_fancy_enter.xml
+++ b/core/res/res/anim/input_method_fancy_enter.xml
@@ -19,7 +19,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/decelerate_interpolator">
+        android:interpolator="@interpolator/decelerate_quad">
     <scale android:fromXScale="2.0" android:toXScale="1.0"
            android:fromYScale="2.0" android:toYScale="1.0"
            android:pivotX="50%" android:pivotY="50%"
diff --git a/core/res/res/anim/input_method_fancy_exit.xml b/core/res/res/anim/input_method_fancy_exit.xml
index 7333cca..6cb7e6f 100644
--- a/core/res/res/anim/input_method_fancy_exit.xml
+++ b/core/res/res/anim/input_method_fancy_exit.xml
@@ -18,7 +18,7 @@
 */
 -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/accelerate_interpolator">
+        android:interpolator="@interpolator/accelerate_quad">
     <scale android:fromXScale="1.0" android:toXScale="2.0"
            android:fromYScale="1.0" android:toYScale="2.0"
            android:pivotX="50%" android:pivotY="50%"
diff --git a/core/res/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml
index 0bfe806..c01e265 100644
--- a/core/res/res/anim/lock_screen_behind_enter.xml
+++ b/core/res/res/anim/lock_screen_behind_enter.xml
@@ -17,7 +17,7 @@
 */
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_cubic_interpolator">
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/accelerate_cubic">
     <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
             android:duration="@android:integer/config_activityDefaultDur" />
 </set>
diff --git a/core/res/res/anim/lock_screen_enter.xml b/core/res/res/anim/lock_screen_enter.xml
index 0a169fd..3a6c5b6 100644
--- a/core/res/res/anim/lock_screen_enter.xml
+++ b/core/res/res/anim/lock_screen_enter.xml
@@ -18,7 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/accelerate_cubic_interpolator">
+        android:interpolator="@interpolator/accelerate_cubic">
     <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
             android:duration="@android:integer/config_activityDefaultDur" />
 </set>
diff --git a/core/res/res/anim/lock_screen_exit.xml b/core/res/res/anim/lock_screen_exit.xml
index f06a6e5..44ca736 100644
--- a/core/res/res/anim/lock_screen_exit.xml
+++ b/core/res/res/anim/lock_screen_exit.xml
@@ -18,7 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/decelerate_cubic_interpolator">
+        android:interpolator="@interpolator/decelerate_cubic">
 	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
             android:duration="@android:integer/config_activityDefaultDur" />
 </set>
diff --git a/core/res/res/anim/options_panel_enter.xml b/core/res/res/anim/options_panel_enter.xml
index d81866b..31b16ed 100644
--- a/core/res/res/anim/options_panel_enter.xml
+++ b/core/res/res/anim/options_panel_enter.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator">
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/decelerate_quad">
 	<translate android:fromYDelta="25%" android:toYDelta="0"
         android:duration="@android:integer/config_shortAnimTime"/>
 	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
diff --git a/core/res/res/anim/options_panel_exit.xml b/core/res/res/anim/options_panel_exit.xml
index 4e7af7a..c95ad5f 100644
--- a/core/res/res/anim/options_panel_exit.xml
+++ b/core/res/res/anim/options_panel_exit.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator">
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/accelerate_quad">
 	<translate android:fromYDelta="0" android:toYDelta="50%"
             android:duration="@android:integer/config_shortAnimTime"/>
 	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
diff --git a/core/res/res/anim/priority_alert_enter.xml b/core/res/res/anim/priority_alert_enter.xml
index c8ce23c..4fd6a7c 100644
--- a/core/res/res/anim/priority_alert_enter.xml
+++ b/core/res/res/anim/priority_alert_enter.xml
@@ -2,13 +2,13 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         >
     <scale
-        android:interpolator="@android:anim/overshoot_interpolator"
+        android:interpolator="@android:interpolator/overshoot"
         android:fromXScale="0.7" android:toXScale="1.0"
         android:fromYScale="0.7" android:toYScale="1.0"
         android:pivotX="50%" android:pivotY="50%"
         android:duration="@android:integer/config_shortAnimTime" />
     <alpha 
-        android:interpolator="@android:anim/decelerate_interpolator"
+        android:interpolator="@android:interpolator/decelerate_quad"
         android:fromAlpha="0.0" android:toAlpha="1.0"
         android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/priority_alert_exit.xml b/core/res/res/anim/priority_alert_exit.xml
index b538cb2..05c144a 100644
--- a/core/res/res/anim/priority_alert_exit.xml
+++ b/core/res/res/anim/priority_alert_exit.xml
@@ -2,13 +2,13 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         >
     <scale
-        android:interpolator="@android:anim/accelerate_interpolator"
+        android:interpolator="@android:interpolator/accelerate_quad"
         android:fromXScale="1.0" android:toXScale="0.7"
         android:fromYScale="1.0" android:toYScale="0.7"
         android:pivotX="50%" android:pivotY="50%"
         android:duration="@android:integer/config_shortAnimTime" />
     <alpha 
-        android:interpolator="@android:anim/accelerate_interpolator"
+        android:interpolator="@android:interpolator/accelerate_quad"
         android:fromAlpha="1.0" android:toAlpha="0.0"
         android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/recent_enter.xml b/core/res/res/anim/recent_enter.xml
index 8faa2c1..46d5a9d 100644
--- a/core/res/res/anim/recent_enter.xml
+++ b/core/res/res/anim/recent_enter.xml
@@ -18,7 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/decelerate_interpolator">
+        android:interpolator="@interpolator/decelerate_quad">
     <scale android:fromXScale="0.9" android:toXScale="1.0"
            android:fromYScale="0.9" android:toYScale="1.0"
            android:pivotX="50%" android:pivotY="50%"
diff --git a/core/res/res/anim/recent_exit.xml b/core/res/res/anim/recent_exit.xml
index 9399329..446ffe6 100644
--- a/core/res/res/anim/recent_exit.xml
+++ b/core/res/res/anim/recent_exit.xml
@@ -18,7 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/accelerate_interpolator">
+        android:interpolator="@interpolator/accelerate_quad">
     <scale android:fromXScale="1.0" android:toXScale="0.9"
            android:fromYScale="1.0" android:toYScale="0.9"
            android:pivotX="50%" android:pivotY="50%"
diff --git a/core/res/res/anim/screen_rotate_0_enter.xml b/core/res/res/anim/screen_rotate_0_enter.xml
index 9e9a8ad..93cf365 100644
--- a/core/res/res/anim/screen_rotate_0_enter.xml
+++ b/core/res/res/anim/screen_rotate_0_enter.xml
@@ -20,6 +20,6 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:shareInterpolator="false">
     <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/screen_rotate_0_exit.xml b/core/res/res/anim/screen_rotate_0_exit.xml
index 09d0ac3..f1df2de 100644
--- a/core/res/res/anim/screen_rotate_0_exit.xml
+++ b/core/res/res/anim/screen_rotate_0_exit.xml
@@ -20,6 +20,6 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:shareInterpolator="false">
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/screen_rotate_180_enter.xml b/core/res/res/anim/screen_rotate_180_enter.xml
index a050d9b..95cc562 100644
--- a/core/res/res/anim/screen_rotate_180_enter.xml
+++ b/core/res/res/anim/screen_rotate_180_enter.xml
@@ -23,12 +23,12 @@
             android:fromYScale=".9" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
             android:fillEnabled="true" android:fillBefore="true"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:startOffset="160"
             android:duration="300" />
     <alpha android:fromAlpha="0" android:toAlpha="1.0"
             android:fillEnabled="true" android:fillBefore="true"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:startOffset="160"
             android:duration="300"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/screen_rotate_180_exit.xml b/core/res/res/anim/screen_rotate_180_exit.xml
index f6a6572..d3dd4c0 100644
--- a/core/res/res/anim/screen_rotate_180_exit.xml
+++ b/core/res/res/anim/screen_rotate_180_exit.xml
@@ -22,9 +22,9 @@
     <scale android:fromXScale="1.0" android:toXScale="1.0"
             android:fromYScale="1.0" android:toYScale="0.0"
             android:pivotX="50%p" android:pivotY="50%p"
-            android:interpolator="@anim/accelerate_cubic_interpolator"
+            android:interpolator="@interpolator/accelerate_cubic"
             android:duration="160" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:duration="160"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/screen_rotate_minus_90_enter.xml b/core/res/res/anim/screen_rotate_minus_90_enter.xml
index 92a7779..30518e0 100644
--- a/core/res/res/anim/screen_rotate_minus_90_enter.xml
+++ b/core/res/res/anim/screen_rotate_minus_90_enter.xml
@@ -22,10 +22,10 @@
     <scale android:fromXScale="100%p" android:toXScale="100%"
             android:fromYScale="100%p" android:toYScale="100%"
             android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_mediumAnimTime" />
     <rotate android:fromDegrees="-90" android:toDegrees="0"
             android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/screen_rotate_minus_90_exit.xml b/core/res/res/anim/screen_rotate_minus_90_exit.xml
index c530759..65294f6 100644
--- a/core/res/res/anim/screen_rotate_minus_90_exit.xml
+++ b/core/res/res/anim/screen_rotate_minus_90_exit.xml
@@ -22,13 +22,13 @@
     <scale android:fromXScale="100%" android:toXScale="100%p"
             android:fromYScale="100%" android:toYScale="100%p"
             android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_mediumAnimTime" />
     <rotate android:fromDegrees="0" android:toDegrees="90"
             android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_mediumAnimTime" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/screen_rotate_plus_90_enter.xml b/core/res/res/anim/screen_rotate_plus_90_enter.xml
index f4ffaa8..20943c8 100644
--- a/core/res/res/anim/screen_rotate_plus_90_enter.xml
+++ b/core/res/res/anim/screen_rotate_plus_90_enter.xml
@@ -22,10 +22,10 @@
     <scale android:fromXScale="100%p" android:toXScale="100%"
             android:fromYScale="100%p" android:toYScale="100%"
             android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_mediumAnimTime" />
     <rotate android:fromDegrees="90" android:toDegrees="0"
             android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/screen_rotate_plus_90_exit.xml b/core/res/res/anim/screen_rotate_plus_90_exit.xml
index 0728bfb..63c0b09 100644
--- a/core/res/res/anim/screen_rotate_plus_90_exit.xml
+++ b/core/res/res/anim/screen_rotate_plus_90_exit.xml
@@ -22,13 +22,13 @@
     <scale android:fromXScale="100%" android:toXScale="100%p"
             android:fromYScale="100%" android:toYScale="100%p"
             android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_mediumAnimTime" />
     <rotate android:fromDegrees="0" android:toDegrees="-90"
             android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_mediumAnimTime" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/anim/search_bar_enter.xml b/core/res/res/anim/search_bar_enter.xml
index c85caaa..1a26e01 100644
--- a/core/res/res/anim/search_bar_enter.xml
+++ b/core/res/res/anim/search_bar_enter.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator">
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/decelerate_quad">
 	<translate android:fromYDelta="-25%" android:toYDelta="0"
             android:duration="@android:integer/config_shortAnimTime"/>
 	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
diff --git a/core/res/res/anim/search_bar_exit.xml b/core/res/res/anim/search_bar_exit.xml
index 1609a12..ca9a9b7 100644
--- a/core/res/res/anim/search_bar_exit.xml
+++ b/core/res/res/anim/search_bar_exit.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator">
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/accelerate_quad">
 	<translate android:fromYDelta="0" android:toYDelta="-50%"
             android:duration="@android:integer/config_shortAnimTime"/>
 	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
diff --git a/core/res/res/anim/shrink_fade_out.xml b/core/res/res/anim/shrink_fade_out.xml
index 7229a17..8f02362d 100644
--- a/core/res/res/anim/shrink_fade_out.xml
+++ b/core/res/res/anim/shrink_fade_out.xml
@@ -19,12 +19,12 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
-    <scale 	android:interpolator="@anim/decelerate_quint_interpolator"
+    <scale 	android:interpolator="@interpolator/decelerate_quint"
 	    	android:fromXScale="1.0" android:toXScale="0.9"
 	        android:fromYScale="1.0" android:toYScale="0.9"
            	android:pivotX="50%" android:pivotY="0%"
            	android:duration="@android:integer/config_activityDefaultDur" />
-    <alpha 	android:interpolator="@anim/decelerate_cubic_interpolator"
+    <alpha 	android:interpolator="@interpolator/decelerate_cubic"
             android:fromAlpha="1.0" android:toAlpha="0.0"
             android:duration="@android:integer/config_activityShortDur" />
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/shrink_fade_out_center.xml b/core/res/res/anim/shrink_fade_out_center.xml
index 23fa0b0..0374223 100644
--- a/core/res/res/anim/shrink_fade_out_center.xml
+++ b/core/res/res/anim/shrink_fade_out_center.xml
@@ -19,12 +19,12 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
-    <scale 	android:interpolator="@anim/decelerate_quint_interpolator"
+    <scale 	android:interpolator="@interpolator/decelerate_quint"
 	    	android:fromXScale="1.0" android:toXScale="0.9"
 	        android:fromYScale="1.0" android:toYScale="0.9"
            	android:pivotX="50%" android:pivotY="50%"
            	android:duration="@android:integer/config_activityDefaultDur" />
-    <alpha 	android:interpolator="@anim/decelerate_cubic_interpolator"
+    <alpha 	android:interpolator="@interpolator/decelerate_cubic"
             android:fromAlpha="1.0" android:toAlpha="0.0"
             android:duration="@android:integer/config_activityShortDur" />
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/shrink_fade_out_from_bottom.xml b/core/res/res/anim/shrink_fade_out_from_bottom.xml
index 0639425..4716641 100644
--- a/core/res/res/anim/shrink_fade_out_from_bottom.xml
+++ b/core/res/res/anim/shrink_fade_out_from_bottom.xml
@@ -19,12 +19,12 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
-    <scale 	android:interpolator="@anim/decelerate_quint_interpolator"
+    <scale 	android:interpolator="@interpolator/decelerate_quint"
 	    	android:fromXScale="1.0" android:toXScale="0.9"
 	        android:fromYScale="1.0" android:toYScale="0.9"
            	android:pivotX="50%" android:pivotY="100%"
            	android:duration="@android:integer/config_activityDefaultDur" />
-    <alpha 	android:interpolator="@anim/decelerate_cubic_interpolator"
+    <alpha 	android:interpolator="@interpolator/decelerate_cubic"
             android:fromAlpha="1.0" android:toAlpha="0.0"
             android:duration="@android:integer/config_activityShortDur" />
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/slide_in_child_bottom.xml b/core/res/res/anim/slide_in_child_bottom.xml
index 2ab0f66..5b143bd 100644
--- a/core/res/res/anim/slide_in_child_bottom.xml
+++ b/core/res/res/anim/slide_in_child_bottom.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator">
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/decelerate_quad">
 	<translate android:fromYDelta="100%" android:toYDelta="0"
             android:duration="@android:integer/config_mediumAnimTime"/>
 	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
diff --git a/core/res/res/anim/status_bar_enter.xml b/core/res/res/anim/status_bar_enter.xml
index d308ad5..1a1dc9b 100644
--- a/core/res/res/anim/status_bar_enter.xml
+++ b/core/res/res/anim/status_bar_enter.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator">
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/decelerate_quad">
 	<translate android:fromYDelta="-75%" android:toYDelta="0"
         android:duration="@android:integer/config_mediumAnimTime"/>
 	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
diff --git a/core/res/res/anim/status_bar_exit.xml b/core/res/res/anim/status_bar_exit.xml
index 43a1b9a..1f71090 100644
--- a/core/res/res/anim/status_bar_exit.xml
+++ b/core/res/res/anim/status_bar_exit.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator">
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/accelerate_quad">
 	<translate android:fromYDelta="0" android:toYDelta="-75%"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
 	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
diff --git a/core/res/res/anim/submenu_enter.xml b/core/res/res/anim/submenu_enter.xml
index 5a94971..a3840fc 100644
--- a/core/res/res/anim/submenu_enter.xml
+++ b/core/res/res/anim/submenu_enter.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/decelerate_interpolator">
+<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@interpolator/decelerate_quad">
 	<translate android:fromXDelta="-25%" android:toXDelta="0"
             android:duration="@android:integer/config_shortAnimTime"/>
 	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
diff --git a/core/res/res/anim/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml
index 1e29309..b479543 100644
--- a/core/res/res/anim/task_close_enter.xml
+++ b/core/res/res/anim/task_close_enter.xml
@@ -23,12 +23,12 @@
             android:fromYScale="0.95" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
 			android:fillEnabled="true" android:fillBefore="true"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:startOffset="160"
             android:duration="300" />
     <alpha 	android:fromAlpha="0" android:toAlpha="1.0"
             android:fillEnabled="true" android:fillBefore="true"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:startOffset="160"
             android:duration="300"/>
 </set>
diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml
index b232e42..e561e97 100644
--- a/core/res/res/anim/task_close_exit.xml
+++ b/core/res/res/anim/task_close_exit.xml
@@ -23,10 +23,10 @@
             android:fromYScale="1.0" android:toYScale="0.0"
             android:pivotX="50%p" android:pivotY="50%p"
 			android:fillEnabled="true" android:fillAfter="true"
-            android:interpolator="@anim/accelerate_cubic_interpolator"
+            android:interpolator="@interpolator/accelerate_cubic"
             android:duration="160" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
 			android:fillEnabled="true" android:fillAfter="true"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:duration="160"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml
index 4a2ae3b..e3e8585 100644
--- a/core/res/res/anim/task_open_enter.xml
+++ b/core/res/res/anim/task_open_enter.xml
@@ -23,12 +23,12 @@
             android:fromYScale=".9" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
             android:fillEnabled="true" android:fillBefore="true"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:startOffset="160"
             android:duration="300" />
     <alpha android:fromAlpha="0" android:toAlpha="1.0"
             android:fillEnabled="true" android:fillBefore="true"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:startOffset="160"
             android:duration="300"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml
index a213bdf..5f03516 100644
--- a/core/res/res/anim/task_open_exit.xml
+++ b/core/res/res/anim/task_open_exit.xml
@@ -23,10 +23,10 @@
             android:fromYScale="1.0" android:toYScale="0.0"
             android:pivotX="50%p" android:pivotY="50%p"
 			android:fillEnabled="true" android:fillAfter="true"
-            android:interpolator="@anim/accelerate_cubic_interpolator"
+            android:interpolator="@interpolator/accelerate_cubic"
             android:duration="160" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0"		
 			android:fillEnabled="true" android:fillAfter="true"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:duration="160"/>
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/toast_enter.xml b/core/res/res/anim/toast_enter.xml
index 57310d9..03e76a5 100644
--- a/core/res/res/anim/toast_enter.xml
+++ b/core/res/res/anim/toast_enter.xml
@@ -19,6 +19,6 @@
 -->
 
 <alpha xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/decelerate_interpolator"
+        android:interpolator="@interpolator/decelerate_quad"
         android:fromAlpha="0.0" android:toAlpha="1.0"
         android:duration="@android:integer/config_longAnimTime" />
diff --git a/core/res/res/anim/toast_exit.xml b/core/res/res/anim/toast_exit.xml
index b7c5fa0..33a7357 100644
--- a/core/res/res/anim/toast_exit.xml
+++ b/core/res/res/anim/toast_exit.xml
@@ -19,7 +19,7 @@
 -->
 
 <alpha xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/accelerate_interpolator" 
+        android:interpolator="@interpolator/accelerate_quad" 
         android:fromAlpha="1.0" android:toAlpha="0.0"
         android:duration="@android:integer/config_longAnimTime" 
 />
diff --git a/core/res/res/anim/translucent_enter.xml b/core/res/res/anim/translucent_enter.xml
index 04852a8..4526b21 100644
--- a/core/res/res/anim/translucent_enter.xml
+++ b/core/res/res/anim/translucent_enter.xml
@@ -18,7 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/decelerate_interpolator">
+        android:interpolator="@interpolator/decelerate_quad">
 	<translate android:fromXDelta="75%" android:toXDelta="0"
         android:duration="@android:integer/config_shortAnimTime"/>
     <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
diff --git a/core/res/res/anim/translucent_exit.xml b/core/res/res/anim/translucent_exit.xml
index adaf3d1..1ceb892 100644
--- a/core/res/res/anim/translucent_exit.xml
+++ b/core/res/res/anim/translucent_exit.xml
@@ -18,7 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/accelerate_interpolator">
+        android:interpolator="@interpolator/accelerate_quad">
 	<translate android:fromXDelta="0%" android:toXDelta="75%"
         android:duration="@android:integer/config_shortAnimTime"/>
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
diff --git a/core/res/res/anim/wallpaper_close_enter.xml b/core/res/res/anim/wallpaper_close_enter.xml
index 1ce0738..42a9d38 100644
--- a/core/res/res/anim/wallpaper_close_enter.xml
+++ b/core/res/res/anim/wallpaper_close_enter.xml
@@ -23,12 +23,12 @@
             android:fromYScale=".9" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
             android:fillEnabled="true" android:fillBefore="true"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:startOffset="200"
             android:duration="300" />
     <alpha android:fromAlpha="0" android:toAlpha="1.0"
             android:fillEnabled="true" android:fillBefore="true"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:startOffset="200"
             android:duration="300"/>
 </set>
diff --git a/core/res/res/anim/wallpaper_close_exit.xml b/core/res/res/anim/wallpaper_close_exit.xml
index 39af5f9..df7acc9 100644
--- a/core/res/res/anim/wallpaper_close_exit.xml
+++ b/core/res/res/anim/wallpaper_close_exit.xml
@@ -23,10 +23,10 @@
             android:fromYScale="1.0" android:toYScale="0.9"
             android:pivotX="50%p" android:pivotY="50%p"
             android:fillEnabled="true" android:fillAfter="true"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="300" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
             android:fillEnabled="true" android:fillAfter="true"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:duration="150"/>
 </set>
diff --git a/core/res/res/anim/wallpaper_enter.xml b/core/res/res/anim/wallpaper_enter.xml
index c240a9a..b28dbd4 100644
--- a/core/res/res/anim/wallpaper_enter.xml
+++ b/core/res/res/anim/wallpaper_enter.xml
@@ -18,7 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/decelerate_interpolator">
+        android:interpolator="@interpolator/decelerate_quad">
     <scale android:fromXScale="3.0" android:toXScale="1.0"
            android:fromYScale="3.0" android:toYScale="1.0"
            android:pivotX="50%" android:pivotY="50%"
diff --git a/core/res/res/anim/wallpaper_exit.xml b/core/res/res/anim/wallpaper_exit.xml
index 742286f..87ed20b 100644
--- a/core/res/res/anim/wallpaper_exit.xml
+++ b/core/res/res/anim/wallpaper_exit.xml
@@ -18,7 +18,7 @@
 -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:interpolator="@anim/accelerate_interpolator">
+        android:interpolator="@interpolator/accelerate_quad">
     <scale android:fromXScale="1.0" android:toXScale="3.0"
            android:fromYScale="1.0" android:toYScale="3.0"
            android:pivotX="50%" android:pivotY="50%"
diff --git a/core/res/res/anim/wallpaper_intra_close_enter.xml b/core/res/res/anim/wallpaper_intra_close_enter.xml
index 1ce0738..42a9d38 100644
--- a/core/res/res/anim/wallpaper_intra_close_enter.xml
+++ b/core/res/res/anim/wallpaper_intra_close_enter.xml
@@ -23,12 +23,12 @@
             android:fromYScale=".9" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
             android:fillEnabled="true" android:fillBefore="true"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:startOffset="200"
             android:duration="300" />
     <alpha android:fromAlpha="0" android:toAlpha="1.0"
             android:fillEnabled="true" android:fillBefore="true"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:startOffset="200"
             android:duration="300"/>
 </set>
diff --git a/core/res/res/anim/wallpaper_intra_close_exit.xml b/core/res/res/anim/wallpaper_intra_close_exit.xml
index 39af5f9..df7acc9 100644
--- a/core/res/res/anim/wallpaper_intra_close_exit.xml
+++ b/core/res/res/anim/wallpaper_intra_close_exit.xml
@@ -23,10 +23,10 @@
             android:fromYScale="1.0" android:toYScale="0.9"
             android:pivotX="50%p" android:pivotY="50%p"
             android:fillEnabled="true" android:fillAfter="true"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:duration="300" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
             android:fillEnabled="true" android:fillAfter="true"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:duration="150"/>
 </set>
diff --git a/core/res/res/anim/wallpaper_intra_open_enter.xml b/core/res/res/anim/wallpaper_intra_open_enter.xml
index 0a8b7d2..ff310a1 100644
--- a/core/res/res/anim/wallpaper_intra_open_enter.xml
+++ b/core/res/res/anim/wallpaper_intra_open_enter.xml
@@ -22,11 +22,11 @@
     <scale android:fromXScale="0.95" android:toXScale="1.0"
             android:fromYScale="0.95" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:startOffset="200"
             android:duration="300" />
     <alpha android:fromAlpha="0" android:toAlpha="1.0"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:startOffset="200"
             android:duration="300"/>
 </set>
diff --git a/core/res/res/anim/wallpaper_intra_open_exit.xml b/core/res/res/anim/wallpaper_intra_open_exit.xml
index d55ee6e..c750047 100644
--- a/core/res/res/anim/wallpaper_intra_open_exit.xml
+++ b/core/res/res/anim/wallpaper_intra_open_exit.xml
@@ -22,9 +22,9 @@
     <scale android:fromXScale="1.0" android:toXScale="1.0"
             android:fromYScale="1.0" android:toYScale="0.0"
             android:pivotX="50%p" android:pivotY="50%p"
-            android:interpolator="@anim/linear_interpolator"
+            android:interpolator="@interpolator/linear"
             android:duration="300" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:duration="160"/>
 </set> 
diff --git a/core/res/res/anim/wallpaper_open_enter.xml b/core/res/res/anim/wallpaper_open_enter.xml
index 0a8b7d2..ff310a1 100644
--- a/core/res/res/anim/wallpaper_open_enter.xml
+++ b/core/res/res/anim/wallpaper_open_enter.xml
@@ -22,11 +22,11 @@
     <scale android:fromXScale="0.95" android:toXScale="1.0"
             android:fromYScale="0.95" android:toYScale="1.0"
             android:pivotX="50%p" android:pivotY="50%p"
-            android:interpolator="@anim/decelerate_quint_interpolator"
+            android:interpolator="@interpolator/decelerate_quint"
             android:startOffset="200"
             android:duration="300" />
     <alpha android:fromAlpha="0" android:toAlpha="1.0"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:startOffset="200"
             android:duration="300"/>
 </set>
diff --git a/core/res/res/anim/wallpaper_open_exit.xml b/core/res/res/anim/wallpaper_open_exit.xml
index d55ee6e..c750047 100644
--- a/core/res/res/anim/wallpaper_open_exit.xml
+++ b/core/res/res/anim/wallpaper_open_exit.xml
@@ -22,9 +22,9 @@
     <scale android:fromXScale="1.0" android:toXScale="1.0"
             android:fromYScale="1.0" android:toYScale="0.0"
             android:pivotX="50%p" android:pivotY="50%p"
-            android:interpolator="@anim/linear_interpolator"
+            android:interpolator="@interpolator/linear"
             android:duration="300" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
-            android:interpolator="@anim/decelerate_cubic_interpolator"
+            android:interpolator="@interpolator/decelerate_cubic"
             android:duration="160"/>
 </set> 
diff --git a/core/res/res/anim/window_move_from_decor.xml b/core/res/res/anim/window_move_from_decor.xml
index 94062db..7fc9b5f 100644
--- a/core/res/res/anim/window_move_from_decor.xml
+++ b/core/res/res/anim/window_move_from_decor.xml
@@ -24,5 +24,5 @@
 <translate xmlns:android="http://schemas.android.com/apk/res/android"
         android:fromYDelta="100%p" android:toYDelta="0"
         android:fromXDelta="100%p" android:toXDelta="0"
-        android:interpolator="@anim/decelerate_quint_interpolator"
+        android:interpolator="@interpolator/decelerate_quint"
         android:duration="@android:integer/config_mediumAnimTime" />
diff --git a/core/res/res/animator/fade_in.xml b/core/res/res/animator/fade_in.xml
new file mode 100644
index 0000000..cff98cf
--- /dev/null
+++ b/core/res/res/animator/fade_in.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@interpolator/accelerate_quad"
+    android:valueFrom="0"
+    android:valueTo="1"
+    android:propertyName="alpha"
+    android:duration="@android:integer/config_mediumAnimTime"
+/>
diff --git a/core/res/res/animator/fade_out.xml b/core/res/res/animator/fade_out.xml
new file mode 100644
index 0000000..6a3d5ee
--- /dev/null
+++ b/core/res/res/animator/fade_out.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@interpolator/accelerate_quad"
+    android:valueFrom="1.0"
+    android:valueTo="0.0"
+    android:propertyName="alpha"
+    android:duration="@android:integer/config_mediumAnimTime"
+/>
diff --git a/core/res/res/animator/fragment_close_enter.xml b/core/res/res/animator/fragment_close_enter.xml
new file mode 100644
index 0000000..c0abbc5
--- /dev/null
+++ b/core/res/res/animator/fragment_close_enter.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License. 
+*/
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+	android:zAdjustment="normal">
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_quint"
+        android:valueFrom="0.975" android:valueTo="1.0"
+        android:valueType="floatType"
+        android:propertyName="scaleY"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_quint"
+        android:valueFrom="0.975" android:valueTo="1.0"
+        android:valueType="floatType"
+        android:propertyName="scaleX"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_cubic"
+        android:valueFrom="0.0" android:valueTo="1.0"
+        android:valueType="floatType"
+        android:propertyName="alpha"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/animator/fragment_close_exit.xml b/core/res/res/animator/fragment_close_exit.xml
new file mode 100644
index 0000000..9a5708c
--- /dev/null
+++ b/core/res/res/animator/fragment_close_exit.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License. 
+*/
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+	android:zAdjustment="top">
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_quint"
+        android:valueFrom="1.0" android:valueTo="1.075"
+        android:valueType="floatType"
+        android:propertyName="scaleY"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_quint"
+        android:valueFrom="1.0" android:valueTo="1.075"
+        android:valueType="floatType"
+        android:propertyName="scaleX"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_cubic"
+        android:valueFrom="1.0" android:valueTo="0.0"
+        android:valueType="floatType"
+        android:propertyName="alpha"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/animator/fragment_next_enter.xml b/core/res/res/animator/fragment_next_enter.xml
new file mode 100644
index 0000000..13b15f3
--- /dev/null
+++ b/core/res/res/animator/fragment_next_enter.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+	android:zAdjustment="top">
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_cubic"
+        android:valueFrom="0"
+        android:valueTo="1"
+        android:valueType="floatType"
+        android:propertyName="alpha"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/animator/fragment_next_exit.xml b/core/res/res/animator/fragment_next_exit.xml
new file mode 100644
index 0000000..503b7ad
--- /dev/null
+++ b/core/res/res/animator/fragment_next_exit.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+	android:zAdjustment="normal">
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_cubic"
+        android:valueFrom="1"
+        android:valueTo="0"
+        android:valueType="floatType"
+        android:propertyName="alpha"
+        android:duration="@android:integer/config_activityShortDur"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/animator/fragment_open_enter.xml b/core/res/res/animator/fragment_open_enter.xml
new file mode 100644
index 0000000..6b16cb4
--- /dev/null
+++ b/core/res/res/animator/fragment_open_enter.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License. 
+*/
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_quint"
+        android:valueFrom="1.125" android:valueTo="1.0"
+        android:valueType="floatType"
+        android:propertyName="scaleY"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_quint"
+        android:valueFrom="1.125" android:valueTo="1.0"
+        android:valueType="floatType"
+        android:propertyName="scaleX"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_cubic"
+        android:valueFrom="0.0" android:valueTo="1.0"
+        android:valueType="floatType"
+        android:propertyName="alpha"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/animator/fragment_open_exit.xml b/core/res/res/animator/fragment_open_exit.xml
new file mode 100644
index 0000000..d77ee8e
--- /dev/null
+++ b/core/res/res/animator/fragment_open_exit.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License. 
+*/
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <objectAnimator
+        android:interpolator="@interpolator/linear"
+        android:valueFrom="1.0" android:valueTo="0.975"
+        android:valueType="floatType"
+        android:propertyName="scaleY"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+    <objectAnimator
+        android:interpolator="@interpolator/linear"
+        android:valueFrom="1.0" android:valueTo="0.975"
+        android:valueType="floatType"
+        android:propertyName="scaleX"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_cubic"
+        android:valueFrom="1.0" android:valueTo="0.0"
+        android:valueType="floatType"
+        android:propertyName="alpha"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/animator/fragment_prev_enter.xml b/core/res/res/animator/fragment_prev_enter.xml
new file mode 100644
index 0000000..13b15f3
--- /dev/null
+++ b/core/res/res/animator/fragment_prev_enter.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+	android:zAdjustment="top">
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_cubic"
+        android:valueFrom="0"
+        android:valueTo="1"
+        android:valueType="floatType"
+        android:propertyName="alpha"
+        android:duration="@android:integer/config_activityDefaultDur"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/animator/fragment_prev_exit.xml b/core/res/res/animator/fragment_prev_exit.xml
new file mode 100644
index 0000000..503b7ad
--- /dev/null
+++ b/core/res/res/animator/fragment_prev_exit.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+	android:zAdjustment="normal">
+    <objectAnimator
+        android:interpolator="@interpolator/decelerate_cubic"
+        android:valueFrom="1"
+        android:valueTo="0"
+        android:valueType="floatType"
+        android:propertyName="alpha"
+        android:duration="@android:integer/config_activityShortDur"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/drawable-hdpi/btn_check_off.png b/core/res/res/drawable-hdpi/btn_check_off.png
old mode 100644
new mode 100755
index aad9ef7..bb62e6f
--- a/core/res/res/drawable-hdpi/btn_check_off.png
+++ b/core/res/res/drawable-hdpi/btn_check_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable.png b/core/res/res/drawable-hdpi/btn_check_off_disable.png
old mode 100644
new mode 100755
index eaee9e0..b346381
--- a/core/res/res/drawable-hdpi/btn_check_off_disable.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_focused.png b/core/res/res/drawable-hdpi/btn_check_off_disable_focused.png
old mode 100644
new mode 100755
index 6d2c293..8663369
--- a/core/res/res/drawable-hdpi/btn_check_off_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_pressed.png b/core/res/res/drawable-hdpi/btn_check_off_pressed.png
old mode 100644
new mode 100755
index 1c442e9..67e49df
--- a/core/res/res/drawable-hdpi/btn_check_off_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_selected.png b/core/res/res/drawable-hdpi/btn_check_off_selected.png
old mode 100644
new mode 100755
index b852b2c..1791d1f
--- a/core/res/res/drawable-hdpi/btn_check_off_selected.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on.png b/core/res/res/drawable-hdpi/btn_check_on.png
old mode 100644
new mode 100755
index cd5c181..15cd25e
--- a/core/res/res/drawable-hdpi/btn_check_on.png
+++ b/core/res/res/drawable-hdpi/btn_check_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable.png b/core/res/res/drawable-hdpi/btn_check_on_disable.png
old mode 100644
new mode 100755
index b4fc51a..e3fe323
--- a/core/res/res/drawable-hdpi/btn_check_on_disable.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_focused.png b/core/res/res/drawable-hdpi/btn_check_on_disable_focused.png
old mode 100644
new mode 100755
index bf34647..fa41bb7
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed.png b/core/res/res/drawable-hdpi/btn_check_on_pressed.png
old mode 100644
new mode 100755
index fa5c7a2..906e283
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_selected.png b/core/res/res/drawable-hdpi/btn_check_on_selected.png
old mode 100644
new mode 100755
index a6a21ad..eb496a8
--- a/core/res/res/drawable-hdpi/btn_check_on_selected.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_circle_disable.png b/core/res/res/drawable-hdpi/btn_circle_disable.png
old mode 100644
new mode 100755
index d829716..39652a8
--- a/core/res/res/drawable-hdpi/btn_circle_disable.png
+++ b/core/res/res/drawable-hdpi/btn_circle_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_circle_disable_focused.png b/core/res/res/drawable-hdpi/btn_circle_disable_focused.png
old mode 100644
new mode 100755
index c1b5b6e..1aa7ffe
--- a/core/res/res/drawable-hdpi/btn_circle_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_circle_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_circle_normal.png b/core/res/res/drawable-hdpi/btn_circle_normal.png
old mode 100644
new mode 100755
index bf3fb5a..6011219
--- a/core/res/res/drawable-hdpi/btn_circle_normal.png
+++ b/core/res/res/drawable-hdpi/btn_circle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_circle_pressed.png b/core/res/res/drawable-hdpi/btn_circle_pressed.png
old mode 100644
new mode 100755
index 50e22e6..4942e50
--- a/core/res/res/drawable-hdpi/btn_circle_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_circle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_circle_selected.png b/core/res/res/drawable-hdpi/btn_circle_selected.png
old mode 100644
new mode 100755
index cfc68fb..fe49a40
--- a/core/res/res/drawable-hdpi/btn_circle_selected.png
+++ b/core/res/res/drawable-hdpi/btn_circle_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_close_normal.png b/core/res/res/drawable-hdpi/btn_close_normal.png
old mode 100644
new mode 100755
index 38b49f1..47f11e5
--- a/core/res/res/drawable-hdpi/btn_close_normal.png
+++ b/core/res/res/drawable-hdpi/btn_close_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_close_pressed.png b/core/res/res/drawable-hdpi/btn_close_pressed.png
old mode 100644
new mode 100755
index aa9ea49f0..5b96b4e
--- a/core/res/res/drawable-hdpi/btn_close_pressed.png
+++ b/core/res/res/drawable-hdpi/btn_close_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_close_selected.png b/core/res/res/drawable-hdpi/btn_close_selected.png
old mode 100644
new mode 100755
index 870c670..e27d684
--- a/core/res/res/drawable-hdpi/btn_close_selected.png
+++ b/core/res/res/drawable-hdpi/btn_close_selected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal.9.png b/core/res/res/drawable-hdpi/btn_default_normal.9.png
old mode 100644
new mode 100755
index 329ce6e..803651b
--- a/core/res/res/drawable-hdpi/btn_default_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_disable.9.png b/core/res/res/drawable-hdpi/btn_default_normal_disable.9.png
old mode 100644
new mode 100755
index a518c6b..f4f01c7
--- a/core/res/res/drawable-hdpi/btn_default_normal_disable.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_disable_focused.9.png b/core/res/res/drawable-hdpi/btn_default_normal_disable_focused.9.png
old mode 100644
new mode 100755
index 71a05b7..5376db2
--- a/core/res/res/drawable-hdpi/btn_default_normal_disable_focused.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed.9.png b/core/res/res/drawable-hdpi/btn_default_pressed.9.png
old mode 100644
new mode 100755
index d9d02bf..4312c27
--- a/core/res/res/drawable-hdpi/btn_default_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_selected.9.png b/core/res/res/drawable-hdpi/btn_default_selected.9.png
old mode 100644
new mode 100755
index ab7c612..06b7790
--- a/core/res/res/drawable-hdpi/btn_default_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_small_normal.9.png b/core/res/res/drawable-hdpi/btn_default_small_normal.9.png
old mode 100644
new mode 100755
index baafed6..6d3ea9a
--- a/core/res/res/drawable-hdpi/btn_default_small_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_small_normal_disable.9.png b/core/res/res/drawable-hdpi/btn_default_small_normal_disable.9.png
old mode 100644
new mode 100755
index 175197b..2646ba0
--- a/core/res/res/drawable-hdpi/btn_default_small_normal_disable.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png b/core/res/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
old mode 100644
new mode 100755
index ec1feff..013210c
--- a/core/res/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_small_pressed.9.png b/core/res/res/drawable-hdpi/btn_default_small_pressed.9.png
old mode 100644
new mode 100755
index c1f9a0f..24cefd4
--- a/core/res/res/drawable-hdpi/btn_default_small_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_small_selected.9.png b/core/res/res/drawable-hdpi/btn_default_small_selected.9.png
old mode 100644
new mode 100755
index 0ea3f40..bedbceb
--- a/core/res/res/drawable-hdpi/btn_default_small_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dropdown_disabled.9.png b/core/res/res/drawable-hdpi/btn_dropdown_disabled.9.png
index c6503c7..0d25b6e 100644
--- a/core/res/res/drawable-hdpi/btn_dropdown_disabled.9.png
+++ b/core/res/res/drawable-hdpi/btn_dropdown_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dropdown_disabled_focused.9.png b/core/res/res/drawable-hdpi/btn_dropdown_disabled_focused.9.png
index 152de8b..e21fd75 100644
--- a/core/res/res/drawable-hdpi/btn_dropdown_disabled_focused.9.png
+++ b/core/res/res/drawable-hdpi/btn_dropdown_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dropdown_normal.9.png b/core/res/res/drawable-hdpi/btn_dropdown_normal.9.png
old mode 100644
new mode 100755
index 9392495..f10402f
--- a/core/res/res/drawable-hdpi/btn_dropdown_normal.9.png
+++ b/core/res/res/drawable-hdpi/btn_dropdown_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dropdown_pressed.9.png b/core/res/res/drawable-hdpi/btn_dropdown_pressed.9.png
old mode 100644
new mode 100755
index beaba45..366c6e0
--- a/core/res/res/drawable-hdpi/btn_dropdown_pressed.9.png
+++ b/core/res/res/drawable-hdpi/btn_dropdown_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_dropdown_selected.9.png b/core/res/res/drawable-hdpi/btn_dropdown_selected.9.png
old mode 100644
new mode 100755
index ec51fc9..f063c8d
--- a/core/res/res/drawable-hdpi/btn_dropdown_selected.9.png
+++ b/core/res/res/drawable-hdpi/btn_dropdown_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/day_picker_week_view_dayline_holo_dark.9.png b/core/res/res/drawable-hdpi/day_picker_week_view_dayline_holo.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/day_picker_week_view_dayline_holo_dark.9.png
rename to core/res/res/drawable-hdpi/day_picker_week_view_dayline_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/day_picker_week_view_dayline_holo_light.9.png b/core/res/res/drawable-hdpi/day_picker_week_view_dayline_holo_light.9.png
deleted file mode 100644
index 2edae8f..0000000
--- a/core/res/res/drawable-hdpi/day_picker_week_view_dayline_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
index bbfb9f7..065cc9c 100644
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
index af69ee5..94decee 100644
--- a/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo.9.png b/core/res/res/drawable-hdpi/dialog_full_holo.9.png
deleted file mode 100644
index 5d2e4e1..0000000
--- a/core/res/res/drawable-hdpi/dialog_full_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
index 59b9b13..3b9e0cf 100644
--- a/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
index e1ec9dc..0665b08 100644
--- a/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
index a9f85ea..dc62ab2 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
index c4c4652..e78e134 100644
--- a/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo.9.png b/core/res/res/drawable-hdpi/dialog_top_holo.9.png
deleted file mode 100644
index 0275c18..0000000
--- a/core/res/res/drawable-hdpi/dialog_top_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
index 32c2cb4..ae223c8 100644
--- a/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
index 7a8fb0e..7baced0 100644
--- a/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_ic_maximized.9.png b/core/res/res/drawable-hdpi/expander_ic_maximized.9.png
index 04943aa..2ec27af 100644
--- a/core/res/res/drawable-hdpi/expander_ic_maximized.9.png
+++ b/core/res/res/drawable-hdpi/expander_ic_maximized.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_ic_minimized.9.png b/core/res/res/drawable-hdpi/expander_ic_minimized.9.png
index 7bddbce..0c19bb7 100644
--- a/core/res/res/drawable-hdpi/expander_ic_minimized.9.png
+++ b/core/res/res/drawable-hdpi/expander_ic_minimized.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_round_more_disabled.png b/core/res/res/drawable-hdpi/ic_btn_round_more_disabled.png
old mode 100644
new mode 100755
index 0125944..3f1176f
--- a/core/res/res/drawable-hdpi/ic_btn_round_more_disabled.png
+++ b/core/res/res/drawable-hdpi/ic_btn_round_more_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_round_more_normal.png b/core/res/res/drawable-hdpi/ic_btn_round_more_normal.png
old mode 100644
new mode 100755
index 33d7f89..8abda4d
--- a/core/res/res/drawable-hdpi/ic_btn_round_more_normal.png
+++ b/core/res/res/drawable-hdpi/ic_btn_round_more_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_clear_off.png b/core/res/res/drawable-hdpi/ic_clear_disabled.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_clear_off.png
rename to core/res/res/drawable-hdpi/ic_clear_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_clear.png b/core/res/res/drawable-hdpi/ic_clear_normal.png
similarity index 100%
rename from core/res/res/drawable-hdpi/ic_clear.png
rename to core/res/res/drawable-hdpi/ic_clear_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_clear_search_api_disabled_holo_light.png b/core/res/res/drawable-hdpi/ic_clear_search_api_disabled_holo_light.png
new file mode 100644
index 0000000..3edbd74
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_clear_search_api_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_clear_search_api_holo_light.png b/core/res/res/drawable-hdpi/ic_clear_search_api_holo_light.png
new file mode 100644
index 0000000..90db01b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_clear_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_commit_search_api_holo_light.png b/core/res/res/drawable-hdpi/ic_commit_search_api_holo_light.png
new file mode 100644
index 0000000..b01688f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_commit_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_alert_holo_dark.png b/core/res/res/drawable-hdpi/ic_dialog_alert_holo_dark.png
new file mode 100644
index 0000000..f0ba889
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_dialog_alert_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_alert_holo_light.png b/core/res/res/drawable-hdpi/ic_dialog_alert_holo_light.png
new file mode 100644
index 0000000..1374a53
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_dialog_alert_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_go_search_api_holo_light.png b/core/res/res/drawable-hdpi/ic_go_search_api_holo_light.png
new file mode 100644
index 0000000..7e1ba2a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_go_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_help.png b/core/res/res/drawable-hdpi/ic_menu_help.png
index 4300e86..01a77da 100644
--- a/core/res/res/drawable-hdpi/ic_menu_help.png
+++ b/core/res/res/drawable-hdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_search_api_holo_light.png b/core/res/res/drawable-hdpi/ic_search_api_holo_light.png
new file mode 100644
index 0000000..72e207b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_voice_search_api_holo_light.png b/core/res/res/drawable-hdpi/ic_voice_search_api_holo_light.png
new file mode 100644
index 0000000..3481c98
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_voice_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png
old mode 100644
new mode 100755
index ab377d8..9e1c42a
--- a/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_focus.9.png b/core/res/res/drawable-hdpi/list_selector_background_focus.9.png
old mode 100644
new mode 100755
index 94a9fba..5563c80
--- a/core/res/res/drawable-hdpi/list_selector_background_focus.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png b/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png
old mode 100644
new mode 100755
index bd74426..72d3a08
--- a/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_longpress.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png b/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png
old mode 100644
new mode 100755
index d18d6f7..7568b30
--- a/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png
+++ b/core/res/res/drawable-hdpi/list_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_background.9.png b/core/res/res/drawable-hdpi/menu_background.9.png
index 60f0731..f4c9e08 100644
--- a/core/res/res/drawable-hdpi/menu_background.9.png
+++ b/core/res/res/drawable-hdpi/menu_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_background_fill_parent_width.9.png b/core/res/res/drawable-hdpi/menu_background_fill_parent_width.9.png
index 09eac9b..a3cec11 100644
--- a/core/res/res/drawable-hdpi/menu_background_fill_parent_width.9.png
+++ b/core/res/res/drawable-hdpi/menu_background_fill_parent_width.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
index 7ec3a33f..ec91bd8 100644
--- a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
index da1fe94..67c5950 100644
--- a/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/nav_divider.png b/core/res/res/drawable-hdpi/nav_divider.png
deleted file mode 100644
index 7ca3e61..0000000
--- a/core/res/res/drawable-hdpi/nav_divider.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_disabled.9.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_down_disabled.9.png
rename to core/res/res/drawable-hdpi/numberpicker_down_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_disabled_focused.9.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_down_disabled_focused.9.png
rename to core/res/res/drawable-hdpi/numberpicker_down_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..f43f9ad
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_light.png
new file mode 100644
index 0000000..2ada3ef
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_dark.png
new file mode 100644
index 0000000..5ed7040
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_light.png
new file mode 100644
index 0000000..d4a01cf
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_down_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png
new file mode 100644
index 0000000..ada6251
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png
new file mode 100644
index 0000000..1247c7a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_down_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png
new file mode 100644
index 0000000..3d13454
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png
new file mode 100644
index 0000000..4898244
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_down_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_normal.9.png b/core/res/res/drawable-hdpi/numberpicker_down_normal.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_down_normal.9.png
rename to core/res/res/drawable-hdpi/numberpicker_down_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png
new file mode 100644
index 0000000..bb1074c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png
new file mode 100644
index 0000000..e6e5a0f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_down_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_pressed.9.png b/core/res/res/drawable-hdpi/numberpicker_down_pressed.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_down_pressed.9.png
rename to core/res/res/drawable-hdpi/numberpicker_down_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_dark.png
new file mode 100644
index 0000000..b54e603
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_light.png
new file mode 100644
index 0000000..70ee54c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_down_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_selected.9.png b/core/res/res/drawable-hdpi/numberpicker_down_selected.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_down_selected.9.png
rename to core/res/res/drawable-hdpi/numberpicker_down_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_input_disabled.9.png b/core/res/res/drawable-hdpi/numberpicker_input_disabled.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_input_disabled.9.png
rename to core/res/res/drawable-hdpi/numberpicker_input_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_input_normal.9.png b/core/res/res/drawable-hdpi/numberpicker_input_normal.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_input_normal.9.png
rename to core/res/res/drawable-hdpi/numberpicker_input_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_input_pressed.9.png b/core/res/res/drawable-hdpi/numberpicker_input_pressed.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_input_pressed.9.png
rename to core/res/res/drawable-hdpi/numberpicker_input_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_input_selected.9.png b/core/res/res/drawable-hdpi/numberpicker_input_selected.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_input_selected.9.png
rename to core/res/res/drawable-hdpi/numberpicker_input_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_disabled.9.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_up_disabled.9.png
rename to core/res/res/drawable-hdpi/numberpicker_up_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_disabled_focused.9.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_up_disabled_focused.9.png
rename to core/res/res/drawable-hdpi/numberpicker_up_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..a55c96a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_light.png
new file mode 100644
index 0000000..4e31c72
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_dark.png
new file mode 100644
index 0000000..8158596
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_light.png
new file mode 100644
index 0000000..37e5c0d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_up_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png
new file mode 100644
index 0000000..7ec94e6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png
new file mode 100644
index 0000000..780fff1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_up_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png
new file mode 100644
index 0000000..73c8dd9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png
new file mode 100644
index 0000000..3b96480
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_up_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_normal.9.png b/core/res/res/drawable-hdpi/numberpicker_up_normal.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_up_normal.9.png
rename to core/res/res/drawable-hdpi/numberpicker_up_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png
new file mode 100644
index 0000000..21f0871
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png
new file mode 100644
index 0000000..49e3c15
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_up_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_pressed.9.png b/core/res/res/drawable-hdpi/numberpicker_up_pressed.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_up_pressed.9.png
rename to core/res/res/drawable-hdpi/numberpicker_up_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_dark.png b/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_dark.png
new file mode 100644
index 0000000..a15a5f5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_light.png b/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_light.png
new file mode 100644
index 0000000..7441361
--- /dev/null
+++ b/core/res/res/drawable-hdpi/numberpicker_up_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_selected.9.png b/core/res/res/drawable-hdpi/numberpicker_up_selected.9.png
similarity index 100%
rename from core/res/res/drawable-hdpi/timepicker_up_selected.9.png
rename to core/res/res/drawable-hdpi/numberpicker_up_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/panel_background.9.png b/core/res/res/drawable-hdpi/panel_background.9.png
index bfe5713..03175d4 100644
--- a/core/res/res/drawable-hdpi/panel_background.9.png
+++ b/core/res/res/drawable-hdpi/panel_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/picture_emergency.png b/core/res/res/drawable-hdpi/picture_emergency.png
index b0f10f9..e088f12 100644
--- a/core/res/res/drawable-hdpi/picture_emergency.png
+++ b/core/res/res/drawable-hdpi/picture_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_bottom_bright.9.png b/core/res/res/drawable-hdpi/popup_bottom_bright.9.png
index cca47d3..6e5fbb5 100644
--- a/core/res/res/drawable-hdpi/popup_bottom_bright.9.png
+++ b/core/res/res/drawable-hdpi/popup_bottom_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_bottom_dark.9.png b/core/res/res/drawable-hdpi/popup_bottom_dark.9.png
index 62a0bd0..3434b2d 100644
--- a/core/res/res/drawable-hdpi/popup_bottom_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_bottom_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_bottom_medium.9.png b/core/res/res/drawable-hdpi/popup_bottom_medium.9.png
index 6ebb4f7..673a509 100644
--- a/core/res/res/drawable-hdpi/popup_bottom_medium.9.png
+++ b/core/res/res/drawable-hdpi/popup_bottom_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_center_bright.9.png b/core/res/res/drawable-hdpi/popup_center_bright.9.png
index 756e9ed..c2a739c 100644
--- a/core/res/res/drawable-hdpi/popup_center_bright.9.png
+++ b/core/res/res/drawable-hdpi/popup_center_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_center_dark.9.png b/core/res/res/drawable-hdpi/popup_center_dark.9.png
index 77b4524..9d2bfb1 100644
--- a/core/res/res/drawable-hdpi/popup_center_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_center_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_center_medium.9.png b/core/res/res/drawable-hdpi/popup_center_medium.9.png
index de4be2a..4375bf2d 100644
--- a/core/res/res/drawable-hdpi/popup_center_medium.9.png
+++ b/core/res/res/drawable-hdpi/popup_center_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_full_bright.9.png b/core/res/res/drawable-hdpi/popup_full_bright.9.png
index 6c30bec..6b8aa9d 100644
--- a/core/res/res/drawable-hdpi/popup_full_bright.9.png
+++ b/core/res/res/drawable-hdpi/popup_full_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_full_dark.9.png b/core/res/res/drawable-hdpi/popup_full_dark.9.png
index fc8c00e..2884abe 100644
--- a/core/res/res/drawable-hdpi/popup_full_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_full_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_top_bright.9.png b/core/res/res/drawable-hdpi/popup_top_bright.9.png
index ddd30ab..76c35ec 100644
--- a/core/res/res/drawable-hdpi/popup_top_bright.9.png
+++ b/core/res/res/drawable-hdpi/popup_top_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_top_dark.9.png b/core/res/res/drawable-hdpi/popup_top_dark.9.png
index 144d0fc..f317330 100644
--- a/core/res/res/drawable-hdpi/popup_top_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_top_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_audio_away.png b/core/res/res/drawable-hdpi/presence_audio_away.png
index fb5e123..b26c0e0 100644
--- a/core/res/res/drawable-hdpi/presence_audio_away.png
+++ b/core/res/res/drawable-hdpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_audio_busy.png b/core/res/res/drawable-hdpi/presence_audio_busy.png
index 81aeb01..0124659 100644
--- a/core/res/res/drawable-hdpi/presence_audio_busy.png
+++ b/core/res/res/drawable-hdpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_audio_online.png b/core/res/res/drawable-hdpi/presence_audio_online.png
index 553acbb..520bcd8 100644
--- a/core/res/res/drawable-hdpi/presence_audio_online.png
+++ b/core/res/res/drawable-hdpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_away.png b/core/res/res/drawable-hdpi/presence_away.png
index 84b00bb..6a27382 100644
--- a/core/res/res/drawable-hdpi/presence_away.png
+++ b/core/res/res/drawable-hdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_busy.png b/core/res/res/drawable-hdpi/presence_busy.png
index d77a463..7278aec 100644
--- a/core/res/res/drawable-hdpi/presence_busy.png
+++ b/core/res/res/drawable-hdpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_invisible.png b/core/res/res/drawable-hdpi/presence_invisible.png
index 0d83e70a..cff85be 100644
--- a/core/res/res/drawable-hdpi/presence_invisible.png
+++ b/core/res/res/drawable-hdpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_offline.png b/core/res/res/drawable-hdpi/presence_offline.png
index 2619e9f..6c3fbb6 100644
--- a/core/res/res/drawable-hdpi/presence_offline.png
+++ b/core/res/res/drawable-hdpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_online.png b/core/res/res/drawable-hdpi/presence_online.png
index 7e846ef..77c368a 100644
--- a/core/res/res/drawable-hdpi/presence_online.png
+++ b/core/res/res/drawable-hdpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_video_away.png b/core/res/res/drawable-hdpi/presence_video_away.png
index ab5493b..302f538 100644
--- a/core/res/res/drawable-hdpi/presence_video_away.png
+++ b/core/res/res/drawable-hdpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_video_busy.png b/core/res/res/drawable-hdpi/presence_video_busy.png
index 456cdb0..8fdea57 100644
--- a/core/res/res/drawable-hdpi/presence_video_busy.png
+++ b/core/res/res/drawable-hdpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/presence_video_online.png b/core/res/res/drawable-hdpi/presence_video_online.png
index bd9f8a4..6c1fd6b 100644
--- a/core/res/res/drawable-hdpi/presence_video_online.png
+++ b/core/res/res/drawable-hdpi/presence_video_online.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png b/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png
index 079de61..5aea3d9 100644
--- a/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png b/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png
index 2272b41..5743d06 100644
--- a/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png b/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png
index 16b7349..f134a59 100644
--- a/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png b/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png
index 7229343..f134a59 100644
--- a/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png b/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png
index 894dfcf..22d608a 100644
--- a/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png b/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png
index f553ba6..22d608a 100644
--- a/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo1.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo1.png
new file mode 100644
index 0000000..595e0a4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo2.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo2.png
new file mode 100644
index 0000000..75ad3d6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo3.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo3.png
new file mode 100644
index 0000000..74e90fd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo4.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo4.png
new file mode 100644
index 0000000..7e6948a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo5.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo5.png
new file mode 100644
index 0000000..38b376c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo5.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo6.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo6.png
new file mode 100644
index 0000000..7cbdcf8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo6.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo7.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo7.png
new file mode 100644
index 0000000..b362b20
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo7.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo8.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo8.png
new file mode 100644
index 0000000..45f4f59
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo8.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png
new file mode 100644
index 0000000..a2264ec
--- /dev/null
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png
new file mode 100644
index 0000000..9dd657f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
new file mode 100644
index 0000000..7e7a164
--- /dev/null
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png
new file mode 100644
index 0000000..45a5e30
--- /dev/null
+++ b/core/res/res/drawable-hdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_pressed.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_pressed.9.png
deleted file mode 100644
index 75c8162..0000000
--- a/core/res/res/drawable-hdpi/quickcontact_badge_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_small_pressed.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_small_pressed.9.png
deleted file mode 100644
index aebfa29..0000000
--- a/core/res/res/drawable-hdpi/quickcontact_badge_small_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_small_unpressed.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_small_unpressed.9.png
deleted file mode 100644
index ed416f1..0000000
--- a/core/res/res/drawable-hdpi/quickcontact_badge_small_unpressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_badge_unpressed.9.png b/core/res/res/drawable-hdpi/quickcontact_badge_unpressed.9.png
deleted file mode 100644
index d063229..0000000
--- a/core/res/res/drawable-hdpi/quickcontact_badge_unpressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/quickcontact_nobadge.9.png b/core/res/res/drawable-hdpi/quickcontact_nobadge.9.png
deleted file mode 100644
index 68d43c4..0000000
--- a/core/res/res/drawable-hdpi/quickcontact_nobadge.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_disabled_holo.png b/core/res/res/drawable-hdpi/scrubber_control_disabled_holo.png
new file mode 100644
index 0000000..401e904
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_holo.png b/core/res/res/drawable-hdpi/scrubber_control_holo.png
index 3a72307..175917e 100644
--- a/core/res/res/drawable-hdpi/scrubber_control_holo.png
+++ b/core/res/res/drawable-hdpi/scrubber_control_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_primary_holo.9.png b/core/res/res/drawable-hdpi/scrubber_primary_holo.9.png
new file mode 100644
index 0000000..3bc78a8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_primary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_secondary_holo.9.png b/core/res/res/drawable-hdpi/scrubber_secondary_holo.9.png
new file mode 100644
index 0000000..8eadf00
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_secondary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_track_holo_dark.9.png b/core/res/res/drawable-hdpi/scrubber_track_holo_dark.9.png
index e6d7123..14ce985 100644
--- a/core/res/res/drawable-hdpi/scrubber_track_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_track_holo_light.9.png b/core/res/res/drawable-hdpi/scrubber_track_holo_light.9.png
index f75bfa0..5edaed5 100644
--- a/core/res/res/drawable-hdpi/scrubber_track_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/scrubber_track_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/simple_week_dayline_holo_light.9.png b/core/res/res/drawable-hdpi/simple_week_dayline_holo_light.9.png
deleted file mode 100644
index ed1a5e9..0000000
--- a/core/res/res/drawable-hdpi/simple_week_dayline_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_call_mute.png b/core/res/res/drawable-hdpi/stat_notify_call_mute.png
index b86d2ca..b0f7990 100755
--- a/core/res/res/drawable-hdpi/stat_notify_call_mute.png
+++ b/core/res/res/drawable-hdpi/stat_notify_call_mute.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_car_mode.png b/core/res/res/drawable-hdpi/stat_notify_car_mode.png
index 03499a4..e700d79 100644
--- a/core/res/res/drawable-hdpi/stat_notify_car_mode.png
+++ b/core/res/res/drawable-hdpi/stat_notify_car_mode.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_chat.png b/core/res/res/drawable-hdpi/stat_notify_chat.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_disk_full.png b/core/res/res/drawable-hdpi/stat_notify_disk_full.png
index 6ceeda8..66e7380 100755
--- a/core/res/res/drawable-hdpi/stat_notify_disk_full.png
+++ b/core/res/res/drawable-hdpi/stat_notify_disk_full.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 07de4cb..bc5fcab 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_error.png b/core/res/res/drawable-hdpi/stat_notify_error.png
old mode 100644
new mode 100755
index 37c8853..b3a18b3
--- a/core/res/res/drawable-hdpi/stat_notify_error.png
+++ b/core/res/res/drawable-hdpi/stat_notify_error.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 1aadf68..ea8beae 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-hdpi/stat_notify_missed_call.png b/core/res/res/drawable-hdpi/stat_notify_missed_call.png
old mode 100755
new mode 100644
index 192574d..3c19c93
--- a/core/res/res/drawable-hdpi/stat_notify_missed_call.png
+++ b/core/res/res/drawable-hdpi/stat_notify_missed_call.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_more.png b/core/res/res/drawable-hdpi/stat_notify_more.png
index 1c7f9db..f54b3d4 100755
--- a/core/res/res/drawable-hdpi/stat_notify_more.png
+++ b/core/res/res/drawable-hdpi/stat_notify_more.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sdcard.png b/core/res/res/drawable-hdpi/stat_notify_sdcard.png
old mode 100644
new mode 100755
index d3b624b..dd947a5
--- a/core/res/res/drawable-hdpi/stat_notify_sdcard.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sdcard.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sdcard_prepare.png b/core/res/res/drawable-hdpi/stat_notify_sdcard_prepare.png
old mode 100644
new mode 100755
index a483ba2..4b9b9ca
--- a/core/res/res/drawable-hdpi/stat_notify_sdcard_prepare.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sdcard_prepare.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png b/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png
old mode 100644
new mode 100755
index a5e369e2..fb2b26a
--- a/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sim_toolkit.png b/core/res/res/drawable-hdpi/stat_notify_sim_toolkit.png
index 3b14c26..8865bda 100755
--- a/core/res/res/drawable-hdpi/stat_notify_sim_toolkit.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sim_toolkit.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sync.png b/core/res/res/drawable-hdpi/stat_notify_sync.png
index 6f9cf84..004cfab 100755
--- a/core/res/res/drawable-hdpi/stat_notify_sync.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sync.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sync_anim0.png b/core/res/res/drawable-hdpi/stat_notify_sync_anim0.png
index 6f9cf84..6973fc5 100755
--- a/core/res/res/drawable-hdpi/stat_notify_sync_anim0.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sync_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sync_error.png b/core/res/res/drawable-hdpi/stat_notify_sync_error.png
index 6e3b545..26b2446 100755
--- a/core/res/res/drawable-hdpi/stat_notify_sync_error.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sync_error.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_voicemail.png b/core/res/res/drawable-hdpi/stat_notify_voicemail.png
index 70b2411..5b77846 100755
--- a/core/res/res/drawable-hdpi/stat_notify_voicemail.png
+++ b/core/res/res/drawable-hdpi/stat_notify_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png
old mode 100755
new mode 100644
index e9405dd..76034e5
--- a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png
+++ b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_adb.png b/core/res/res/drawable-hdpi/stat_sys_adb.png
old mode 100644
new mode 100755
index aef8650..f99b780
--- a/core/res/res/drawable-hdpi/stat_sys_adb.png
+++ b/core/res/res/drawable-hdpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_bluetooth.png b/core/res/res/drawable-hdpi/stat_sys_data_bluetooth.png
index 7a8b78f..e8fbc9e 100644
--- a/core/res/res/drawable-hdpi/stat_sys_data_bluetooth.png
+++ b/core/res/res/drawable-hdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_data_usb.png b/core/res/res/drawable-hdpi/stat_sys_data_usb.png
index 4c14c07..e916fbb 100755
--- a/core/res/res/drawable-hdpi/stat_sys_data_usb.png
+++ b/core/res/res/drawable-hdpi/stat_sys_data_usb.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_download_anim0.png b/core/res/res/drawable-hdpi/stat_sys_download_anim0.png
index d9c9e4c..c127e6e 100755
--- a/core/res/res/drawable-hdpi/stat_sys_download_anim0.png
+++ b/core/res/res/drawable-hdpi/stat_sys_download_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_gps_on.png b/core/res/res/drawable-hdpi/stat_sys_gps_on.png
index 99a8c6c..2ed6082 100644
--- a/core/res/res/drawable-hdpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-hdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_r_signal_0_cdma.png b/core/res/res/drawable-hdpi/stat_sys_r_signal_0_cdma.png
index 28b2fc2..14a7e94 100644
--- a/core/res/res/drawable-hdpi/stat_sys_r_signal_0_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_r_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_r_signal_1_cdma.png b/core/res/res/drawable-hdpi/stat_sys_r_signal_1_cdma.png
index a7449cd..9cf04b5 100644
--- a/core/res/res/drawable-hdpi/stat_sys_r_signal_1_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_r_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_r_signal_2_cdma.png b/core/res/res/drawable-hdpi/stat_sys_r_signal_2_cdma.png
index c4c1fb8..dbd3308 100644
--- a/core/res/res/drawable-hdpi/stat_sys_r_signal_2_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_r_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_r_signal_3_cdma.png b/core/res/res/drawable-hdpi/stat_sys_r_signal_3_cdma.png
old mode 100644
new mode 100755
index 0a32d2e..a3a6b6c
--- a/core/res/res/drawable-hdpi/stat_sys_r_signal_3_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_r_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_r_signal_4_cdma.png b/core/res/res/drawable-hdpi/stat_sys_r_signal_4_cdma.png
index beefdd2..0f95041 100644
--- a/core/res/res/drawable-hdpi/stat_sys_r_signal_4_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_r_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_ra_signal_0_cdma.png b/core/res/res/drawable-hdpi/stat_sys_ra_signal_0_cdma.png
old mode 100644
new mode 100755
index 3333933..a2fa547
--- a/core/res/res/drawable-hdpi/stat_sys_ra_signal_0_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_ra_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_ra_signal_1_cdma.png b/core/res/res/drawable-hdpi/stat_sys_ra_signal_1_cdma.png
old mode 100644
new mode 100755
index 6d69ed6..17c8681
--- a/core/res/res/drawable-hdpi/stat_sys_ra_signal_1_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_ra_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_ra_signal_2_cdma.png b/core/res/res/drawable-hdpi/stat_sys_ra_signal_2_cdma.png
old mode 100644
new mode 100755
index a78957d..4a21fb6
--- a/core/res/res/drawable-hdpi/stat_sys_ra_signal_2_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_ra_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_ra_signal_3_cdma.png b/core/res/res/drawable-hdpi/stat_sys_ra_signal_3_cdma.png
index 91037da..188b1f9 100644
--- a/core/res/res/drawable-hdpi/stat_sys_ra_signal_3_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_ra_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_ra_signal_4_cdma.png b/core/res/res/drawable-hdpi/stat_sys_ra_signal_4_cdma.png
old mode 100644
new mode 100755
index 44c1dca..5729f7d
--- a/core/res/res/drawable-hdpi/stat_sys_ra_signal_4_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_ra_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_secure.png b/core/res/res/drawable-hdpi/stat_sys_secure.png
old mode 100644
new mode 100755
index 4bae258..0889e49
--- a/core/res/res/drawable-hdpi/stat_sys_secure.png
+++ b/core/res/res/drawable-hdpi/stat_sys_secure.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_0_cdma.png b/core/res/res/drawable-hdpi/stat_sys_signal_0_cdma.png
index 3c7db08..af43e00 100755
--- a/core/res/res/drawable-hdpi/stat_sys_signal_0_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_1_cdma.png b/core/res/res/drawable-hdpi/stat_sys_signal_1_cdma.png
index f8f40a8..4ffe421 100755
--- a/core/res/res/drawable-hdpi/stat_sys_signal_1_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_2_cdma.png b/core/res/res/drawable-hdpi/stat_sys_signal_2_cdma.png
index a243195..6f27b96 100755
--- a/core/res/res/drawable-hdpi/stat_sys_signal_2_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_3_cdma.png b/core/res/res/drawable-hdpi/stat_sys_signal_3_cdma.png
index 9c369e7..ddc46b0 100755
--- a/core/res/res/drawable-hdpi/stat_sys_signal_3_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_4_cdma.png b/core/res/res/drawable-hdpi/stat_sys_signal_4_cdma.png
index 219bbbd..fb3cfe9 100755
--- a/core/res/res/drawable-hdpi/stat_sys_signal_4_cdma.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_0.png b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_0.png
index ae18ecd..b697ca4 100755
--- a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_0.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_0.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_1.png b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_1.png
index 4fed92c..a61de4d 100755
--- a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_1.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_2.png b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_2.png
index 96f1248..62e0393 100755
--- a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_2.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_3.png b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_3.png
index b0e1328..09eae9d 100755
--- a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_3.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_4.png b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_4.png
index da15645..4012ac5 100755
--- a/core/res/res/drawable-hdpi/stat_sys_signal_evdo_4.png
+++ b/core/res/res/drawable-hdpi/stat_sys_signal_evdo_4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_speakerphone.png b/core/res/res/drawable-hdpi/stat_sys_speakerphone.png
old mode 100644
new mode 100755
index 51dea58..21f96c4
--- a/core/res/res/drawable-hdpi/stat_sys_speakerphone.png
+++ b/core/res/res/drawable-hdpi/stat_sys_speakerphone.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_throttled.png b/core/res/res/drawable-hdpi/stat_sys_throttled.png
old mode 100644
new mode 100755
index 33c0521..58eafc0
--- a/core/res/res/drawable-hdpi/stat_sys_throttled.png
+++ b/core/res/res/drawable-hdpi/stat_sys_throttled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_sys_warning.png b/core/res/res/drawable-hdpi/stat_sys_warning.png
old mode 100644
new mode 100755
index 37c8853..cb8a3d4
--- a/core/res/res/drawable-hdpi/stat_sys_warning.png
+++ b/core/res/res/drawable-hdpi/stat_sys_warning.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/timepicker_down_disabled_focused_holo_dark.png
deleted file mode 100644
index 6fbd7d2..0000000
--- a/core/res/res/drawable-hdpi/timepicker_down_disabled_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/timepicker_down_disabled_focused_holo_light.png
deleted file mode 100644
index 3a4cdec..0000000
--- a/core/res/res/drawable-hdpi/timepicker_down_disabled_focused_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_disabled_holo_dark.png b/core/res/res/drawable-hdpi/timepicker_down_disabled_holo_dark.png
deleted file mode 100644
index b1c3991..0000000
--- a/core/res/res/drawable-hdpi/timepicker_down_disabled_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_disabled_holo_light.png b/core/res/res/drawable-hdpi/timepicker_down_disabled_holo_light.png
deleted file mode 100644
index 6fbce8c..0000000
--- a/core/res/res/drawable-hdpi/timepicker_down_disabled_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_focused_holo_dark.png b/core/res/res/drawable-hdpi/timepicker_down_focused_holo_dark.png
deleted file mode 100644
index 3bb4c29..0000000
--- a/core/res/res/drawable-hdpi/timepicker_down_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_focused_holo_light.png b/core/res/res/drawable-hdpi/timepicker_down_focused_holo_light.png
deleted file mode 100644
index 8f02162..0000000
--- a/core/res/res/drawable-hdpi/timepicker_down_focused_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_longpressed_holo_dark.png b/core/res/res/drawable-hdpi/timepicker_down_longpressed_holo_dark.png
deleted file mode 100644
index 8f57d2c..0000000
--- a/core/res/res/drawable-hdpi/timepicker_down_longpressed_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_longpressed_holo_light.png b/core/res/res/drawable-hdpi/timepicker_down_longpressed_holo_light.png
deleted file mode 100644
index df6f76b..0000000
--- a/core/res/res/drawable-hdpi/timepicker_down_longpressed_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_normal_holo_dark.png b/core/res/res/drawable-hdpi/timepicker_down_normal_holo_dark.png
deleted file mode 100644
index a47bf31..0000000
--- a/core/res/res/drawable-hdpi/timepicker_down_normal_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_normal_holo_light.png b/core/res/res/drawable-hdpi/timepicker_down_normal_holo_light.png
deleted file mode 100644
index 04046aa..0000000
--- a/core/res/res/drawable-hdpi/timepicker_down_normal_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_pressed_holo_dark.png b/core/res/res/drawable-hdpi/timepicker_down_pressed_holo_dark.png
deleted file mode 100644
index b6021e0..0000000
--- a/core/res/res/drawable-hdpi/timepicker_down_pressed_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_down_pressed_holo_light.png b/core/res/res/drawable-hdpi/timepicker_down_pressed_holo_light.png
deleted file mode 100644
index 0f38d6b..0000000
--- a/core/res/res/drawable-hdpi/timepicker_down_pressed_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-hdpi/timepicker_up_disabled_focused_holo_dark.png
deleted file mode 100644
index 14a4e31..0000000
--- a/core/res/res/drawable-hdpi/timepicker_up_disabled_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-hdpi/timepicker_up_disabled_focused_holo_light.png
deleted file mode 100644
index 21a2ac1..0000000
--- a/core/res/res/drawable-hdpi/timepicker_up_disabled_focused_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_disabled_holo_dark.png b/core/res/res/drawable-hdpi/timepicker_up_disabled_holo_dark.png
deleted file mode 100644
index 1a1da57..0000000
--- a/core/res/res/drawable-hdpi/timepicker_up_disabled_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_disabled_holo_light.png b/core/res/res/drawable-hdpi/timepicker_up_disabled_holo_light.png
deleted file mode 100644
index a242c80..0000000
--- a/core/res/res/drawable-hdpi/timepicker_up_disabled_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_focused_holo_dark.png b/core/res/res/drawable-hdpi/timepicker_up_focused_holo_dark.png
deleted file mode 100644
index 50045e4..0000000
--- a/core/res/res/drawable-hdpi/timepicker_up_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_focused_holo_light.png b/core/res/res/drawable-hdpi/timepicker_up_focused_holo_light.png
deleted file mode 100644
index 659b3c7..0000000
--- a/core/res/res/drawable-hdpi/timepicker_up_focused_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_longpressed_holo_dark.png b/core/res/res/drawable-hdpi/timepicker_up_longpressed_holo_dark.png
deleted file mode 100644
index 9112530..0000000
--- a/core/res/res/drawable-hdpi/timepicker_up_longpressed_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_longpressed_holo_light.png b/core/res/res/drawable-hdpi/timepicker_up_longpressed_holo_light.png
deleted file mode 100644
index 21aa7f7..0000000
--- a/core/res/res/drawable-hdpi/timepicker_up_longpressed_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_normal_holo_dark.png b/core/res/res/drawable-hdpi/timepicker_up_normal_holo_dark.png
deleted file mode 100644
index d145975..0000000
--- a/core/res/res/drawable-hdpi/timepicker_up_normal_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_normal_holo_light.png b/core/res/res/drawable-hdpi/timepicker_up_normal_holo_light.png
deleted file mode 100644
index 167bab7..0000000
--- a/core/res/res/drawable-hdpi/timepicker_up_normal_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_pressed_holo_dark.png b/core/res/res/drawable-hdpi/timepicker_up_pressed_holo_dark.png
deleted file mode 100644
index 2844c3f..0000000
--- a/core/res/res/drawable-hdpi/timepicker_up_pressed_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/timepicker_up_pressed_holo_light.png b/core/res/res/drawable-hdpi/timepicker_up_pressed_holo_light.png
deleted file mode 100644
index 9d83038..0000000
--- a/core/res/res/drawable-hdpi/timepicker_up_pressed_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/toast_frame.9.png b/core/res/res/drawable-hdpi/toast_frame.9.png
index 8f5d811..7f830bc 100644
--- a/core/res/res/drawable-hdpi/toast_frame.9.png
+++ b/core/res/res/drawable-hdpi/toast_frame.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_down_disabled.9.png b/core/res/res/drawable-ldpi/numberpicker_down_disabled.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_down_disabled.9.png
rename to core/res/res/drawable-ldpi/numberpicker_down_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_down_disabled_focused.9.png b/core/res/res/drawable-ldpi/numberpicker_down_disabled_focused.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_down_disabled_focused.9.png
rename to core/res/res/drawable-ldpi/numberpicker_down_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_down_normal.9.png b/core/res/res/drawable-ldpi/numberpicker_down_normal.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_down_normal.9.png
rename to core/res/res/drawable-ldpi/numberpicker_down_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_down_pressed.9.png b/core/res/res/drawable-ldpi/numberpicker_down_pressed.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_down_pressed.9.png
rename to core/res/res/drawable-ldpi/numberpicker_down_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_down_selected.9.png b/core/res/res/drawable-ldpi/numberpicker_down_selected.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_down_selected.9.png
rename to core/res/res/drawable-ldpi/numberpicker_down_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_input_disabled.9.png b/core/res/res/drawable-ldpi/numberpicker_input_disabled.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_input_disabled.9.png
rename to core/res/res/drawable-ldpi/numberpicker_input_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_input_normal.9.png b/core/res/res/drawable-ldpi/numberpicker_input_normal.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_input_normal.9.png
rename to core/res/res/drawable-ldpi/numberpicker_input_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_input_pressed.9.png b/core/res/res/drawable-ldpi/numberpicker_input_pressed.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_input_pressed.9.png
rename to core/res/res/drawable-ldpi/numberpicker_input_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_input_selected.9.png b/core/res/res/drawable-ldpi/numberpicker_input_selected.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_input_selected.9.png
rename to core/res/res/drawable-ldpi/numberpicker_input_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_up_disabled.9.png b/core/res/res/drawable-ldpi/numberpicker_up_disabled.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_up_disabled.9.png
rename to core/res/res/drawable-ldpi/numberpicker_up_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_up_disabled_focused.9.png b/core/res/res/drawable-ldpi/numberpicker_up_disabled_focused.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_up_disabled_focused.9.png
rename to core/res/res/drawable-ldpi/numberpicker_up_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_up_normal.9.png b/core/res/res/drawable-ldpi/numberpicker_up_normal.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_up_normal.9.png
rename to core/res/res/drawable-ldpi/numberpicker_up_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_up_pressed.9.png b/core/res/res/drawable-ldpi/numberpicker_up_pressed.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_up_pressed.9.png
rename to core/res/res/drawable-ldpi/numberpicker_up_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/timepicker_up_selected.9.png b/core/res/res/drawable-ldpi/numberpicker_up_selected.9.png
similarity index 100%
rename from core/res/res/drawable-ldpi/timepicker_up_selected.9.png
rename to core/res/res/drawable-ldpi/numberpicker_up_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/quickcontact_badge_pressed.9.png b/core/res/res/drawable-ldpi/quickcontact_badge_pressed.9.png
deleted file mode 100644
index ff43fed..0000000
--- a/core/res/res/drawable-ldpi/quickcontact_badge_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-ldpi/quickcontact_badge_small_pressed.9.png b/core/res/res/drawable-ldpi/quickcontact_badge_small_pressed.9.png
deleted file mode 100644
index 5aedb70..0000000
--- a/core/res/res/drawable-ldpi/quickcontact_badge_small_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-ldpi/quickcontact_badge_small_unpressed.9.png b/core/res/res/drawable-ldpi/quickcontact_badge_small_unpressed.9.png
deleted file mode 100644
index 6e212b6..0000000
--- a/core/res/res/drawable-ldpi/quickcontact_badge_small_unpressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-ldpi/quickcontact_badge_unpressed.9.png b/core/res/res/drawable-ldpi/quickcontact_badge_unpressed.9.png
deleted file mode 100644
index 417c11b..0000000
--- a/core/res/res/drawable-ldpi/quickcontact_badge_unpressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off.png b/core/res/res/drawable-mdpi/btn_check_off.png
index 56d3861..251ddff 100644
--- a/core/res/res/drawable-mdpi/btn_check_off.png
+++ b/core/res/res/drawable-mdpi/btn_check_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable.png b/core/res/res/drawable-mdpi/btn_check_off_disable.png
index e012afd..45e6804 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_focused.png b/core/res/res/drawable-mdpi/btn_check_off_disable_focused.png
index 0837bbd..193acd2 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable_focused.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_pressed.png b/core/res/res/drawable-mdpi/btn_check_off_pressed.png
index 984dfd7..807901c 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_selected.png b/core/res/res/drawable-mdpi/btn_check_off_selected.png
index 20842d4..dbc3beb 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_selected.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on.png b/core/res/res/drawable-mdpi/btn_check_on.png
index 791ac1d..4c83e2e 100644
--- a/core/res/res/drawable-mdpi/btn_check_on.png
+++ b/core/res/res/drawable-mdpi/btn_check_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable.png b/core/res/res/drawable-mdpi/btn_check_on_disable.png
index 6cb02f3..f1bf178 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_focused.png b/core/res/res/drawable-mdpi/btn_check_on_disable_focused.png
index 8a73b33..ea232ee 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_focused.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed.png b/core/res/res/drawable-mdpi/btn_check_on_pressed.png
index 300d64a..0de8a4c 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_selected.png b/core/res/res/drawable-mdpi/btn_check_on_selected.png
index 0b36adb..20294f3 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_selected.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_circle_disable.png b/core/res/res/drawable-mdpi/btn_circle_disable.png
index 33b74a6..29e227c 100644
--- a/core/res/res/drawable-mdpi/btn_circle_disable.png
+++ b/core/res/res/drawable-mdpi/btn_circle_disable.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_circle_disable_focused.png b/core/res/res/drawable-mdpi/btn_circle_disable_focused.png
index 005ad8d..c5aa3c5 100644
--- a/core/res/res/drawable-mdpi/btn_circle_disable_focused.png
+++ b/core/res/res/drawable-mdpi/btn_circle_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_circle_normal.png b/core/res/res/drawable-mdpi/btn_circle_normal.png
index fc5af1c..6358351 100644
--- a/core/res/res/drawable-mdpi/btn_circle_normal.png
+++ b/core/res/res/drawable-mdpi/btn_circle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_circle_pressed.png b/core/res/res/drawable-mdpi/btn_circle_pressed.png
index 8f40afd..dc07a61 100644
--- a/core/res/res/drawable-mdpi/btn_circle_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_circle_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_circle_selected.png b/core/res/res/drawable-mdpi/btn_circle_selected.png
index c74fac2..6eb2ff5 100644
--- a/core/res/res/drawable-mdpi/btn_circle_selected.png
+++ b/core/res/res/drawable-mdpi/btn_circle_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_close_normal.png b/core/res/res/drawable-mdpi/btn_close_normal.png
index 4c6e79d..eca5828 100644
--- a/core/res/res/drawable-mdpi/btn_close_normal.png
+++ b/core/res/res/drawable-mdpi/btn_close_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_close_pressed.png b/core/res/res/drawable-mdpi/btn_close_pressed.png
index fc983af..3c745bb 100644
--- a/core/res/res/drawable-mdpi/btn_close_pressed.png
+++ b/core/res/res/drawable-mdpi/btn_close_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_close_selected.png b/core/res/res/drawable-mdpi/btn_close_selected.png
index f2bf91a..c41f039 100644
--- a/core/res/res/drawable-mdpi/btn_close_selected.png
+++ b/core/res/res/drawable-mdpi/btn_close_selected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal.9.png b/core/res/res/drawable-mdpi/btn_default_normal.9.png
index a2d5ccd..7ff74b2 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png b/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
index edd3a3e..d3e11b5 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png b/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
index f506179..843ca7a 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed.9.png b/core/res/res/drawable-mdpi/btn_default_pressed.9.png
index 033bf89..74fd58b 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_selected.9.png b/core/res/res/drawable-mdpi/btn_default_selected.9.png
index 1e900bf..415b145 100644
--- a/core/res/res/drawable-mdpi/btn_default_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
index bcedd5f..5dddd46 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
index ac6260f..6ab5c4a 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal_disable.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png b/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
index 4ee1b3f..c65bace 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_normal_disable_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png b/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
index 25e38f4..43e82f9 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_small_selected.9.png b/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
index cc209c6..7a376a9 100644
--- a/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_small_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dropdown_disabled.9.png b/core/res/res/drawable-mdpi/btn_dropdown_disabled.9.png
index f7464c7..72915b5 100644
--- a/core/res/res/drawable-mdpi/btn_dropdown_disabled.9.png
+++ b/core/res/res/drawable-mdpi/btn_dropdown_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dropdown_disabled_focused.9.png b/core/res/res/drawable-mdpi/btn_dropdown_disabled_focused.9.png
index ffe219f..438c06a 100644
--- a/core/res/res/drawable-mdpi/btn_dropdown_disabled_focused.9.png
+++ b/core/res/res/drawable-mdpi/btn_dropdown_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dropdown_normal.9.png b/core/res/res/drawable-mdpi/btn_dropdown_normal.9.png
index f6e9a19..8540501 100644
--- a/core/res/res/drawable-mdpi/btn_dropdown_normal.9.png
+++ b/core/res/res/drawable-mdpi/btn_dropdown_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dropdown_pressed.9.png b/core/res/res/drawable-mdpi/btn_dropdown_pressed.9.png
index 3bdf52d..9a50396 100644
--- a/core/res/res/drawable-mdpi/btn_dropdown_pressed.9.png
+++ b/core/res/res/drawable-mdpi/btn_dropdown_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_dropdown_selected.9.png b/core/res/res/drawable-mdpi/btn_dropdown_selected.9.png
index 087956e..a0a3fef 100644
--- a/core/res/res/drawable-mdpi/btn_dropdown_selected.9.png
+++ b/core/res/res/drawable-mdpi/btn_dropdown_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/day_picker_week_view_dayline_holo_dark.9.png b/core/res/res/drawable-mdpi/day_picker_week_view_dayline_holo.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/day_picker_week_view_dayline_holo_dark.9.png
rename to core/res/res/drawable-mdpi/day_picker_week_view_dayline_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/day_picker_week_view_dayline_holo_light.9.png b/core/res/res/drawable-mdpi/day_picker_week_view_dayline_holo_light.9.png
deleted file mode 100644
index a8cfd77..0000000
--- a/core/res/res/drawable-mdpi/day_picker_week_view_dayline_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
index 1e2d327..43e6528 100644
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
index ac2d7a3..09a1cd8 100644
--- a/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo.9.png b/core/res/res/drawable-mdpi/dialog_full_holo.9.png
deleted file mode 100644
index 0ec9421..0000000
--- a/core/res/res/drawable-mdpi/dialog_full_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
index 9d93403..bd5f9e0 100644
--- a/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_full_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
index 1c08e6a..45e9712 100644
--- a/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_full_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
index 741b8dc..8082ddd9 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
index 0854fe5..ccdcd1d 100644
--- a/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo.9.png b/core/res/res/drawable-mdpi/dialog_top_holo.9.png
deleted file mode 100644
index 1ed519b..0000000
--- a/core/res/res/drawable-mdpi/dialog_top_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png b/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
index 43c0050..79aaffb 100644
--- a/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/dialog_top_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png b/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
index bc5fc92..0740051 100644
--- a/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/dialog_top_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_ic_maximized.9.png b/core/res/res/drawable-mdpi/expander_ic_maximized.9.png
index 465cabd..d5c3276 100644
--- a/core/res/res/drawable-mdpi/expander_ic_maximized.9.png
+++ b/core/res/res/drawable-mdpi/expander_ic_maximized.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_ic_minimized.9.png b/core/res/res/drawable-mdpi/expander_ic_minimized.9.png
index 9967ecb..4515b42 100644
--- a/core/res/res/drawable-mdpi/expander_ic_minimized.9.png
+++ b/core/res/res/drawable-mdpi/expander_ic_minimized.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_round_more_disabled.png b/core/res/res/drawable-mdpi/ic_btn_round_more_disabled.png
index 1ab98c9..428edf2 100644
--- a/core/res/res/drawable-mdpi/ic_btn_round_more_disabled.png
+++ b/core/res/res/drawable-mdpi/ic_btn_round_more_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_round_more_normal.png b/core/res/res/drawable-mdpi/ic_btn_round_more_normal.png
index ebdc55c..c2ecb01 100644
--- a/core/res/res/drawable-mdpi/ic_btn_round_more_normal.png
+++ b/core/res/res/drawable-mdpi/ic_btn_round_more_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_bullet_key_permission.png b/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
index ccb010f..68ad039 100644
--- a/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
+++ b/core/res/res/drawable-mdpi/ic_bullet_key_permission.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear_off.png b/core/res/res/drawable-mdpi/ic_clear_disabled.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_clear_off.png
rename to core/res/res/drawable-mdpi/ic_clear_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear.png b/core/res/res/drawable-mdpi/ic_clear_normal.png
similarity index 100%
rename from core/res/res/drawable-mdpi/ic_clear.png
rename to core/res/res/drawable-mdpi/ic_clear_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear_search_api_disabled_holo_light.png b/core/res/res/drawable-mdpi/ic_clear_search_api_disabled_holo_light.png
new file mode 100644
index 0000000..3edbd74
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_clear_search_api_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear_search_api_holo_light.png b/core/res/res/drawable-mdpi/ic_clear_search_api_holo_light.png
new file mode 100644
index 0000000..90db01b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_clear_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_commit_search_api_holo_light.png b/core/res/res/drawable-mdpi/ic_commit_search_api_holo_light.png
new file mode 100644
index 0000000..b01688f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_commit_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_alert_holo_dark.png b/core/res/res/drawable-mdpi/ic_dialog_alert_holo_dark.png
new file mode 100644
index 0000000..75d9db7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_dialog_alert_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_alert_holo_light.png b/core/res/res/drawable-mdpi/ic_dialog_alert_holo_light.png
new file mode 100644
index 0000000..9e7f0bd
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_dialog_alert_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_go_search_api_holo_light.png b/core/res/res/drawable-mdpi/ic_go_search_api_holo_light.png
new file mode 100644
index 0000000..7e1ba2a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_go_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_ff.png b/core/res/res/drawable-mdpi/ic_media_ff.png
old mode 100755
new mode 100644
index ce7e195..d99779d
--- a/core/res/res/drawable-mdpi/ic_media_ff.png
+++ b/core/res/res/drawable-mdpi/ic_media_ff.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_next.png b/core/res/res/drawable-mdpi/ic_media_next.png
old mode 100755
new mode 100644
index 84f38e8..cee4930
--- a/core/res/res/drawable-mdpi/ic_media_next.png
+++ b/core/res/res/drawable-mdpi/ic_media_next.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_pause.png b/core/res/res/drawable-mdpi/ic_media_pause.png
old mode 100755
new mode 100644
index 688118e..9e8b675
--- a/core/res/res/drawable-mdpi/ic_media_pause.png
+++ b/core/res/res/drawable-mdpi/ic_media_pause.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_play.png b/core/res/res/drawable-mdpi/ic_media_play.png
old mode 100755
new mode 100644
index 7aa7af8..41cd65f
--- a/core/res/res/drawable-mdpi/ic_media_play.png
+++ b/core/res/res/drawable-mdpi/ic_media_play.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_previous.png b/core/res/res/drawable-mdpi/ic_media_previous.png
old mode 100755
new mode 100644
index 1bba544..1be95b4
--- a/core/res/res/drawable-mdpi/ic_media_previous.png
+++ b/core/res/res/drawable-mdpi/ic_media_previous.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_rew.png b/core/res/res/drawable-mdpi/ic_media_rew.png
old mode 100755
new mode 100644
index 132df7f..8311508
--- a/core/res/res/drawable-mdpi/ic_media_rew.png
+++ b/core/res/res/drawable-mdpi/ic_media_rew.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_help.png b/core/res/res/drawable-mdpi/ic_menu_help.png
index 7c55dfd..12ca235 100644
--- a/core/res/res/drawable-mdpi/ic_menu_help.png
+++ b/core/res/res/drawable-mdpi/ic_menu_help.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_search_api_holo_light.png b/core/res/res/drawable-mdpi/ic_search_api_holo_light.png
new file mode 100644
index 0000000..72e207b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_voice_search_api_holo_light.png b/core/res/res/drawable-mdpi/ic_voice_search_api_holo_light.png
new file mode 100644
index 0000000..3481c98
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_voice_search_api_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png b/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png
index 60f19fe..43c36cb 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_focus.9.png b/core/res/res/drawable-mdpi/list_selector_background_focus.9.png
index 421e734..53a7eac 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_focus.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_focus.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png b/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png
index 7817667..0818761 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_longpress.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png b/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png
index 1531d9d..8bd86b2 100644
--- a/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png
+++ b/core/res/res/drawable-mdpi/list_selector_background_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_background.9.png b/core/res/res/drawable-mdpi/menu_background.9.png
index 9f16df9..41a3d34 100644
--- a/core/res/res/drawable-mdpi/menu_background.9.png
+++ b/core/res/res/drawable-mdpi/menu_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_background_fill_parent_width.9.png b/core/res/res/drawable-mdpi/menu_background_fill_parent_width.9.png
index da3011b..1ddf091 100644
--- a/core/res/res/drawable-mdpi/menu_background_fill_parent_width.9.png
+++ b/core/res/res/drawable-mdpi/menu_background_fill_parent_width.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
index 7d5c10c..3b30ee0 100644
--- a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
index a0d3094d..5a3e2b1 100644
--- a/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/menu_dropdown_panel_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/nav_divider.png b/core/res/res/drawable-mdpi/nav_divider.png
deleted file mode 100644
index c9413d7..0000000
--- a/core/res/res/drawable-mdpi/nav_divider.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_disabled.9.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_down_disabled.9.png
rename to core/res/res/drawable-mdpi/numberpicker_down_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_disabled_focused.9.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_down_disabled_focused.9.png
rename to core/res/res/drawable-mdpi/numberpicker_down_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..113b369
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png
new file mode 100644
index 0000000..e3c416e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_dark.png
new file mode 100644
index 0000000..e123db9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_light.png
new file mode 100644
index 0000000..f93d082
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_down_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_dark.png
new file mode 100644
index 0000000..d8bd34f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_light.png
new file mode 100644
index 0000000..0747f82
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_down_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_dark.png
new file mode 100644
index 0000000..1c7abf8
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_light.png
new file mode 100644
index 0000000..ec9d1f2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_down_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_normal.9.png b/core/res/res/drawable-mdpi/numberpicker_down_normal.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_down_normal.9.png
rename to core/res/res/drawable-mdpi/numberpicker_down_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_dark.png
new file mode 100644
index 0000000..d6259e2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_light.png
new file mode 100644
index 0000000..aac5f31
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_down_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_pressed.9.png b/core/res/res/drawable-mdpi/numberpicker_down_pressed.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_down_pressed.9.png
rename to core/res/res/drawable-mdpi/numberpicker_down_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png
new file mode 100644
index 0000000..fd8076f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png
new file mode 100644
index 0000000..c06ff40
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_down_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_selected.9.png b/core/res/res/drawable-mdpi/numberpicker_down_selected.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_down_selected.9.png
rename to core/res/res/drawable-mdpi/numberpicker_down_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_input_disabled.9.png b/core/res/res/drawable-mdpi/numberpicker_input_disabled.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_input_disabled.9.png
rename to core/res/res/drawable-mdpi/numberpicker_input_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_input_normal.9.png b/core/res/res/drawable-mdpi/numberpicker_input_normal.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_input_normal.9.png
rename to core/res/res/drawable-mdpi/numberpicker_input_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_input_pressed.9.png b/core/res/res/drawable-mdpi/numberpicker_input_pressed.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_input_pressed.9.png
rename to core/res/res/drawable-mdpi/numberpicker_input_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_input_selected.9.png b/core/res/res/drawable-mdpi/numberpicker_input_selected.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_input_selected.9.png
rename to core/res/res/drawable-mdpi/numberpicker_input_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_disabled.9.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_up_disabled.9.png
rename to core/res/res/drawable-mdpi/numberpicker_up_disabled.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_disabled_focused.9.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_up_disabled_focused.9.png
rename to core/res/res/drawable-mdpi/numberpicker_up_disabled_focused.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png
new file mode 100644
index 0000000..d69615d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png
new file mode 100644
index 0000000..eb7a283
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_dark.png
new file mode 100644
index 0000000..1ee5510
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_light.png
new file mode 100644
index 0000000..2269577
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_up_disabled_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_dark.png
new file mode 100644
index 0000000..9954130
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_light.png
new file mode 100644
index 0000000..8553d1c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_up_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_dark.png
new file mode 100644
index 0000000..b4ed2c5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_light.png
new file mode 100644
index 0000000..2496fb8
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_up_longpressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_normal.9.png b/core/res/res/drawable-mdpi/numberpicker_up_normal.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_up_normal.9.png
rename to core/res/res/drawable-mdpi/numberpicker_up_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_dark.png
new file mode 100644
index 0000000..3bcdd71
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_light.png
new file mode 100644
index 0000000..1113de7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_up_normal_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_pressed.9.png b/core/res/res/drawable-mdpi/numberpicker_up_pressed.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_up_pressed.9.png
rename to core/res/res/drawable-mdpi/numberpicker_up_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png
new file mode 100644
index 0000000..7303a19
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png
new file mode 100644
index 0000000..7abdbfc
--- /dev/null
+++ b/core/res/res/drawable-mdpi/numberpicker_up_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_selected.9.png b/core/res/res/drawable-mdpi/numberpicker_up_selected.9.png
similarity index 100%
rename from core/res/res/drawable-mdpi/timepicker_up_selected.9.png
rename to core/res/res/drawable-mdpi/numberpicker_up_selected.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/panel_background.9.png b/core/res/res/drawable-mdpi/panel_background.9.png
index 2305be4..822b6c6 100644
--- a/core/res/res/drawable-mdpi/panel_background.9.png
+++ b/core/res/res/drawable-mdpi/panel_background.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/picture_emergency.png b/core/res/res/drawable-mdpi/picture_emergency.png
index 3690b07..a224b80 100644
--- a/core/res/res/drawable-mdpi/picture_emergency.png
+++ b/core/res/res/drawable-mdpi/picture_emergency.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_arrow.png b/core/res/res/drawable-mdpi/pointer_arrow.png
new file mode 100644
index 0000000..e01129c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_arrow_icon.xml b/core/res/res/drawable-mdpi/pointer_arrow_icon.xml
new file mode 100644
index 0000000..2f5676f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_arrow_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_arrow"
+    android:hotSpotX="6"
+    android:hotSpotY="6" />
diff --git a/core/res/res/drawable-mdpi/popup_bottom_bright.9.png b/core/res/res/drawable-mdpi/popup_bottom_bright.9.png
index e8e203b..e7b713d 100644
--- a/core/res/res/drawable-mdpi/popup_bottom_bright.9.png
+++ b/core/res/res/drawable-mdpi/popup_bottom_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_bottom_dark.9.png b/core/res/res/drawable-mdpi/popup_bottom_dark.9.png
index 76a2a7f..88ce336 100644
--- a/core/res/res/drawable-mdpi/popup_bottom_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_bottom_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_bottom_medium.9.png b/core/res/res/drawable-mdpi/popup_bottom_medium.9.png
old mode 100755
new mode 100644
index dee6d6b..e5aaad0
--- a/core/res/res/drawable-mdpi/popup_bottom_medium.9.png
+++ b/core/res/res/drawable-mdpi/popup_bottom_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_center_bright.9.png b/core/res/res/drawable-mdpi/popup_center_bright.9.png
index c817338db..a259356 100644
--- a/core/res/res/drawable-mdpi/popup_center_bright.9.png
+++ b/core/res/res/drawable-mdpi/popup_center_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_center_dark.9.png b/core/res/res/drawable-mdpi/popup_center_dark.9.png
index 79ffdaa..9378dbf 100644
--- a/core/res/res/drawable-mdpi/popup_center_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_center_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_center_medium.9.png b/core/res/res/drawable-mdpi/popup_center_medium.9.png
old mode 100755
new mode 100644
index ba2e9bf..885403c
--- a/core/res/res/drawable-mdpi/popup_center_medium.9.png
+++ b/core/res/res/drawable-mdpi/popup_center_medium.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_full_bright.9.png b/core/res/res/drawable-mdpi/popup_full_bright.9.png
index d33ff2b..d7fb3db 100644
--- a/core/res/res/drawable-mdpi/popup_full_bright.9.png
+++ b/core/res/res/drawable-mdpi/popup_full_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_full_dark.9.png b/core/res/res/drawable-mdpi/popup_full_dark.9.png
index 2305be4..7b9f291 100644
--- a/core/res/res/drawable-mdpi/popup_full_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_full_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_top_bright.9.png b/core/res/res/drawable-mdpi/popup_top_bright.9.png
index 727a948..72d82f0 100644
--- a/core/res/res/drawable-mdpi/popup_top_bright.9.png
+++ b/core/res/res/drawable-mdpi/popup_top_bright.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/popup_top_dark.9.png b/core/res/res/drawable-mdpi/popup_top_dark.9.png
index af511f2..616d80f 100644
--- a/core/res/res/drawable-mdpi/popup_top_dark.9.png
+++ b/core/res/res/drawable-mdpi/popup_top_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_audio_away.png b/core/res/res/drawable-mdpi/presence_audio_away.png
index db96754..cb30b32 100644
--- a/core/res/res/drawable-mdpi/presence_audio_away.png
+++ b/core/res/res/drawable-mdpi/presence_audio_away.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_audio_busy.png b/core/res/res/drawable-mdpi/presence_audio_busy.png
index 0a29948..40f168c 100644
--- a/core/res/res/drawable-mdpi/presence_audio_busy.png
+++ b/core/res/res/drawable-mdpi/presence_audio_busy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_audio_online.png b/core/res/res/drawable-mdpi/presence_audio_online.png
index df415ba..3faede8 100644
--- a/core/res/res/drawable-mdpi/presence_audio_online.png
+++ b/core/res/res/drawable-mdpi/presence_audio_online.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_away.png b/core/res/res/drawable-mdpi/presence_away.png
index f98e908..a777440 100644
--- a/core/res/res/drawable-mdpi/presence_away.png
+++ b/core/res/res/drawable-mdpi/presence_away.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_busy.png b/core/res/res/drawable-mdpi/presence_busy.png
index 933261f4..d33d0f0 100644
--- a/core/res/res/drawable-mdpi/presence_busy.png
+++ b/core/res/res/drawable-mdpi/presence_busy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_invisible.png b/core/res/res/drawable-mdpi/presence_invisible.png
index 8d72756..527e97c 100644
--- a/core/res/res/drawable-mdpi/presence_invisible.png
+++ b/core/res/res/drawable-mdpi/presence_invisible.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_offline.png b/core/res/res/drawable-mdpi/presence_offline.png
index fc78396..4320963 100644
--- a/core/res/res/drawable-mdpi/presence_offline.png
+++ b/core/res/res/drawable-mdpi/presence_offline.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_online.png b/core/res/res/drawable-mdpi/presence_online.png
index 943eee0..b41e8d9 100644
--- a/core/res/res/drawable-mdpi/presence_online.png
+++ b/core/res/res/drawable-mdpi/presence_online.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_video_away.png b/core/res/res/drawable-mdpi/presence_video_away.png
index f3ec5d4..b56275f 100644
--- a/core/res/res/drawable-mdpi/presence_video_away.png
+++ b/core/res/res/drawable-mdpi/presence_video_away.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_video_busy.png b/core/res/res/drawable-mdpi/presence_video_busy.png
index 7379e00..f1cf238 100644
--- a/core/res/res/drawable-mdpi/presence_video_busy.png
+++ b/core/res/res/drawable-mdpi/presence_video_busy.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/presence_video_online.png b/core/res/res/drawable-mdpi/presence_video_online.png
index 24ceb39..10bbd74 100644
--- a/core/res/res/drawable-mdpi/presence_video_online.png
+++ b/core/res/res/drawable-mdpi/presence_video_online.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png b/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png
index 0376e53..c5418f9 100644
--- a/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png b/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png
index e825119..c943b2e 100644
--- a/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png b/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png
index e525eaf..bac0a23 100644
--- a/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png b/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png
index 0532f0e..bac0a23 100644
--- a/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png b/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png
index 99f8f06..8be8656 100644
--- a/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png b/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png
index 198d7d9..8be8656 100644
--- a/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo1.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo1.png
new file mode 100644
index 0000000..c22a53a3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo2.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo2.png
new file mode 100644
index 0000000..c288541
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo3.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo3.png
new file mode 100644
index 0000000..25df6b9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo4.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo4.png
new file mode 100644
index 0000000..65718e1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo4.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo5.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo5.png
new file mode 100644
index 0000000..39148e0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo5.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo6.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo6.png
new file mode 100644
index 0000000..8ff7b24
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo6.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo7.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo7.png
new file mode 100644
index 0000000..a7302c1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo7.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo8.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo8.png
new file mode 100644
index 0000000..70bf210
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo8.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png
new file mode 100644
index 0000000..9626ab9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png
new file mode 100644
index 0000000..3876d3b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_normal_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
new file mode 100644
index 0000000..db12ac6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png
new file mode 100644
index 0000000..b3a49fc
--- /dev/null
+++ b/core/res/res/drawable-mdpi/quickcontact_badge_overlay_pressed_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_pressed.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_pressed.9.png
deleted file mode 100644
index c8ca33a..0000000
--- a/core/res/res/drawable-mdpi/quickcontact_badge_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_small_pressed.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_small_pressed.9.png
deleted file mode 100644
index b23e921..0000000
--- a/core/res/res/drawable-mdpi/quickcontact_badge_small_pressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_small_unpressed.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_small_unpressed.9.png
deleted file mode 100644
index 38f14f7..0000000
--- a/core/res/res/drawable-mdpi/quickcontact_badge_small_unpressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_badge_unpressed.9.png b/core/res/res/drawable-mdpi/quickcontact_badge_unpressed.9.png
deleted file mode 100644
index d8dff34..0000000
--- a/core/res/res/drawable-mdpi/quickcontact_badge_unpressed.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/quickcontact_nobadge.9.png b/core/res/res/drawable-mdpi/quickcontact_nobadge.9.png
deleted file mode 100644
index ebe747b..0000000
--- a/core/res/res/drawable-mdpi/quickcontact_nobadge.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_disabled_holo.png b/core/res/res/drawable-mdpi/scrubber_control_disabled_holo.png
new file mode 100644
index 0000000..26f018f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_disabled_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_holo.png b/core/res/res/drawable-mdpi/scrubber_control_holo.png
index 8457833..242c16d 100644
--- a/core/res/res/drawable-mdpi/scrubber_control_holo.png
+++ b/core/res/res/drawable-mdpi/scrubber_control_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_primary_holo.9.png b/core/res/res/drawable-mdpi/scrubber_primary_holo.9.png
index 8582b13..ac63e7d 100644
--- a/core/res/res/drawable-mdpi/scrubber_primary_holo.9.png
+++ b/core/res/res/drawable-mdpi/scrubber_primary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_secondary_holo.9.png b/core/res/res/drawable-mdpi/scrubber_secondary_holo.9.png
index 6ad876e..9590bdc 100644
--- a/core/res/res/drawable-mdpi/scrubber_secondary_holo.9.png
+++ b/core/res/res/drawable-mdpi/scrubber_secondary_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_track_holo_dark.9.png b/core/res/res/drawable-mdpi/scrubber_track_holo_dark.9.png
index baf70cd..017b593 100644
--- a/core/res/res/drawable-mdpi/scrubber_track_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/scrubber_track_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_track_holo_light.9.png b/core/res/res/drawable-mdpi/scrubber_track_holo_light.9.png
index 6f31497..12c6e21 100644
--- a/core/res/res/drawable-mdpi/scrubber_track_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/scrubber_track_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/simple_week_dayline_holo_light.9.png b/core/res/res/drawable-mdpi/simple_week_dayline_holo_light.9.png
deleted file mode 100644
index f264cb6..0000000
--- a/core/res/res/drawable-mdpi/simple_week_dayline_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_call_mute.png b/core/res/res/drawable-mdpi/stat_notify_call_mute.png
index 6da8313..4a3b057 100644
--- a/core/res/res/drawable-mdpi/stat_notify_call_mute.png
+++ b/core/res/res/drawable-mdpi/stat_notify_call_mute.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_car_mode.png b/core/res/res/drawable-mdpi/stat_notify_car_mode.png
index 0272e6b..3b644d3 100644
--- a/core/res/res/drawable-mdpi/stat_notify_car_mode.png
+++ b/core/res/res/drawable-mdpi/stat_notify_car_mode.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 8cf02cc..306d9c5 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_disk_full.png b/core/res/res/drawable-mdpi/stat_notify_disk_full.png
index 9120f00..3eebeb8 100755
--- a/core/res/res/drawable-mdpi/stat_notify_disk_full.png
+++ b/core/res/res/drawable-mdpi/stat_notify_disk_full.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 5b866bf..1620ad5 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 907306d..4860c34 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-mdpi/stat_notify_missed_call.png b/core/res/res/drawable-mdpi/stat_notify_missed_call.png
index fe746b3..7bd5fcd 100644
--- a/core/res/res/drawable-mdpi/stat_notify_missed_call.png
+++ b/core/res/res/drawable-mdpi/stat_notify_missed_call.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_more.png b/core/res/res/drawable-mdpi/stat_notify_more.png
index e129ba9..a85a16e 100644
--- a/core/res/res/drawable-mdpi/stat_notify_more.png
+++ b/core/res/res/drawable-mdpi/stat_notify_more.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_sim_toolkit.png b/core/res/res/drawable-mdpi/stat_notify_sim_toolkit.png
index c1ce8f2..8b33a0f 100755
--- a/core/res/res/drawable-mdpi/stat_notify_sim_toolkit.png
+++ b/core/res/res/drawable-mdpi/stat_notify_sim_toolkit.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_sync.png b/core/res/res/drawable-mdpi/stat_notify_sync.png
index 0edf692..03ce57a 100644
--- a/core/res/res/drawable-mdpi/stat_notify_sync.png
+++ b/core/res/res/drawable-mdpi/stat_notify_sync.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_sync_anim0.png b/core/res/res/drawable-mdpi/stat_notify_sync_anim0.png
index 0edf692..5481461 100644
--- a/core/res/res/drawable-mdpi/stat_notify_sync_anim0.png
+++ b/core/res/res/drawable-mdpi/stat_notify_sync_anim0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_sync_error.png b/core/res/res/drawable-mdpi/stat_notify_sync_error.png
index 3078b8c..f849b50 100644
--- a/core/res/res/drawable-mdpi/stat_notify_sync_error.png
+++ b/core/res/res/drawable-mdpi/stat_notify_sync_error.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_voicemail.png b/core/res/res/drawable-mdpi/stat_notify_voicemail.png
index 658fa05..636d1cc 100644
--- a/core/res/res/drawable-mdpi/stat_notify_voicemail.png
+++ b/core/res/res/drawable-mdpi/stat_notify_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_gps_on.png b/core/res/res/drawable-mdpi/stat_sys_gps_on.png
old mode 100755
new mode 100644
index a2c677d..df737f29
--- a/core/res/res/drawable-mdpi/stat_sys_gps_on.png
+++ b/core/res/res/drawable-mdpi/stat_sys_gps_on.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_r_signal_0_cdma.png b/core/res/res/drawable-mdpi/stat_sys_r_signal_0_cdma.png
index f615681..f39f5ba 100644
--- a/core/res/res/drawable-mdpi/stat_sys_r_signal_0_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_r_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_r_signal_1_cdma.png b/core/res/res/drawable-mdpi/stat_sys_r_signal_1_cdma.png
index c3962a2..86bb2de 100644
--- a/core/res/res/drawable-mdpi/stat_sys_r_signal_1_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_r_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_r_signal_2_cdma.png b/core/res/res/drawable-mdpi/stat_sys_r_signal_2_cdma.png
index 68bfe94..b6eda07 100644
--- a/core/res/res/drawable-mdpi/stat_sys_r_signal_2_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_r_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_r_signal_3_cdma.png b/core/res/res/drawable-mdpi/stat_sys_r_signal_3_cdma.png
index 4ccd416..b7ca7f9 100644
--- a/core/res/res/drawable-mdpi/stat_sys_r_signal_3_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_r_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_r_signal_4_cdma.png b/core/res/res/drawable-mdpi/stat_sys_r_signal_4_cdma.png
index 0b25570..61a9575 100644
--- a/core/res/res/drawable-mdpi/stat_sys_r_signal_4_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_r_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_ra_signal_0_cdma.png b/core/res/res/drawable-mdpi/stat_sys_ra_signal_0_cdma.png
index 9a38733..feb4f2c 100644
--- a/core/res/res/drawable-mdpi/stat_sys_ra_signal_0_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_ra_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_ra_signal_1_cdma.png b/core/res/res/drawable-mdpi/stat_sys_ra_signal_1_cdma.png
index c70e283..a42ff0c 100644
--- a/core/res/res/drawable-mdpi/stat_sys_ra_signal_1_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_ra_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_ra_signal_2_cdma.png b/core/res/res/drawable-mdpi/stat_sys_ra_signal_2_cdma.png
index a09564c..e991c76 100644
--- a/core/res/res/drawable-mdpi/stat_sys_ra_signal_2_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_ra_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_ra_signal_3_cdma.png b/core/res/res/drawable-mdpi/stat_sys_ra_signal_3_cdma.png
index 2637dec..4b743fb 100644
--- a/core/res/res/drawable-mdpi/stat_sys_ra_signal_3_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_ra_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_ra_signal_4_cdma.png b/core/res/res/drawable-mdpi/stat_sys_ra_signal_4_cdma.png
index aba13e7..65172b7 100644
--- a/core/res/res/drawable-mdpi/stat_sys_ra_signal_4_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_ra_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_secure.png b/core/res/res/drawable-mdpi/stat_sys_secure.png
index 5f9ae69..a632fb2 100644
--- a/core/res/res/drawable-mdpi/stat_sys_secure.png
+++ b/core/res/res/drawable-mdpi/stat_sys_secure.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_0_cdma.png b/core/res/res/drawable-mdpi/stat_sys_signal_0_cdma.png
index 11f9dfe..03c51ce 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_0_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_1_cdma.png b/core/res/res/drawable-mdpi/stat_sys_signal_1_cdma.png
index 4ef3dba..dced6df 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_1_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_2_cdma.png b/core/res/res/drawable-mdpi/stat_sys_signal_2_cdma.png
index 530ed45..9eac4c6 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_2_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_3_cdma.png b/core/res/res/drawable-mdpi/stat_sys_signal_3_cdma.png
index 60a868a..74d983c 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_3_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_4_cdma.png b/core/res/res/drawable-mdpi/stat_sys_signal_4_cdma.png
index 5f2950e..8cc40b5 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_4_cdma.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_0.png b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_0.png
index defc129..177e0e9 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_0.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_0.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_1.png b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_1.png
index e3a81ed..5f66319 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_1.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_2.png b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_2.png
index 68c99a9..c365912 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_2.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_3.png b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_3.png
index 2f6c435..58d631b 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_3.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_4.png b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_4.png
index 4c9d4c6..e63af68 100644
--- a/core/res/res/drawable-mdpi/stat_sys_signal_evdo_4.png
+++ b/core/res/res/drawable-mdpi/stat_sys_signal_evdo_4.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_speakerphone.png b/core/res/res/drawable-mdpi/stat_sys_speakerphone.png
index 642dfd4..d0411cf 100644
--- a/core/res/res/drawable-mdpi/stat_sys_speakerphone.png
+++ b/core/res/res/drawable-mdpi/stat_sys_speakerphone.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_throttled.png b/core/res/res/drawable-mdpi/stat_sys_throttled.png
index 97ac427..bc9b223 100644
--- a/core/res/res/drawable-mdpi/stat_sys_throttled.png
+++ b/core/res/res/drawable-mdpi/stat_sys_throttled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_warning.png b/core/res/res/drawable-mdpi/stat_sys_warning.png
index be00f47..c0823da 100644
--- a/core/res/res/drawable-mdpi/stat_sys_warning.png
+++ b/core/res/res/drawable-mdpi/stat_sys_warning.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/timepicker_down_disabled_focused_holo_dark.png
deleted file mode 100644
index d86534c..0000000
--- a/core/res/res/drawable-mdpi/timepicker_down_disabled_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/timepicker_down_disabled_focused_holo_light.png
deleted file mode 100644
index 6ae5d4b..0000000
--- a/core/res/res/drawable-mdpi/timepicker_down_disabled_focused_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_disabled_holo_dark.png b/core/res/res/drawable-mdpi/timepicker_down_disabled_holo_dark.png
deleted file mode 100644
index fd578b6..0000000
--- a/core/res/res/drawable-mdpi/timepicker_down_disabled_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_disabled_holo_light.png b/core/res/res/drawable-mdpi/timepicker_down_disabled_holo_light.png
deleted file mode 100644
index a0caaa9..0000000
--- a/core/res/res/drawable-mdpi/timepicker_down_disabled_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_focused_holo_dark.png b/core/res/res/drawable-mdpi/timepicker_down_focused_holo_dark.png
deleted file mode 100644
index f6f4ed2..0000000
--- a/core/res/res/drawable-mdpi/timepicker_down_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_focused_holo_light.png b/core/res/res/drawable-mdpi/timepicker_down_focused_holo_light.png
deleted file mode 100644
index 2591adb..0000000
--- a/core/res/res/drawable-mdpi/timepicker_down_focused_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_longpressed_holo_dark.png b/core/res/res/drawable-mdpi/timepicker_down_longpressed_holo_dark.png
deleted file mode 100644
index efee099..0000000
--- a/core/res/res/drawable-mdpi/timepicker_down_longpressed_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_longpressed_holo_light.png b/core/res/res/drawable-mdpi/timepicker_down_longpressed_holo_light.png
deleted file mode 100644
index f7b09de..0000000
--- a/core/res/res/drawable-mdpi/timepicker_down_longpressed_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_normal_holo_dark.png b/core/res/res/drawable-mdpi/timepicker_down_normal_holo_dark.png
deleted file mode 100644
index 76f13a6..0000000
--- a/core/res/res/drawable-mdpi/timepicker_down_normal_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_normal_holo_light.png b/core/res/res/drawable-mdpi/timepicker_down_normal_holo_light.png
deleted file mode 100644
index cb8e764..0000000
--- a/core/res/res/drawable-mdpi/timepicker_down_normal_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_pressed_holo_dark.png b/core/res/res/drawable-mdpi/timepicker_down_pressed_holo_dark.png
deleted file mode 100644
index 7c0d0bc..0000000
--- a/core/res/res/drawable-mdpi/timepicker_down_pressed_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_down_pressed_holo_light.png b/core/res/res/drawable-mdpi/timepicker_down_pressed_holo_light.png
deleted file mode 100644
index 9d7ff6b..0000000
--- a/core/res/res/drawable-mdpi/timepicker_down_pressed_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_disabled_focused_holo_dark.png b/core/res/res/drawable-mdpi/timepicker_up_disabled_focused_holo_dark.png
deleted file mode 100644
index cfdfd174..0000000
--- a/core/res/res/drawable-mdpi/timepicker_up_disabled_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_disabled_focused_holo_light.png b/core/res/res/drawable-mdpi/timepicker_up_disabled_focused_holo_light.png
deleted file mode 100644
index 43bdf1d..0000000
--- a/core/res/res/drawable-mdpi/timepicker_up_disabled_focused_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_disabled_holo_dark.png b/core/res/res/drawable-mdpi/timepicker_up_disabled_holo_dark.png
deleted file mode 100644
index 2ffe46b..0000000
--- a/core/res/res/drawable-mdpi/timepicker_up_disabled_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_disabled_holo_light.png b/core/res/res/drawable-mdpi/timepicker_up_disabled_holo_light.png
deleted file mode 100644
index 51bb2d0..0000000
--- a/core/res/res/drawable-mdpi/timepicker_up_disabled_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_focused_holo_dark.png b/core/res/res/drawable-mdpi/timepicker_up_focused_holo_dark.png
deleted file mode 100644
index dece157..0000000
--- a/core/res/res/drawable-mdpi/timepicker_up_focused_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_focused_holo_light.png b/core/res/res/drawable-mdpi/timepicker_up_focused_holo_light.png
deleted file mode 100644
index 384cb32..0000000
--- a/core/res/res/drawable-mdpi/timepicker_up_focused_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_longpressed_holo_dark.png b/core/res/res/drawable-mdpi/timepicker_up_longpressed_holo_dark.png
deleted file mode 100644
index 84ec4f7..0000000
--- a/core/res/res/drawable-mdpi/timepicker_up_longpressed_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_longpressed_holo_light.png b/core/res/res/drawable-mdpi/timepicker_up_longpressed_holo_light.png
deleted file mode 100644
index 318befc..0000000
--- a/core/res/res/drawable-mdpi/timepicker_up_longpressed_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_normal_holo_dark.png b/core/res/res/drawable-mdpi/timepicker_up_normal_holo_dark.png
deleted file mode 100644
index d97a832..0000000
--- a/core/res/res/drawable-mdpi/timepicker_up_normal_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_normal_holo_light.png b/core/res/res/drawable-mdpi/timepicker_up_normal_holo_light.png
deleted file mode 100644
index 19d75e5..0000000
--- a/core/res/res/drawable-mdpi/timepicker_up_normal_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_pressed_holo_dark.png b/core/res/res/drawable-mdpi/timepicker_up_pressed_holo_dark.png
deleted file mode 100644
index 1189e5c..0000000
--- a/core/res/res/drawable-mdpi/timepicker_up_pressed_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/timepicker_up_pressed_holo_light.png b/core/res/res/drawable-mdpi/timepicker_up_pressed_holo_light.png
deleted file mode 100644
index 9f283ab..0000000
--- a/core/res/res/drawable-mdpi/timepicker_up_pressed_holo_light.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/toast_frame.9.png b/core/res/res/drawable-mdpi/toast_frame.9.png
index 08c4f86..911f86d 100755
--- a/core/res/res/drawable-mdpi/toast_frame.9.png
+++ b/core/res/res/drawable-mdpi/toast_frame.9.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 0000000..e936fac
--- /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 0000000..eb626df
--- /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 0000000..d6bc7d3
--- /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 0000000..8c8f25d
--- /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 0000000..661cc2f
--- /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/ic_lock_idle_alarm.png b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_alarm.png
index 336a820..97ac023 100644
--- a/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_alarm.png
+++ b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_alarm.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_charging.png b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_charging.png
index ebef531..4210db2 100644
--- a/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_charging.png
+++ b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_charging.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_lock.png b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_lock.png
index 405e218..1060f5a 100644
--- a/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_lock.png
+++ b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_lock.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_low_battery.png b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_low_battery.png
index f349b63..72e4afa 100644
--- a/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_low_battery.png
+++ b/core/res/res/drawable-xlarge-mdpi/ic_lock_idle_low_battery.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 0000000..b2d7186
--- /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 0000000..36ab1ff
--- /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 0000000..a14b3c7
--- /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 0000000..81a66c1
--- /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 0000000..a286ac6
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/drawable/edit_text_holo_dark.xml b/core/res/res/drawable/edit_text_holo_dark.xml
index 29a5150c..d00747f 100644
--- a/core/res/res/drawable/edit_text_holo_dark.xml
+++ b/core/res/res/drawable/edit_text_holo_dark.xml
@@ -15,10 +15,19 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_multiline="true" android:state_window_focused="false" android:state_enabled="true"  android:drawable="@drawable/textfield_multiline_default_holo_dark" />
+    <item android:state_multiline="true" android:state_window_focused="false" android:state_enabled="false" android:drawable="@drawable/textfield_multiline_disabled_holo_dark" />
+    <item android:state_multiline="true" android:state_enabled="true" android:state_focused="true" android:drawable="@drawable/textfield_multiline_activated_holo_dark" />
+    <item android:state_multiline="true" android:state_enabled="true" android:state_activated="true" android:drawable="@drawable/textfield_multiline_focused_holo_dark" />
+    <item android:state_multiline="true" android:state_enabled="true" android:drawable="@drawable/textfield_multiline_default_holo_dark" />
+    <item android:state_multiline="true" android:state_focused="true" android:drawable="@drawable/textfield_multiline_disabled_focused_holo_dark" />
+    <item android:state_multiline="true" android:drawable="@drawable/textfield_multiline_disabled_holo_dark" />
+
     <item android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/textfield_default_holo_dark" />
     <item android:state_window_focused="false" android:state_enabled="false" android:drawable="@drawable/textfield_disabled_holo_dark" />
     <item android:state_enabled="true" android:state_focused="true" android:drawable="@drawable/textfield_activated_holo_dark" />
-    <item android:state_enabled="true" android:state_activated="true" android:drawable="@drawable/textfield_focused_holo_dark" />
+    <iten android:state_enabled="true" android:state_activated="true" android:drawable="@drawable/textfield_focused_holo_dark" />
     <item android:state_enabled="true" android:drawable="@drawable/textfield_default_holo_dark" />
     <item android:state_focused="true" android:drawable="@drawable/textfield_disabled_focused_holo_dark" />
     <item android:drawable="@drawable/textfield_disabled_holo_dark" />
diff --git a/core/res/res/drawable/edit_text_holo_light.xml b/core/res/res/drawable/edit_text_holo_light.xml
index 5426916..5bdcbd9 100644
--- a/core/res/res/drawable/edit_text_holo_light.xml
+++ b/core/res/res/drawable/edit_text_holo_light.xml
@@ -15,6 +15,15 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_multiline="true" android:state_window_focused="false" android:state_enabled="true"  android:drawable="@drawable/textfield_multiline_default_holo_light" />
+    <item android:state_multiline="true" android:state_window_focused="false" android:state_enabled="false" android:drawable="@drawable/textfield_multiline_disabled_holo_light" />
+    <item android:state_multiline="true" android:state_enabled="true" android:state_focused="true" android:drawable="@drawable/textfield_multiline_activated_holo_light" />
+    <item android:state_multiline="true" android:state_enabled="true" android:state_activated="true" android:drawable="@drawable/textfield_multiline_focused_holo_light" />
+    <item android:state_multiline="true" android:state_enabled="true" android:drawable="@drawable/textfield_multiline_default_holo_light" />
+    <item android:state_multiline="true" android:state_focused="true" android:drawable="@drawable/textfield_multiline_disabled_focused_holo_light" />
+    <item android:state_multiline="true" android:drawable="@drawable/textfield_multiline_disabled_holo_light" />
+
     <item android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/textfield_default_holo_light" />
     <item android:state_window_focused="false" android:state_enabled="false" android:drawable="@drawable/textfield_disabled_holo_light" />
     <item android:state_enabled="true" android:state_focused="true" android:drawable="@drawable/textfield_activated_holo_light" />
diff --git a/core/res/res/drawable/edit_text_multiline_holo_dark.xml b/core/res/res/drawable/edit_text_multiline_holo_dark.xml
deleted file mode 100644
index d20ea19..0000000
--- a/core/res/res/drawable/edit_text_multiline_holo_dark.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_window_focused="false" android:state_enabled="true"  android:drawable="@drawable/textfield_multiline_default_holo_dark" />
-    <item android:state_window_focused="false" android:state_enabled="false" android:drawable="@drawable/textfield_multiline_disabled_holo_dark" />
-    <item android:state_enabled="true" android:state_focused="true" android:drawable="@drawable/textfield_multiline_activated_holo_dark" />
-    <item android:state_enabled="true" android:state_activated="true" android:drawable="@drawable/textfield_multiline_focused_holo_dark" />
-    <item android:state_enabled="true" android:drawable="@drawable/textfield_multiline_default_holo_dark" />
-    <item android:state_focused="true" android:drawable="@drawable/textfield_multiline_disabled_focused_holo_dark" />
-    <item android:drawable="@drawable/textfield_multiline_disabled_holo_dark" />
-</selector>
diff --git a/core/res/res/drawable/edit_text_multiline_holo_light.xml b/core/res/res/drawable/edit_text_multiline_holo_light.xml
deleted file mode 100644
index 41a4eab..0000000
--- a/core/res/res/drawable/edit_text_multiline_holo_light.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_window_focused="false" android:state_enabled="true"  android:drawable="@drawable/textfield_multiline_default_holo_light" />
-    <item android:state_window_focused="false" android:state_enabled="false" android:drawable="@drawable/textfield_multiline_disabled_holo_light" />
-    <item android:state_enabled="true" android:state_focused="true" android:drawable="@drawable/textfield_multiline_activated_holo_light" />
-    <item android:state_enabled="true" android:state_activated="true" android:drawable="@drawable/textfield_multiline_focused_holo_light" />
-    <item android:state_enabled="true" android:drawable="@drawable/textfield_multiline_default_holo_light" />
-    <item android:state_focused="true" android:drawable="@drawable/textfield_multiline_disabled_focused_holo_light" />
-    <item android:drawable="@drawable/textfield_multiline_disabled_holo_light" />
-</selector>
diff --git a/core/res/res/drawable/ic_clear.xml b/core/res/res/drawable/ic_clear.xml
new file mode 100644
index 0000000..f353496
--- /dev/null
+++ b/core/res/res/drawable/ic_clear.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false"
+        android:drawable="@drawable/ic_clear_disabled" />
+    <item
+         android:drawable="@drawable/ic_clear_normal" />
+</selector>
diff --git a/core/res/res/drawable/ic_clear_holo_light.xml b/core/res/res/drawable/ic_clear_holo_light.xml
new file mode 100644
index 0000000..8ba1e3c
--- /dev/null
+++ b/core/res/res/drawable/ic_clear_holo_light.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false"
+        android:drawable="@drawable/ic_clear_search_api_disabled_holo_light" />
+    <item
+         android:drawable="@drawable/ic_clear_search_api_holo_light" />
+</selector>
diff --git a/core/res/res/drawable/numberpicker_down_btn.xml b/core/res/res/drawable/numberpicker_down_btn.xml
new file mode 100644
index 0000000..0046df5
--- /dev/null
+++ b/core/res/res/drawable/numberpicker_down_btn.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_down_normal" />
+
+    <item android:state_pressed="true"
+          android:state_enabled="true"
+          android:drawable="@drawable/numberpicker_down_pressed" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_down_selected" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_down_disabled" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_down_disabled_focused" />
+
+</selector>
diff --git a/core/res/res/drawable/numberpicker_down_btn_holo_dark.xml b/core/res/res/drawable/numberpicker_down_btn_holo_dark.xml
new file mode 100644
index 0000000..dd6332d
--- /dev/null
+++ b/core/res/res/drawable/numberpicker_down_btn_holo_dark.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_down_normal_holo_dark" />
+
+    <item android:state_pressed="true"
+          android:state_enabled="true"
+          android:drawable="@drawable/numberpicker_down_pressed_holo_dark" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_down_focused_holo_dark" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_down_disabled_holo_dark" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_down_disabled_focused_holo_dark" />
+
+</selector>
diff --git a/core/res/res/drawable/numberpicker_down_btn_holo_light.xml b/core/res/res/drawable/numberpicker_down_btn_holo_light.xml
new file mode 100644
index 0000000..565fd86
--- /dev/null
+++ b/core/res/res/drawable/numberpicker_down_btn_holo_light.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_down_normal_holo_light" />
+
+    <item android:state_pressed="true"
+          android:state_enabled="true"
+          android:drawable="@drawable/numberpicker_down_pressed_holo_light" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_down_focused_holo_light" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_down_disabled_holo_light" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_down_disabled_focused_holo_light" />
+
+</selector>
diff --git a/core/res/res/drawable/numberpicker_input.xml b/core/res/res/drawable/numberpicker_input.xml
new file mode 100644
index 0000000..e4ebde2
--- /dev/null
+++ b/core/res/res/drawable/numberpicker_input.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_input_normal" />
+
+    <item android:state_pressed="true"
+          android:state_enabled="true"
+          android:drawable="@drawable/numberpicker_input_pressed" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_input_selected" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_input_disabled" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_input_normal" />
+
+</selector>
diff --git a/core/res/res/drawable/numberpicker_up_btn.xml b/core/res/res/drawable/numberpicker_up_btn.xml
new file mode 100644
index 0000000..6ea1a33
--- /dev/null
+++ b/core/res/res/drawable/numberpicker_up_btn.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_up_normal" />
+
+    <item android:state_pressed="true"
+          android:state_enabled="true"
+          android:drawable="@drawable/numberpicker_up_pressed" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_up_selected" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_up_disabled" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_up_disabled_focused" />
+
+</selector>
diff --git a/core/res/res/drawable/numberpicker_up_btn_holo_dark.xml b/core/res/res/drawable/numberpicker_up_btn_holo_dark.xml
new file mode 100644
index 0000000..7af3ee4
--- /dev/null
+++ b/core/res/res/drawable/numberpicker_up_btn_holo_dark.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_up_normal_holo_dark" />
+
+    <item android:state_pressed="true"
+          android:state_enabled="true"
+          android:drawable="@drawable/numberpicker_up_pressed_holo_dark" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_up_focused_holo_dark" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_up_disabled_holo_dark" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_up_disabled_focused_holo_dark" />
+
+</selector>
diff --git a/core/res/res/drawable/numberpicker_up_btn_holo_light.xml b/core/res/res/drawable/numberpicker_up_btn_holo_light.xml
new file mode 100644
index 0000000..cbcbb07
--- /dev/null
+++ b/core/res/res/drawable/numberpicker_up_btn_holo_light.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_up_normal_holo_light" />
+
+    <item android:state_pressed="true"
+          android:state_enabled="true"
+          android:drawable="@drawable/numberpicker_up_pressed_holo_light" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="true"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_up_focused_holo_light" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="false"
+          android:drawable="@drawable/numberpicker_up_focused_holo_light" />
+
+    <item android:state_pressed="false"
+          android:state_enabled="false"
+          android:state_focused="true"
+          android:drawable="@drawable/numberpicker_up_disabled_focused_holo_light" />
+
+</selector>
diff --git a/core/res/res/drawable/progress_indeterminate_horizontal_holo.xml b/core/res/res/drawable/progress_indeterminate_horizontal_holo.xml
new file mode 100644
index 0000000..e99c35b
--- /dev/null
+++ b/core/res/res/drawable/progress_indeterminate_horizontal_holo.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+<animation-list
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:oneshot="false">
+    <item android:drawable="@drawable/progressbar_indeterminate_holo1" android:duration="50" />
+    <item android:drawable="@drawable/progressbar_indeterminate_holo2" android:duration="50" />
+    <item android:drawable="@drawable/progressbar_indeterminate_holo3" android:duration="50" />
+    <item android:drawable="@drawable/progressbar_indeterminate_holo4" android:duration="50" />
+    <item android:drawable="@drawable/progressbar_indeterminate_holo5" android:duration="50" />
+    <item android:drawable="@drawable/progressbar_indeterminate_holo6" android:duration="50" />
+    <item android:drawable="@drawable/progressbar_indeterminate_holo7" android:duration="50" />
+    <item android:drawable="@drawable/progressbar_indeterminate_holo8" android:duration="50" />
+</animation-list>
diff --git a/core/res/res/drawable/quickcontact_badge.xml b/core/res/res/drawable/quickcontact_badge.xml
deleted file mode 100644
index bd5aeb6..0000000
--- a/core/res/res/drawable/quickcontact_badge.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item
-        android:state_focused="false"
-        android:state_selected="false"
-        android:state_pressed="false"
-        android:drawable="@drawable/quickcontact_badge_unpressed" />
-
-    <item
-        android:state_pressed="true"
-        android:drawable="@drawable/quickcontact_badge_pressed" />
-
-</selector>
diff --git a/core/res/res/drawable/quickcontact_badge_overlay_dark.xml b/core/res/res/drawable/quickcontact_badge_overlay_dark.xml
new file mode 100644
index 0000000..972488d
--- /dev/null
+++ b/core/res/res/drawable/quickcontact_badge_overlay_dark.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_focused="false"
+        android:state_selected="false"
+        android:state_pressed="false"
+        android:drawable="@drawable/quickcontact_badge_overlay_normal_dark" />
+
+    <item
+        android:state_pressed="true"
+        android:drawable="@drawable/quickcontact_badge_overlay_pressed_dark" />
+
+</selector>
diff --git a/core/res/res/drawable/quickcontact_badge_overlay_light.xml b/core/res/res/drawable/quickcontact_badge_overlay_light.xml
new file mode 100644
index 0000000..bf95d52
--- /dev/null
+++ b/core/res/res/drawable/quickcontact_badge_overlay_light.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:state_focused="false"
+        android:state_selected="false"
+        android:state_pressed="false"
+        android:drawable="@drawable/quickcontact_badge_overlay_normal_light" />
+
+    <item
+        android:state_pressed="true"
+        android:drawable="@drawable/quickcontact_badge_overlay_pressed_light" />
+
+</selector>
diff --git a/core/res/res/drawable/quickcontact_badge_small.xml b/core/res/res/drawable/quickcontact_badge_small.xml
deleted file mode 100644
index a38ba1e..0000000
--- a/core/res/res/drawable/quickcontact_badge_small.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item
-        android:state_focused="false"
-        android:state_selected="false"
-        android:state_pressed="false"
-        android:drawable="@drawable/quickcontact_badge_small_unpressed" />
-
-    <item
-        android:state_pressed="true"
-        android:drawable="@drawable/quickcontact_badge_small_pressed" />
-
-</selector>
diff --git a/core/res/res/drawable/scrubber_control_selector_holo.xml b/core/res/res/drawable/scrubber_control_selector_holo.xml
new file mode 100644
index 0000000..c7b8854
--- /dev/null
+++ b/core/res/res/drawable/scrubber_control_selector_holo.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true" android:drawable="@android:drawable/scrubber_control_holo" />
+    <item                              android:drawable="@android:drawable/scrubber_control_disabled_holo" />
+</selector>
diff --git a/core/res/res/drawable/timepicker_down_btn.xml b/core/res/res/drawable/timepicker_down_btn.xml
deleted file mode 100644
index d4908cb..0000000
--- a/core/res/res/drawable/timepicker_down_btn.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_down_normal" />
-
-    <item android:state_pressed="true"
-          android:state_enabled="true"
-          android:drawable="@drawable/timepicker_down_pressed" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_down_selected" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_down_disabled" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_down_disabled_focused" />
-
-</selector>
diff --git a/core/res/res/drawable/timepicker_down_btn_holo_dark.xml b/core/res/res/drawable/timepicker_down_btn_holo_dark.xml
deleted file mode 100644
index b4b824d..0000000
--- a/core/res/res/drawable/timepicker_down_btn_holo_dark.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_down_normal_holo_dark" />
-
-    <item android:state_pressed="true"
-          android:state_enabled="true"
-          android:drawable="@drawable/timepicker_down_pressed_holo_dark" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_down_focused_holo_dark" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_down_disabled_holo_dark" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_down_disabled_focused_holo_dark" />
-
-</selector>
diff --git a/core/res/res/drawable/timepicker_down_btn_holo_light.xml b/core/res/res/drawable/timepicker_down_btn_holo_light.xml
deleted file mode 100644
index 7ae5e53..0000000
--- a/core/res/res/drawable/timepicker_down_btn_holo_light.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_down_normal_holo_light" />
-
-    <item android:state_pressed="true"
-          android:state_enabled="true"
-          android:drawable="@drawable/timepicker_down_pressed_holo_light" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_down_focused_holo_light" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_down_disabled_holo_light" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_down_disabled_focused_holo_light" />
-
-</selector>
diff --git a/core/res/res/drawable/timepicker_input.xml b/core/res/res/drawable/timepicker_input.xml
deleted file mode 100644
index 17686738..0000000
--- a/core/res/res/drawable/timepicker_input.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_input_normal" />
-
-    <item android:state_pressed="true"
-          android:state_enabled="true"
-          android:drawable="@drawable/timepicker_input_pressed" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_input_selected" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_input_disabled" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_input_normal" />
-
-</selector>
diff --git a/core/res/res/drawable/timepicker_up_btn.xml b/core/res/res/drawable/timepicker_up_btn.xml
deleted file mode 100644
index fbaed08..0000000
--- a/core/res/res/drawable/timepicker_up_btn.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_up_normal" />
-
-    <item android:state_pressed="true"
-          android:state_enabled="true"
-          android:drawable="@drawable/timepicker_up_pressed" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_up_selected" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_up_disabled" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_up_disabled_focused" />
-
-</selector>
diff --git a/core/res/res/drawable/timepicker_up_btn_holo_dark.xml b/core/res/res/drawable/timepicker_up_btn_holo_dark.xml
deleted file mode 100644
index af5f6eb..0000000
--- a/core/res/res/drawable/timepicker_up_btn_holo_dark.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_up_normal_holo_dark" />
-
-    <item android:state_pressed="true"
-          android:state_enabled="true"
-          android:drawable="@drawable/timepicker_up_pressed_holo_dark" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_up_focused_holo_dark" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_up_disabled_holo_dark" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_up_disabled_focused_holo_dark" />
-
-</selector>
diff --git a/core/res/res/drawable/timepicker_up_btn_holo_light.xml b/core/res/res/drawable/timepicker_up_btn_holo_light.xml
deleted file mode 100644
index 6025d3a..0000000
--- a/core/res/res/drawable/timepicker_up_btn_holo_light.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_up_normal_holo_light" />
-
-    <item android:state_pressed="true"
-          android:state_enabled="true"
-          android:drawable="@drawable/timepicker_up_pressed_holo_light" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="true"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_up_focused_holo_light" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="false"
-          android:drawable="@drawable/timepicker_up_focused_holo_light" />
-
-    <item android:state_pressed="false"
-          android:state_enabled="false"
-          android:state_focused="true"
-          android:drawable="@drawable/timepicker_up_disabled_focused_holo_light" />
-
-</selector>
diff --git a/core/res/res/anim/accelerate_cubic_interpolator.xml b/core/res/res/interpolator/accelerate_cubic.xml
similarity index 100%
rename from core/res/res/anim/accelerate_cubic_interpolator.xml
rename to core/res/res/interpolator/accelerate_cubic.xml
diff --git a/core/res/res/interpolator/accelerate_decelerate.xml b/core/res/res/interpolator/accelerate_decelerate.xml
new file mode 100644
index 0000000..e7f9d9f
--- /dev/null
+++ b/core/res/res/interpolator/accelerate_decelerate.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<accelerateDecelerateInterpolator />
diff --git a/core/res/res/interpolator/accelerate_quad.xml b/core/res/res/interpolator/accelerate_quad.xml
new file mode 100644
index 0000000..18207f2
--- /dev/null
+++ b/core/res/res/interpolator/accelerate_quad.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<accelerateInterpolator />
diff --git a/core/res/res/anim/accelerate_quint_interpolator.xml b/core/res/res/interpolator/accelerate_quint.xml
similarity index 100%
rename from core/res/res/anim/accelerate_quint_interpolator.xml
rename to core/res/res/interpolator/accelerate_quint.xml
diff --git a/core/res/res/interpolator/anticipate.xml b/core/res/res/interpolator/anticipate.xml
new file mode 100644
index 0000000..7a16b5f
--- /dev/null
+++ b/core/res/res/interpolator/anticipate.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<anticipateInterpolator />
diff --git a/core/res/res/interpolator/anticipate_overshoot.xml b/core/res/res/interpolator/anticipate_overshoot.xml
new file mode 100644
index 0000000..d61ddd1
--- /dev/null
+++ b/core/res/res/interpolator/anticipate_overshoot.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<anticipateOvershootInterpolator />
diff --git a/core/res/res/interpolator/bounce.xml b/core/res/res/interpolator/bounce.xml
new file mode 100644
index 0000000..d89ba49
--- /dev/null
+++ b/core/res/res/interpolator/bounce.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<bounceInterpolator />
diff --git a/core/res/res/interpolator/cycle.xml b/core/res/res/interpolator/cycle.xml
new file mode 100644
index 0000000..70ebcb1
--- /dev/null
+++ b/core/res/res/interpolator/cycle.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<cycleInterpolator />
diff --git a/core/res/res/anim/decelerate_cubic_interpolator.xml b/core/res/res/interpolator/decelerate_cubic.xml
similarity index 100%
rename from core/res/res/anim/decelerate_cubic_interpolator.xml
rename to core/res/res/interpolator/decelerate_cubic.xml
diff --git a/core/res/res/interpolator/decelerate_quad.xml b/core/res/res/interpolator/decelerate_quad.xml
new file mode 100644
index 0000000..48e2308
--- /dev/null
+++ b/core/res/res/interpolator/decelerate_quad.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<decelerateInterpolator />
diff --git a/core/res/res/anim/decelerate_quint_interpolator.xml b/core/res/res/interpolator/decelerate_quint.xml
similarity index 100%
rename from core/res/res/anim/decelerate_quint_interpolator.xml
rename to core/res/res/interpolator/decelerate_quint.xml
diff --git a/core/res/res/interpolator/linear.xml b/core/res/res/interpolator/linear.xml
new file mode 100644
index 0000000..f4d256a
--- /dev/null
+++ b/core/res/res/interpolator/linear.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/anim/linear_interpolator.xml
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<linearInterpolator />
diff --git a/core/res/res/interpolator/overshoot.xml b/core/res/res/interpolator/overshoot.xml
new file mode 100644
index 0000000..725ea48
--- /dev/null
+++ b/core/res/res/interpolator/overshoot.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<overshootInterpolator />
diff --git a/core/res/res/layout-xlarge/alert_dialog.xml b/core/res/res/layout-xlarge/alert_dialog.xml
deleted file mode 100644
index 9444206..0000000
--- a/core/res/res/layout-xlarge/alert_dialog.xml
+++ /dev/null
@@ -1,152 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/res/layout/alert_dialog.xml
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<com.android.internal.widget.WeightedLinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/parentPanel"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:paddingTop="9dip"
-    android:paddingBottom="3dip"
-    android:paddingLeft="3dip"
-    android:paddingRight="1dip"
-    android:majorWeightMin="0.45"
-    android:minorWeightMin="0.72">
-
-    <LinearLayout android:id="@+id/topPanel"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:minHeight="54dip"
-        android:orientation="vertical">
-        <LinearLayout android:id="@+id/title_template"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            android:gravity="center_vertical"
-            android:layout_marginTop="6dip"
-            android:layout_marginBottom="9dip"
-            android:layout_marginLeft="10dip"
-            android:layout_marginRight="10dip">
-            <ImageView android:id="@+id/icon"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="top"
-                android:paddingTop="6dip"
-                android:paddingRight="10dip"
-                android:src="@drawable/ic_dialog_info" />
-            <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
-                style="?android:attr/textAppearanceLarge"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
-        </LinearLayout>
-        <ImageView android:id="@+id/titleDivider"
-            android:layout_width="match_parent"
-            android:layout_height="1dip"
-            android:visibility="gone"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_horizontal_dark" />
-        <!-- If the client uses a customTitle, it will be added here. -->
-    </LinearLayout>
-
-    <LinearLayout android:id="@+id/contentPanel"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:orientation="vertical">
-        <ScrollView android:id="@+id/scrollView"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingTop="2dip"
-            android:paddingBottom="12dip"
-            android:paddingLeft="14dip"
-            android:paddingRight="10dip">
-            <TextView android:id="@+id/message"
-                style="?android:attr/textAppearanceMedium"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:padding="5dip" />
-        </ScrollView>
-    </LinearLayout>
-
-    <FrameLayout android:id="@+id/customPanel"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="1">
-        <FrameLayout android:id="@+android:id/custom"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingTop="5dip"
-            android:paddingBottom="5dip" />
-    </FrameLayout>
-
-    <LinearLayout android:id="@+id/buttonPanel"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:minHeight="54dip"
-        android:orientation="vertical" >
-        <LinearLayout
-            style="?android:attr/buttonBarStyle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            android:paddingTop="4dip"
-            android:paddingLeft="2dip"
-            android:paddingRight="2dip"
-            android:measureWithLargestChild="true">
-            <LinearLayout android:id="@+id/leftSpacer"
-                android:layout_weight="0.25"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:visibility="gone" />
-            <Button android:id="@+id/button1"
-                android:layout_width="0dip"
-                android:layout_gravity="left"
-                android:layout_weight="1"
-                style="?android:attr/buttonBarButtonStyle"
-                android:maxLines="2"
-                android:layout_height="wrap_content" />
-            <Button android:id="@+id/button3"
-                android:layout_width="0dip"
-                android:layout_gravity="center_horizontal"
-                android:layout_weight="1"
-                style="?android:attr/buttonBarButtonStyle"
-                android:maxLines="2"
-                android:layout_height="wrap_content" />
-            <Button android:id="@+id/button2"
-                android:layout_width="0dip"
-                android:layout_gravity="right"
-                android:layout_weight="1"
-                style="?android:attr/buttonBarButtonStyle"
-                android:maxLines="2"
-                android:layout_height="wrap_content" />
-            <LinearLayout android:id="@+id/rightSpacer"
-                android:layout_width="0dip"
-                android:layout_weight="0.25"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:visibility="gone" />
-        </LinearLayout>
-     </LinearLayout>
-</com.android.internal.widget.WeightedLinearLayout>
diff --git a/core/res/res/layout-xlarge/alert_dialog_holo.xml b/core/res/res/layout-xlarge/alert_dialog_holo.xml
deleted file mode 100644
index fca7c78..0000000
--- a/core/res/res/layout-xlarge/alert_dialog_holo.xml
+++ /dev/null
@@ -1,155 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<com.android.internal.widget.WeightedLinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/parentPanel"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:paddingTop="9dip"
-    android:paddingBottom="3dip"
-    android:paddingLeft="3dip"
-    android:paddingRight="1dip"
-    android:majorWeightMin="0.45"
-    android:minorWeightMin="0.72">
-
-    <LinearLayout android:id="@+id/topPanel"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:minHeight="48dip"
-        android:orientation="vertical">
-        <LinearLayout android:id="@+id/title_template"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            android:gravity="center_vertical"
-            android:layout_marginTop="8dip"
-            android:layout_marginBottom="8dip"
-            android:layout_marginLeft="32dip"
-            android:layout_marginRight="32dip">
-            <ImageView android:id="@+id/icon"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:paddingRight="16dip"
-                android:src="@null" />
-            <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
-                style="?android:attr/textAppearanceMedium"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
-        </LinearLayout>
-        <ImageView android:id="@+id/titleDivider"
-            android:layout_width="match_parent"
-            android:layout_height="1dip"
-            android:visibility="gone"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_horizontal_dark" />
-        <!-- If the client uses a customTitle, it will be added here. -->
-    </LinearLayout>
-
-    <LinearLayout android:id="@+id/contentPanel"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:orientation="vertical">
-        <ScrollView android:id="@+id/scrollView"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
-            android:paddingTop="32dip"
-            android:paddingBottom="32dip"
-            android:clipToPadding="false">
-            <TextView android:id="@+id/message"
-                style="?android:attr/textAppearanceMedium"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingLeft="16dip"
-                android:paddingRight="16dip" />
-        </ScrollView>
-    </LinearLayout>
-
-    <FrameLayout android:id="@+id/customPanel"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_weight="1">
-        <FrameLayout android:id="@+android:id/custom"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingTop="8dip"
-            android:paddingBottom="8dip"
-            android:paddingLeft="32dip"
-            android:paddingRight="32dip" />
-    </FrameLayout>
-
-    <LinearLayout android:id="@+id/buttonPanel"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:minHeight="54dip"
-        android:orientation="vertical"
-        android:divider="?android:attr/dividerHorizontal"
-        android:showDividers="beginning"
-        android:dividerPadding="16dip">
-        <LinearLayout
-            style="?android:attr/buttonBarStyle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            android:paddingLeft="2dip"
-            android:paddingRight="2dip"
-            android:measureWithLargestChild="true">
-            <LinearLayout android:id="@+id/leftSpacer"
-                android:layout_weight="0.25"
-                android:layout_width="0dip"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:visibility="gone" />
-            <Button android:id="@+id/button1"
-                android:layout_width="0dip"
-                android:layout_gravity="left"
-                android:layout_weight="1"
-                android:maxLines="2"
-                style="?android:attr/buttonBarButtonStyle"
-                android:layout_height="wrap_content" />
-            <Button android:id="@+id/button3"
-                android:layout_width="0dip"
-                android:layout_gravity="center_horizontal"
-                android:layout_weight="1"
-                android:maxLines="2"
-                style="?android:attr/buttonBarButtonStyle"
-                android:layout_height="wrap_content" />
-            <Button android:id="@+id/button2"
-                android:layout_width="0dip"
-                android:layout_gravity="right"
-                android:layout_weight="1"
-                android:maxLines="2"
-                style="?android:attr/buttonBarButtonStyle"
-                android:layout_height="wrap_content" />
-            <LinearLayout android:id="@+id/rightSpacer"
-                android:layout_width="0dip"
-                android:layout_weight="0.25"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:visibility="gone" />
-        </LinearLayout>
-     </LinearLayout>
-</com.android.internal.widget.WeightedLinearLayout>
diff --git a/core/res/res/layout-xlarge/keyguard_screen_lock.xml b/core/res/res/layout-xlarge/keyguard_screen_lock.xml
index 733a350..c7aa654 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_lock.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_lock.xml
@@ -16,7 +16,7 @@
 ** limitations under the License.
 */
 -->
-        
+
 <!-- This is the general lock screen which shows information about the
   state of the device, as well as instructions on how to get past it
   depending on the state of the device.  It is the same for landscape
@@ -25,9 +25,7 @@
     android:orientation="vertical"
     android:gravity="bottom"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="#ff800000"
-        >
+    android:layout_height="match_parent">
 
     <LinearLayout
         android:orientation="vertical"
diff --git a/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml b/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml
index c2d87a2..4bc7292 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml
@@ -22,18 +22,23 @@
     android:layout_height="match_parent"
     android:orientation="horizontal"
         >
-    
-    <!-- left side: status and emergency call button -->
-    <LinearLayout
-            android:layout_height="match_parent"
-            android:layout_weight="1"
-            android:layout_width="0dip"
-            android:orientation="vertical"
-            android:gravity="center_vertical"
-                >
-        <include layout="@layout/keyguard_screen_status_land" />
-    </LinearLayout>
-    
+
+    <!-- left side: status -->
+    <RelativeLayout
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:layout_width="0dip">
+
+        <include layout="@layout/keyguard_screen_status_land"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="102dip"
+            android:layout_marginTop="320dip"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentLeft="true"/>
+
+    </RelativeLayout>
+
     <!-- right side: password -->
     <LinearLayout
         android:layout_width="0dip"
diff --git a/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml b/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
index 0927e59..e63fb9b 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
@@ -19,21 +19,23 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical"
-        >
-    
-    <!-- left side: status and emergency call button -->
-    <LinearLayout
+    android:orientation="vertical">
+
+    <!-- top: status -->
+    <RelativeLayout
             android:layout_width="match_parent"
             android:layout_height="0dip"
-            android:layout_weight="1"
-            android:orientation="vertical"
-            android:gravity="center_vertical"
-                >
-        <include layout="@layout/keyguard_screen_status_land" />
-    </LinearLayout>
-    
-    <!-- right side: password -->
+            android:layout_weight="1">
+        <include layout="@layout/keyguard_screen_status_port"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="134dip"
+            android:layout_marginLeft="266dip"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentLeft="true"/>
+    </RelativeLayout>
+
+    <!-- bottom: password -->
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="0dip"
diff --git a/core/res/res/layout-xlarge/keyguard_screen_status_land.xml b/core/res/res/layout-xlarge/keyguard_screen_status_land.xml
index 8589862..0a485e2 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_status_land.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_status_land.xml
@@ -23,8 +23,6 @@
         android:orientation="vertical"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="140dip"
-        android:layout_marginTop="20dip"
         android:gravity="left"
         >
 
@@ -38,6 +36,7 @@
         android:layout_marginTop="32dip"
         android:singleLine="true"
         android:ellipsize="marquee"
+        android:visibility="gone"
         />
 
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
@@ -47,81 +46,107 @@
         android:layout_alignParentLeft="true"
         android:layout_marginTop="8dip"
         android:layout_marginBottom="8dip"
+        android:layout_marginLeft="-10dip"
         >
 
-        <TextView android:id="@+id/timeDisplay"
+        <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
+        top of the other. Hence the redundant layout... -->
+        <TextView android:id="@+id/timeDisplayBackground"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
-            android:textSize="120sp"
+            android:textSize="98sp"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:shadowColor="#C0000000"
-            android:shadowDx="0"
-            android:shadowDy="0"
-            android:shadowRadius="3.0"
+            android:textColor="@color/lockscreen_clock_background"
             android:layout_marginBottom="6dip"
             />
 
+        <TextView android:id="@+id/timeDisplayForeground"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="none"
+            android:textSize="98sp"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textColor="@color/lockscreen_clock_foreground"
+            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignTop="@id/timeDisplayBackground"
+            android:layout_marginBottom="6dip"
+            />
 
         <TextView android:id="@+id/am_pm"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/timeDisplay"
-            android:layout_alignBaseline="@id/timeDisplay"
+            android:layout_toRightOf="@id/timeDisplayBackground"
+            android:layout_alignBaseline="@id/timeDisplayBackground"
             android:singleLine="true"
             android:ellipsize="none"
             android:textSize="30sp"
             android:layout_marginLeft="8dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:shadowColor="#C0000000"
-            android:shadowDx="0"
-            android:shadowDy="0"
-            android:shadowRadius="3.0"
+            android:textColor="@color/lockscreen_clock_am_pm"
             />
 
     </com.android.internal.widget.DigitalClock>
 
-    <TextView
-        android:id="@+id/date"
+    <LinearLayout
+        android:orientation="horizontal"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_below="@id/time"
-        android:layout_marginTop="5dip"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="32sp"
-        />
+        android:layout_marginTop="10dip">
 
-    <!-- used for instructions such as "draw pattern to unlock", the next alarm, and charging
-         status.  -->
+        <TextView
+            android:id="@+id/date"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="17sp"/>
+
+        <TextView
+            android:id="@+id/alarm_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="30dip"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="17sp"/>
+
+    </LinearLayout>
+
+    <!-- Status2 is generally charge status  -->
     <TextView
         android:id="@+id/status2"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="32sp"
-        android:layout_marginTop="50dip"
+        android:textSize="17sp"
+        android:layout_marginTop="10dip"
         android:drawablePadding="4dip"
+        android:visibility="gone"
         />
+
+    <!-- Status1 is generally battery status and informational messages -->
     <TextView
         android:id="@+id/status1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginTop="15dip"
-        android:textSize="32sp"
+        android:layout_marginTop="10dip"
+        android:textSize="17sp"
         android:textAppearance="?android:attr/textAppearanceMedium"
         />
-        
+
     <TextView
         android:id="@+id/propertyOf"
         android:lineSpacingExtra="8dip"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="22sp"
-        android:layout_marginTop="50dip"
+        android:textSize="17sp"
+        android:layout_marginTop="20dip"
         android:singleLine="false"
+        android:textColor="@color/lockscreen_owner_info"
         android:visibility="invisible"
         />
 </LinearLayout>
diff --git a/core/res/res/layout-xlarge/keyguard_screen_status_port.xml b/core/res/res/layout-xlarge/keyguard_screen_status_port.xml
index 8589862..346b21e 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_status_port.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_status_port.xml
@@ -38,90 +38,113 @@
         android:layout_marginTop="32dip"
         android:singleLine="true"
         android:ellipsize="marquee"
+        android:visibility="gone"
         />
 
     <com.android.internal.widget.DigitalClock android:id="@+id/time"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentLeft="true"
         android:layout_marginTop="8dip"
         android:layout_marginBottom="8dip"
-        >
+        android_layout_marginLeft="-10dip">
 
-        <TextView android:id="@+id/timeDisplay"
+        <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
+        top of the other. Hence the redundant layout... -->
+        <TextView android:id="@+id/timeDisplayBackground"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
-            android:textSize="120sp"
+            android:textSize="98sp"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:shadowColor="#C0000000"
-            android:shadowDx="0"
-            android:shadowDy="0"
-            android:shadowRadius="3.0"
+            android:textColor="@color/lockscreen_clock_background"
             android:layout_marginBottom="6dip"
             />
 
+        <TextView android:id="@+id/timeDisplayForeground"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="none"
+            android:textSize="98sp"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textColor="@color/lockscreen_clock_foreground"
+            android:layout_marginBottom="6dip"
+            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignTop="@id/timeDisplayBackground"
+            />
 
         <TextView android:id="@+id/am_pm"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/timeDisplay"
-            android:layout_alignBaseline="@id/timeDisplay"
+            android:layout_toRightOf="@id/timeDisplayBackground"
+            android:layout_alignBaseline="@id/timeDisplayBackground"
             android:singleLine="true"
             android:ellipsize="none"
             android:textSize="30sp"
             android:layout_marginLeft="8dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:shadowColor="#C0000000"
-            android:shadowDx="0"
-            android:shadowDy="0"
-            android:shadowRadius="3.0"
+            android:textColor="@color/lockscreen_clock_am_pm"
             />
 
     </com.android.internal.widget.DigitalClock>
 
-    <TextView
-        android:id="@+id/date"
+    <LinearLayout
+        android:orientation="horizontal"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_below="@id/time"
-        android:layout_marginTop="5dip"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="32sp"
-        />
+        android:layout_marginTop="10dip">
 
-    <!-- used for instructions such as "draw pattern to unlock", the next alarm, and charging
-         status.  -->
+        <TextView
+            android:id="@+id/date"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="17sp"/>
+
+        <TextView
+            android:id="@+id/alarm_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="30dip"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="17sp"/>
+
+    </LinearLayout>
+
+    <!-- used for status such as the next alarm, and charging status.  -->
     <TextView
         android:id="@+id/status2"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="32sp"
-        android:layout_marginTop="50dip"
+        android:textSize="17sp"
+        android:layout_marginTop="10dip"
         android:drawablePadding="4dip"
+        android:visibility="gone"
         />
+
     <TextView
         android:id="@+id/status1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginTop="15dip"
-        android:textSize="32sp"
+        android:layout_marginTop="10dip"
+        android:textSize="17sp"
         android:textAppearance="?android:attr/textAppearanceMedium"
         />
-        
+
     <TextView
         android:id="@+id/propertyOf"
         android:lineSpacingExtra="8dip"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_marginTop="20dip"
         android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textSize="22sp"
-        android:layout_marginTop="50dip"
+        android:textSize="17sp"
         android:singleLine="false"
         android:visibility="invisible"
+        android:textColor="@color/lockscreen_owner_info"
         />
 </LinearLayout>
diff --git a/core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml b/core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml
index c76e833..c9c1692 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml
@@ -26,18 +26,20 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:id="@+id/root"
-    android:background="#70000000">
+    android:id="@+id/root">
 
-    <!-- left side: status and emergency call button -->
-    <LinearLayout
+    <!-- top: status -->
+    <RelativeLayout
         android:layout_width="match_parent"
         android:layout_height="0dip"
         android:layout_weight="1"
-        android:orientation="vertical"
-        android:gravity="center_vertical">
-        <include layout="@layout/keyguard_screen_status_port" />
-    </LinearLayout>
+        android:orientation="vertical">
+        <include layout="@layout/keyguard_screen_status_port"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="134dip"
+            android:layout_marginLeft="266dip"/>
+    </RelativeLayout>
 
     <LinearLayout
             android:layout_width="match_parent"
@@ -75,6 +77,7 @@
             android:text="@string/emergency_calls_only"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:textColor="@color/white"
+            android:visibility="gone"
            />
 
         <!-- emergency call button shown when sim is PUKd and tab_selector is
@@ -86,7 +89,7 @@
             android:drawableLeft="@drawable/ic_emergency"
             android:layout_centerInParent="true"
             android:layout_alignParentBottom="true"
-            android:layout_marginBottom="80dip"
+            android:layout_marginBottom="90dip"
             style="@style/Widget.Button.Transparent"
             android:drawablePadding="8dip"
             android:visibility="gone"
diff --git a/core/res/res/layout-xlarge/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout-xlarge/keyguard_screen_tab_unlock_land.xml
index 6c99ccac..fbb9983 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_tab_unlock_land.xml
@@ -25,19 +25,23 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="horizontal"
-    android:background="#70000000"
     android:id="@+id/root">
 
-    <!-- left side: status and emergency call button -->
-    <LinearLayout
-            android:layout_height="match_parent"
-            android:layout_weight="1"
-            android:layout_width="0dip"
-            android:orientation="vertical"
-            android:gravity="center_vertical"
-                >
-        <include layout="@layout/keyguard_screen_status_land" />
-    </LinearLayout>
+    <!-- left side: status -->
+    <RelativeLayout
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:layout_width="0dip">
+
+        <include layout="@layout/keyguard_screen_status_land"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="102dip"
+            android:layout_marginTop="320dip"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentLeft="true"/>
+
+    </RelativeLayout>
 
     <!-- right side -->
     <LinearLayout
diff --git a/core/res/res/layout-xlarge/keyguard_screen_unlock_landscape.xml b/core/res/res/layout-xlarge/keyguard_screen_unlock_landscape.xml
index 52be82c..8acb656 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_unlock_landscape.xml
@@ -25,82 +25,92 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="horizontal"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-        >
+    android:layout_height="match_parent">
 
-    <!-- left side: status and emergency call button -->
-    <LinearLayout
-            android:layout_height="match_parent"
-            android:layout_weight="1"
-            android:layout_width="0dip"
-            android:orientation="vertical"
-            android:gravity="center_vertical"
-                >
-        
-        <include layout="@layout/keyguard_screen_status_land" />
+    <!-- left side: status  -->
+    <RelativeLayout
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:layout_width="0dip">
 
-        <!-- footer -->
-        <FrameLayout
-            android:layout_width="match_parent"
+        <include layout="@layout/keyguard_screen_status_land"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="140dip"
-            >
+            android:layout_marginLeft="102dip"
+            android:layout_marginTop="320dip"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentLeft="true"/>
 
-            <!-- option 1: a single emergency call button -->
-            <RelativeLayout android:id="@+id/footerNormal"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:gravity="left"
-                >
-                <Button android:id="@+id/emergencyCallAlone"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:text="@string/lockscreen_emergency_call"
-                    style="@style/Widget.Button.Transparent"
-                    android:drawableLeft="@drawable/ic_emergency"
-                    android:drawablePadding="8dip"
-                    android:visibility="gone"
-                    />
-            </RelativeLayout>
-
-            <!-- option 2: an emergency call button, and a 'forgot pattern?' button -->
-            <LinearLayout android:id="@+id/footerForgotPattern"
-                android:orientation="vertical"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:gravity="left"
-                >
-                <Button android:id="@+id/forgotPattern"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    style="@style/Widget.Button.Transparent"
-                    />
-                <Button android:id="@+id/emergencyCallTogether"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:text="@string/lockscreen_emergency_call"
-                    style="@style/Widget.Button.Transparent"
-                    android:drawableLeft="@drawable/ic_emergency"
-                    android:drawablePadding="8dip"
-                    android:visibility="gone"
-                    />
-            </LinearLayout>
-        </FrameLayout>
-    </LinearLayout>
+    </RelativeLayout>
 
     <!-- right side: lock pattern -->
-    <LinearLayout
+    <RelativeLayout
         android:layout_weight="1"
         android:layout_width="0dip"
-        android:layout_height="match_parent"
-        android:gravity="center"
-        >
+        android:layout_height="match_parent">
+
         <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
             android:layout_width="354dip"
             android:layout_height="354dip"
-            android:layout_marginTop="90dip"
-            android:layout_marginRight="90dip"
-          />
-    </LinearLayout>
+            android:layout_marginLeft="143dip"
+            android:layout_marginTop="201dip"
+            android:layout_gravity="center_vertical"
+        />
+
+        <!-- footer -->
+
+        <!-- option 1: a single emergency call button -->
+        <RelativeLayout android:id="@+id/footerNormal"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/lockPattern"
+            android:layout_alignLeft="@id/lockPattern"
+            android:layout_alignRight="@id/lockPattern"
+            android:layout_marginTop="28dip"
+            android:layout_marginLeft="28dip"
+            android:layout_marginRight="28dip"
+            >
+            <Button android:id="@+id/emergencyCallAlone"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/lockscreen_emergency_call"
+                style="@style/Widget.Button.Transparent"
+                android:drawableLeft="@drawable/ic_emergency"
+                android:drawablePadding="8dip"
+                android:visibility="gone"
+                />
+        </RelativeLayout>
+
+        <!-- option 2: an emergency call button, and a 'forgot pattern?' button -->
+        <LinearLayout android:id="@+id/footerForgotPattern"
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/footerNormal"
+            android:layout_alignLeft="@id/lockPattern"
+            android:layout_alignRight="@id/lockPattern"
+            android:layout_marginTop="28dip"
+            android:layout_marginLeft="28dip"
+            android:layout_marginRight="28dip">
+
+            <Button android:id="@+id/forgotPattern"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                style="@style/Widget.Button.Transparent"
+            />
+
+            <Button android:id="@+id/emergencyCallTogether"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/lockscreen_emergency_call"
+                style="@style/Widget.Button.Transparent"
+                android:drawableLeft="@drawable/ic_emergency"
+                android:drawablePadding="8dip"
+                android:visibility="gone"
+            />
+
+        </LinearLayout>
+
+    </RelativeLayout>
 
 </com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
diff --git a/core/res/res/layout-xlarge/keyguard_screen_unlock_portrait.xml b/core/res/res/layout-xlarge/keyguard_screen_unlock_portrait.xml
index e170a76..f35897e 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_unlock_portrait.xml
@@ -21,19 +21,20 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-        >
+    android:layout_height="match_parent">
 
-    <!-- left side: status and emergency call button -->
+    <!-- top: status -->
     <LinearLayout
-            android:layout_height="0dip"
-            android:layout_weight="1"
-            android:layout_width="match_parent"
-            android:orientation="vertical"
-            android:gravity="center_vertical"
-                >
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:layout_width="match_parent"
+        android:orientation="vertical">
 
-        <include layout="@layout/keyguard_screen_status_port" />
+        <include layout="@layout/keyguard_screen_status_port"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="134dip"
+            android:layout_marginLeft="266dip"/>
 
         <!-- footer -->
         <FrameLayout
diff --git a/core/res/res/layout-xlarge/preference_list_content_single.xml b/core/res/res/layout-xlarge/preference_list_content_single.xml
index 6899ed0..6725996 100644
--- a/core/res/res/layout-xlarge/preference_list_content_single.xml
+++ b/core/res/res/layout-xlarge/preference_list_content_single.xml
@@ -30,18 +30,14 @@
 
         <LinearLayout
             android:id="@+id/headers"
+            style="?attr/preferencePanelStyle"
             android:orientation="vertical"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:layout_marginRight="@dimen/preference_screen_side_margin"
-            android:layout_marginLeft="@dimen/preference_screen_side_margin"
-            android:layout_marginTop="48dp"
-            android:layout_marginBottom="48dp"
             android:paddingLeft="32dip"
             android:paddingRight="32dip"
             android:paddingTop="32dip"
-            android:paddingBottom="32dip"
-            android:background="?attr/preferencePanelBackground">
+            android:paddingBottom="32dip" >
 
             <ListView android:id="@android:id/list"
                 android:layout_width="match_parent"
diff --git a/core/res/res/layout/action_menu_item_layout.xml b/core/res/res/layout/action_menu_item_layout.xml
index 94fcc2f..e001894 100644
--- a/core/res/res/layout/action_menu_item_layout.xml
+++ b/core/res/res/layout/action_menu_item_layout.xml
@@ -20,16 +20,21 @@
     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"
                  android:layout_gravity="center"
                  android:visibility="gone"
-                 style="?attr/actionButtonStyle" />
+                 android:paddingLeft="4dip"
+                 android:paddingRight="4dip"
+                 android:minHeight="56dip"
+                 android:scaleType="center"
+                 android:background="@null" />
     <Button android:id="@+id/textButton"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
diff --git a/core/res/res/layout/alert_dialog.xml b/core/res/res/layout/alert_dialog.xml
index a1498f7..4477e07 100644
--- a/core/res/res/layout/alert_dialog.xml
+++ b/core/res/res/layout/alert_dialog.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<com.android.internal.widget.WeightedLinearLayout
+<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/parentPanel"
     android:layout_width="match_parent"
@@ -27,9 +27,7 @@
     android:paddingTop="9dip"
     android:paddingBottom="3dip"
     android:paddingLeft="3dip"
-    android:paddingRight="1dip"
-    android:majorWeightMin="0.65"
-    android:minorWeightMin="0.9">
+    android:paddingRight="1dip">
 
     <LinearLayout android:id="@+id/topPanel"
         android:layout_width="match_parent"
@@ -150,4 +148,4 @@
                 android:visibility="gone" />
         </LinearLayout>
      </LinearLayout>
-</com.android.internal.widget.WeightedLinearLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/alert_dialog_holo.xml b/core/res/res/layout/alert_dialog_holo.xml
index ea6e11e..57eb9c7 100644
--- a/core/res/res/layout/alert_dialog_holo.xml
+++ b/core/res/res/layout/alert_dialog_holo.xml
@@ -17,31 +17,32 @@
 */
 -->
 
-<com.android.internal.widget.WeightedLinearLayout
+<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/parentPanel"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:paddingTop="9dip"
-    android:paddingBottom="3dip"
-    android:paddingLeft="3dip"
-    android:paddingRight="1dip"
-    android:majorWeightMin="0.65"
-    android:minorWeightMin="0.9">
+    android:orientation="vertical">
 
     <LinearLayout android:id="@+id/topPanel"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:minHeight="48dip"
         android:orientation="vertical">
+        <ImageView android:id="@+id/titleDividerTop"
+            android:layout_width="match_parent"
+            android:layout_height="4dip"
+            android:visibility="gone"
+            android:scaleType="fitXY"
+            android:gravity="fill_horizontal"
+            android:paddingLeft="16dip"
+            android:paddingRight="16dip"
+            android:src="@android:drawable/divider_strong_holo" />
         <LinearLayout android:id="@+id/title_template"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:gravity="center_vertical"
-            android:layout_marginTop="8dip"
-            android:layout_marginBottom="8dip"
+            android:gravity="center_vertical|left"
+            android:minHeight="60dip"
             android:layout_marginLeft="32dip"
             android:layout_marginRight="32dip">
             <ImageView android:id="@+id/icon"
@@ -58,11 +59,13 @@
         </LinearLayout>
         <ImageView android:id="@+id/titleDivider"
             android:layout_width="match_parent"
-            android:layout_height="1dip"
+            android:layout_height="4dip"
             android:visibility="gone"
             android:scaleType="fitXY"
             android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_horizontal_dark" />
+            android:paddingLeft="16dip"
+            android:paddingRight="16dip"
+            android:src="@android:drawable/divider_strong_holo" />
         <!-- If the client uses a customTitle, it will be added here. -->
     </LinearLayout>
 
@@ -152,4 +155,4 @@
                 android:visibility="gone" />
         </LinearLayout>
      </LinearLayout>
-</com.android.internal.widget.WeightedLinearLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/alert_dialog_progress.xml b/core/res/res/layout/alert_dialog_progress.xml
index c519692..ac95cdb 100644
--- a/core/res/res/layout/alert_dialog_progress.xml
+++ b/core/res/res/layout/alert_dialog_progress.xml
@@ -40,9 +40,9 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingBottom="12dip"
-            android:layout_marginLeft="50dip"
-            android:layout_marginRight="15dip"
-            android:layout_alignParentLeft="true"
+            android:layout_marginLeft="10dip"
+            android:layout_marginRight="10dip"
+            android:layout_alignParentRight="true"
             android:layout_below="@id/progress"
         />
 </RelativeLayout>
diff --git a/core/res/res/layout/calendar_view.xml b/core/res/res/layout/calendar_view.xml
new file mode 100644
index 0000000..176bb8b
--- /dev/null
+++ b/core/res/res/layout/calendar_view.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fillViewport="true" >
+
+    <TextView android:id="@+android:id/month_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:paddingTop="10dip"
+        android:paddingBottom="10dip"
+        style="@android:style/TextAppearance.Medium" />
+
+    <LinearLayout android:id="@+android:id/day_names"
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="6dip"
+        android:layout_marginRight="2dip"
+        android:layout_marginLeft="2dip"
+        android:gravity="center" >
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:visibility="gone" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center" />
+
+        <TextView android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:gravity="center" />
+
+    </LinearLayout>
+
+    <ImageView android:layout_width="match_parent"
+        android:layout_height="1dip"
+        android:scaleType="fitXY"
+        android:gravity="fill_horizontal"
+        android:src="?android:attr/dividerHorizontal" />
+
+    <ListView android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:drawSelectorOnTop="false"
+        android:cacheColorHint="@android:color/transparent"
+        android:fastScrollEnabled="false"
+        android:overScrollMode="never" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/date_picker.xml b/core/res/res/layout/date_picker.xml
index 5c023ee..e9663b1 100644
--- a/core/res/res/layout/date_picker.xml
+++ b/core/res/res/layout/date_picker.xml
@@ -32,8 +32,8 @@
     <LinearLayout android:id="@+id/pickers"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginRight="15dip"
-        android:layout_weight="0.5"
+        android:layout_marginRight="22dip"
+        android:layout_weight="1"
         android:orientation="horizontal"
         android:gravity="center">
 
@@ -42,10 +42,8 @@
             android:id="@+id/month"
             android:layout_width="48dip"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="15dip"
-            android:layout_marginRight="15dip"
-            android:layout_marginTop="35dip"
-            android:layout_marginBottom="35dip"
+            android:layout_marginLeft="22dip"
+            android:layout_marginRight="22dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -55,10 +53,8 @@
             android:id="@+id/day"
             android:layout_width="48dip"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="15dip"
-            android:layout_marginRight="15dip"
-            android:layout_marginTop="35dip"
-            android:layout_marginBottom="35dip"
+            android:layout_marginLeft="22dip"
+            android:layout_marginRight="22dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -68,25 +64,23 @@
             android:id="@+id/year"
             android:layout_width="48dip"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="15dip"
-            android:layout_marginRight="15dip"
-            android:layout_marginTop="35dip"
-            android:layout_marginBottom="35dip"       
+            android:layout_marginLeft="22dip"
+            android:layout_marginRight="22dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
 
     </LinearLayout>
 
-    <!-- mini-month day-picker -->
-      <DayPicker
-          android:id="@+id/mini_month_day_picker"
-          android:layout_width="200dip"
-          android:layout_height="230dip"
-          android:layout_marginLeft="15dip"
-          android:layout_weight="0.5"
-          android:focusable="true"
-          android:focusableInTouchMode="true"
-          />
+    <!-- calendar view -->
+    <CalendarView
+        android:id="@+id/calendar_view"
+        android:layout_width="245dip"
+        android:layout_height="280dip"
+        android:layout_marginLeft="22dip"
+        android:layout_weight="1"
+        android:focusable="true"
+        android:focusableInTouchMode="true"
+        />
 
 </LinearLayout>
diff --git a/core/res/res/layout/date_picker_dialog.xml b/core/res/res/layout/date_picker_dialog.xml
index 148e192..004d52a 100644
--- a/core/res/res/layout/date_picker_dialog.xml
+++ b/core/res/res/layout/date_picker_dialog.xml
@@ -20,5 +20,6 @@
 <DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/datePicker"
     android:layout_gravity="center_horizontal"
-    android:layout_width="250dip"
-    android:layout_height="600dip"/>
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    />
diff --git a/core/res/res/layout/day_picker.xml b/core/res/res/layout/day_picker.xml
deleted file mode 100644
index a030df8..0000000
--- a/core/res/res/layout/day_picker.xml
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* Copyright 2010, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License")
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:fillViewport="true" >
-
-    <TextView android:id="@+android:id/month_name"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal"
-        android:paddingTop="10dip"
-        android:paddingBottom="10dip"
-        style="@android:style/TextAppearance.Medium" />
-
-    <LinearLayout android:id="@+android:id/day_names"
-        android:orientation="horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="6dip"
-        android:layout_marginRight="2dip"
-        android:layout_marginLeft="2dip"
-        android:gravity="center" >
-
-        <TextView android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:gravity="center"
-            android:visibility="gone" />
-
-        <TextView android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:gravity="center"
-            style="?android:attr/dayPickerWeekDayViewStyle" />
-        <TextView android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:gravity="center"
-            style="?android:attr/dayPickerWeekDayViewStyle" />
-
-        <TextView android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:gravity="center"
-            style="?android:attr/dayPickerWeekDayViewStyle" />
-
-        <TextView android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:gravity="center"
-            style="?android:attr/dayPickerWeekDayViewStyle" />
-
-        <TextView android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:gravity="center"
-            style="?android:attr/dayPickerWeekDayViewStyle" />
-
-        <TextView android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:gravity="center"
-            style="?android:attr/dayPickerWeekDayViewStyle" />
-
-        <TextView android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:gravity="center"
-            style="?android:attr/dayPickerWeekDayViewStyle" />
-
-    </LinearLayout>
-
-    <ImageView android:layout_width="match_parent"
-        android:layout_height="1dip"
-        android:scaleType="fitXY"
-        android:gravity="fill_horizontal"
-        android:src="?android:attr/dividerHorizontal" />
-
-    <ListView android:id="@android:id/list"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:drawSelectorOnTop="false"
-        android:cacheColorHint="@android:color/transparent"
-        android:fastScrollEnabled="false"
-        android:overScrollMode="never" />
-
-</LinearLayout>
diff --git a/core/res/res/layout/dialog_custom_title_holo.xml b/core/res/res/layout/dialog_custom_title_holo.xml
new file mode 100644
index 0000000..854873f
--- /dev/null
+++ b/core/res/res/layout/dialog_custom_title_holo.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+This is an custom layout for a dialog.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:fitsSystemWindows="true">
+    <FrameLayout android:id="@android:id/title_container"
+        android:layout_width="match_parent"
+        android:layout_height="24dip"
+        android:layout_weight="0"
+        style="?android:attr/windowTitleBackgroundStyle">
+    </FrameLayout>
+    <FrameLayout
+        android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:foreground="?android:attr/windowContentOverlay">
+        <FrameLayout android:id="@android:id/content"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:paddingTop="6dip"
+            android:paddingBottom="10dip"
+            android:paddingLeft="10dip"
+            android:paddingRight="10dip" />
+    </FrameLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/dialog_title_holo.xml b/core/res/res/layout/dialog_title_holo.xml
new file mode 100644
index 0000000..534dd8d
--- /dev/null
+++ b/core/res/res/layout/dialog_title_holo.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+This is an optimized layout for a screen, with the minimum set of features
+enabled.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:fitsSystemWindows="true">
+    <TextView android:id="@android:id/title" style="?android:attr/windowTitleStyle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="60dip"
+        android:paddingLeft="32dip"
+        android:paddingRight="32dip"
+        android:gravity="center_vertical|left" />
+    <ImageView android:id="@+id/titleDivider"
+            android:layout_width="match_parent"
+            android:layout_height="4dip"
+            android:scaleType="fitXY"
+            android:gravity="fill_horizontal"
+            android:paddingLeft="16dip"
+            android:paddingRight="16dip"
+            android:src="@android:drawable/divider_strong_holo" />
+    <FrameLayout
+        android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:foreground="?android:attr/windowContentOverlay">
+        <FrameLayout android:id="@android:id/content"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+    </FrameLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/dialog_title_icons_holo.xml b/core/res/res/layout/dialog_title_icons_holo.xml
new file mode 100644
index 0000000..a3cd3af
--- /dev/null
+++ b/core/res/res/layout/dialog_title_icons_holo.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+This is an optimized layout for a screen, with the minimum set of features
+enabled.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:fitsSystemWindows="true">
+
+    <LinearLayout android:id="@+id/title_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:gravity="center_vertical"
+        android:minHeight="60dip"
+        android:paddingLeft="32dip"
+        android:paddingRight="32dip">
+        <ImageView android:id="@+id/left_icon"
+            android:layout_width="32dip"
+            android:layout_height="32dip"
+            android:scaleType="fitCenter"
+            android:layout_marginRight="8dip" />
+        <TextView android:id="@android:id/title"
+		style="?android:attr/windowTitleStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="0" />
+        <ImageView android:id="@+id/right_icon"
+            android:layout_width="32dip"
+            android:layout_height="32dip"
+            android:scaleType="fitCenter"
+            android:layout_marginLeft="8dip" />
+    </LinearLayout>
+
+    <ImageView android:id="@+id/titleDivider"
+            android:layout_width="match_parent"
+            android:layout_height="4dip"
+            android:scaleType="fitXY"
+            android:gravity="fill_horizontal"
+            android:paddingLeft="16dip"
+            android:paddingRight="16dip"
+            android:src="@android:drawable/divider_strong_holo" />
+
+    <FrameLayout
+        android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical"
+        android:foreground="?android:attr/windowContentOverlay">
+        <FrameLayout android:id="@android:id/content"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+    </FrameLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/fragment_bread_crumb_item.xml b/core/res/res/layout/fragment_bread_crumb_item.xml
index e97508f..dbbb9a5 100644
--- a/core/res/res/layout/fragment_bread_crumb_item.xml
+++ b/core/res/res/layout/fragment_bread_crumb_item.xml
@@ -20,11 +20,12 @@
         >
     <ImageView
             android:id="@android:id/left_icon"
-            android:src="@drawable/nav_divider"
+            android:src="?attr/dividerVertical"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_marginTop="8dip"
-            android:layout_marginBottom="8dip"
+            android:scaleType="fitXY"
+            android:layout_marginTop="12dip"
+            android:layout_marginBottom="12dip"
         />
 
     <TextView
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index 3d52f71..4d8c688 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -20,7 +20,6 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:background="#70000000"
     android:gravity="center_horizontal">
 
     <LinearLayout
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index af8a3ef..93966de 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -20,7 +20,6 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:background="#70000000"
     android:gravity="center_horizontal">
 
     <!-- "Enter PIN(Password) to unlock" -->
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 6edbdf9..5fe38d5 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -25,7 +25,6 @@
     xmlns:tabunlock="http://schemas.android.com/apk/res/com.android.tabunlock"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="#70000000"
     android:gravity="center_horizontal"
     android:id="@+id/root">
 
@@ -67,35 +66,43 @@
         android:layout_marginBottom="8dip"
         >
 
-        <TextView android:id="@+id/timeDisplay"
+        <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
+        top of the other. Hence the redundant layout... -->
+        <TextView android:id="@+id/timeDisplayBackground"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:ellipsize="none"
             android:textSize="72sp"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:shadowColor="#C0000000"
-            android:shadowDx="0"
-            android:shadowDy="0"
-            android:shadowRadius="3.0"
-            android:layout_marginBottom="10dip"
+            android:layout_marginBottom="6dip"
+            android:textColor="@color/lockscreen_clock_background"
             />
 
+        <TextView android:id="@+id/timeDisplayForeground"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="none"
+            android:textSize="72sp"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:layout_marginBottom="6dip"
+            android:textColor="@color/lockscreen_clock_foreground"
+            android:layout_alignLeft="@id/timeDisplayBackground"
+            android:layout_alignTop="@id/timeDisplayBackground"
+            />
 
         <TextView android:id="@+id/am_pm"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/timeDisplay"
-            android:layout_alignBaseline="@id/timeDisplay"
+            android:layout_toRightOf="@id/timeDisplayBackground"
+            android:layout_alignBaseline="@id/timeDisplayBackground"
             android:singleLine="true"
             android:ellipsize="none"
             android:textSize="22sp"
             android:layout_marginLeft="8dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:shadowColor="#C0000000"
-            android:shadowDx="0"
-            android:shadowDy="0"
-            android:shadowRadius="3.0"
+            android:textColor="@color/lockscreen_clock_am_pm"
             />
 
     </com.android.internal.widget.DigitalClock>
@@ -109,11 +116,24 @@
         android:textAppearance="?android:attr/textAppearanceMedium"
         />
 
+    <!-- TODO: Redo layout when we release on phones -->
+    <TextView
+        android:id="@+id/alarm_status"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textSize="18sp"
+        android:drawablePadding="4dip"
+        android:layout_below="@id/date"
+        android:layout_marginTop="4dip"
+        android:layout_marginLeft="24dip"
+        />
+
     <TextView
         android:id="@+id/status1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_below="@id/date"
+        android:layout_below="@id/alarm_status"
         android:layout_marginTop="4dip"
         android:layout_marginLeft="24dip"
         android:textAppearance="?android:attr/textAppearanceMedium"
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index e66b492..3c2ad9a 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -25,7 +25,6 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="horizontal"
-    android:background="#70000000"
     android:id="@+id/root">
 
     <!-- left side -->
@@ -68,35 +67,43 @@
             android:layout_marginBottom="8dip"
             >
 
-            <TextView android:id="@+id/timeDisplay"
+           <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
+            top of the other. Hence the redundant layout... -->
+            <TextView android:id="@+id/timeDisplayBackground"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:singleLine="true"
                 android:ellipsize="none"
                 android:textSize="72sp"
                 android:textAppearance="?android:attr/textAppearanceMedium"
-                android:shadowColor="#C0000000"
-                android:shadowDx="0"
-                android:shadowDy="0"
-                android:shadowRadius="3.0"
                 android:layout_marginBottom="6dip"
+                android:textColor="@color/lockscreen_clock_background"
                 />
 
+            <TextView android:id="@+id/timeDisplayForeground"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="none"
+                android:textSize="72sp"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:layout_marginBottom="6dip"
+                android:textColor="@color/lockscreen_clock_foreground"
+                android:layout_alignLeft="@id/timeDisplayBackground"
+                android:layout_alignTop="@id/timeDisplayBackground"
+                />
 
             <TextView android:id="@+id/am_pm"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_toRightOf="@id/timeDisplay"
-                android:layout_alignBaseline="@id/timeDisplay"
+                android:layout_toRightOf="@id/timeDisplayBackground"
+                android:layout_alignBaseline="@id/timeDisplayBackground"
                 android:singleLine="true"
                 android:ellipsize="none"
                 android:textSize="22sp"
                 android:layout_marginLeft="8dip"
                 android:textAppearance="?android:attr/textAppearanceMedium"
-                android:shadowColor="#C0000000"
-                android:shadowDx="0"
-                android:shadowDy="0"
-                android:shadowRadius="3.0"
+                android:textColor="@color/lockscreen_clock_am_pm"
                 />
 
         </com.android.internal.widget.DigitalClock>
@@ -110,11 +117,24 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             />
 
+        <!-- TODO: Redo layout when we release on phones -->
+        <TextView
+            android:id="@+id/alarm_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="18sp"
+            android:drawablePadding="4dip"
+            android:layout_below="@id/date"
+            android:layout_marginTop="4dip"
+            android:layout_marginLeft="24dip"
+            />
+
         <TextView
             android:id="@+id/status1"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_below="@id/date"
+            android:layout_below="@id/alarm_status"
             android:layout_marginTop="6dip"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:drawablePadding="4dip"
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index 83381a1..c7b78c4 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -25,9 +25,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="horizontal"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="#70000000"
-        >
+    android:layout_height="match_parent">
 
     <!-- left side: instructions and emergency call button -->
     <LinearLayout
@@ -38,6 +36,15 @@
             android:layout_marginLeft="24dip"
             android:gravity="left"
             >
+
+        <TextView
+            android:id="@+id/alarm_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="18sp"
+            android:drawablePadding="4dip"
+            />
         <TextView
             android:id="@+id/status1"
             android:layout_width="wrap_content"
@@ -68,35 +75,45 @@
             android:layout_marginBottom="8dip"
             >
 
-            <TextView android:id="@+id/timeDisplay"
+            <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
+            top of the other. Hence the redundant layout... -->
+            <TextView android:id="@+id/timeDisplayBackground"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:singleLine="true"
                 android:ellipsize="none"
                 android:textSize="72sp"
                 android:textAppearance="?android:attr/textAppearanceMedium"
-                android:shadowColor="#C0000000"
-                android:shadowDx="0"
-                android:shadowDy="0"
-                android:shadowRadius="3.0"
                 android:layout_marginBottom="6dip"
+                android:textColor="@color/lockscreen_clock_background"
                 />
 
+            <TextView android:id="@+id/timeDisplayForeground"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="none"
+                android:textSize="72sp"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:layout_marginBottom="6dip"
+                android:layout_alignLeft="@id/timeDisplayBackground"
+                android:layout_alignTop="@id/timeDisplayBackground"
+                android:textColor="@color/lockscreen_clock_foreground"
+                />
+
+
 
             <TextView android:id="@+id/am_pm"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_toRightOf="@id/timeDisplay"
-                android:layout_alignBaseline="@id/timeDisplay"
+                android:layout_toRightOf="@id/timeDisplayBackground"
+                android:layout_alignBaseline="@id/timeDisplayBackground"
                 android:singleLine="true"
                 android:ellipsize="none"
                 android:textSize="22sp"
                 android:layout_marginLeft="8dip"
                 android:textAppearance="?android:attr/textAppearanceMedium"
-                android:shadowColor="#C0000000"
-                android:shadowDx="0"
-                android:shadowDy="0"
-                android:shadowRadius="3.0"
+                android:textColor="@color/lockscreen_clock_am_pm"
                 />
 
         </com.android.internal.widget.DigitalClock>
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index 8dacfaf..15f2afb 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -25,9 +25,7 @@
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:gravity="center_horizontal"
-    android:background="#70000000"
-    >
+    android:gravity="center_horizontal">
 
     <RelativeLayout
         android:layout_width="match_parent"
@@ -58,34 +56,41 @@
             android:layout_marginBottom="8dip"
             >
 
-            <TextView android:id="@+id/timeDisplay"
+            <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
+            top of the other. Hence the redundant layout... -->
+            <TextView android:id="@+id/timeDisplayBackground"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:singleLine="true"
                 android:ellipsize="none"
                 android:textSize="56sp"
                 android:textAppearance="?android:attr/textAppearanceMedium"
-                android:shadowColor="#C0000000"
-                android:shadowDx="0"
-                android:shadowDy="0"
-                android:shadowRadius="3.0"
                 android:layout_marginBottom="6dip"
+                android:textColor="@color/lockscreen_clock_background"
+                />
+
+            <TextView android:id="@+id/timeDisplayForeground"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="none"
+                android:textSize="56sp"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:layout_marginBottom="6dip"
+                android:textColor="@color/lockscreen_clock_foreground"
                 />
 
             <TextView android:id="@+id/am_pm"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_toRightOf="@id/timeDisplay"
-                android:layout_alignBaseline="@id/timeDisplay"
+                android:layout_toRightOf="@id/timeDisplayBackground"
+                android:layout_alignBaseline="@id/timeDisplayBackground"
                 android:singleLine="true"
                 android:ellipsize="none"
                 android:textSize="18sp"
                 android:layout_marginLeft="4dip"
                 android:textAppearance="?android:attr/textAppearanceMedium"
-                android:shadowColor="#C0000000"
-                android:shadowDx="0"
-                android:shadowDy="0"
-                android:shadowRadius="3.0"
+                android:textColor="@color/lockscreen_clock_am_pm"
                 />
 
         </com.android.internal.widget.DigitalClock>
@@ -120,6 +125,15 @@
         android:layout_marginLeft="12dip"
         android:gravity="left"
         >
+        <!-- TODO: Redo layout when we release on phones -->
+        <TextView
+            android:id="@+id/alarm_status"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textSize="18sp"
+            android:drawablePadding="4dip"
+            />
         <TextView
             android:id="@+id/status1"
             android:layout_width="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 2be9fab..6ff14dd 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/number_picker.xml b/core/res/res/layout/number_picker.xml
index 44c99cf..f92c1bc 100644
--- a/core/res/res/layout/number_picker.xml
+++ b/core/res/res/layout/number_picker.xml
@@ -24,7 +24,7 @@
         android:layout_height="wrap_content"
         style="?android:attr/numberPickerUpButtonStyle" />
 
-    <EditText android:id="@+id/timepicker_input"
+    <EditText android:id="@+id/numberpicker_input"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         style="?android:attr/numberPickerInputTextStyle" />
diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml
index c30c4f2..d22f74a 100644
--- a/core/res/res/layout/popup_menu_item_layout.xml
+++ b/core/res/res/layout/popup_menu_item_layout.xml
@@ -16,7 +16,10 @@
 
 <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">
     
     <!-- Icon will be inserted here. -->
     
@@ -26,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/preference_dialog.xml b/core/res/res/layout/preference_dialog.xml
deleted file mode 100644
index 9e988ad..0000000
--- a/core/res/res/layout/preference_dialog.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2006 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<!-- Layout used by DialogPreference in a PreferenceActivity. -->
-<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center"
-    android:background="@drawable/btn_circle"
-    android:src="@drawable/ic_btn_round_more" />
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index e7783da..5d034a5 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -34,7 +34,7 @@
             android:orientation="vertical"
             android:layout_width="0px"
             android:layout_height="match_parent"
-            android:layout_marginRight="0dp"
+            android:layout_marginRight="@dimen/preference_screen_side_margin_negative"
             android:layout_marginLeft="@dimen/preference_screen_side_margin"
             android:layout_marginTop="32dp"
             android:layout_marginBottom="32dp"
@@ -61,11 +61,11 @@
                 android:layout_width="0px"
                 android:layout_height="match_parent"
                 android:layout_weight="20"
-                android:layout_marginLeft="-4dp"
+                android:layout_marginLeft="@dimen/preference_screen_side_margin"
                 android:layout_marginRight="@dimen/preference_screen_side_margin"
                 android:layout_marginTop="16dp"
                 android:layout_marginBottom="16dp"
-                android:background="?attr/preferencePanelBackground"
+                android:background="?attr/detailsElementBackground"
                 android:orientation="vertical"
                 android:visibility="gone" >
 
diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml
index 4bc2d1a..ccc6326 100644
--- a/core/res/res/layout/search_bar.xml
+++ b/core/res/res/layout/search_bar.xml
@@ -25,7 +25,7 @@
     android:layout_height="wrap_content"
     android:orientation="horizontal"
     android:focusable="true"
-    android:background="?attr/actionModeBackground"
+    android:background="@drawable/cab_background_opaque_holo_light"
     android:descendantFocusability="afterDescendants">
 
     <RelativeLayout
diff --git a/core/res/res/layout/search_dropdown_item_icons_2line.xml b/core/res/res/layout/search_dropdown_item_icons_2line.xml
index fcdf91b..53906f9 100644
--- a/core/res/res/layout/search_dropdown_item_icons_2line.xml
+++ b/core/res/res/layout/search_dropdown_item_icons_2line.xml
@@ -42,8 +42,8 @@
         android:layout_alignParentRight="true"
         android:layout_alignParentTop="true"
         android:layout_alignParentBottom="true"
-        android:src="@android:drawable/edit_query"
-        android:background="@android:drawable/edit_query_background"
+        android:src="?attr/searchViewEditQuery"
+        android:background="?attr/searchViewEditQueryBackground"
         android:visibility="gone" />
 
     <ImageView android:id="@android:id/icon2"
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index 0fb824f..46d0341 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -44,7 +44,8 @@
         android:layout_width="wrap_content"
         android:layout_gravity="center_vertical"
         android:background="?android:attr/selectableItemBackground"
-        android:src="@android:drawable/ic_search"
+        android:src="?android:attr/searchViewSearchIcon"
+        style="?android:attr/actionButtonStyle"
     />
 
     <LinearLayout
@@ -79,7 +80,7 @@
                 android:layout_height="36dip"
                 android:layout_width="0dp"
                 android:layout_weight="1"
-                android:minWidth="100dp"
+                android:minWidth="@dimen/search_view_text_min_width"
                 android:layout_gravity="bottom"
                 android:paddingLeft="8dip"
                 android:paddingRight="6dip"
diff --git a/core/res/res/layout/simple_dropdown_item_1line.xml b/core/res/res/layout/simple_dropdown_item_1line.xml
index 18e7b88..3ec930c 100644
--- a/core/res/res/layout/simple_dropdown_item_1line.xml
+++ b/core/res/res/layout/simple_dropdown_item_1line.xml
@@ -20,7 +20,7 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
     android:id="@android:id/text1"
     style="?android:attr/dropDownItemStyle"
-    android:textAppearance="?android:attr/textAppearanceLargeInverse"
+    android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
     android:singleLine="true"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/listPreferredItemHeight"
diff --git a/core/res/res/layout/simple_dropdown_item_2line.xml b/core/res/res/layout/simple_dropdown_item_2line.xml
index 903adb0..d6f911a 100644
--- a/core/res/res/layout/simple_dropdown_item_2line.xml
+++ b/core/res/res/layout/simple_dropdown_item_2line.xml
@@ -37,7 +37,7 @@
         <TextView
             android:id="@android:id/text1"
             style="?android:attr/dropDownItemStyle"
-            android:textAppearance="?android:attr/textAppearanceLargeInverse"
+            android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
             android:singleLine="true"
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
@@ -45,7 +45,7 @@
         <TextView
             android:id="@android:id/text2"
             style="?android:attr/dropDownItemStyle"
-            android:textAppearance="?android:attr/textAppearanceSmallInverse"
+            android:textAppearance="?android:attr/textAppearanceSmallPopupMenu"
             android:textColor="#323232"
             android:singleLine="true"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/textview_hint.xml b/core/res/res/layout/textview_hint.xml
index 4978be5..20b08bf 100644
--- a/core/res/res/layout/textview_hint.xml
+++ b/core/res/res/layout/textview_hint.xml
@@ -18,5 +18,6 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@drawable/popup_inline_error"
-    android:textAppearance="?android:attr/textAppearanceSmallInverse"
+    android:textAppearance="?android:attr/textAppearanceSmall"
+    android:textColor="@color/primary_text_light"
 />
diff --git a/core/res/res/layout/time_picker.xml b/core/res/res/layout/time_picker.xml
index bf81c18..382b2f6 100644
--- a/core/res/res/layout/time_picker.xml
+++ b/core/res/res/layout/time_picker.xml
@@ -30,9 +30,8 @@
         android:id="@+id/hour"
         android:layout_width="48dip"
         android:layout_height="wrap_content"
-        android:layout_marginRight="13dip"
-        android:layout_marginTop="35dip"
-        android:layout_marginBottom="35dip"
+        android:layout_marginLeft="22dip"
+        android:layout_marginRight="20dip"
         android:focusable="true"
         android:focusableInTouchMode="true"
         />
@@ -50,10 +49,8 @@
         android:id="@+id/minute"
         android:layout_width="48dip"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="13dip"
-        android:layout_marginRight="15dip"
-        android:layout_marginTop="35dip"
-        android:layout_marginBottom="35dip"
+        android:layout_marginLeft="20dip"
+        android:layout_marginRight="22dip"
         android:focusable="true"
         android:focusableInTouchMode="true"
         />
@@ -63,9 +60,8 @@
         android:id="@+id/amPm"
         android:layout_width="48dip"
         android:layout_height="wrap_content"
-        android:layout_marginLeft="15dip"
-        android:layout_marginTop="35dip"
-        android:layout_marginBottom="35dip"
+        android:layout_marginLeft="22dip"
+        android:layout_marginRight="22dip"
         android:focusable="true"
         android:focusableInTouchMode="true"
         />
diff --git a/core/res/res/layout/volume_adjust.xml b/core/res/res/layout/volume_adjust.xml
index 946ca7e..18da85f 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/panel_background"
-    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/mipmap-hdpi/sym_app_on_sd_unavailable_icon.png b/core/res/res/mipmap-hdpi/sym_app_on_sd_unavailable_icon.png
new file mode 100644
index 0000000..d915d41
--- /dev/null
+++ b/core/res/res/mipmap-hdpi/sym_app_on_sd_unavailable_icon.png
Binary files differ
diff --git a/core/res/res/mipmap-hdpi/sym_def_app_icon.png b/core/res/res/mipmap-hdpi/sym_def_app_icon.png
new file mode 100644
index 0000000..075d908
--- /dev/null
+++ b/core/res/res/mipmap-hdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/mipmap-ldpi/sym_app_on_sd_unavailable_icon.png b/core/res/res/mipmap-ldpi/sym_app_on_sd_unavailable_icon.png
new file mode 100644
index 0000000..d88250a
--- /dev/null
+++ b/core/res/res/mipmap-ldpi/sym_app_on_sd_unavailable_icon.png
Binary files differ
diff --git a/core/res/res/mipmap-ldpi/sym_def_app_icon.png b/core/res/res/mipmap-ldpi/sym_def_app_icon.png
new file mode 100644
index 0000000..2c205c8
--- /dev/null
+++ b/core/res/res/mipmap-ldpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/mipmap-mdpi/sym_app_on_sd_unavailable_icon.png b/core/res/res/mipmap-mdpi/sym_app_on_sd_unavailable_icon.png
new file mode 100644
index 0000000..47306683f
--- /dev/null
+++ b/core/res/res/mipmap-mdpi/sym_app_on_sd_unavailable_icon.png
Binary files differ
diff --git a/core/res/res/mipmap-mdpi/sym_def_app_icon.png b/core/res/res/mipmap-mdpi/sym_def_app_icon.png
new file mode 100644
index 0000000..9777d11
--- /dev/null
+++ b/core/res/res/mipmap-mdpi/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 73b1286..080d66d 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"البريد الصوتي"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"حدثت مشكلة في الاتصال أو أن كود MMI غير صحيح."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"تم تقييد التشغيل لأرقام الاتصال الثابت فقط."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"تم تمكين الخدمة."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"تم تمكين الخدمة لـ:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"تم تعطيل الخدمة."</string>
@@ -126,7 +125,7 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"مزامنة"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"مزامنة"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"عمليات حذف <xliff:g id="CONTENT_TYPE">%s</xliff:g> كثيرة للغاية."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"سعة تخزين الجهاز اللوحي ممتلئة! احذف بعض الملفات لتحرير مساحة."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"وحدة تخزين الجهاز اللوحي ممتلئة! احذف بعض الملفات لتوفير مساحة."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"سعة تخزين الهاتف ممتلئة! احذف بعض الملفات لتحرير مساحة."</string>
     <string name="me" msgid="6545696007631404292">"أنا"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"خيارات الجهاز اللوحي"</string>
@@ -139,8 +138,7 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"جارٍ إيقاف التشغيل..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"سيتم إيقاف تشغيل الجهاز اللوحي."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"سيتم إيقاف تشغيل هاتفك."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"هل تريد إيقاف التشغيل؟"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"حديثة"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"ليس هناك أية تطبيقات حديثة."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"خيارات الجهاز اللوحي"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"وضع الطائرة"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"وضع الطائرة قيد التشغيل"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"وضع الطائرة متوقف"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"نظام Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"الخدمات التي تكلفك المال"</string>
@@ -160,7 +160,7 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"رسائلك"</string>
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"قراءة وكتابة الرسائل القصيرة SMS والرسائل الإلكترونية والرسائل الأخرى."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"معلوماتك الشخصية"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"للدخول المباشر إلى التقويم وجهات الاتصال المخزّنة في الجهاز اللوحي."</string>
+    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"الدخول المباشر إلى جهات اتصالك والتقويم المخزنين على الجهاز اللوحي."</string>
     <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"الدخول المباشر إلى التقويم وجهات الاتصال المخزّنة على الهاتف."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"موقعك"</string>
     <string name="permgroupdesc_location" msgid="2430258821648348660">"مراقبة موقعك الفعلي"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"أدوات التطوير"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"الميزات مطلوبة فقط لمطوّري التطبيق."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"التخزين"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"الدخول إلى بطاقة SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"الدخول إلى وحدة تخزين USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"الدخول إلى بطاقة SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"تعطيل شريط الحالة أو تعديله"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"للسماح للتطبيق بتعطيل شريط الحالة أو إضافة رموز نظام وإزالتها."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"شريط الحالة"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"للسماح للتطبيق بأن يكون شريط الحالة."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"توسيع/تصغير شريط الحالة"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"للسماح للتطبيق بتوسيع شريط الحالة أو تصغيره."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"اعتراض المكالمات الصادرة"</string>
@@ -196,10 +194,10 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"إرسال رسائل قصيرة SMS"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"للسماح للتطبيق بإرسال رسائل قصيرة SMS. قد تكلفك التطبيقات الضارة المال من خلال إرسال رسائل بدون تأكيدك."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"قراءة الرسائل القصيرة SMS أو رسائل الوسائط المتعددة"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"للسماح للتطبيق بقراءة الرسائل القصيرة SMS المخزنة على الجهاز اللوحي أو بطاقة SIM. قد تقرأ التطبيقات الضارة رسائلك السرية."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"للسماح للتطبيق بقراءة الرسائل القصيرة SMS المخزنة على الجهاز اللوحي أو بطاقة SIM. يمكن للتطبيقات الضارة قراءة رسائلك السرية."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"للسماح للتطبيق بقراءة الرسائل القصيرة SMS المخزنة على الهاتف أو بطاقة SIM. قد تقرأ التطبيقات الضارة رسائلك السرية."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"تعديل الرسائل القصيرة SMS أو رسائل الوسائط المتعددة"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"للسماح للتطبيق بالكتابة إلى الرسائل القصيرة SMS المخزّنة في الجهاز اللوحي أو بطاقة SIM. قد تحذف التطبيقات الضارة رسائلك."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"للسماح للتطبيق بالكتابة على الرسائل القصيرة SMS المخزنة على الجهاز اللوحي أو بطاقة SIM. يمكن للتطبيقات الضارة حذف رسائلك."</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"للسماح للتطبيق بالكتابة إلى الرسائل القصيرة SMS المخزنة على الهاتف أو بطاقة SIM. قد تحذف التطبيقات الضارة رسائلك."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"تلقي WAP"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"للسماح للتطبيق بتلقي رسائل WAP ومعالجتها. قد تراقب بعض التطبيقات الضارة رسائلك أو تحذفها بدون عرضها لك."</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"منع التبديل بين التطبيقات"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"منع المستخدم من التبديل إلى تطبيق آخر."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"مراقبة بدء تشغيل جميع التطبيقات والتحكم فيها"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"للسماح لأحد التطبيقات بمراقبة كيفية بدء النظام للأنشطة والتحكم فيها. قد تُعرِّض التطبيقات الضارة النظام للضرر بشكل كامل. لن تكون هناك حاجة لهذا الإذن سوى للتطوير فقط، وليس للاستخدام العادي على الإطلاق."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"للسماح لتطبيق ما بمراقبة كيفية تشغيل النظام للأنشطة والتحكم بها. ربما تهدد التطبيقات الضارة النظام. ويكون هذا الإذن ضروريًا فقط للتطوير، وليس للاستخدام العادي مطلقًا."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"إرسال بث الحزمة الذي تمت إزالته"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"للسماح لتطبيق ما ببث تنبيه يفيد بإزالة حزمة تطبيق ما. قد تستخدم التطبيقات الضارة هذا لإنهاء أية تطبيقات أخرى قيد التشغيل."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"إرسال بث SMS مستلم"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"عرض النوافذ غير المصرح بها"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"للسماح بإنشاء نوافذ بقصد استخدامها بواسطة واجهة مستخدم النظام الداخلي. ليس للاستخدام بواسطة التطبيقات العادية."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"عرض تنبيهات مستوى النظام"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"للسماح لأحد التطبيقات بعرض نوافذ تنبيه النظام. يمكن أن تستحوذ التطبيقات الضارة على الشاشة بالكامل."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"للسماح للتطبيق بإظهار نوافذ تنبيه النظام. يمكن أن تتحكم التطبيقات الضارة في الشاشة بأكملها."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"تعديل سرعة الرسوم المتحركة العمومية"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"للسماح لتطبيق ما بتغيير سرعة الرسوم المتحركة العمومية (رسوم متحركة أسرع أو أبطأ) في أي وقت."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"إدارة رموز التطبيق"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"للسماح للتطبيقات بإنشاء وإدارة رموزها الخاصة، وتجاوز ترتيب Z العادي. لا يجب استخدامه على الإطلاق للتطبيقات العادية."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"مفاتيح الضغط وأزرار التحكم"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"للسماح لأحد التطبيقات بتسليم أحداث الإرسال الخاصة به (ضغطات المفاتيح وغير ذلك) إلى تطبيقات أخرى. يمكن أن تستخدم التطبيقات الضارة ذلك للاستحواذ على الجهاز اللوحي."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"للسماح للتطبيق بتوصيل أحداث إدخالاته الخاصة (ضغطات المفاتيح، وما إلى ذلك) للتطبيقات الأخرى. يمكن أن تستخدم التطبيقات الضارة ذلك للتحكم في الجهاز اللوحي."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"للسماح لتطبيق ما بتسليم أحداث الإرسال الخاصة به (ضغطات المفاتيح وغير ذلك) إلى تطبيقات أخرى. يمكن أن تستخدم التطبيقات الضارة ذلك للاستحواذ على الهاتف."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"تسجيل ما تكتبه والإجراءات التي تتخذها"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"للسماح للتطبيقات بمراقبة الأحرف التي تضغط عليها حتى عند التفاعل مع تطبيق آخر (مثل إدخال كلمة مرور). لا يجب استخدامه على الإطلاق للتطبيقات العادية."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"تثبيت التطبيقات مباشرة"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"للسماح لتطبيق ما بتثبيت حزم Android الجديدة أو المحدّثة. يمكن أن تستخدم التطبيقات الضارة ذلك لإضافة تطبيقات جديدة ذات أذونات قوية على نحو عشوائي."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"حذف جميع بيانات ذاكرة التخزين المؤقت للتطبيق"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"للسماح لأحد التطبيقات بتفريغ سعة تخزين الجهاز اللوحي من خلال حذف بعض الملفات من دليل ذاكرة التخزين المؤقت للتطبيق. ويكون الدخول في العادة مقيّدًا بشدة لمعالجة النظام."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"للسماح لتطبيق ما بإفراغ وحدة تخزين الجهاز اللوحي من خلال حذف بعض الملفات في دليل ذاكرة التخزين المؤقت للتطبيق. وعادةً يكون الدخول مقيدًا جدًا لتشغيل النظام."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"للسماح لتطبيق ما بتفريغ سعة تخزين الهاتف من خلال حذف بعض الملفات من دليل ذاكرة التخزين المؤقت للتطبيق. ويكون الدخول في العادة مقيّدًا بشدة لمعالجة النظام."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"نقل موارد التطبيق"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"للسماح لتطبيق ما بنقل موارد التطبيق من الوسائط الداخلية إلى الوسائط الخارجية والعكس."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"قراءة ملفات سجل النظام"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"للسماح لأحد التطبيقات بالقراءة من ملفات السجل المختلفة بالنظام. يسمح هذا باكتشاف معلومات عامة حول ما تجريه في الجهاز اللوحي، ومن المحتمل أن تحتوي على معلومات شخصية أو خاصة."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"للسماح لأحد التطبيقات بالقراءة من ملفات السجل المختلفة بالنظام. يسمح هذا باكتشاف معلومات عامة حول ما تجريه في الجهاز اللوحي، ومن المحتمل أن تحتوي على معلومات شخصية أو خاصة."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"قراءة بيانات السجل الحساسة"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"للسماح لتطبيق ما بالقراءة من ملفات سجلات النظام المتنوعة. ويسمح ذلك للتطبيق باكتشاف المعلومات العامة حول ما تفعله بالجهاز اللوحي، ومن المحتمل أن يتضمن معلومات شخصية أو خاصة."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"للسماح لتطبيق ما بالقراءة من ملفات سجلات النظام المتنوعة. ويسمح ذلك للتطبيق باكتشاف المعلومات العامة حول ما تفعله بالهاتف، ومن المحتمل أن يتضمن معلومات شخصية أو خاصة."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"قراءة/كتابة إلى الموارد المملوكة بواسطة التشخيص"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"للسماح لتطبيق ما بالقراءة والكتابة إلى أي مورد مملوك بواسطة مجموعة التشخيصات؛ على سبيل المثال، الملفات في /dev. من المحتمل أن يؤثر ذلك في استقرار النظام وأمانه. يجب ألا يستخدم ذلك سوى للتشخيصات الخاصة بالنظام من قِبل المصنِّع أو المشغِّل."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"تمكين مكونات التطبيق أو تعطيلها"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"للسماح لأحد التطبيقات بتغير ما إذ كان مكون تطبيق آخر ممكّنًا أم لا. يمكن أن تستخدم التطبيقات الضارة ذلك لتعطيل قدرات الجهاز اللوحي المهمة. يجب توخي الحذر عند استخدام هذا الإذن، إذ يحتمل أن يحول مكونات التطبيق إلى حالة غير قابلة للاستخدام أو غير متسقة أو غير مستقرة."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"للسماح لأحد التطبيقات بتغير ما إذ كان مكون تطبيق آخر ممكّنًا أم لا. يمكن أن تستخدم التطبيقات الضارة ذلك لتعطيل قدرات الجهاز اللوحي المهمة. يجب توخي الحذر عند استخدام هذا الإذن، إذ يحتمل أن يحول مكونات التطبيق إلى حالة غير قابلة للاستخدام أو غير متسقة أو غير مستقرة."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"للسماح لتطبيق ما بتغيير ما إذا كان سيتم تمكين مكون لتطبيق آخر أم لا. يمكن أن تستخدم التطبيقات الضارة ذلك لتعطيل قدرات الجهاز اللوحي المهمة. يجب توخي الحذر عند استخدام هذا الإذن، وذلك لأنه من الممكن أن يؤدي ذلك إلى جعل حالة مكونات التطبيق غير قابلة للاستخدام أو غير متناسقة أو غير مستقرة."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"للسماح لتطبيق ما بتغيير ما إذا كان سيتم تمكين مكون لتطبيق آخر أم لا. يمكن أن تستخدم التطبيقات الضارة ذلك لتعطيل قدرات الهاتف المهمة. يجب توخي الحذر عند استخدام هذا الإذن، وذلك لأنه من الممكن أن يؤدي ذلك إلى جعل حالة مكونات التطبيق غير قابلة للاستخدام أو غير متناسقة أو غير مستقرة."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"تعيين التطبيقات المفضلة"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"للسماح لتطبيق ما بتعديل التطبيقات المفضلة. يمكن أن يسمح ذلك للتطبيقات الضارة بتغيير التطبيقات قيد التشغيل بشكل غير ملحوظ، وانتحال صفة تطبيقاتك الحالية لجمع بيانات خاصة منك."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"تعديل إعدادات النظام العمومية"</string>
@@ -298,19 +296,19 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"تعديل خريطة خدمات Google"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"للسماح لتطبيق ما بتعديل خريطة خدمات Google. ليس للاستخدام بواسطة التطبيقات العادية."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"البدء تلقائيًا عند التشغيل"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"للسماح لأحد التطبيقات ببدء تشغيل نفسه عقب انتهاء النظام من التشغيل. قد يؤدي ذلك إلى استغراق مزيد من الوقت عند بدء الجهاز اللوحي والسماح للتطبيق بإبطاء الأداء الإجمالي للجهاز اللوحي من خلال تشغيله دومًا."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"للسماح للتطبيق ببدء ذاته فور انتهاء النظام من التمهيد. ويمكن أن يؤدي ذلك إلى إطالة فترة بدء الجهاز اللوحي والسماح للتطبيق بإبطاء الجهاز اللوحي بالكامل من خلال التشغيل بصفة مستمرة."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"للسماح لتطبيق ما ببدء تشغيل نفسه عقب انتهاء النظام من التشغيل. قد يؤدي ذلك إلى استغراق مزيد من الوقت عن بدء الهاتف والسماح للتطبيق بإبطاء الأداء الإجمالي للهاتف حيث يتم تشغيله دومًا."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"إرسال بث طويل الزيارة"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"للسماح لأحد التطبيقات بإرسال بث طويل الزيارة، والذي يظل بعد انتهاء البث. قد تجعل التطبيقات الضارة الجهاز اللوحي بطيئًا أو غير مستقر من خلال التسبب في استخدامه لمساحة كبيرة للغاية من الذاكرة."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"للسماح للتطبيق بإرسال عمليات بث طويلة الزيارة، والتي تبقى بعد انتهاء البث. يمكن أن تبطئ التطبيقات الضارة الجهاز اللوحي أو تجعله غير مستقر عبر جعله يستخدم ذاكرة كبيرة جدًا."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"للسماح لتطبيق ما بإرسال بث طويل الزيارة، والذي يظل بعد انتهاء البث. قد تجعل التطبيقات الضارة الهاتف بطيئًا أو غير مستقر من خلال التسبب في استخدام مساحة كبيرة للغاية من الذاكرة."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"قراءة بيانات جهة الاتصال"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"للسماح لأحد التطبيقات بقراءة جميع بيانات (عنوان) جهات الاتصال المخزّنة في الجهاز اللوحي. يمكن أن تستخدم التطبيقات الضارة هذا لإرسال بياناتك إلى أشخاص آخرين."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"للسماح لتطبيق ما بقراءة كل بيانات جهة الاتصال (العنوان) المخزنة على الجهاز اللوحي. ويمكن للتطبيقات الضارة استخدام ذلك لإرسال بياناتك إلى أشخاص آخرين."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"للسماح لتطبيق ما بقراءة جميع بيانات (عنوان) جهات الاتصال المخزّنة في هاتفك. يمكن أن تستخدم التطبيقات الضارة هذا لإرسال بياناتك إلى أشخاص آخرين."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"كتابة بيانات جهة الاتصال"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"للسماح لأحد التطبيقات بتعديل بيانات (عنوان) جهة الاتصال المخزّنة في الجهاز اللوحي. يمكن أن تستخدم التطبيقات الضارة ذلك لمسح بيانات جهة الاتصال أو تعديلها."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"للسماح للتطبيق بتعديل بيانات جهة الاتصال (العنوان) المخزنة على الجهاز اللوحي. يمكن أن تستخدم التطبيقات الضارة ذلك لمحو بيانات جهة الاتصال أو تعديلها."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"للسماح لتطبيق ما بتعديل بيانات (عنوان) جهة الاتصال المخزّنة في هاتفك. يمكن أن تستخدم التطبيقات الضارة ذلك لمسح بيانات جهة الاتصال أو تعديلها."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"قراءة أحداث التقويم"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"للسماح لأحد التطبيقات بقراءة جميع أحداث التقويم المخزّنة في الجهاز اللوحي. يمكن أن تستخدم التطبيقات الضارة هذا لإرسال أحداث تقويمك إلى أشخاص آخرين."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"للسماح لتطبيق ما بقراءة كل أحداث التقويم المخزنة على الجهاز اللوحي. ويمكن للتطبيقات الضارة استخدام ذلك لإرسال أحداث التقويم إلى أشخاص آخرين."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"للسماح لتطبيق ما بقراءة جميع أحداث التقويم المخزّنة في هاتفك. يمكن أن تستخدم التطبيقات الضارة هذا لإرسال أحداث تقويمك إلى أشخاص آخرين."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"إضافة أحداث تقويم أو تعديلها وإرسال رسالة إلكترونية إلى الضيوف"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"للسماح لتطبيق ما بإضافة أحداث أو تغييرها في تقويمك، مما قد يؤدي إلى إرسال رسائل إلكترونية إلى الضيوف. يمكن أن تستخدم التطبيقات الضارة ذلك لمسح أحداث تقويمك أو تعديلها أو لإرسال رسائل إلكترونية إلى الضيوف."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"إذن لتثبيت موفر خدمة موقع"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"إنشاء مصادر مواقع وهمية للاختبار. قد تستخدم التطبيقات الضارة هذا لتجاوز الموقع و/أو الحالة المُرجَعة بواسطة مصادر مواقع حقيقية مثل موفري خدمة الشبكة أو GPS أو مراقبة وإعداد تقارير حول موقعك إلى مصدر خارجي."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"موقع (GPS) جيد"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"للدخول إلى مصادر المواقع الجيدة، مثل نظام تحديد المواقع العالمي على الجهاز اللوحي، حيث يتوفر ذلك. يمكن أن تستخدم التطبيقات الضارة ذلك لتحديد مكانك، وقد تستهلك المزيد من طاقة البطارية."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"الدخول إلى مصادر المواقع الجيدة مثل نظام تحديد المواقع العالمي على الجهاز اللوحي، حيث يتوفر ذلك. يمكن أن تستخدم التطبيقات الضارة ذلك لتحديد مكانك، وقد تستهلك المزيد من طاقة البطارية."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"الدخول إلى مصادر المواقع الجيدة مثل نظام تحديد المواقع العالمي على الهاتف، حيث يتوفر ذلك. يمكن أن تستخدم التطبيقات الضارة ذلك لتحديد مكانك، وقد تستهلك المزيد من طاقة البطارية."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"موقع تقريبي (مستند إلى الشبكة)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"للدخول إلى مصادر المواقع التقريبية، مثل قاعدة بيانات شبكة الهاتف الخلوي لتحديد موقع تقريبي للجهاز اللوحي، حيث يتوفر ذلك. يمكن أن تستخدم التطبيقات الضارة ذلك لتحديد مكانك بالتقريب."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"الدخول إلى مصادر المواقع التقريبية مثل قاعدة بيانات شبكة الهاتف الخلوي لتحديد موقع تقريبي للجهاز اللوحي، حيث يتوفر ذلك. يمكن أن تستخدم التطبيقات الضارة ذلك لتحديد مكانك بالتقريب."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"الدخول إلى مصادر المواقع التقريبية مثل قاعدة بيانات شبكة الهاتف الخلوي لتحديد موقع تقريبي للهاتف، حيث يتوفر ذلك. يمكن أن تستخدم التطبيقات الضارة ذلك لتحديد مكانك بالتقريب."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"الدخول إلى SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"للسماح للتطبيق باستخدام ميزات SurfaceFlinger ذات المستوى المنخفض."</string>
@@ -334,11 +332,11 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"للسماح للتطبيق بتعديل الإعدادات الصوتية العمومية مثل مستوى الصوت والتوجيه."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"تسجيل الصوت"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"للسماح للتطبيق بالدخول إلى مسار تسجيل الصوت."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"التقاط صور"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"للسماح للتطبيق بالتقاط صور بالكاميرا. يتيح ذلك للتطبيق جمع الصور التي تعرضها الكاميرا في أي وقت."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"تعطيل الجهاز اللوحي بشكل دائم"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"التقاط صور ومقاطع فيديو"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"للسماح للتطبيق بالتقاط صور ومقاطع فيديو باستخدام الكاميرا. يسمح ذلك للتطبيق بتجميع الصور التي تعرضها الكاميرا في أي وقت."</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"تعطيل الجهاز اللوحي نهائيًا"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"تعطيل الهاتف على الدوام"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"للسماح للتطبيق بتعطيل الجهاز اللوحي بالكامل بشكل دائم. هذا خطير للغاية."</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"للسماح للتطبيق بتعطيل الجهاز اللوحي بأكمله نهائيًا. هذا خطير جدًا."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"للسماح للتطبيق بتعطيل الهاتف بالكامل على الدوام. هذا خطير للغاية."</string>
     <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"فرض إعادة تشغيل الجهاز اللوحي"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"فرض إعادة تشغيل الهاتف"</string>
@@ -348,23 +346,25 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"للسماح للتطبيق بتحميل أنظمة الملفات وإلغاء تحميلها لسعة التخزين القابلة للإزالة."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"تنسيق سعة التخزين الخارجية"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"للسماح للتطبيق بتنسيق سعة التخزين القابلة للإزالة."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"الحصول على معلومات حول سعة التخزين الآمنة"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"للسماح للتطبيق بالحصول على معلومات حول سعة التخزين الآمنة."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"إنشاء سعة تخزين آمنة"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"للسماح للتطبيق بإنشاء سعة تخزين آمنة."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"مسح سعة التخزين الآمنة"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"للسماح للتطبيق بمسح سعة التخزين الآمنة."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"تحميل/إلغاء تحميل سعة التخزين الآمنة"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"للسماح للتطبيق بتحميل / إلغاء تحميل سعة تخزين آمنة."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"إعادة تسمية سعة التخزين الآمنة"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"للسماح للتطبيق بإعادة تسمية سعة التخزين الآمنة."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"الحصول على معلومات حول وحدة التخزين الداخلية"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"للسماح للتطبيقات بالحصول على معلومات حول وحدة التخزين الداخلية."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"إنشاء وحدة تخزين داخلية"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"للسماح لتطبيق ما بإنشاء وحدة تخزين داخلية."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"مسح وحدة التخزين الداخلية"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"للسماح لتطبيق ما بمسح وحدة التخزين الداخلية."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"تركيب / إلغاء تركيب وحدة التخزين الداخلية"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"للسماح لتطبيق ما بتركيب/إلغاء تركيب وحدة التخزين الداخلية."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"إعادة تسمية وحدة التخزين الداخلية"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"للسماح لتطبيق ما بإعادة تسمية وحدة التخزين الداخلية."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"التحكم بالهزاز"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"للسماح للتطبيق بالتحكم في الهزاز."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"التحكم في الضوء الوامض"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"للسماح للتطبيق بالتحكم في الضوء الوامض."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"الدخول إلى أجهزة USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"للسماح للتطبيق بالدخول إلى أجهزة USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"اختبار الأجهزة"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"للسماح للتطبيق بالتحكم في الأجهزة الطرفية المتنوعة بغرض اختبار الأجهزة."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"للسماح للتطبيق بالاتصال بأرقام الهواتف بدون تدخل منك. قد تسبب التطبيقات في وجود اتصالات غير متوقعة في فاتورة الهاتف. لاحظ أن هذا لا يسمح للتطبيق بالاتصال بأرقام الطوارئ."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"اتصال مباشر بأي رقم من أرقام الهواتف"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"للسماح للتطبيق بالاتصال بأي رقم هاتف، بما في ذلك أرقام الطوارئ، بدون تدخل منك. قد تجري التطبيقات الضارة اتصالات غير ضرورية وغير قانونية بخدمات الطوارئ."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"بدء إعداد جهاز CDMA لوحي مباشرة"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"بدء إعداد الجهاز اللوحي CDMA مباشرةً"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"بدء إعداد هاتف CDMA مباشرة"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"للسماح للتطبيق ببدء توفير CDMA. قد تبدأ التطبيقات الضارة توفير CDMA بدون الحاجة إلى ذلك."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"التحكم في تنبيهات تحديث الموقع"</string>
@@ -387,14 +387,14 @@
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"للسماح للتطبيق بالدخول إلى ميزات الهاتف للجهاز. يمكن أن يحدد تطبيق، بهذا الإذن، رقم الهاتف والرقم التسلسلي لهذا الهاتف وما إذا كانت هناك مكالمة نشطة والرقم الذي يجري الاتصال به وما إلى ذلك."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"منع الجهاز اللوحي من الدخول في وضع السكون"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"منع الهاتف من الدخول في وضع السكون"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"للسماح لأحد التطبيقات بمنع الجهاز اللوحي من الانتقال إلى وضع السكون."</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"للسماح لتطبيق ما بمنع الجهاز اللوحي من الانتقال إلى وضع السكون."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"للسماح لتطبيق ما بمنع الهاتف من الانتقال إلى وضع السكون."</string>
     <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"تشغيل الجهاز اللوحي أو إيقاف تشغيله"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"تشغيل الهاتف أو إيقاف تشغيله"</string>
     <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"للسماح للتطبيق بتشغيل الجهاز اللوحي أو إيقاف تشغيله."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"للسماح للتطبيق بتشغيل الهاتف أو إيقاف تشغيله."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"تشغيل في وضع اختبار المصنع"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"للتشغيل كاختبار مصنِّع بمستوى أدنى، مما يسمح بالدخول الكامل إلى جهاز الجهاز اللوحي. لا يتوفر سوى عند تشغيل الجهاز اللوحي في وضع اختبار المصنِّع."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"التشغيل كاختبار للشركة المصنعة من المستوى المنخفض، مما يسمح بإكمال الدخول إلى الجهاز اللوحي. ويتوفر فقط عندما يتم تشغيل الجهاز اللوحي في وضع اختبار المصنِّع."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"للتشغيل كاختبار مصنِّع بمستوى أدنى، مما يسمح بالدخول الكامل إلى جهاز الهاتف. لا يتوفر سوى عند تشغيل الهاتف في وضع اختبار المصنِّع."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"تعيين الخلفية"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"للسماح للتطبيق بتعيين خلفية النظام."</string>
@@ -403,15 +403,15 @@
     <string name="permlab_masterClear" msgid="2315750423139697397">"إعادة تعيين النظام إلى الإعدادات الافتراضية للمصنع"</string>
     <string name="permdesc_masterClear" msgid="5033465107545174514">"للسماح لتطبيق ما بإعادة تعيين النظام بالكامل على إعدادات المصنع، ومسح جميع البيانات والتهيئة والتطبيقات المثبتة."</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"تعيين الوقت"</string>
-    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"للسماح لأحد التطبيقات بتغيير وقت ساعة الجهاز اللوحي."</string>
+    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"للسماح لتطبيق ما بتغيير وقت ساعة الجهاز اللوحي."</string>
     <string name="permdesc_setTime" product="default" msgid="667294309287080045">"للسماح لتطبيق ما بتغيير وقت ساعة الهاتف."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"تعيين المنطقة الزمنية"</string>
-    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"للسماح لأحد التطبيقات بتغيير المنطقة الزمنية للجهاز اللوحي."</string>
+    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"للسماح لتطبيق ما بتغيير المنطقة الزمنية للجهاز اللوحي."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"للسماح لتطبيق ما بتغيير المنطقة الزمنية للهاتف."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"العمل كخدمة مدير حساب"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"للسماح لتطبيق ما بإجراء مكالمات إلى مصدِّقي الحساب"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"اكتشاف الحسابات المعروفة"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"للسماح لأحد التطبيقات بالحصول على قائمة بالحسابات المعروفة بواسطة الجهاز اللوحي."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"للسماح لتطبيق ما بالحصول على قائمة بالحسابات المعروفة بواسطة الجهاز اللوحي."</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"للسماح لتطبيق ما بالحصول على قائمة الحسابات المعروفة بواسطة الهاتف."</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"العمل كمصدِّق للحساب"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"للسماح لتطبيق ما باستخدام إمكانيات مصدِّق الحساب لـ AccountManager، بما في ذلك إنشاء حسابات والحصول على كلمات مرورها وتعينها."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"السماح باستقبال بث Wi-Fi متعدد"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"للسماح لتطبيق ما باستلام حزم غير موجهة مباشرة إلى جهازك. يمكن أن يكون ذلك مفيدًا عند اكتشاف خدمات معروضة بالقرب منك. يستخدم ذلك الطاقة أكثر من وضع البث غير المتعدد."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"إدارة البلوتوث"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"للسماح لأحد التطبيقات بتهيئة جهاز البلوتوث اللوحي المحلي، واكتشاف الأجهزة البعيدة والاقتران بها."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"للسماح لتطبيق ما بتهيئة لوحة البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران بها."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"للسماح لتطبيق ما بتهيئة هاتف البلوتوث المحلي، واكتشاف أجهزة التحكم عن بعد والاقتران معها."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"إنشاء اتصالات بلوتوث"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"للسماح لأحد التطبيقات بعرض تهيئة جهاز البلوتوث اللوحي المحلي، وإجراء اتصالات مع أجهزة مقترنة وقبولها."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"للسماح للتطبيق بعرض مكونات لوحة البلوتوث المحلي، وإجراء الاتصالات وقبولها مع الأجهزة المقترنة."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"للسماح لتطبيق ما بعرض تهيئة هاتف البلوتوث المحلي، وإجراء اتصالات وقبولها باستخدام الأجهزة المقترنة."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"التحكم في اتصال الحقل القريب"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"للسماح لتطبيق ما بالاتصال بعلامات اتصال حقل قريب (NFC)، والبطاقات وبرامج القراءة."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"تعطيل تأمين المفاتيح"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"للسماح لتطبيق ما بتعطيل تأمين المفاتيح وأي أمان كلمة مرور مرتبطة. ومثال صحيح لذلك هو تعطيل الهاتف لتأمين المفاتيح عند استلام مكالمة هاتفية واردة، ثم إعادة تمكين تأمين المفاتيح عند انتهاء المكالمة."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"قراءة إعدادات المزامنة"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"للسماح لتطبيق ما بقراءة أي كلمات وأسماء وعبارات خاصة ربما خزنها المستخدم في قاموس المستخدم."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"كتابة إلى القاموس المعرّف بواسطة المستخدم"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"للسماح لتطبيق ما بكتابة كلمات جديدة إلى قاموس المستخدم."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"تعديل/حذف محتويات بطاقة SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"تعديل/حذف محتويات وحدة تخزين USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"تعديل/حذف محتويات بطاقة SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"للسماح لتطبيق ما بالكتابة إلى بطاقة SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"للسماح لتطبيق ما بالكتابة على وحدة تخزين USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"للسماح لتطبيق ما بالكتابة إلى بطاقة SD."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"تعديل/حذف محتويات وحدة تخزين الوسائط الداخلية"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"للسماح لتطبيق ما بتعديل محتويات وحدة تخزين الوسائط الداخلية."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"الدخول إلى نظام ملفات ذاكرة التخزين المؤقت"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"للسماح لتطبيق ما بقراءة نظام ملفات ذاكرة التخزين المؤقت والكتابة به."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"تحديد كلمة المرور"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"لتقييد أنواع كلمات المرور المسموح لك باستخدامها."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"ملاحظة محاولات تسجيل الدخول"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"لمراقبة عدد مرات إدخال كلمات المرور غير الصحيحة عند إلغاء تأمين الشاشة وتأمين الجهاز اللوحي أو مسح جميع بياناته في حالة إدخال الكثير من كلمات المرور غير الصحيحة"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"لمراقبة عدد مرات إدخال كلمات المرور غير الصحيحة عند إلغاء تأمين الشاشة وتأمين الجهاز اللوحي أو مسح جميع بياناته في حالة إدخال الكثير من كلمات المرور غير الصحيحة"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"إعادة تعيين كلمة المرور"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"فرض كلمة مرورك إلى قيمة جديدة، مما يتطلب منحك المشرف إياها قبل أن تتمكن من تسجيل الدخول."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"فرض التأمين"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"التحكم أثناء تأمين الجهاز، يتطلب إعادة إدخال كلمة المرور."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"إجراء/تلقي مكالمات عبر الإنترنت"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"للسماح لتطبيق ما باستخدام خدمة SIP لإجراء/تلقي مكالمات عبر الإنترنت."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"تعيين قواعد كلمة المرور"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"التحكم في الطول والأحرف المسموح بها في كلمات مرور إلغاء قفل الشاشة"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"مراقبة محاولات إلغاء قفل الشاشة"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"مراقبة عدد كلمات المرور غير الصحيحة التي تم إدخالها عند إلغاء قفل الشاشة، وقفل الجهاز اللوحي ومحو كل بيانات الجهاز إذا تم إدخال عدد أكبر من اللازم من كلمات المرور غير الصحيحة"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"مراقبة عدد كلمات المرور غير الصحيحة التي تم إدخالها عند إلغاء قفل الشاشة، وقفل الهاتف ومحو كل بيانات الهاتف إذا تم إدخال عدد أكبر من اللازم من كلمات المرور غير الصحيحة"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"تغيير كلمة مرور إلغاء قفل الشاشة"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"تغيير كلمة مرور إلغاء قفل الشاشة"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"تأمين الشاشة"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"التحكم في كيفية ووقت قفل الشاشة"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"مسح جميع البيانات"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"لمسح بيانات الجهاز اللوحي بدون تحذير، من خلال إجراء إعادة الضبط بحسب بيانات المصنع"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"لمسح بيانات الجهاز اللوحي بدون تحذير، من خلال إجراء إعادة الضبط بحسب بيانات المصنع"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"محو بيانات الجهاز اللوحي بدون تحذير، وذلك عبر إجراء إعادة الضبط بحسب بيانات المصنع"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"محو بيانات الهاتف بدون تحذير، وذلك عبر إجراء إعادة الضبط بحسب بيانات المصنع"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"تعيين الخادم الوكيل العمومي للجهاز"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"تعيين الخادم الوكيل العمومي للجهاز لكي يتم استخدامه أثناء تمكين السياسة. يعين مشرف الجهاز الأول فقط الخادم الوكيل العمومي الفعال."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"تعيين انتهاء صلاحية كلمة المرور"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"التحكم في الوقت المستغرق قبل الحاجة إلى تغيير كلمة مرور شاشة التوقف"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"الرئيسية"</item>
     <item msgid="869923650527136615">"الجوال"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"جهاز نداء العمل"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"مساعد"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"رسالة وسائط متعددة"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"مخصص"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"عيد ميلاد"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"الذكرى السنوية"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"حدث"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"غير ذلك"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"مخصص"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"الرئيسية"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"عمل"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"عمل"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"آخر"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"مخصص"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"مخصص"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"مساعد"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"أخ"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"طفل"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"الزوج/الزوجة"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"أب"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"صديق"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"مدير"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"أم"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"الأبوان"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"شريك"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"جهة الإحالة"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"قريب"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"أخت"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"زوج/زوجة"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"مخصص"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"المنزل"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"العمل"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"غير ذلك"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"أدخل رقم التعريف الشخصي"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"أدخل كلمة المرور لإلغاء التأمين"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"أدخل رقم التعريف الشخصي (PIN) لإلغاء القفل"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"كود PIN غير صحيح!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"لإلغاء التأمين، اضغط على \"القائمة\" ثم على 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"رقم الطوارئ"</string>
@@ -646,14 +615,13 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"العودة إلى الاتصال"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"صحيح!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"عذرًا، حاول مرة أخرى"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"عذرًا، أعد المحاولة"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"شحن (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"تم الشحن."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"توصيل جهاز الشحن."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"ليس هناك بطاقة SIM."</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ليست هناك بطاقة SIM في الجهاز اللوحي."</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ليس هناك بطاقة SIM في الجهاز اللوحي."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ليس هناك بطاقة SIM في الهاتف."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"الرجاء إدخال بطاقة SIM."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"مكالمات الطوارئ فقط"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"بطاقة SIM مؤمّنة."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"جارٍ إلغاء تأمين بطاقة SIM…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"لقد رسمت نقش إلغاء التأمين بطريقة غير صحيحة <xliff:g id="NUMBER_0">%d</xliff:g> مرة. "\n\n"الرجاء إعادة المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"لقد رسمت نقش إلغاء التأمين بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الجهاز اللوحي باستخدام معلومات تسجيل الدخول إلى Google.‏"\n\n" الرجاء المحاولة مرة أخرى في غضون <xliff:g id="NUMBER_2">%d</xliff:g> ثانية."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"لقد أدخلت كلمة المرور بشكل غير صحيح عدد <xliff:g id="NUMBER_0">%d</xliff:g> من المرات. "\n\n"الرجاء إعادة المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"لقد أدخلت رقم التعريف الشخصي (PIN) بشكل غير صحيح عدد <xliff:g id="NUMBER_0">%d</xliff:g> من المرات. "\n\n"الرجاء إعادة المحاولة خلال <xliff:g id="NUMBER_1">%d</xliff:g> ثانية."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"لقد رسمت نقش إلغاء التأمين بصورة خاطئة عدد <xliff:g id="NUMBER_0">%d</xliff:g> من المرات. بعد إجراء <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات الأخرى غير الناجحة، ستتم مطالبتك بإلغاء تأمين الجهاز اللوحي باستخدام معلومات تسجيل الدخول إلى Google."\n\n" الرجاء إعادة المحاولة خلال <xliff:g id="NUMBER_2">%d</xliff:g> ثانية."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"لقد رسمت نقش إلغاء التأمين بشكل غير صحيح <xliff:g id="NUMBER_0">%d</xliff:g> مرة. بعد <xliff:g id="NUMBER_1">%d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الهاتف باستخدام معلومات تسجيل الدخول إلى Google."\n\n" الرجاء المحاولة مرة أخرى خلال <xliff:g id="NUMBER_2">%d</xliff:g> ثانية."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"حاول مرة أخرى خلال <xliff:g id="NUMBER">%d</xliff:g> ثانية."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"هل نسيت النمط؟"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"هل تريد الانتقال بعيدًا عن هذه الصفحة؟"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"حدد \"موافق\" للمتابعة، أو \"إلغاء\" للبقاء في الصفحة الحالية."</string>
     <string name="save_password_label" msgid="6860261758665825069">"تأكيد"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"نصيحة: اضغط مرتين للتكبير والتصغير."</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"الملء التلقائي"</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"ملء تلقائي"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"إعداد ملء تلقائي"</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">"، "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"قراءة سجل المتصفح والإشارات"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"للسماح للتطبيق بقراءة جميع عناوين URL التي انتقل إليها المتصفح. وجميع إشارات المتصفح."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"كتابة سجل المتصفح والإشارات"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"للسماح لأحد التطبيقات بتعديل سجل المتصفح أو الإشارات المرجعية المخزّنة في الجهاز اللوحي. يمكن أن تستخدم التطبيقات الضارة ذلك لمسح بيانات المتصفح أو تعديلها."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"للسماح لتطبيق ما بتعديل سجل المتصفح أو الإشارات المخزنة على الجهاز اللوحي. يمكن للتطبيقات الضارة استخدام هذا لمحو بيانات المتصفح أو تعديلها."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"للسماح لتطبيق ما بتعديل سجل المتصفح أو الإشارات في هاتفك. يمكن أن تستخدم التطبيقات الضارة ذلك لمسح بيانات المتصفح أو تعديلها."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"تعيين المنبه في ساعة المنبه"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"للسماح للتطبيق بضبط المنبه في تطبيق ساعة منبه مثبّت. ربما لا تنفذ بعض تطبيقات المنبه هذه الميزة."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"تعديل أذونات الموقع الجغرافي للمتصفح"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"للسماح لتطبيق ما بتعديل أذونات الموقع الجغرافي للمتصفح. يمكن أن تستخدم التطبيقات الضارة هذا للسماح بإرسال معلومات الموقع إلى مواقع ويب عشوائية."</string>
     <string name="save_password_message" msgid="767344687139195790">"هل تريد من المتصفح تذكر كلمة المرور هذه؟"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"قص"</string>
     <string name="copy" msgid="2681946229533511987">"نسخ"</string>
     <string name="paste" msgid="5629880836805036433">"لصق"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"ليس هناك شيء للصقه"</string>
     <string name="copyUrl" msgid="2538211579596067402">"نسخ عنوان URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"تحديد نص..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"تحديد النص"</string>
     <string name="inputMethod" msgid="1653630062304567879">"طريقة الإرسال"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"تعديل النص"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"إجراءات النص"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"المساحة منخفضة"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"مساحة تخزين الجهاز اللوحي منخفضة."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"انخفضت مساحة تخزين الجهاز اللوحي."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"مساحة تخزين الهاتف منخفضة."</string>
     <string name="ok" msgid="5970060430562524910">"موافق"</string>
     <string name="cancel" msgid="6442560571259935130">"إلغاء"</string>
     <string name="yes" msgid="5362982303337969312">"موافق"</string>
     <string name="no" msgid="5141531044935541497">"إلغاء"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"تنبيه"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"جارٍ التحميل..."</string>
     <string name="capital_on" msgid="1544682755514494298">"في"</string>
     <string name="capital_off" msgid="6815870386972805832">"إيقاف"</string>
     <string name="whichApplication" msgid="4533185947064773386">"إكمال الإجراء باستخدام"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"فرض الإغلاق"</string>
     <string name="report" msgid="4060218260984795706">"إرسال تقرير"</string>
     <string name="wait" msgid="7147118217226317732">"انتظار"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"تمت إعادة توجيه التطبيق"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> قيد التشغيل الآن."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"تم تشغيل <xliff:g id="APP_NAME">%1$s</xliff:g> من الأصل."</string>
+    <string name="smv_application" msgid="295583804361236288">"انتهك التطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> (العملية <xliff:g id="PROCESS">%2$s</xliff:g>) سياسة.StrictMode المفروضة ذاتيًا."</string>
+    <string name="smv_process" msgid="5120397012047462446">"انتهكت العملية <xliff:g id="PROCESS">%1$s</xliff:g> سياسة StrictMode المفروضة ذاتيًا."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> يعمل"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"تحديد للتبديل إلى التطبيق"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"هل تريد التبديل بين التطبيقات؟"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"يوجد تطبيق آخر قيد التشغيل فعليًا ويجب إيقافه لكي تتمكن من بدء تطبيق جديد."</string>
+    <string name="old_app_action" msgid="493129172238566282">"عودة إلى <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"عدم بدء التطبيق الجديد."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"بدء <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"إيقاف التطبيق القديم بدون الحفظ."</string>
     <string name="sendText" msgid="5132506121645618310">"تحديد إجراء للنص"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"مستوى صوت الرنين"</string>
     <string name="volume_music" msgid="5421651157138628171">"مستوى صوت الوسائط"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"عرض الكل"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"تخزين USB كبير السعة"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB متصل"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"لقد أوصلت هاتفك بجهاز الكمبيوتر عبر USB. حدد الزر أدناه إذا كنت تريد نسخ ملفات بين الكمبيوتر وبطاقة SD لجهاز Android."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"لقد أوصلت هاتفك بجهاز الكمبيوتر عبر USB. حدد الزر أدناه إذا كنت تريد نسخ ملفات بين الكمبيوتر وبطاقة SD لجهاز Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"لقد اتصلت بجهاز الكمبيوتر من خلال USB. المس الزر أدناه إذا كنت تريد نسخ الملفات بين جهاز الكمبيوتر ووحدة تخزين Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"لقد اتصلت بجهاز الكمبيوتر من خلال USB. المس الزر أدناه إذا كنت تريد نسخ الملفات بين جهاز الكمبيوتر وبطاقة SD لـ Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"تشغيل سعة تخزين USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"هناك مشكلة في استخدام بطاقة SD لسعة تخزين USB."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"هناك مشكلة في استخدام بطاقة SD لسعة تخزين USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"هناك مشكلة في استخدام وحدة تخزين USB للتخزين الجماعي لـ USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"هناك مشكلة في استخدام بطاقة SD للتخزين الجماعي لـ USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB متصل"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"يمكنك التحديد لنسخ الملفات إلى/من جهاز الكمبيوتر."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"إيقاف تشغيل سعة تخزين USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"حدد لإيقاف تشغيل سعة تخزين USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"سعة USB التخزينية المستخدمة"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"قبل إيقاف تشغيل سعة تخزين USB، تأكد من إلغاء تحميل (\"تم إخراجها\") بطاقة SD لـ Android من جهاز الكمبيوتر."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"قبل إيقاف تشغيل وحدة تخزين USB، تأكد من إلغاء تركيب (\"إخراج\") وحدة تخزين USB لـ Android من الكمبيوتر."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"قبل إيقاف تشغيل سعة تخزين USB، تأكد من إلغاء تحميل (\"تم إخراجها\") بطاقة SD لـ Android من جهاز الكمبيوتر."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"إيقاف تشغيل سعة تخزين USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"حدثت مشكلة في إيقاف تشغيل سعة USB التخزينية. تحقق من إلغاء تحميل مضيف USB، ثم حاول مرة أخرى."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"إذا شغّلت سعة تخزين USB، فستتوقف بعض التطبيقات التي تستخدمها وربما تصبح غير متاحة لحين إيقاف تشغيل سعة تخزين USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"أخفقت عملية USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"موافق"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"تنسيق بطاقة SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"تهيئة وحدة تخزين USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"تنسيق بطاقة SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"هل تريد تنسيق بطاقة SD؟ ستفقد جميع البيانات على بطاقتك."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"هل تريد تهيئة وحدة تخزين USB، ومحو كل الملفات المخزنة بها؟ لا يمكن عكس هذا الإجراء!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"هل تريد تنسيق بطاقة SD؟ ستفقد جميع البيانات على بطاقتك."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"تنسيق"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"تم توصيل تصحيح أخطاء USB"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789 أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"العناصر المرشحة"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"تحضير بطاقة SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"تحضير وحدة تخزين USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"تحضير بطاقة SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"التحقق من الأخطاء."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"بطاقة SD فارغة"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"وحدة تخزين USB فارغة"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"بطاقة SD فارغة"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"بطاقة SD فارغة أو تحتوي على نظام ملفات غير معتمد."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"وحدة تخزين USB فارغة أو بها نظام ملفات غير صالح."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"بطاقة SD فارغة أو تحتوي على نظام ملفات غير معتمد."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"بطاقة SD تالفة"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"وحدة تخزين USB تالفة"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"بطاقة SD تالفة"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"بطاقة SD تالفة. قد يجب عليك إعادة تنسيقها."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"تلف وحدة تخزين USB. ربما يتوجب عليك إعادة تهيئتها."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"بطاقة SD تالفة. قد يجب عليك إعادة تنسيقها."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"تمت إزالة بطاقة SD على نحو غير متوقع"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"تمت إزالة وحدة تخزين USB على غير المتوقع"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"تمت إزالة بطاقة SD على نحو غير متوقع"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"ألغ تحميل بطاقة SD قبل الإزالة لتجنب فقدان البيانات."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"إلغاء تركيب وحدة تخزين USB قبل الإزالة لتجنب فقد البيانات."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"ألغ تحميل بطاقة SD قبل الإزالة لتجنب فقدان البيانات."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"يمكن إزالة بطاقة SD بأمان"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"يمكنك إزالة وحدة تخزين USB بشكل آمن"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"يمكن إزالة بطاقة SD بأمان"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"يمكنك إزالة بطاقة SD بأمان."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"يمكنك إزالة وحدة تخزين USB بشكل آمن."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"يمكنك إزالة بطاقة SD بأمان."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"تمت إزالة بطاقة SD"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"تمت إزالة وحدة تخزين USB"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"تمت إزالة بطاقة SD"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"تمت إزالة بطاقة SD. أدخل بطاقة جديدة."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"تمت إزالة وحدة تخزين USB. أدرج وسائط جديدة."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"تمت إزالة بطاقة SD. أدخل بطاقة جديدة."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"لم يتم العثور على أية أنشطة متطابقة"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"تحديث إحصاءات استخدام المكون"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"إرسال"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"التالي"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"تم"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"السابق"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"تنفيذ"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"طلب رقم"\n"باستخدام <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"إنشاء جهة اتصال"\n"باستخدام <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"بروتوكول L2TP/IPSec VPN المستند إلى المفتاح المشترك مسبقًا"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"بروتوكول L2TP/IPSec VPN المستند إلى الشهادة"</string>
     <string name="upload_file" msgid="2897957172366730416">"اختيار ملف"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"لم يتم اختيار أي ملف"</string>
     <string name="reset" msgid="2448168080964209908">"إعادة تعيين"</string>
     <string name="submit" msgid="1602335572089911941">"إرسال"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"تم تمكين وضع السيارة"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"حدد للخروج من وضع السيارة."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"النطاق أو نقطة الاتصال نشطة"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"يمكنك اللمس للتهيئة"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"رجوع"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"التالي"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"تخطٍ"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"الاستخدام المرتفع لبيانات الجوال"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"يمكنك اللمس لمعرفة المزيد حول استخدام بيانات الجوال"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"تم تجاوز حد بيانات الجوال"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"يمكنك اللمس لمعرفة المزيد حول استخدام بيانات الجوال"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"ليس هناك أية مطابقات"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"بحث في الصفحة"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"مطابقة واحدة"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> من <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"تم"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"جارٍ إلغاء تركيب وحدة تخزين USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"جارٍ إلغاء تركيب بطاقة SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"جارٍ محو وحدة تخزين USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"جارٍ محو بطاقة SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"أخفق محو وحدة تخزين USB."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"أخفق محو بطاقة SD."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"تمت إزالة بطاقة SD قبل أن يتم إلغاء تركيبها."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"يتم حاليًا التحقق من وحدة تخزين USB."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"يتم الآن التحقق من بطاقة SD."</string>
+    <string name="media_removed" msgid="7001526905057952097">"تمت إزالة بطاقة SD."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"وحدة تخزين USB قيد الاستخدام بواسطة كمبيوتر حاليًا."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"بطاقة SD قيد الاستخدام حاليًا بواسطة كمبيوتر."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"وسائط خارجية في حالة غير معروفة."</string>
+    <string name="share" msgid="1778686618230011964">"مشاركة"</string>
+    <string name="find" msgid="4808270900322985960">"بحث"</string>
+    <string name="websearch" msgid="4337157977400211589">"بحث الويب"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index d6684c5..d1176b8 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Гласова поща"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Има проблем с връзката или MMI кодът е невалиден."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Операцията е ограничена само до фиксираните номера за набиране."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Услугата бе активирана."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Услугата бе активирана за:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Услугата бе деактивирана."</string>
@@ -129,7 +128,7 @@
     <string name="low_memory" product="tablet" msgid="2292820184396262278">"Хранилището на таблета е пълно! Изтрийте файлове, за да освободите място."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"Хранилището на телефона е пълно! Изтрийте файлове, за да освободите място."</string>
     <string name="me" msgid="6545696007631404292">"Аз"</string>
-    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Опции на таблета"</string>
+    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Опции за таблета"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"Опции на телефона"</string>
     <string name="silent_mode" msgid="7167703389802618663">"Тих режим"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"Включване на радиото"</string>
@@ -139,11 +138,10 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"Изключва се..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Таблетът ви ще се изключи."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Телефонът ви ще се изключи."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Искате ли да изключите?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Скорошни"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Няма скорошни приложения."</string>
-    <string name="global_actions" product="tablet" msgid="408477140088053665">"Опции на таблета"</string>
+    <string name="global_actions" product="tablet" msgid="408477140088053665">"Опции за таблета"</string>
     <string name="global_actions" product="default" msgid="2406416831541615258">"Опции на телефона"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Заключване на екрана"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Изключване"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Самолетен режим"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Самолетният режим е ВКЛЮЧЕН"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Самолетният режим е ИЗКЛЮЧЕН"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Системно от Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Услуги, които ви струват пари"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Инструменти за програмиране"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Функции, необходими само за програмисти на приложения."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Съхранение"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Достъп до SD картата."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Достъп до USB хранилището."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Достъп до SD картата."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"деактивиране или промяна на лентата на състоянието"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Разрешава на приложението да деактивира лентата на състоянието или да добавя и премахва системни икони."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"лента на състоянието"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Разрешава на приложението да бъде лентата на състоянието."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"разгъване или свиване на лентата на състоянието"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Разрешава на приложението да разгъва или свива лентата на състоянието."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"прехващане на изходящи обаждания"</string>
@@ -281,14 +279,14 @@
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Разрешава на приложението да освобождава място в хранилището на телефона, като изтрива файлове в директорията за кеш на приложенията. Достъпът е много ограничен, обикновено до системния процес."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Преместване на ресурси на приложенията"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Разрешава на приложението да мести ресурси на приложения от вътрешни към външни носители и обратно."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"четене на системните журнални файлове"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Разрешава на приложението да чете от различните регистрационни файлове на системата. Това му позволява да получи обща информация какво правите с таблета, което потенциално включва лични или поверителни данни."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Разрешава на приложението да чете от различните регистрационни файлове на системата. Това му позволява да получи обща информация какво правите с таблета, което потенциално включва лични или поверителни данни."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"четене на поверителни данни от регистрационните файлове"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Разрешава на приложението да чете от различните регистрационни файлове на системата. Това му позволява да получи обща информация какво правите с таблета, потенциално включително и лични или поверителни данни."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Разрешава на приложението да чете от различните регистрационни файлове на системата. Това му позволява да получи обща информация какво правите с телефона, потенциално включително и лични или поверителни данни."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"четене/запис в ресурси, притежавани от diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Разрешава на приложението да чете и записва във всеки ресурс, притежаван от групата diag, например файловете в /dev. Това потенциално може да засегне стабилността и защитеността на системата. То трябва да се използва САМО за специфично за хардуера диагностициране от страна на производителя или оператора."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"активиране или деактивиране на компоненти на приложенията"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Разрешава на приложението да активира или деактивира компонент на друго приложение. Злонамерените приложения могат да използват това, за да деактивират важни функционалности на таблета. С това разрешение трябва да се внимава, тъй като компонентите на приложенията може да бъдат приведени в неизползваемо, несъгласувано или нестабилно състояние."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Разрешава на приложението да активира или деактивира компонент на друго приложение. Злонамерените приложения могат да използват това, за да деактивират важни функционалности на таблета. С това разрешение трябва да се внимава, тъй като компонентите на приложенията може да бъдат приведени в неизползваемо, несъгласувано или нестабилно състояние."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Разрешава на приложението да активира или деактивира компонент на друго приложение. Злонамерените приложения могат да използват това, за да деактивират важни възможности на таблета. С това разрешение трябва да се внимава, тъй като компонентите на приложенията може да бъдат приведени в неизползваемо, нееднородно или нестабилно състояние."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Разрешава на приложението да активира или деактивира компонент на друго приложение. Злонамерените приложения могат да използват това, за да деактивират важни възможности на телефона. С това разрешение трябва да се внимава, тъй като компонентите на приложенията може да бъдат приведени в неизползваемо, нееднородно или нестабилно състояние."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"задаване на предпочитани приложения"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Разрешава на приложението да променя предпочитаните ви приложения. Това може да позволи на злонамерени приложения скрито да променят приложенията, които се изпълняват, като ги фалшифицират, за да се сдобият с ваши лични данни."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"промяна на глобалните системни настройки"</string>
@@ -298,19 +296,19 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"промяна на картата на услугите на Google"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"Разрешава на приложението да променя картата на услугите на Google. Не е предназначено за нормални приложения."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"автоматично стартиране при зареждане"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Разрешава на приложението да се стартира веднага, щом системата завърши зареждането си. Това може да доведе до по-бавно стартиране на таблета и да позволи на приложението да забави таблета като цяло, тъй като се изпълнява постоянно."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Разрешава на приложението да се стартира веднага щом системата завърши зареждането си. Това може да доведе до по-бавно стартиране на таблета и да позволи на приложението да забави таблета като цяло, тъй като се изпълнява постоянно."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Разрешава на приложението да се стартира веднага щом системата завърши зареждането си. Това може да доведе до по-бавно стартиране на телефона и да позволи на приложението да забави телефона като цяло, тъй като се изпълнява постоянно."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"изпращане на оставащи излъчвания"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Разрешава на приложението да изпраща оставащи излъчвания, които се запазват след края на излъчването. Злонамерените приложения могат да причинят бавна или нестабилна работа на таблета, като го накарат да използва твърде много памет."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Разрешава на приложението да изпраща оставащи излъчвания, които се запазват след края на излъчването. Злонамерените приложения могат да причинят бавна или нестабилна работа на телефона, като го накарат да използва твърде много памет."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"четене на данни за контактите"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Разрешава на приложението да чете всички данни за контактите (за адрес), съхранени в таблета. Злонамерените приложения могат да използват това, за да изпратят данните ви на други хора."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Разрешава на приложението да чете всички данни за контактите (за адрес), съхранени в таблета. Злонамерените приложения могат да използват това, за да изпращат данните ви на други хора."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Разрешава на приложението да чете всички данни за контактите (за адрес), съхранени в телефона. Злонамерените приложения могат да използват това, за да изпратят данните ви на други хора."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"запис на данни за контактите"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Разрешава на приложението да променя данните за контактите (за адрес), съхранени в таблета ви. Злонамерените приложения могат да използват това, за да изтрият или променят тези данни."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Разрешава на приложението да променя данните за контактите (за адрес), съхранени в таблета ви. Злонамерените приложения може да използват това, за да изтрият или променят тези данни."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Разрешава на приложението да променя данните за контактите (за адрес), съхранени в телефона ви. Злонамерените приложения могат да използват това, за да изтрият или променят тези данни."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"четене на събития от календара"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Разрешава на приложението да чете всички съхранени в таблета събития в календара ви. Злонамерените приложения могат да използват това, за да изпратят тези събития на други хора."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Разрешава на приложението да чете всички съхранени в таблета събития в календара ви. Злонамерените приложения могат да използват това, за да изпращат тези събития на други хора."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Разрешава на приложението да чете всички съхранени в телефона събития в календара ви. Злонамерените приложения могат да използват това, за да изпратят тези събития на други хора."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"добавяне или промяна на събития в календара и изпращане на имейл до гостите"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Разрешава на приложението да добавя или променя събитията в календара ви, при което може да се изпрати имейл до гостите. Злонамерените приложения могат да използват това, за да изтрият или променят тези събития или да изпратят имейл до гостите."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"разрешение за инсталиране на доставчик на местоположение"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Създаване на мними източници на местоположение за тестване. Злонамерените приложения могат да използват това, за да заменят местоположението и/или състоянието, връщано от истинските източници, като GPS или мрежовите доставчици, или да наблюдават местоположението ви и да го предават на външен източник."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"местоположение с висока точност (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Достъп до източници за местоположение с висока точност, където са налице, например системата GPS на таблета. Злонамерените приложения могат да използват това, за да определят приблизително къде се намирате, и може да изразходват повече енергия от батерията."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Достъп до източници за местоположение с висока точност, където са налице, като системата GPS на таблета. Злонамерените приложения могат да използват това, за да определят къде се намирате, и може да изразходват повече енергия от батерията."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Достъп до източници за местоположение с висока точност, където са налице, като системата GPS на телефона. Злонамерените приложения могат да използват това, за да определят приблизително къде се намирате, и може да изразходват повече енергия от батерията."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"местоположение с ниска точност (основано на мрежата)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Достъп до източници за местоположение с ниска точност, където са налице, например базата от данни за клетъчната мрежа, за да се определи приблизително местоположение на таблета. Злонамерените приложения могат да използват това, за да определят приблизително къде се намирате."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Достъп до източници за местоположение с ниска точност, където са налице, като например базата от данни за клетъчната мрежа, за да се определи приблизително местоположение на таблета. Злонамерените приложения могат да използват това, за да определят приблизително къде се намирате."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Достъп до източници за местоположение с ниска точност, където са налице, като например базата от данни за клетъчната мрежа, за да се определи приблизително местоположение на телефона. Злонамерените приложения могат да използват това, за да определят приблизително къде се намирате."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"достъп до SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Разрешава на приложението да използва функциите на SurfaceFlinger от ниско ниво."</string>
@@ -334,8 +332,8 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Разрешава на приложението да променя глобалните настройки на звука, като например силата или пътя на сигнала."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"запис на звук"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Разрешава на приложението достъп до пътя за запис на звук."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"правене на снимки"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Разрешава на приложението да прави снимки. Това му позволява по всяко време да събира изображенията, които камерата вижда."</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"правене на снимки и видеоклипове"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Разрешава на приложението да прави снимки и видеоклипове. Това му позволява по всяко време да събира изображенията, които камерата вижда."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"деактивиране на таблета за постоянно"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"деактивиране на телефона за постоянно"</string>
     <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Разрешава на приложението да деактивира целия таблет за постоянно. Това е много опасно."</string>
@@ -348,23 +346,25 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Разрешава на приложението да активира или деактивира файлови системи за сменяемо устройство за съхранение."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"форматиране на външно устройство за съхранение"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Разрешава на приложението да форматира сменяемо устройство за съхранение."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"поставяне на информация в защитено хранилище"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Разрешава на приложението да поставя информация в защитено хранилище."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"създаване на защитено хранилище"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Разрешава на приложението да създава защитено хранилище."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"унищожаване на защитено хранилище"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Разрешава на приложението да унищожава защитено хранилище."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"активира и деактивира защитено хранилище"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Разрешава на приложението да активира или да деактивира защитено хранилище."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"преименуване на защитено хранилище"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Разрешава на приложението да преименува защитено хранилище."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"получаване на информация за вътрешното хранилище"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Разрешава на приложението да получава информация за вътрешното хранилище."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"създаване на вътрешно хранилище"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Разрешава на приложението да създаде вътрешно хранилище."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"унищожаване на вътрешното хранилище"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Разрешава на приложението да унищожи вътрешното хранилище."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"свързване / спиране на вътрешно хранилище"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Разрешава на приложението да свързва или спира вътрешното хранилище."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"преименуване на вътрешно хранилище"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Разрешава на приложението да преименува вътрешното хранилище."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"контролиране на вибрацията"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Разрешава на приложението да контролира устройството за вибрация."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"контролиране на фенерчето"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Разрешава на приложението да контролира фенерчето."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"достъп до USB устройства"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Разрешава на приложението достъп до USB устройства."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"тест на хардуера"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Разрешава на приложението да контролира различни периферни устройства с цел тестване на хардуера."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"разрешаване на приемане на мултикаст през Wi-Fi мрежата"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Разрешава на приложението да получава пакети, които не са адресирани директно към устройството ви. Това може да е полезно при откриване на предлагани в района услуги. Консумира се повече мощност, отколкото в режим без мултикаст."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"администриране на Bluetooth"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Разрешава на приложението да конфигурира локалния Bluetooth таблет, както и да открива и да се сдвоява с отдалечени устройства."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Разрешава на приложението да конфигурира локалния таблет с Bluetooth, както и да открива и да се сдвоява с отдалечени устройства."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Разрешава на приложението да конфигурира локалния Bluetooth телефон, както и да открива и да се сдвоява с отдалечени устройства."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"създаване на връзки през Bluetooth"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Разрешава на приложението да вижда конфигурацията на локалния Bluetooth таблет и да изгражда и приема връзки със сдвоени устройства."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Разрешава на приложението да вижда конфигурацията на локалния таблет с Bluetooth и да изгражда и приема връзки със сдвоени устройства."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Разрешава на приложението да вижда конфигурацията на локалния Bluetooth телефон и да изгражда и приема връзки със сдвоени устройства."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"контролиране на комуникацията в близкото поле"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Разрешава на приложението да комуникира с маркери, карти и четци, ползващи комуникация в близкото поле (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"деактивиране на заключването на клавиатурата"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Разрешава на приложението да деактивира заключването на клавиатурата и свързаната защита с парола. Това е допустимо, когато например телефонът деактивира заключването при получаване на входящо обаждане и после го активира отново, когато обаждането завърши."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"четене на настройките за синхронизиране"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Разрешава на приложението да чете частни думи, имена и фрази, които потребителят може да е съхранил в потребителския речник."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"запис в дефинирания от потребителя речник"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Разрешава на приложението да записва нови думи в потребителския речник."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"промяна/изтриване на съдържанието на SD картата"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"промяна/изтриване на съдържанието в USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"промяна/изтриване на съдържанието на SD картата"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Разрешава на приложението да записва върху SD картата."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Разрешава на приложението да записва в USB хранилището."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Разрешава на приложението да записва върху SD картата."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"промяна/изтриване на съдържанието на вътрешното мултимедийно хранилище"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Разрешава на приложението да променя съдържанието на вътрешното мултимедийно хранилище."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"достъп до файловата система на кеша"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Разрешава на приложението да чете и записва във файловата система на кеша."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ограничаване на паролата"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Ограничава типовете пароли, които можете да използвате."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Наблюдение на опитите за вход"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Наблюдава броя на неправилните пароли, въведени при отключване на екрана, и заключва таблета или изтрива всички данни от него, ако са въведени твърде много неправилни пароли"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Наблюдава броя на неправилните пароли, въведени при отключване на екрана, и заключва таблета или изтрива всички данни от него, ако са въведени твърде много неправилни пароли"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Повторно задаване на паролата"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Принудително задава нова стойност на паролата ви, при което администраторът трябва да ви я даде, преди да можете да влезете."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Принудително заключване"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Контролира кога устройството се заключва, при което се изисква отново да въведете паролата му."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"извършване/получаване на интернет обаждания"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Разрешава на приложението да използва услугата SIP за извършване/получаване на интернет обаждания."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Задаване на правила за паролата"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Контролирайте дължината и позволените знаци за паролите за отключване на екрана"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Наблюдаване на опитите за отключване на екрана"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Наблюдава броя въведени неправилни пароли при отключването на екрана и заключва таблета или изтрива всички данни от него, ако неправилните пароли са твърде много"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Наблюдава броя въведени неправилни пароли при отключването на екрана и заключва телефона или изтрива всички данни от него, ако неправилните пароли са твърде много"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Промяна на паролата за отключване на екрана"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Промяна на паролата за отключване на екрана"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Заключване на екрана"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Контролирайте как и кога екранът се заключва"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Изтриване на всички данни"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Изтрива данните от таблета без предупреждение, като извършва възстановяване на фабричните настройки"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Изтрива данните от таблета без предупреждение, като извършва възстановяване на фабричните настройки"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Изтриване на данните в таблета без предупреждение чрез възстановяване на фабричните настройки"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Изтриване на данните в телефона без предупреждение чрез възстановяване на фабричните настройки"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Задаване на глобален прокси сървър за устройството"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Задаване на глобалния прокси сървър, който да се използва, когато правилото е активирано. Само първият администратор на устройството задава действителния глобален прокси сървър."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Срок на валидност на паролата"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Контролирайте след колко време трябва да се променя паролата при заключване на екрана"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Домашен"</item>
     <item msgid="869923650527136615">"Мобилен"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Служебен пейджър"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Асистент"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Персонализирано"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Рожден ден"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Годишнина"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Събитие"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Друго"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"По избор"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Домашен"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Служебен"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Работа"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Друго"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"По избор"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Персонализирано"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Асистент"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Брат"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Дете"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Домашен партньор"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Баща"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Приятел"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Мениджър"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Майка"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Родител"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Партньор"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Препоръчан/а от"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Роднина"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Сестра"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Съпруг/а"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Персонализиран"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Домашен"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Служебен"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Друг"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Въведете PIN кода"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Въведете паролата, за да отключите"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Въведете PIN за отключване"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Неправилен PIN код!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"За да отключите, натиснете „Меню“ и после 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Спешен номер"</string>
@@ -646,8 +615,7 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Назад към обаждането"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Правилно!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Съжаляваме, опитайте отново"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Съжаляваме, опитайте отново"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Зарежда се (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Зареден."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM картата е заключена."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM картата се отключва..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Нарисувахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%d</xliff:g> пъти. "\n\n"Моля, опитайте отново след <xliff:g id="NUMBER_1">%d</xliff:g> секунди."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Нарисувахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни опита ще ви бъде поискано да отключите таблета си, използвайки данните си за вход в Google."\n\n" Моля, опитайте отново след <xliff:g id="NUMBER_2">%d</xliff:g> секунди."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Въведохте неправилно паролата си <xliff:g id="NUMBER_0">%d</xliff:g> пъти. "\n\n"Моля, опитайте отново след <xliff:g id="NUMBER_1">%d</xliff:g> секунди."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Въведохте неправилно своя PIN <xliff:g id="NUMBER_0">%d</xliff:g> пъти. "\n\n"Моля, опитайте отново след <xliff:g id="NUMBER_1">%d</xliff:g> секунди."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни опита ще бъдете помолени да отключите таблета посредством данните си за вход в Google."\n\n" Моля, опитайте отново след <xliff:g id="NUMBER_2">%d</xliff:g> секунди."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Нарисувахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%d</xliff:g> неуспешни опита ще ви бъде поискано да отключите телефона, използвайки данните си за вход в Google."\n\n" Моля, опитайте отново след <xliff:g id="NUMBER_2">%d</xliff:g> секунди."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Опитайте отново след <xliff:g id="NUMBER">%d</xliff:g> секунди."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Забравили сте фигурата?"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Искате ли да напуснете тази страница?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Изберете „OK“, за да продължите, или „Отказ“, за да останете на нея."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Потвърждение"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Съвет: докоснете двукратно, за да увеличите или намалите мащаба."</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"Автопоп."</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"Автоматично попълване"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Настройка"</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"четене на историята и отметките на браузъра"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Разрешава на приложението да чете всички URL адреси, посетени от браузъра, и всички негови отметки."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"запис в историята и отметките на браузъра"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Разрешава на приложението да променя историята или отметките на браузъра, съхранени в таблета ви. Злонамерените приложения могат да използват това, за да изтрият или променят данните на браузъра ви."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Разрешава на приложението да променя историята или отметките на браузъра, съхранени в таблета ви. Злонамерените приложения може да използват това, за да изтрият или променят данните на браузъра ви."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Разрешава на приложението да променя историята или отметките на браузъра, съхранени на телефона ви. Злонамерените приложения могат да използват това, за да изтрият или променят данните на браузъра ви."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"навиване на будилника"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Разрешава на приложението да навие инсталирано приложение будилник. Някои будилници може да не изпълнят тази функция."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Промяна на разрешенията за местоположение в браузъра"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Разрешава на приложението да променя разрешенията на браузъра за местоположение. Злонамерените приложения могат да използват това, за да изпращат информация за местоположението до произволни уебсайтове."</string>
     <string name="save_password_message" msgid="767344687139195790">"Искате ли браузърът да запомни тази парола?"</string>
@@ -830,15 +790,12 @@
     <string name="cut" msgid="3092569408438626261">"Изрязване"</string>
     <string name="copy" msgid="2681946229533511987">"Копиране"</string>
     <string name="paste" msgid="5629880836805036433">"Поставяне"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Нищо за поставяне"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Копиране на URL адреса"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Избиране на текст..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Избиране на текст"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод на въвеждане"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Редактиране на текст"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Действия с текста"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Мястото не достига"</string>
     <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Мястото в хранилището на таблета намалява."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Мястото в хранилището на телефона намалява."</string>
@@ -847,8 +804,7 @@
     <string name="yes" msgid="5362982303337969312">"OK"</string>
     <string name="no" msgid="5141531044935541497">"Отказ"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Внимание"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Зарежда се..."</string>
     <string name="capital_on" msgid="1544682755514494298">"ВКЛ"</string>
     <string name="capital_off" msgid="6815870386972805832">"ИЗКЛ"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Изпълняване на действието чрез"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Принудително затваряне"</string>
     <string name="report" msgid="4060218260984795706">"Подаване на сигнал"</string>
     <string name="wait" msgid="7147118217226317732">"Изчакване"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Приложението се пренасочи"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> се изпълнява."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Първоначално бе стартирано: <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="smv_application" msgid="295583804361236288">"Приложението <xliff:g id="APPLICATION">%1$s</xliff:g> (процес <xliff:g id="PROCESS">%2$s</xliff:g>) наруши правилото за стриктен режим, наложено от самото него."</string>
+    <string name="smv_process" msgid="5120397012047462446">"Процесът <xliff:g id="PROCESS">%1$s</xliff:g> наруши правилото за стриктен режим, наложено от самия него."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> се изпълнява"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Изберете за превключване към приложение"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Да се превключат ли приложенията?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Вече се изпълнява друго приложение, което трябва да бъде спряно, преди да можете да стартирате ново."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Назад към <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Новото приложение да не се стартира."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Стартиране на <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Спиране на старото приложение без запазване."</string>
     <string name="sendText" msgid="5132506121645618310">"Избиране на действие за текст"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Сила на звука при звънене"</string>
     <string name="volume_music" msgid="5421651157138628171">"Сила на звука"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Показване на всички"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB устройство за съхранение"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Връзка през USB"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Свързахте телефона с компютъра си през USB. Изберете долния бутон, ако искате да копирате файлове между компютъра и SD картата си от Android."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Свързахте телефона с компютъра си през USB. Изберете долния бутон, ако искате да копирате файлове между компютъра и SD картата си от Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Свързахте се с компютъра си през USB. Докоснете долния бутон, ако искате да копирате файлове между компютъра и USB хранилището си от Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Свързахте се с компютъра си през USB. Докоснете долния бутон, ако искате да копирате файлове между компютъра и SD картата си от Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Включване на USB устройството за съхранение"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Възникна проблем при използването на SD картата ви като USB устройство за съхранение."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Възникна проблем при използването на SD картата ви като USB устройство за съхранение."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Възникна проблем при използването на USB хранилището ви като масово USB хранилище."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Възникна проблем при използването на SD картата ви като масово USB хранилище."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Връзка през USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Изберете, за да копирате файлове към или от компютъра си."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Изключване на USB устройството за съхранение"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Изберете, за да изключите USB устройството за съхранение."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB устройството за съхранение се използва"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Преди да изключите работата като USB устройство за съхранение, уверете се, че сте премахнали активирането (че сте „изхвърлили“) SD картата от Android от компютъра си."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Преди да изключите USB хранилището си за Android, уверете се, че сте го спрели (със съответната команда за изваждане) от компютъра си."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Преди да изключите работата като USB устройство за съхранение, уверете се, че сте премахнали активирането (че сте „изхвърлили“) SD картата от Android от компютъра си."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Изключване на USB устройството за съхранение"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"При изключването на работата като USB устройство за съхранение възникна проблем. Уверете се, че сте премахнали активирането на USB хоста, и опитайте отново."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ако включите работата като USB устройство за съхранение, някои използвани от вас приложения ще спрат и може да бъдат недостъпни, докато не я изключите."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Операцията през USB не бе успешна"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматиране на SD картата"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматиране на USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Форматиране на SD картата"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Наистина ли искате да форматирате SD картата? Всички данни на нея ще се заличат."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Да се форматира ли USB хранилището, изтривайки всички файлове в него? Действието не може да бъде отменено!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Наистина ли искате да форматирате SD картата? Всички данни на нея ще се заличат."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Форматиране"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Отстраняването на грешки през USB е свързано"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"SD картата се подготвя"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"USB хранилището се подготвя"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD картата се подготвя"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Проверява се за грешки."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Празна SD карта"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Празно USB хранилище"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Празна SD карта"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"SD картата е празна или е с неподдържана файлова система."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB хранилището е празно или е с неподдържана файлова система."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD картата е празна или е с неподдържана файлова система."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"SD картата е повредена"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Повредено USB хранилище"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"SD картата е повредена"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"SD картата е повредена. Може да трябва да я преформатирате."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB хранилището е повредено. Може да трябва да го форматирате отново."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD картата е повредена. Може да трябва да я преформатирате."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"SD картата бе премахната неочаквано."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB е премахнато неочаквано"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD картата бе премахната неочаквано."</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Премахнете активирането на SD картата, преди да я извадите, за да избегнете загуба на данни."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Спрете USB хранилището, преди да го извадите, за да избегнете загуба на данни."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Премахнете активирането на SD картата, преди да я извадите, за да избегнете загуба на данни."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Премахването на SD картата е безопасно"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB е безопасно за премахване"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Премахването на SD картата е безопасно"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Можете безопасно да премахнете SD картата."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Можете безопасно да премахнете USB хранилището."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Можете безопасно да премахнете SD картата."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"SD картата бе премахната"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB хранилището е премахнато"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD картата бе премахната"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"SD картата е премахната. Поставете нова."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB хранилището е премахнато. Поставете нов носител."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD картата е премахната. Поставете нова."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Не бяха намерени съответстващи дейности"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"актуализиране на статистическите данни за използването на компонентите"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Изпращане"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Напред"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Готово"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Пред."</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Изпълнение"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Набиране"\n"с използване на <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Създаване на контакт"\n"с използване на <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Основана на предварително споделен ключ L2TP/IPSec VPN"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Основана на сертификати L2TP/IPSec VPN"</string>
     <string name="upload_file" msgid="2897957172366730416">"Избор на файл"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Няма избран файл"</string>
     <string name="reset" msgid="2448168080964209908">"Повторно задаване"</string>
     <string name="submit" msgid="1602335572089911941">"Изпращане"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Мото режимът е активиран"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Изберете, за да излезете от мото режима."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Има активна споделена връзка или безжична точка за достъп"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Докоснете, за да конфигурирате"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Назад"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Напред"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Пропускане"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Голям обем на мобилния трафик на данни"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Докоснете, за да научите повече за мобилния трафик на данни"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Лимитът за мобилния трафик на данни бе надхвърлен"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Докоснете, за да научите повече за мобилния трафик на данни"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Няма съответствия"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Намиране в страницата"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 съответствие"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> от <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Готово"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"USB хранилището се спира..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"SD картата се спира..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"USB хранилището се изтрива..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"SD картата се изтрива..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Изтриването на USB хранилището не бе успешно."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Изтриването на SD картата не бе успешно."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD картата бе премахната, преди да бъде спряна."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB хранилището понастоящем се проверява."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"SD картата се проверява понастоящем."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD картата бе премахната."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB хранилището понастоящем се използва от компютър."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"SD картата се използва понастоящем от компютър."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Външният носител е в неизвестно състояние."</string>
+    <string name="share" msgid="1778686618230011964">"Споделяне"</string>
+    <string name="find" msgid="4808270900322985960">"Намиране"</string>
+    <string name="websearch" msgid="4337157977400211589">"Уеб търсене"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 76b2725..e352fc0 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Correu de veu"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Problema de connexió o codi MMI no vàlid."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"L\'operació està restringida a números de marcatge fixos."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"El servei s\'ha activat."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"S\'ha activat el servei per a:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"El servei s\'ha desactivat."</string>
@@ -126,7 +125,7 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"Sincronització"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronització"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Massa supressions de <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"L\'emmagatzematge de la tauleta és ple. Suprimeix fitxers per alliberar espai."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"L\'emmagatzematge de la tauleta és ple. Suprimeix uns quants fitxers per alliberar espai."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"L\'emmagatzematge del telèfon és ple. Suprimiu fitxers per alliberar espai."</string>
     <string name="me" msgid="6545696007631404292">"Mi"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opcions de la tauleta"</string>
@@ -139,8 +138,7 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"S\'està apagant..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"La tauleta s\'apagarà."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"El telèfon s\'apagarà."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Vols desconnectar-lo?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recents"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"No hi ha cap aplicació recent."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Opcions de la tauleta"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode d\'avió"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mode d\'avió activat"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mode d\'avió desactivat"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mode segur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serveis de pagament"</string>
@@ -160,7 +160,7 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Els vostres missatges"</string>
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"Llegeix i escriu SMS, correu electrònic i altres missatges."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"La vostra informació personal"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Accés directe als contactes i al calendari emmagatzemats a la tauleta."</string>
+    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Accés directe als contactes i al calendari emmagatzemat a la tauleta."</string>
     <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Accés directe als contactes i al calendari emmagatzemats al telèfon."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"La vostra ubicació"</string>
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Supervisa la ubicació física"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Eines de desenvolupament"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funcions que només necessiten els desenvolupadors d\'aplicacions."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Emmagatzematge"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Accedeix a la targeta SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Accedeix a l\'emmag. USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Accedeix a la targeta SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"desactivar o modificar la barra d\'estat"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Permet a l\'aplicació desactivar la barra d\'estat o afegir i eliminar icones del sistema."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"barra d\'estat"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Permet que l\'aplicació sigui la barra d\'estat."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"ampliar/reduir la barra d\'estat"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Permet a l\'aplicació ampliar o reduir la barra d\'estat."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"interceptar les trucades de sortida"</string>
@@ -196,10 +194,10 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"enviar missatges SMS"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Permet a l\'aplicació enviar missatges SMS. Les aplicacions malicioses poden costar-vos diners en enviar missatges sense la vostra confirmació."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"llegir SMS o MMS"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Permet a l\'aplicació llegir missatges SMS emmagatzemats a la tauleta o a la targeta SIM. Les aplicacions malicioses podrien llegir els missatges confidencials."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Permet que una aplicació llegeixi missatges SMS emmagatzemats a la tauleta o a la targeta SIM. Les aplicacions malicioses poden llegir els teus missatges confidencials."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Permet a l\'aplicació llegir missatges SMS emmagatzemats al telèfon o a la targeta SIM. Les aplicacions malicioses podrien llegir els missatges confidencials."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"editar SMS o MMS"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Permet que l\'aplicació escrigui als missatges SMS emmagatzemats a la tauleta o a la targeta SIM. Les aplicacions malicioses podrien suprimir els missatges."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Permet que una aplicació escrigui a missatges SMS emmagatzemats a la tauleta o a la targeta SIM. Les aplicacions malicioses poden suprimir els teus missatges."</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Permet a l\'aplicació escriure als missatges SMS emmagatzemats al telèfon o a la targeta SIM. Les aplicacions malicioses podrien suprimir els missatges."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"rebre WAP"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Permet a l\'aplicació rebre i processar missatges WAP. Les aplicacions malicioses poden supervisar els missatges o suprimir-los sense mostrar-vos-els."</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir els canvis d\'aplicació"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Impedeix que l\'usuari canviï a una altra aplicació."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"supervisar i controlar tots els inicis d\'aplicacions"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Permet que una aplicació supervisi i controli com el sistema inicia les activitats. Les aplicacions malicioses poden posar el sistema en greu perill. Aquest permís només és necessari per al desenvolupament, mai per a l\'ús normal."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Permet que una aplicació supervisi i controli com el sistema inicia activitats. Les aplicacions malicioses poden comprometre totalment el sistema. Aquest permís només és necessari per a desenvolupament, mai per a ús normal."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar difusió d\'eliminació de paquet"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Permet a una aplicació difondre una notificació que indica que s\'ha eliminat un paquet d\'aplicació. Les aplicacions malicioses poden utilitzar-ho per destruir qualsevol altra aplicació que s\'executi."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"enviar difusió d\'SMS rebut"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"visualitzar finestres no autoritzades"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Permet la creació de finestres que utilitzarà la interfície d\'usuari del sistema interna. No indicat per a les aplicacions normals."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"visualitzar les alertes del sistema"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Permet que una aplicació mostri les finestres d\'alerta del sistema. Les aplicacions malicioses poden agafar el control de tota la pantalla."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Permet que una aplicació mostri finestres d\'alertes del sistema. Les aplicacions malicioses poden ocupar tota la pantalla."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"modificar la velocitat d\'animacions global"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Permet a una aplicació canviar la velocitat global d\'animació (animacions més ràpides o lentes) en qualsevol moment."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"gestionar els testimonis d\'aplicació"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Permet a les aplicacions crear i gestionar els seus propis testimonis passant per alt l\'ordre Z normal. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"prémer tecles i botons de control"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Permet que una aplicació lliuri els seus propis esdeveniments d\'entrada (tecles premudes, etc.) a altres aplicacions. Les aplicacions malicioses poden utilitzar-ho per agafar el control de la tauleta."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Permet que una aplicació lliuri els seus propis esdeveniments d\'entrada (tecles premudes, etc.) a d\'altres aplicacions. Les aplicacions malicioses poden utilitzar aquesta funció per controlar la tauleta."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Permet a una aplicació lliurar els seus propis esdeveniments d\'entrada (tecles premudes, etc.) a altres aplicacions. Les aplicacions malicioses poden utilitzar-ho per agafar el control del telèfon."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"enregistrar allò que escriviu i les accions que dueu a terme"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Permet a les aplicacions fer un seguiment de les tecles que premeu, fins i tot quan s\'interactua amb una altra aplicació (com ara introduir una contrasenya). No s\'hauria de necessitar mai per a les aplicacions normals."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"instal·lar aplicacions directament"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Permet a una aplicació instal·lar paquets d\'Android nous o actualitzats. Les aplicacions malicioses poden utilitzar-ho per afegir aplicacions noves amb permisos arbitràriament potents."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"suprimir totes les dades de memòria cau d\'aplicacions"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Permet que una aplicació alliberi emmagatzematge a la tauleta suprimint fitxers del directori de la memòria cau d\'aplicacions. Normalment l\'accés es restringeix als processos del sistema."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Permet que una aplicació alliberi emmagatzematge de la tauleta suprimint fitxers al directori de la memòria cau de l\'aplicació. Habitualment, l\'accés és molt restringit a processos del sistema."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Permet a una aplicació alliberar emmagatzematge al telèfon suprimint fitxers del directori de la memòria cau d\'aplicacions. Normalment l\'accés es restringeix als processos del sistema."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Desplaça els recursos de les aplicacions"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Permet a una aplicació desplaçar els recursos d\'aplicació de suports interns a externs i viceversa."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"llegir els fitxers de registre del sistema"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Permet que una aplicació llegeixi dels fitxers de registre del sistema. Això li permet descobrir informació general sobre allò que fas amb la tauleta, i pot incloure informació personal o privada."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Permet que una aplicació llegeixi dels fitxers de registre del sistema. Això li permet descobrir informació general sobre allò que fas amb la tauleta, i pot incloure informació personal o privada."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"llegeix les dades sensibles del registre"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Permet que una aplicació llegeixi els diversos fitxers de registre del sistema. Això li permet descobrir informació general sobre què estàs fent amb la tauleta, i pot incloure informació personal o privada."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Permet que una aplicació llegeixi els diversos fitxers de registre del sistema. Això li permet descobrir informació general sobre què estàs fent amb el telèfon i, potencialment, pot incloure informació personal o privada."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"llegir/escriure recursos propietat de diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Permet a una aplicació llegir i escriure a qualsevol recurs propietat del grup diag; per exemple, els fitxers de /dev. Això podria afectar l\'estabilitat i la seguretat del sistema. Només l\'hauria d\'utilitzar el fabricant o l\'operador per a diagnòstics de maquinari."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"activar o desactivar els components de l\'aplicació"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Permet que una aplicació canviï si un component d\'una altra aplicació està activat o no. Les aplicacions malicioses poden utilitzar-ho per desactivar funcions importants de la tauleta. Cal anar amb compte amb aquest permís, ja que pot ser que els components de l\'aplicació passin a un estat inutilitzable, incoherent o inestable."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Permet que una aplicació canviï si un component d\'una altra aplicació està activat o no. Les aplicacions malicioses poden utilitzar-ho per desactivar funcions importants de la tauleta. Cal anar amb compte amb aquest permís, ja que pot ser que els components de l\'aplicació passin a un estat inutilitzable, incoherent o inestable."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Permet que una aplicació canviï si un component d\'una altra aplicació està activat o no. Les aplicacions malicioses poden utilitzar aquesta funció per desactivar funcions importants de la tauleta. Cal anar amb compte amb aquest permís, ja que és possible que els components d\'una aplicació esdevinguin inutilitzables, incoherents o inestables."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Permet que una aplicació canviï si un component d\'una altra aplicació està activat o no. Les aplicacions malicioses poden utilitzar aquesta funció per desactivar funcions importants del telèfon. Cal anar amb compte amb aquest permís, ja que és possible que els components d\'una aplicació esdevinguin inutilitzables, incoherents o inestables."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"definir les aplicacions preferides"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Permet a una aplicació modificar les aplicacions preferides. Això pot permetre a les aplicacions malicioses canviar silenciosament les aplicacions que s\'executen, falsejar les aplicacions existents o recollir dades privades vostres."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"modificar la configuració global del sistema"</string>
@@ -301,16 +299,16 @@
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Permet que una aplicació s\'iniciï tan bon punt el sistema hagi acabat d\'arrancar. Això pot fer que es trigui més en iniciar la tauleta i permetre a l\'aplicació alentir de manera generalitzada la tauleta en executar-se sempre."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Permet a una aplicació iniciar-se tan bon punt el sistema hagi acabat d\'arrancar. Això pot fer que es trigui més en iniciar el telèfon i permetre a l\'aplicació alentir de manera generalitzada el telèfon en executar-se sempre."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"enviar difusió permanent"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Permet que una aplicació enviï informacions atractives, que es conserven després de finalitzar la difusió. Les aplicacions malicioses poden alentir o desestabilitzar la tauleta en fer-li utilitzar massa memòria."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Permet que una aplicació enviï transmissions \"enganxoses\" que es queden al sistema un cop finalitzada la transmissió. Les aplicacions malicioses poden alentir la tauleta o fer-la inestable en provocar que utilitzi massa memòria."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Permet a una aplicació enviar difusions permanents, que es conserven després de finalitzar la difusió. Les aplicacions malicioses poden alentir o desestabilitzar el telèfon en fer-li utilitzar massa memòria."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"llegir les dades de contacte"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Permet que una aplicació llegeixi totes les dades de contacte (adreces) emmagatzemades a la tauleta. Les aplicacions malicioses poden utilitzar-ho per enviar les vostres dades a altres persones."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Permet que una aplicació llegeixi totes les dades dels contactes (adreces) de la tauleta. Les aplicacions malicioses poden utilitzar aquesta funció per enviar dades a altres persones."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Permet a una aplicació llegir totes les dades de contacte (adreces) emmagatzemades al telèfon. Les aplicacions malicioses poden utilitzar-ho per enviar les vostres dades a altres persones."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"escriure dades de contacte"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permet que una aplicació modifiqui les dades de contacte (adreça) emmagatzemades a la tauleta. Les aplicacions malicioses poden utilitzar-ho per esborrar o modificar les dades de contacte."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permet que una aplicació modifiqui les dades de contactes (adreces) emmagatzemades a la tauleta. Les aplicacions malicioses poden utilitzar aquesta funció per esborrar o per modificar les teves dades de contactes."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permet a una aplicació modificar les dades de contacte (adreça) emmagatzemades al telèfon. Les aplicacions malicioses poden utilitzar-ho per esborrar o modificar les dades de contacte."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"llegir els esdeveniments del calendari"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permet que una aplicació llegeixi tots els esdeveniments del calendari emmagatzemats a la tauleta. Les aplicacions malicioses poden utilitzar-ho per enviar els teus esdeveniments del calendari a altres persones."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permet que una aplicació llegeixi tots els esdeveniments del calendari emmagatzemats a la tauleta. Les aplicacions malicioses poden utilitzar aquesta funció per enviar els teus esdeveniments del calendari a altres persones."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permet a una aplicació llegir tots els esdeveniments del calendari emmagatzemats al telèfon. Les aplicacions malicioses poden utilitzar-ho per enviar els vostres esdeveniments del calendari a altres persones."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"afegir o modificar esdeveniments del calendari i enviar correu electrònic als convidats"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Permet a una aplicació afegir o canviar els esdeveniments del calendari, cosa que pot fer que s\'enviï correu electrònic als convidats. Les aplicacions malicioses poden utilitzar-ho per esborrar o modificar els esdeveniments del calendari o per enviar correu electrònic als convidats."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"permís per instal·lar un proveïdor d\'ubicacions"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Crea orígens d\'ubicacions ficticis per fer proves. Les aplicacions malicioses poden utilitzar-ho per substituir la ubicació i/o l\'estat retornats per orígens d\'ubicacions reals, com ara els proveïdors de xarxa o GPS o per supervisar i informar de la vostra ubicació a un origen extern."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"ubicació exacta (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Accedeix a orígens d\'ubicacions exactes, com ara el Sistema de posicionament global (GPS) a la tauleta, si estan disponibles. Les aplicacions malicioses poden utilitzar-ho per determinar on sou i poden consumir energia addicional de la bateria."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Accedeix a fonts d\'ubicació precises, com ara el Sistema de Posicionament Global (GPS) a la tauleta, si estan disponibles. Les aplicacions malicioses poden utilitzar aquesta funció per determinar on ets, i és possible que es consumeixi potència addicional."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Accedeix a orígens d\'ubicacions exactes, com ara el Servei de posicionament global (GPS) al telèfon, si estan disponibles. Les aplicacions malicioses poden utilitzar-ho per determinar on sou i poden consumir energia addicional de la bateria."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"ubicació aproximada (basada en xarxa)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Accedeix a orígens d\'ubicacions aproximades, com ara la base de dades de la xarxa de telefonia mòbil, per determinar la ubicació aproximada de la tauleta, si aquesta funció està disponible. Les aplicacions malicioses poden utilitzar-ho per determinar on ets aproximadament."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Accedeix a completes fonts d\'ubicació, com ara la base de dades de la xarxa mòbil, per determinar una ubicació aproximada de la tauleta, si està disponible. Les aplicacions malicioses poden utilitzar aquesta funció per determinar la teva ubicació aproximada."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Accedeix a orígens d\'ubicacions aproximades, com ara la base de dades de la xarxa de telefonia mòbil, per determinar la ubicació aproximada del telèfon, si aquesta funció està disponible. Les aplicacions malicioses poden utilitzar-ho per determinar on sou aproximadament."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"accedir a SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Permet a l\'aplicació utilitzar les funcions de baix nivell de SurfaceFlinger."</string>
@@ -334,37 +332,39 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Permet a l\'aplicació modificar la configuració global de l\'àudio, com ara el volum i l\'encaminament."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"enregistrar àudio"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Permet a l\'aplicació accedir al camí d\'enregistrament d\'àudio."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"fer fotos"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Permet a l\'aplicació fer fotos amb la càmera. Això li permet recollir les imatges que veu la càmera en qualsevol moment."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"desactivar la tauleta de manera permanent"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"fes fotos i vídeos"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Permet que l\'aplicació faci fotos i vídeos amb la càmera. Això permet que l\'aplicació pugui recopilar les imatges que està veient la càmera en qualsevol moment."</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"desactiva la tauleta de manera permanent"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"desactivar definitivament el telèfon"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Permet a l\'aplicació desactivar tota la tauleta definitivament. Això és molt perillós."</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Permet que l\'aplicació desactivi tota la tauleta de manera permanent. Aquesta acció és molt perillosa."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Permet a l\'aplicació desactivar tot el telèfon definitivament. Això és molt perillós."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"forçar l\'arrencada de la tauleta"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"fes que la tauleta es reiniciï"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"forçar el reinici del telèfon"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Permet que l\'aplicació forci l\'arrencada de la tauleta."</string>
+    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Permet que l\'aplicació faci que es reiniciï la tauleta."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Permet a l\'aplicació forçar el reinici del telèfon."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"muntar i desmuntar sistemes de fitxers"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Permet a l\'aplicació muntar i desmuntar sistemes de fitxers per a l\'emmagatzematge extraïble."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formatar l\'emmagatzematge extern"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Permet a l\'aplicació formatar l\'emmagatzematge extraïble."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"obtenir informació sobre l\'emmagatzematge segur"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Permet a l\'aplicació obtenir informació sobre l\'emmagatzematge segur."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"crear emmagatzematge segur"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Permet a l\'aplicació crear emmagatzematge segur."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"destruir l\'emmagatzematge segur"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Permet a l\'aplicació destruir l\'emmagatzematge segur."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"muntar i desmuntar l\'emmagatzematge segur"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Permet a l\'aplicació muntar o desmuntar l\'emmagatzematge segur."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"canviar el nom de l\'emmagatzematge segur"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Permet a l\'aplicació canviar el nom de l\'emmagatzematge segur."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"obtén informació sobre l\'emmagatzematge intern"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Permet que l\'aplicació obtingui informació de l\'emmagatzematge intern."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"crea emmagatzematge intern"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Permet que l\'aplicació creï emmagatzematge intern."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"destrueix l\'emmagatzematge intern"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Permet que l\'aplicació destrueixi l\'emmagatzematge intern."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"instal·la / desinstal·la l\'emmagatzematge intern"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Permet que l\'aplicació instal·li / desinstal·li l\'emmagatzematge intern."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"canvia el nom de l\'emmagatzematge intern"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Permet que l\'aplicació canviï el nom de l\'emmagatzematge intern."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"controlar el vibrador"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permet a l\'aplicació controlar el vibrador."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"controlar el flaix"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permet a l\'aplicació controlar el flaix."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"accedeix a dispositius USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Permet que l\'aplicació accedeixi als dispositius USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"provar el maquinari"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Permet a l\'aplicació controlar diversos perifèrics per fer proves de maquinari."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"Permet a l\'aplicació trucar a números de telèfon sense la vostra intervenció. Les aplicacions malicioses poden fer que apareguin trucades inesperades a la factura del telèfon. Tingueu en compte que això no permet a l\'aplicació trucar a números d\'emergència."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"trucar directament a qualsevol número de telèfon"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Permet a l\'aplicació trucar a qualsevol número de telèfon, inclosos els números d\'emergència, sense la vostra intervenció. Les aplicacions malicioses poden fer trucades innecessàries i il·legals a serveis d\'emergència."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"iniciar directament la configuració de la tauleta CDMA"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"inicia directament la configuració de la tauleta CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar directament la configuració del telèfon CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Permet a l\'aplicació iniciar l\'aprovisionament CDMA. Les aplicacions malicioses podrien iniciar l\'aprovisionament CDMA innecessàriament."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar les notificacions d\'actualització de la ubicació"</string>
@@ -385,16 +385,16 @@
     <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Permet a l\'aplicació controlar les funcions de telèfon del dispositiu. Una aplicació amb aquest permís pot canviar de xarxa, activar i desactivar la ràdio del telèfon i dur a terme accions semblants sense notificar-vos-ho."</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"llegir l\'estat i la identitat del telèfon"</string>
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"Permet a l\'aplicació accedir a les funcions de telèfon del dispositiu. Una aplicació amb aquest permís pot determinar el número de telèfon i el número de sèrie del telèfon, si una trucada està activa, el número al qual s\'ha connectat la trucada i elements semblants."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"impedir que la tauleta se suspengui"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evita que la tauleta entri en mode d\'inactivitat"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"impedir que el telèfon se suspengui"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Permet que una aplicació impedeixi que la tauleta se suspengui."</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Permet que una aplicació impedeixi que la tauleta entri en mode d\'inactivitat."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Permet a una aplicació impedir que el telèfon se suspengui."</string>
-    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"engegar o apagar la tauleta"</string>
+    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"activa o desactiva la tauleta"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"engegar o apagar el telèfon"</string>
-    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Permet que l\'aplicació engegui o apagui la tauleta."</string>
+    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Permet que l\'aplicació encengui i apagui la tauleta."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Permet a l\'aplicació engegar o apagar el telèfon."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"executar en mode de proves de fàbrica"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"S\'executa com a prova del fabricant de baix nivell, cosa que permet l\'accés total al maquinari de la tauleta. Només està disponible quan una tauleta s\'executa en mode de proves del fabricant."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Executa com a prova de perfil baix del fabricant que permet accés complet al maquinari de la tauleta. Només està disponible quan la tauleta s\'executa en mode de prova del fabricant."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"S\'executa com a prova del fabricant de baix nivell, cosa que permet l\'accés total al maquinari del telèfon. Només està disponible quan un telèfon s\'executa en mode de proves del fabricant."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"definir l\'empaperat"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Permet l\'aplicació definir l\'empaperat del sistema."</string>
@@ -406,12 +406,12 @@
     <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Permet que una aplicació canviï l\'hora del rellotge de la tauleta."</string>
     <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Permet a una aplicació canviar l\'hora del rellotge del telèfon."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"definir el fus horari"</string>
-    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Permet que una aplicació canviï el fus horari de la tauleta."</string>
+    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Permet que una aplicació canviï la zona horària de la tauleta."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Permet a una aplicació canviar el fus horari del telèfon."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"actuar com a AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Permet a una aplicació fer trucades a autenticadors de comptes"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"descobrir comptes coneguts"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Permet que una aplicació obtingui la llista de comptes que coneix la tauleta."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Permet que una aplicació obtingui la llista de comptes coneguts per la tauleta."</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Permet a una aplicació obtenir la llista de comptes que coneix el telèfon."</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"fer d\'autenticador de comptes"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Permet a una aplicació utilitzar les funcions d\'autenticador de comptes d\'AccountManager, incloses la creació de comptes i l\'obtenció i la definició de les seves contrasenyes."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"permetre la recepció de multidifusió Wi-fi"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Permet a una aplicació rebre paquets no adreçats directament al vostre dispositiu. Això pot ser útil en detectar serveis oferts a prop. Utilitza més energia que el mode que no utilitza la multidifusió."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"administració de Bluetooth"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Permet que una aplicació configuri la tauleta Bluetooth local i que detecti dispositius remots i s\'hi emparelli."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Permet que una aplicació configuri la tauleta Bluetooth local i que cerqui i emparelli dispositius remots."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Permet a una aplicació configurar el telèfon Bluetooth local i detectar dispositius remots i emparellar-se amb ells."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"crear connexions Bluetooth"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Permet que una aplicació visualitzi la configuració de la tauleta Bluetooth local i que estableixi i accepti connexions amb els dispositius emparellats."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Permet que una aplicació mostri la configuració de la tauleta Bluetooth local i que estableixi i accepti connexions amb dispositius emparellats."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Permet a una aplicació visualitzar la configuració del telèfon Bluetooth local i establir i acceptar connexions amb els dispositius emparellats."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"controla Near Field Communication (NFC)"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Permet que una aplicació es comuniqui amb les etiquetes, les targetes i els lectors de Near Field Communication (NFC)"</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"desactivar el bloqueig del teclat"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permet a una aplicació desactivar el bloqueig del teclat i qualsevol element de seguretat de contrasenyes associat. Un exemple d\'això és la desactivació per part del telèfon del bloqueig del teclat en rebre una trucada telefònica entrant i després la reactivació del bloqueig del teclat quan finalitza la trucada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"llegir la configuració de sincronització"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Permet a una aplicació llegir les paraules, els noms i les frases privats que l\'usuari pot haver emmagatzemat al diccionari de l\'usuari."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"escriure al diccionari definit per l\'usuari"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Permet a una aplicació escriure paraules noves al diccionari de l\'usuari."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modificar/suprimir el contingut de les targetes SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modifica/suprimeix el contingut de l\'emmagatzematge USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificar/suprimir el contingut de les targetes SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Permet a una aplicació escriure a la targeta SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Permet que una aplicació gravii a l\'emmagatzematge USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Permet a una aplicació escriure a la targeta SD."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modifica/suprimeix el contingut d\'emmagatzematge de mitjans interns"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Permet que una aplicació modifiqui el contingut de l\'emmagatzematge de mitjans interns."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"accedir al sistema de fitxers de la memòria cau"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permet a una aplicació llegir el sistema de fitxers de la memòria cau i escriure-hi."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Limita la contrasenya"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Restringeix els tipus de contrasenyes que podeu utilitzar."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Vigila els intents d\'inici de sessió"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Controla el nombre de contrasenyes incorrectes que s\'han introduït quan es desbloqueja la pantalla, i bloqueja la tauleta o esborra\'n totes les dades si s\'introdueixen massa contrasenyes incorrectes"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Controla el nombre de contrasenyes incorrectes que s\'han introduït quan es desbloqueja la pantalla, i bloqueja la tauleta o esborra\'n totes les dades si s\'introdueixen massa contrasenyes incorrectes"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Restableix la contrasenya"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Força un valor nou per a la contrasenya, amb la qual cosa l\'administrador us l\'ha de donar perquè pugueu iniciar la sessió."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Força el bloqueig"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Controla quan es bloqueja el dispositiu i requereix que en torneu a introduir la contrasenya."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"fes/rep trucades per Internet"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Permet que una aplicació utilitzi el servei SIP per fer i rebre trucades per Internet."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Defineix les normes de contrasenya"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa els intents de desbloqueig de la pantalla"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja la tauleta o n\'esborra totes les dades si s\'introdueixen massa contrasenyes incorrectes"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el telèfon o esborra totes les dades del telèfon si s\'introdueixen massa contrasenyes incorrectes"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Canvia la contrasenya de desbloqueig de pantalla"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Canvia la contrasenya de desbloqueig de pantalla"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Bloqueja la pantalla"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Controla com i quan es bloqueja la pantalla"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Esborra totes les dades"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Esborra les dades de la tauleta sense cap advertiment i restableix les dades de fàbrica"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Esborra les dades de la tauleta sense cap advertiment i restableix les dades de fàbrica"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Esborra les dades de la tauleta sense advertiment mitjançant un restabliment de les dades de fàbrica"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Esborra les dades del telèfon sense advertiment mitjançant un restabliment de les dades de fàbrica"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Defineix el servidor intermediari global del dispositiu"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Defineix el servidor intermediari global del dispositiu que cal utilitzar mentre la política estigui activada. Només el primer administrador del dispositiu pot definir el servidor intermediari global efectiu."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Defineix la caducitat de la contrasenya"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Controla quant de temps abans de la pantalla de bloqueig cal canviar la contrasenya"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Casa"</item>
     <item msgid="869923650527136615">"Mòbil"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Cercapersones de la feina"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Auxiliar"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Personalitzats"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Aniversari"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Aniversari"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Esdeveniment"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Altres"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Personalitzada"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Casa"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Feina"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Feina"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Altres"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Personalitzat"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Personalitzada"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Assistent"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Germà"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Fill"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Parella de fet"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Pare"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Amic"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Gerent"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Mare"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Pare/mare"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Company"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Recomanat per"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Familiar"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Germana"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Cònjuge"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personalitzada"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Particular"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Feina"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Altres"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Introduïu el codi PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Introduïu la contrasenya per desbloquejar-lo"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Introdueix el PIN per desbloquejar"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Codi PIN incorrecte."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Per desbloquejar-lo, premeu Menú i després 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Número d\'emergència"</string>
@@ -646,8 +615,7 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Torna a la trucada"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Correcte!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Torneu-ho a provar"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Torna-ho a provar"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"S\'està carregant (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Carregada."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"La targeta SIM està bloquejada."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"S\'està desbloquejant la targeta SIM..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Heu dibuixat el patró de desbloqueig de manera incorrecta <xliff:g id="NUMBER_0">%d</xliff:g> vegades. "\n\n"Torneu-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%d</xliff:g> segons."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Has dibuixat malament el patró de desbloqueig <xliff:g id="NUMBER_0">%d</xliff:g> vegades. Després de <xliff:g id="NUMBER_1">%d</xliff:g> intents incorrectes més, se\'t demanarà que desbloquegis la tauleta amb l\'inici de sessió de Google."\n\n" Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%d</xliff:g> segons."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Has introduït una contrasenya incorrecta <xliff:g id="NUMBER_0">%d</xliff:g> vegades. "\n\n"Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%d</xliff:g> segons."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Has introduït un PIN incorrecte <xliff:g id="NUMBER_0">%d</xliff:g> vegades. "\n\n"Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%d</xliff:g> segons."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Has dibuixat incorrectament el teu patró de desbloqueig <xliff:g id="NUMBER_0">%d</xliff:g> vegades. Després de <xliff:g id="NUMBER_1">%d</xliff:g> intents incorrectes més, el sistema et demanarà que desbloquegis la tauleta utilitzant l\'inici de sessió de Google."\n\n" Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%d</xliff:g> segons."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Heu dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%d</xliff:g> vegades de manera incorrecta. Després de <xliff:g id="NUMBER_1">%d</xliff:g> intents incorrectes més, se us demanarà que desbloquegeu el telèfon amb l\'inici de sessió de Google."\n\n" Torneu-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%d</xliff:g> segons."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Torneu-ho a provar d\'aquí a <xliff:g id="NUMBER">%d</xliff:g> segons."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Heu oblidat el patró?"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Voleu sortir d\'aquesta pàgina?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Seleccioneu D\'acord per continuar o Cancel·la per quedar-vos a la pàgina actual."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Confirma"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Consell: Piqueu dos cops per ampliar i reduir."</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"Emp. aut"</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"Emplenament automàtic"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Conf. Empl. aut."</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"llegir l\'historial i les adreces d\'interès del navegador"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permet a l\'aplicació llegir tots els URL que ha visitat el navegador i totes les adreces d\'interès del navegador."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"escriure l\'historial i les adreces d\'interès del navegador"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Permet que una aplicació modifiqui l\'historial o els marcadors del navegador emmagatzemats a la tauleta. Les aplicacions malicioses poden utilitzar-ho per esborrar o per modificar les dades del navegador."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Permet que una aplicació modifiqui l\'historial del navegador o els marcadors emmagatzemats a la tauleta. Les aplicacions malicioses poden utilitzar aquesta funció per esborrar o per modificar les dades del navegador."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permet a una aplicació modificar l\'historial o les adreces d\'interès del navegador emmagatzemats al telèfon. Les aplicacions malicioses poden utilitzar-ho per esborrar o modificar les dades del navegador."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"defineix l\'alarma com a despertador"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permet que l\'aplicació defineixi una alarma en una aplicació de despertador instal·lada. És possible que algunes aplicacions de despertador no incorporin aquesta funció."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modifica els permisos d\'ubicació geogràfica del navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permet a una aplicació modificar els permisos d\'ubicació geogràfica del navegador. Les aplicacions malicioses poden utilitzar-ho per permetre l\'enviament d\'informació d\'ubicació a llocs web arbitraris."</string>
     <string name="save_password_message" msgid="767344687139195790">"Voleu que el navegador recordi aquesta contrasenya?"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"Retalla"</string>
     <string name="copy" msgid="2681946229533511987">"Copia"</string>
     <string name="paste" msgid="5629880836805036433">"Enganxa"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Cap elem. per engan."</string>
     <string name="copyUrl" msgid="2538211579596067402">"Copia l\'URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Selecciona el text..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selecció de text"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Mètode d\'entrada"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Edita el text"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Accions de text"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Queda poc espai"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Comença a quedar poc espai d\'emmagatzematge a la tauleta."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"L\'espai d\'emmagatzematge de la tauleta comença a ser escàs."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Comença a quedar poc espai d\'emmagatzematge al telèfon."</string>
     <string name="ok" msgid="5970060430562524910">"D\'acord"</string>
     <string name="cancel" msgid="6442560571259935130">"Cancel·la"</string>
     <string name="yes" msgid="5362982303337969312">"D\'acord"</string>
     <string name="no" msgid="5141531044935541497">"Cancel·la"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Atenció"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"S\'està carregant..."</string>
     <string name="capital_on" msgid="1544682755514494298">"ACTIVAT"</string>
     <string name="capital_off" msgid="6815870386972805832">"DESACTIVAT"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Completa l\'acció mitjançant"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Força el tancament"</string>
     <string name="report" msgid="4060218260984795706">"Informe"</string>
     <string name="wait" msgid="7147118217226317732">"Espera"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Aplicació redirigida"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> s\'està executant."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> es va iniciar originalment."</string>
+    <string name="smv_application" msgid="295583804361236288">"L\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g> (procés <xliff:g id="PROCESS">%2$s</xliff:g>) ha incomplert la seva política autoimposada de mode estricte."</string>
+    <string name="smv_process" msgid="5120397012047462446">"El procés <xliff:g id="PROCESS">%1$s</xliff:g> ha incomplert la seva política de mode estricte."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> s\'està executant"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Selecciona per canviar a l\'aplicació"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Canvi d\'aplicacions?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Ja està funcionant una altra aplicació que s\'ha d\'aturar abans de poder iniciar-ne una de nova."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Torna a <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"No iniciïs la nova aplicació."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Inicia <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Atura l\'aplicació antiga sense desar."</string>
     <string name="sendText" msgid="5132506121645618310">"Seleccioneu una acció per al text"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Volum del timbre"</string>
     <string name="volume_music" msgid="5421651157138628171">"Volum de multimèdia"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Mostra\'ls tots"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Emmagatzematge massiu USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB connectat"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Heu connectat el telèfon a l\'equip per USB. Seleccioneu el botó de més avall si voleu copiar fitxers entre l\'equip i la targeta SD d\'Android."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Heu connectat el telèfon a l\'equip per USB. Seleccioneu el botó de més avall si voleu copiar fitxers entre l\'equip i la targeta SD d\'Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"T\'has connectat a l\'equip per USB. Toca el botó següent si vols copiar els fitxers entre l\'equip i l\'emmagatzematge USB d\'Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"T\'has connectat a l\'equip per USB. Toca el botó següent si vols copiar els fitxers entre l\'equip i la targeta SD d\'Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Activa l\'emmagatzematge USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Hi ha un problema per utilitzar la targeta SD per a l\'emmagatzematge USB."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Hi ha un problema per utilitzar la targeta SD per a l\'emmagatzematge USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Hi ha un problema en l\'ús del teu emmagatzematge USB per a emmagatzematge massiu USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Hi ha un problema en l\'ús de la teva targeta SD per a l\'emmagatzematge massiu USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB connectat"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Seleccioneu-ho per copiar fitxers a/de l\'equip."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Desactiva l\'emmagatzematge USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Seleccioneu-ho per desactivar l\'emmagatzematge USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"S\'està utilitzant l\'emmagatzematge USB"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Abans de desactivar l\'emmagatzematge USB, assegureu-vos d\'haver desmuntat (\"expulsat\") la targeta SD d\'Android de l\'equip."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Abans de desactivar l\'emmagatzematge USB, assegura\'t d\'haver desinstal·lat (\"expulsat\") l\'emmagatzematge USB de l\'Android del teu equip."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Abans de desactivar l\'emmagatzematge USB, assegureu-vos d\'haver desmuntat (\"expulsat\") la targeta SD d\'Android de l\'equip."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Desactiva l\'emmagatzematge USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"S\'ha produït un problema en desactivar l\'emmagatzematge USB. Comproveu que heu desmuntat l\'amfitrió d\'USB i torneu-ho a provar."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Si activeu l\'emmagatzematge USB, algunes de les aplicacions que utilitzeu s\'aturaran i pot ser que no estiguin disponibles fins que desactiveu l\'emmagatzematge USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Error de l\'operació d\'USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"D\'acord"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formata la targeta SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formata l\'emmag. USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formata la targeta SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Esteu segur que voleu formatar la targeta SD? Es perdran totes les dades de la targeta."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vols formatar l\'emmagatzematge USB i esborrar tots els fitxers que hi ha emmagatzemats? L\'acció no es podrà desfer."</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Esteu segur que voleu formatar la targeta SD? Es perdran totes les dades de la targeta."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formata"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depuració d\'USB connectada"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"S\'està preparant la targeta SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"S\'està preparant l\'emmagatzematge USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"S\'està preparant la targeta SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"S\'està comprovant si hi ha errors."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Targeta SD en blanc"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Emmagatzematge USB buit"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Targeta SD en blanc"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"La targeta SD és buida o té un sistema de fitxers incompatible."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Emmagatzematge USB buit o sistema de fitxers no admès."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"La targeta SD és buida o té un sistema de fitxers incompatible."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Targeta SD malmesa"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Emmagatzematge USB danyat"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Targeta SD malmesa"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Targeta SD malmesa. Pot ser que l\'hàgiu de tornar a formatar."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Emmagatzematge USB danyat. És possible que l\'hagis de tornar a formatar."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Targeta SD malmesa. Pot ser que l\'hàgiu de tornar a formatar."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Targeta SD extreta inesperadament"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Emmag. USB retirat inesperadament"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Targeta SD extreta inesperadament"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Expulseu la targeta SD abans d\'extreure-la per evitar la pèrdua de dades."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Desinstal·la l\'emmagatzematge USB abans de retirar-la per evitar pèrdues de dades."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Expulseu la targeta SD abans d\'extreure-la per evitar la pèrdua de dades."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"La targeta SD es pot extreure"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"És segur retirar l\'emmagatzematge USB"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"La targeta SD es pot extreure"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Podeu extreure la targeta SD sense problemes."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Pots retirar l\'emmagatzematge USB de forma segura."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Podeu extreure la targeta SD sense problemes."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Targeta SD extreta"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Emmagatzematge USB retirat"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Targeta SD extreta"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"S\'ha extret la targeta SD. Inseriu-ne una."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Emmagatzematge USB retirat. Insereix el mitjà nou."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"S\'ha extret la targeta SD. Inseriu-ne una."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"No s\'ha trobat cap activitat coincident"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualitzar les estadístiques d\'ús de components"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Envia"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Següent"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Fet"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Anterior"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Executa"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Marca el número"\n"mitjançant <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Crea un contacte"\n"mitjançant <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec basada en clau compartida prèviament"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec basada en certificats"</string>
     <string name="upload_file" msgid="2897957172366730416">"Trieu un fitxer"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"No s\'ha escollit cap fitxer"</string>
     <string name="reset" msgid="2448168080964209908">"Reinicia"</string>
     <string name="submit" msgid="1602335572089911941">"Envia"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Mode de cotxe activat"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Seleccioneu-ho per sortir del mode de cotxe."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Ancoratge a la xarxa o punt de connexió actiu"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Toqueu per configurar"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Enrere"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Següent"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Omet"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Ús de dades mòbils alt"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Toqueu-ho per obtenir més informació sobre l\'ús de dades als mòbils"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"S\'ha superat el límit de dades mòbils"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Toqueu-ho per obtenir més informació sobre l\'ús de dades als mòbils"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Cap coincidència"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Troba-ho a la pàgina"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 coincidència"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Fet"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"S\'està desinstal·lant l\'emmagatzematge USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"S\'està desinstal·lant la targeta SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"S\'està esborrant l\'emmagatzematge USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"S\'està esborrant la targeta SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"S\'ha produït un error en esborrar l\'emmagatzematge USB."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"S\'ha produït un error en esborrar la targeta SD."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"La targeta SD s\'ha retirat abans de desinstal·lar-la."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Actualment s\'està comprovant l\'emmagatzematge USB."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"S\'està comprovant la targeta SD."</string>
+    <string name="media_removed" msgid="7001526905057952097">"S\'ha retirat la targeta SD."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Actualment, un equip està utilitzant l\'emmagatzematge USB."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Actualment, un equip està utilitzant la targeta SD."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Mitjà extern en un estat desconegut."</string>
+    <string name="share" msgid="1778686618230011964">"Comparteix"</string>
+    <string name="find" msgid="4808270900322985960">"Cerca"</string>
+    <string name="websearch" msgid="4337157977400211589">"Cerca al web"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 50cd0c3..441ad01 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim V letadle"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim V letadle je ZAPNUTÝ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim V letadle je VYPNUTÝ"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Zpoplatněné služby"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Umožňuje aplikaci ovládat kontrolku."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"přístup k zařízením USB"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Umožní aplikaci přístup k zařízením USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testování hardwaru"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Umožňuje aplikaci ovládat různé periferie pro účely testování hardwaru."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"přímé volání na telefonní čísla"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Neznámý stav externího média."</string>
     <string name="share" msgid="1778686618230011964">"Sdílet"</string>
     <string name="find" msgid="4808270900322985960">"Najít"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Vyhledat na webu"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 6c46995..0242ee9 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flytilstand"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flytilstand er TIL"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flytilstand er slået FRA"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tjenester, der koster dig penge"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Tillader, at programmet kontrollerer lommelygten."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"adgang til USB-enheder."</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Tillader, at programmet har adgang til USB-enheder."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"test hardware"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Tillader, at et program kontrollerer forskellige perifere enheder for at teste hardwaren."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"ring direkte op til telefonnumre"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Eksternt medie i ukendt tilstand."</string>
     <string name="share" msgid="1778686618230011964">"Del"</string>
     <string name="find" msgid="4808270900322985960">"Find"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Websøgning"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 8e23d5b..87f14c5 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flugmodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flugmodus ist AN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flugmodus ist aus"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Kostenpflichtige Dienste"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Ermöglicht der Anwendung, die Lichtanzeige zu steuern."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"auf USB-Geräte zugreifen"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Ermöglicht der Anwendung den Zugriff auf USB-Geräte."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"Hardware testen"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Ermöglicht einer Anwendung, verschiedene Peripherie-Geräte zu Hardware-Testzwecken zu steuern."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"Telefonnummern direkt anrufen"</string>
@@ -541,7 +547,7 @@
     <string name="phoneTypeIsdn" msgid="8022453193171370337">"ISDN"</string>
     <string name="phoneTypeMain" msgid="6766137010628326916">"Hauptnummer"</string>
     <string name="phoneTypeOtherFax" msgid="8587657145072446565">"Weitere Faxnummer"</string>
-    <string name="phoneTypeRadio" msgid="4093738079908667513">"Radio"</string>
+    <string name="phoneTypeRadio" msgid="4093738079908667513">"Funktelefon"</string>
     <string name="phoneTypeTelex" msgid="3367879952476250512">"Telex"</string>
     <string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY/TDD"</string>
     <string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Handy (geschäftl.)"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Unbekannter Status des externen Speichermediums"</string>
     <string name="share" msgid="1778686618230011964">"Freigeben"</string>
     <string name="find" msgid="4808270900322985960">"Suchen"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Websuche"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 5dd1372..6b8db1e 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Λειτουργία πτήσης"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Η λειτουργία πτήσης είναι ενεργοποιημένη."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Η λειτουργία πτήσης είναι απενεργοποιημένη"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Σύστημα Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Υπηρεσίες επί πληρωμή"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Επιτρέπει στην εφαρμογή τον έλεγχο του φακού."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"πρόσβαση σε συσκευές USB"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Επιτρέπει στην εφαρμογή την πρόσβαση σε συσκευές USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"δοκιμή υλικού"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Επιτρέπει σε μια εφαρμογή τον έλεγχο διαφόρων περιφερειακών για την εκτέλεση δοκιμών υλικού."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"απευθείας κλήση τηλεφωνικών αριθμών"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Το εξωτερικό μέσο είναι σε άγνωστη κατάσταση."</string>
     <string name="share" msgid="1778686618230011964">"Κοινή χρ."</string>
     <string name="find" msgid="4808270900322985960">"Εύρεση"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Αναζήτηση ιστού"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index f1d19b8..a981ed6 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -138,8 +138,7 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"Shutting down…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Your tablet will shut down."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Your phone will shut down."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Would you like to shut down?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recent"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"No recent applications."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Tablet options"</string>
@@ -152,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Airplane mode"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Aiplane mode is ON"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Airplane mode is OFF"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services that cost you money"</string>
@@ -176,7 +177,7 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Development tools"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Features only needed for application developers."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Storage"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Access the SD card."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Access the USB storage."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Access the SD card."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"disable or modify status bar"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Allows application to disable the status bar or add and remove system icons."</string>
@@ -241,7 +242,7 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"display unauthorised windows"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Allows the creation of windows that are intended to be used by the internal system user interface. Not for use by normal applications."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"display system-level alerts"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Allows an application to show system-alert windows. Malicious applications can take over the entire screen."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Allows an application to show system alert windows. Malicious applications can take over the entire screen."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"modify global animation speed"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Allows an application to change the global animation speed (faster or slower animations) at any time."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"manage application tokens"</string>
@@ -274,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"directly install applications"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Allows an application to install new or updated Android packages. Malicious applications can use this to add new applications with arbitrarily powerful permissions."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"delete all application cache data"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Allows an application to free tablet storage by deleting files in application cache directory. Access is very restricted, usually to system processes."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Allows an application to free tablet storage by deleting files in application cache directory. Access is very restricted, usually to system process."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Allows an application to free phone storage by deleting files in application cache directory. Access is usually very restricted to system process."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Move application resources"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Allows an application to move application resources from internal to external media and vice versa."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"read system log files"</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"read sensitive log data"</string>
     <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Allows an application to read from the system\'s various log files. This allows it to discover general information about what you are doing with the tablet, potentially including personal or private information."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Allows an application to read from the system\'s various log files. This allows it to discover general information about what you are doing with the tablet, potentially including personal or private information."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Allows an application to read from the system\'s various log files. This allows it to discover general information about what you are doing with the phone, potentially including personal or private information."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"read/write to resources owned by diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Allows an application to read and write to any resource owned by the diag group; for example, files in /dev. This could potentially affect system stability and security. This should ONLY be used for hardware-specific diagnostics by the manufacturer or operator."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"enable or disable application components"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Allows an application to change whether a component of another application is enabled or not. Malicious applications can use this to disable important tablet capabilities. Care must be used with this permission, as it is possible to get application components into an unusable, inconsistent or unstable state."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Allows an application to change whether a component of another application is enabled or not. Malicious applications can use this to disable important tablet capabilities. Care must be used with this permission, as it is possible to get application components into an unusable, inconsistent or unstable state."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Allows an application to change whether a component of another application is enabled or not. Malicious applications can use this to disable important phone capabilities. Care must be used with this permission, as it is possible to get application components into an unusable, inconsistent or unstable state."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"set preferred applications"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Allows an application to modify your preferred applications. This can allow malicious applications to silently change the applications that are run, spoofing your existing applications to collect private data from you."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"modify global system settings"</string>
@@ -318,7 +319,7 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"permission to install a location provider"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Create mock location sources for testing. Malicious applications can use this to override the location and/or status returned by real-location sources such as GPS or Network providers, or monitor and report your location to an external source."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"fine (GPS) location"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Access fine location sources, such as the Global Positioning System on the tablet, where available. Malicious applications can use this to determine where you are. This may consume additional battery power."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Access fine location sources such as the Global Positioning System on the tablet, where available. Malicious applications can use this to determine where you are and may consume additional battery power."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Access fine location sources, such as the Global Positioning System on the phone, where available. Malicious applications can use this to determine where you are and may consume additional battery power."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"coarse (network-based) location"</string>
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Access coarse location sources, such as the mobile network database, to determine an approximate tablet location, where available. Malicious applications can use this to determine approximately where you are."</string>
@@ -345,22 +346,26 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Allows the application to mount and unmount file systems for removable storage."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"format external storage"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Allows the application to format removable storage."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"get information on secure storage"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Allows the application to get information on secure storage."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"create secure storage"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Allows the application to create secure storage."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"destroy secure storage"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Allows the application to destroy secure storage."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"mount/unmount secure storage"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Allows the application to mount/unmount secure storage."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"rename secure storage"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Allows the application to rename secure storage."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"get information on internal storage"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Allows the application to get information on internal storage."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"create internal storage"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Allows the application to create internal storage."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"destroy internal storage"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Allows the application to destroy internal storage."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"mount/unmount internal storage"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Allows the application to mount/unmount internal storage."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"rename internal storage"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Allows the application to rename internal storage."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"control vibrator"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Allows the application to control the vibrator."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"control flashlight"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Allows the application to control the flashlight."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"access USB devices"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Allows the application to access USB devices."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"test hardware"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Allows the application to control various peripherals for the purpose of hardware testing."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"directly call phone numbers"</string>
@@ -384,7 +389,7 @@
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"prevent phone from sleeping"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Allows an application to prevent the tablet from going to sleep."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Allows an application to prevent the phone from going to sleep."</string>
-    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"Turn tablet on or off"</string>
+    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"turn tablet on or off"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"turn phone on or off"</string>
     <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Allows the application to turn the tablet on or off."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Allows the application to turn the phone on or off."</string>
@@ -438,10 +443,8 @@
     <string name="permlab_bluetooth" msgid="8361038707857018732">"create Bluetooth connections"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Allows an application to view configuration of the local Bluetooth tablet and to make and accept connections with paired devices."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Allows an application to view configuration of the local Bluetooth phone and to make and accept connections with paired devices."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"control Near-Field Communication"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Allows an application to communicate with Near-Field Communication (NFC) tags, cards and readers."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"disable key lock"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Allows an application to disable the key lock and any associated password security. A legitimate example of this is the phone disabling the key lock when receiving an incoming phone call, then re-enabling the key lock when the call is finished."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"read sync settings"</string>
@@ -458,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Allows an application to read any private words, names and phrases that the user may have stored in the user dictionary."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"write to user-defined dictionary"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Allows an application to write new words into the user dictionary."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modify/delete SD card contents"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modify/delete USB storage contents"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modify/delete SD card contents"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Allows an application to write to the SD card."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Allows an application to write to the USB storage."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Allows an application to write to the SD card."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modify/delete internal media storage contents"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Allows an application to modify the contents of the internal media storage."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"access the cache file system"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Allows an application to read and write the cache file system."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Limit password"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Restrict the types of passwords that you are allowed to use."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Watch login attempts"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Monitor the number of incorrect passwords entered when unlocking the screen and lock the tablet or erase all the tablet\'s data if too many incorrect passwords are entered."</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Monitor the number of incorrect passwords entered when unlocking the screen and lock the tablet or erase all the tablet\'s data if too many incorrect passwords are entered."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Reset Password"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Force your password to a new value, requiring the administrator to give it to you before you can log in."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Force lock"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Control when device locks, requiring you to re-enter its password."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"make/receive Internet calls"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Allows an application to use the SIP service to make/receive Internet calls."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Control the length and the characters allowed in screen-unlock passwords"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Monitor the number of incorrect passwords entered when unlocking the screen and lock the tablet or erase all the tablet\'s data if too many incorrect passwords are entered"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Monitor the number of incorrect passwords entered when unlocking the screen and lock the phone or erase all the phone\'s data if too many incorrect passwords are entered"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Change the screen-unlock password"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Change the screen-unlock password"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Lock the screen"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Control how and when the screen locks"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Erase all data"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Erase the tablet\'s data without warning by performing a factory data reset"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Erase the tablet\'s data without warning by performing a factory data reset"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Erase the phone\'s data without warning by performing a factory data reset"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Set the device global proxy"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Set the device\'s global proxy to be used while policy is enabled. Only the first device admin sets the effective global proxy."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Set password expiry"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Control how long before lock-screen password needs to be changed"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Home"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -556,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Work Pager"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Assistant"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Customised"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Birthday"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Anniversary"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Event"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Other"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Custom"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Home"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Work"</string>
@@ -587,44 +581,25 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Work"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Other"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Custom"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Customised"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Assistant"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Brother"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Child"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Domestic Partner"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Father"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Friend"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Manager"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Mother"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Parent"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Partner"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Referred by"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Relative"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Sister"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Spouse"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Customised"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Home"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Work"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Other"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Enter PIN code"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Enter password to unlock"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Enter PIN to unlock"</string>
@@ -689,23 +664,17 @@
     <string name="double_tap_toast" msgid="1068216937244567247">"Tip: double-tap to zoom in and out."</string>
     <string name="autofill_this_form" msgid="1272247532604569872">"Auto-Fill"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Set up Auto-Fill"</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"read Browser\'s history and bookmarks"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Allows the application to read all the URLs that the browser has visited and all of the browser\'s bookmarks."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"write Browser\'s history and bookmarks"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Allows an application to modify the Browser\'s history or bookmarks stored on your tablet. Malicious applications can use this to erase or modify your Browser\'s data."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Allows an application to modify the browser\'s history or bookmarks stored on your phone. Malicious applications can use this to erase or modify your browser\'s data."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"set alarm in alarm clock"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Allows the application to set an alarm in an installed alarm clock application. Some alarm clock applications may not implement this feature."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modify Browser geo-location permissions"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Allows an application to modify the browser\'s geo-location permissions. Malicious applications can use this to allow the sending of location information to arbitrary websites."</string>
     <string name="save_password_message" msgid="767344687139195790">"Do you want the browser to remember this password?"</string>
@@ -821,15 +790,12 @@
     <string name="cut" msgid="3092569408438626261">"Cut"</string>
     <string name="copy" msgid="2681946229533511987">"Copy"</string>
     <string name="paste" msgid="5629880836805036433">"Paste"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Nothing to paste"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Copy URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Select text..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Text selection"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Input method"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Edit text"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Text actions"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Low on space"</string>
     <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Tablet storage space is getting low."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Phone storage space is getting low."</string>
@@ -857,12 +823,9 @@
     <string name="force_close" msgid="3653416315450806396">"Force close"</string>
     <string name="report" msgid="4060218260984795706">"Report"</string>
     <string name="wait" msgid="7147118217226317732">"Wait"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Application redirected"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> is now running."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> was originally launched."</string>
     <string name="smv_application" msgid="295583804361236288">"The application <xliff:g id="APPLICATION">%1$s</xliff:g> (process <xliff:g id="PROCESS">%2$s</xliff:g>) has violated its self-enforced StrictMode policy."</string>
     <string name="smv_process" msgid="5120397012047462446">"The process <xliff:g id="PROCESS">%1$s</xliff:g> has violated its self-enforced StrictMode policy."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> running"</string>
@@ -911,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Show all"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB Mass Storage"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB connected"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\'s SD card."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\'s SD card."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"You have connected to your computer via USB. Touch the button below if you want to copy files between your computer and your Android‘s USB storage."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"You have connected to your computer via USB. Touch the button below if you want to copy files between your computer and your Android‘s SD card."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Turn off USB storage"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"There is a problem using your SD card for USB storage."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"There is a problem using your SD card for USB storage."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"There is a problem with using your USB storage for USB mass storage."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"There is a problem with using your SD card for USB mass storage."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB connected"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Select to copy files to/from your computer."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Turn off USB storage"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Select to turn off USB storage."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB storage in use"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Before turning off USB storage, make sure that you have unmounted (“ejected”) your Android‘s SD card from your computer."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Before turning off USB storage, make sure that you have unmounted (“ejected”) your Android‘s USB storage from your computer."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Before turning off USB storage, make sure that you have unmounted (“ejected”) your Android‘s SD card from your computer."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Turn off USB storage"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"We\'ve encountered a problem turning off USB storage. Check to ensure that you have unmounted the USB host, then try again."</string>
@@ -929,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"If you turn on USB storage, some applications that you are using will stop and may be unavailable until you turn off USB storage."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB operation failed"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format SD card"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format USB storage"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Format SD card"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Are you sure that you want to format the SD card? All data on your card will be lost."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Format USB storage, erasing all files stored there? Action cannot be reversed!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Are you sure that you want to format the SD card? All data on your card will be lost."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB debugging connected"</string>
@@ -940,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidates"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Preparing SD card"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Preparing USB storage"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Preparing SD card"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Checking for errors."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Blank SD card"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Blank USB storage"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Blank SD card"</string>
-    <!-- outdated translation 1312266820092958014 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"The SD card is blank or using an unsupported file system."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB storage blank or has unsupported file system."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD card blank or has unsupported file system."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Damaged SD card"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Damaged USB storage"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Damaged SD card"</string>
-    <!-- outdated translation 2679412884290061775 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"The SD card is damaged. You may have to reformat your card."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB storage damaged. You may have to reformat it."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD card damaged. You may have to reformat it."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"SD card removed unexpectedly"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB storage removed unexpectedly"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD card removed unexpectedly"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Unmount SD card before removing to avoid data loss."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Unmount USB storage before removing to avoid data loss."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Unmount SD card before removing to avoid data loss."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"SD card safe to remove"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB storage safe to remove"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD card safe to remove"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"You can safely remove SD card."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"You can safely remove USB storage."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"You can safely remove SD card."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Removed SD card"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Removed USB storage"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Removed SD card"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"SD card removed. Insert a new one."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB storage removed. Insert new media."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD card removed. Insert a new one."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"No matching activities found"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"update component usage statistics"</string>
@@ -975,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Send"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Next"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Done"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Prev"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Execute"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Dial number"\n", using <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Create contact"\n", using <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1008,52 +970,34 @@
     <string name="tethered_notification_message" msgid="3067108323903048927">"Touch to configure"</string>
     <string name="back_button_label" msgid="2300470004503343439">"Back"</string>
     <string name="next_button_label" msgid="1080555104677992408">"Next"</string>
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="skip_button_label" msgid="1275362299471631819">"Skip"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"High mobile data use"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Touch to learn more about mobile data usage"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Mobile data limit exceeded"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Touch to learn more about mobile data usage"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"No matches"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Find on page"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 Match"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Done"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Unmounting USB storage..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Unmounting SD card..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Erasing USB storage..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Erasing SD card..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Failed to erase USB storage."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Failed to erase SD card."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD card was removed before being unmounted."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB storage is currently being checked."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"SD card is currently being checked."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD card has been removed."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB storage is currently in use by a computer."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"SD card is currently in use by a computer."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"External media in unknown state."</string>
+    <string name="share" msgid="1778686618230011964">"Share"</string>
+    <string name="find" msgid="4808270900322985960">"Find"</string>
+    <string name="websearch" msgid="4337157977400211589">"Web Search"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1064,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es-rUS-xlarge/strings.xml b/core/res/res/values-es-rUS-xlarge/strings.xml
new file mode 100644
index 0000000..b1409ba
--- /dev/null
+++ b/core/res/res/values-es-rUS-xlarge/strings.xml
@@ -0,0 +1,337 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- XL -->
+    <string name="fileSizeSuffix" msgid="3468563433835560758">"Segmento <xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- XL -->
+    <string name="unknownName" msgid="3202822008051920747">"(Desconocido)"</string>
+    <!-- XL -->
+    <string name="defaultVoiceMailAlphaTag" msgid="3668436100965334106">"Buzón de voz"</string>
+    <!-- XL -->
+    <string name="serviceClassVoice" msgid="7086876533404179039">"Google Voice"</string>
+    <!-- XL -->
+    <string name="cfTemplateNotForwarded" msgid="8534356655497306518">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no se ha reenviado"</string>
+    <!-- XL -->
+    <string name="cfTemplateRegistered" msgid="1255841210142514510">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no se ha reenviado"</string>
+    <!-- XL -->
+    <string name="cfTemplateRegisteredTime" msgid="7798907169190952367">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no se ha reenviado"</string>
+    <!-- XL -->
+    <string name="notification_title" msgid="5210128823045542445">"Error al acceder a <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
+    <!-- XL -->
+    <string name="low_memory" product="tablet" msgid="4855646606241379548">"¡El espacio de almacenamiento de la tableta está completo! Elimina algunos archivos para liberar espacio."</string>
+    <string name="low_memory" product="default" msgid="9195238880281578473">"¡El espacio de almacenamiento está completo! Elimina algunos archivos para liberar espacio."</string>
+    <!-- XL -->
+    <string name="power_dialog" product="tablet" msgid="6884163545695410971">"Opciones de tableta"</string>
+    <string name="power_dialog" product="default" msgid="8882103237148972564">"Opciones de teléfono"</string>
+    <!-- XL -->
+    <string name="silent_mode" msgid="5687977677409351252">"Modo silencio"</string>
+    <!-- XL -->
+    <string name="shutdown_confirm" product="tablet" msgid="5776903973889956395">"Tu tableta se apagará."</string>
+    <string name="shutdown_confirm" product="default" msgid="3040950969577046278">"Tu teléfono se apagará."</string>
+    <!-- XL -->
+    <string name="global_actions" product="tablet" msgid="110297659383505180">"Opciones de tableta"</string>
+    <string name="global_actions" product="default" msgid="2108237350837066773">"Opciones de teléfono"</string>
+    <!-- XL -->
+    <string name="global_action_toggle_silent_mode" msgid="4538951049191334644">"Modo silencio"</string>
+    <!-- XL -->
+    <string name="global_action_silent_mode_off_status" msgid="9045822172493147761">"El sonido está ENCENDIDO"</string>
+    <!-- XL -->
+    <string name="global_actions_airplane_mode_on_status" msgid="7272433204482202219">"El modo avión está ENCENDIDO"</string>
+    <!-- XL -->
+    <string name="android_system_label" msgid="844561213652704593">"Sistema Androide"</string>
+    <!-- XL -->
+    <string name="permgroupdesc_costMoney" msgid="4836624191696189469">"Admitir que las aplicaciones realicen actividades que se cobran."</string>
+    <!-- XL -->
+    <string name="permgroupdesc_developmentTools" msgid="5514251182135739578">"Las funciones sólo son necesarias para los programadores de aplicaciones."</string>
+    <!-- XL -->
+    <string name="permgrouplab_storage" msgid="746210798053836644">"Almacenamiento"</string>
+    <!-- XL -->
+    <string name="permdesc_readSms" product="tablet" msgid="3026416194429353337">"Permite que la aplicación lea los mensajes SMS almacenados en tu tableta o tarjeta SIM. Las aplicaciones maliciosas pueden leer tus mensajes confidenciales."</string>
+    <string name="permdesc_readSms" product="default" msgid="191875931331016383">"Admite que la aplicación lea los mensajes SMS almacenados en tu teléfono o tarjeta SIM. Las aplicaciones maliciosas pueden leer tus mensajes confidenciales."</string>
+    <!-- XL -->
+    <string name="permdesc_writeSms" product="tablet" msgid="692041754996169941">"Permite que la aplicación escriba a los mensajes SMS almacenados en tu tableta o tarjeta SIM. Las aplicaciones maliciosas pueden borrar tus mensajes."</string>
+    <string name="permdesc_writeSms" product="default" msgid="1659315878254882599">"Admite que la aplicación escriba a los mensajes SMS almacenados en tu teléfono o tarjeta SIM. Las aplicaciones maliciosas pueden borrar tus mensajes."</string>
+    <!-- XL -->
+    <string name="permlab_forceStopPackages" msgid="1277034765943155677">"provocar la detención de otras aplicaciones"</string>
+    <!-- XL -->
+    <string name="permlab_forceBack" msgid="4272218642115232597">"cerrar la aplicación a la fuerza"</string>
+    <!-- XL -->
+    <string name="permdesc_injectEvents" product="tablet" msgid="6096352450860864899">"Permite que una aplicación ofrezca sus propios eventos de entrada (presionar teclas, etc.) a otras aplicaciones. Las aplicaciones maliciosas pueden utilizarlo para tomar el control de la tableta."</string>
+    <string name="permdesc_injectEvents" product="default" msgid="2842435693076075109">"Admite una aplicación que ofrece sus propios eventos de entrada (presionar teclas, etc.) a otras aplicaciones. Las aplicaciones maliciosas pueden utilizarlo para tomar el control del teléfono."</string>
+    <!-- XL -->
+    <string name="permdesc_clearAppCache" product="tablet" msgid="1147333973960547529">"Permite que una aplicación libere espacio de almacenamiento en la tableta eliminando archivos del directorio de memoria caché de la aplicación. En general, el acceso es muy restringido para el proceso del sistema."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="5790679870501740958">"Admite una aplicación que libera espacio de almacenamiento en el teléfono al eliminar archivos del directorio de memoria caché de la aplicación. En general, el acceso es muy restringido para el proceso del sistema."</string>
+    <!-- XL -->
+    <string name="permdesc_readLogs" product="tablet" msgid="3701009088710926065">"Permite que una aplicación lea diversos archivos de registro del sistema. Esto le permite descubrir información general acerca de lo que haces con la tableta, y puede potencialmente incluir información personal o privada."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8520101632251038537">"Admite una aplicación que lee diversos archivos de registro del sistema. Esto te permite descubrir información general acerca de lo que haces con el teléfono, y puede potencialmente incluir información personal o privada."</string>
+    <!-- XL -->
+    <string name="permdesc_changeComponentState" product="tablet" msgid="1791075936446230356">"Permite que una aplicación cambie si se debe activar o no un componente de otra aplicación. Las aplicaciones maliciosas pueden utilizarlo para desactivar funciones importantes de la tableta. Se debe tener cuidado con el permiso, ya que es posible que los componentes de la aplicación alcancen un estado inservible, imperfecto e inestable."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="587130297076242796">"Permite que una aplicación cambie si se debe activar o no un componente de otra aplicación. Las aplicaciones maliciosas pueden utilizarlo para desactivar funciones importantes del teléfono. Se debe tener cuidado con el permiso, ya que es posible que los componentes de la aplicación alcancen un estado inservible, imperfecto e inestable."</string>
+    <!-- XL -->
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="8660405432665162821">"Permite que una aplicación se inicie en cuanto el sistema haya finalizado la inicialización. Esto puede ocasionar que la tableta demore más en inicializar y que la aplicación retarde el funcionamiento total de la tableta al estar en ejecución constante."</string>
+    <string name="permdesc_receiveBootCompleted" product="default" msgid="1827765096700833418">"Admite una aplicación que se inicia cuando el sistema haya finalizado la inicialización. Esto puede ocasionar que se demore más tiempo en inicializar el teléfono y que la aplicación retarde el funcionamiento total del teléfono al estar en ejecución constante."</string>
+    <!-- XL -->
+    <string name="permdesc_readContacts" product="tablet" msgid="1611730857475623952">"Permite que una aplicación lea todos los datos de de contacto (direcciones) almacenados en tu tableta. Las aplicaciones maliciosas pueden utilizarlo para enviar tus datos a otras personas."</string>
+    <string name="permdesc_readContacts" product="default" msgid="6610535719925788049">"Admite una aplicación que lee todos los datos de (direcciones) de contactos almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas."</string>
+    <!-- XL -->
+    <string name="permdesc_writeContacts" product="tablet" msgid="4572703488642353934">"Permite que una aplicación modifique los datos de (dirección) guardados en tu tableta. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos de contacto."</string>
+    <string name="permdesc_writeContacts" product="default" msgid="714397557711969040">"Admite una aplicación que modifica los datos de (dirección de) contacto guardados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos de contacto."</string>
+    <!-- XL -->
+    <string name="permdesc_readCalendar" product="tablet" msgid="2991522150157238929">"Permite que una aplicación lea todos los eventos de calendario almacenados en tu tableta. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas."</string>
+    <string name="permdesc_readCalendar" product="default" msgid="2618681024074734985">"Admite que una aplicación lea todos los eventos de calendario almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para enviar tus eventos de calendario a otras personas."</string>
+    <!-- XL -->
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="9186984659787705379">"Accede a las fuentes de ubicación precisa, como el Sistema de posicionamiento global en la tableta, si está disponible. Las aplicaciones maliciosas pueden utilizarlo para determinar donde te encuentras y puede consumir energía adicional de la batería."</string>
+    <string name="permdesc_accessFineLocation" product="default" msgid="7130852247133907221">"Accede a las fuentes de ubicación precisa, como el Sistema de posicionamiento global en el teléfono, si está disponible. Las aplicaciones maliciosas pueden utilizarlo para determinar donde te encuentras y puede consumir energía adicional de la batería."</string>
+    <!-- XL -->
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="2943949975553225591">"Accede a las fuentes de ubicación aproximada, como la base de datos de la red de celulares, para determinar la ubicación aproximada de un tableta, si está disponible. Las aplicaciones maliciosas pueden utilizarlo para determinar aproximadamente dónde te encuentras."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="7474972764638621839">"Accede a las fuentes de ubicación aproximada, como la base de datos de la red de celulares, para determinar una ubicación telefónica aproximada, si está disponible. Las aplicaciones maliciosas pueden utilizarlo para determinar aproximadamente donde te encuentras."</string>
+    <!-- XL -->
+    <string name="permlab_brick" product="tablet" msgid="6967130388106614085">"inhabilitar tableta de forma permanente"</string>
+    <string name="permlab_brick" product="default" msgid="3120283238813720510">"desactivar teléfono de manera permanente"</string>
+    <!-- XL -->
+    <string name="permdesc_brick" product="tablet" msgid="8506097851567246888">"Permite que la aplicación desactive todo la tableta de manera permanente. Esto es muy peligroso."</string>
+    <string name="permdesc_brick" product="default" msgid="6696459767254028146">"Admite que la aplicación desactive todo el teléfono de manera permanente. Esto es muy peligroso."</string>
+    <!-- XL -->
+    <string name="permlab_reboot" product="tablet" msgid="8299304590708874992">"forzar reinicio de la tableta"</string>
+    <string name="permlab_reboot" product="default" msgid="7761230490609718232">"provocar el reinicio del teléfono"</string>
+    <!-- XL -->
+    <string name="permdesc_reboot" product="tablet" msgid="8289402537687518137">"Permite que la aplicación provoque el reinicio de la tableta."</string>
+    <string name="permdesc_reboot" product="default" msgid="2425170170087532554">"Admite que la aplicación provoque que el teléfono se reinicie."</string>
+    <!-- XL -->
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="1602175938040327630">"iniciar directamente la configuración CDMA de la tableta"</string>
+    <string name="permlab_performCdmaProvisioning" product="default" msgid="2364447039211144234">"comienza directamente la configuración CDMA del teléfono"</string>
+    <!-- XL -->
+    <string name="permlab_checkinProperties" msgid="8770356116386811264">"acceder a las propiedades de registro"</string>
+    <!-- XL -->
+    <string name="permlab_bindGadget" msgid="2772444448613501375">"elegir controles"</string>
+    <!-- XL -->
+    <string name="permdesc_bindGadget" msgid="5172327215211875807">"Admite que la aplicación indique al sistema cuáles controles puede utilizar cada aplicación. Con este permiso, las aplicaciones pueden brindar acceso a los datos personales a otras aplicaciones. Las aplicaciones normales no deben utilizarlo."</string>
+    <!-- XL -->
+    <string name="permlab_wakeLock" product="tablet" msgid="8548785337425173690">"evitar que la tableta entre en estado de inactividad"</string>
+    <string name="permlab_wakeLock" product="default" msgid="7590534090355174805">"evitar que el teléfono entre en estado de inactividad"</string>
+    <!-- XL -->
+    <string name="permdesc_wakeLock" product="tablet" msgid="6871828582124115814">"Permite que una aplicación evite que la tableta entre en estado de inactividad."</string>
+    <string name="permdesc_wakeLock" product="default" msgid="1200311528451468554">"Admite una aplicación que evita que el teléfono entre en estado de inactividad."</string>
+    <!-- XL -->
+    <string name="permlab_devicePower" product="tablet" msgid="4737873025369971061">"apagar o encender la tableta"</string>
+    <string name="permlab_devicePower" product="default" msgid="6879460773734563850">"apagar o encender el teléfono"</string>
+    <!-- XL -->
+    <string name="permdesc_devicePower" product="tablet" msgid="5930342678996327905">"Permite que una aplicación encienda o apague la tableta."</string>
+    <string name="permdesc_devicePower" product="default" msgid="6653901512148320818">"Admite que la aplicación encienda o apague el teléfono."</string>
+    <!-- XL -->
+    <string name="permdesc_factoryTest" product="tablet" msgid="396653994609190055">"Se ejecuta como una prueba de fábrica de bajo nivel que permite un acceso completo al hardware de la tableta. Sólo disponible cuando la tableta se ejecuta en el modo de prueba de fábrica."</string>
+    <string name="permdesc_factoryTest" product="default" msgid="4581239666568781766">"Se ejecuta como una prueba de fábrica de bajo nivel que permite un acceso completo al hardware del teléfono. Sólo disponible cuando un teléfono se ejecuta en el modo de prueba de fábrica."</string>
+    <!-- XL -->
+    <string name="permlab_setWallpaper" msgid="845032615203772571">"establecer fondo de pantalla"</string>
+    <!-- XL -->
+    <string name="permdesc_setWallpaper" msgid="3378501759667797259">"Admite que la aplicación establezca el fondo de pantalla del sistema."</string>
+    <!-- XL -->
+    <string name="permlab_setWallpaperHints" msgid="4995885499848128983">"establecer sugerencias de tamaño del fondo de pantalla"</string>
+    <!-- XL -->
+    <string name="permdesc_setWallpaperHints" msgid="8857901708691279048">"Admite que la aplicación establezca las sugerencias de tamaño del fondo de pantalla del sistema."</string>
+    <!-- XL -->
+    <string name="permdesc_setTime" product="tablet" msgid="7329574196603775554">"Permite que una aplicación cambie la hora de la tableta."</string>
+    <string name="permdesc_setTime" product="default" msgid="7787175369529849526">"Permite a una aplicación cambiar la hora del teléfono."</string>
+    <!-- XL -->
+    <string name="permdesc_setTimeZone" product="tablet" msgid="3851480395450283316">"Permite que una aplicación cambie la zona horaria de la tableta."</string>
+    <string name="permdesc_setTimeZone" product="default" msgid="3231143515254577541">"Admite una aplicación que cambia la zona horaria del teléfono."</string>
+    <!-- XL -->
+    <string name="permdesc_getAccounts" product="tablet" msgid="374861616407073729">"Permite que una aplicación obtenga una la lista de cuentas conocidas por la tableta."</string>
+    <string name="permdesc_getAccounts" product="default" msgid="6356501268884684429">"Admite una aplicación que obtiene la lista de cuentas conocidas del teléfono."</string>
+    <!-- XL -->
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="8034248164659819866">"Permite que una aplicación configure el Bluetooth local de la tableta, y descubra y se vincule con dispositivos remotos."</string>
+    <string name="permdesc_bluetoothAdmin" product="default" msgid="2555370145147752776">"Admite una aplicación que configura el teléfono Bluetooth local y descubre y se vincula con dispositivos remotos."</string>
+    <!-- XL -->
+    <string name="permdesc_bluetooth" product="tablet" msgid="4631562404621086816">"Permite que una aplicación vea la configuración de la tableta Bluetooth local, y que realice y acepte conexiones con dispositivos vinculados."</string>
+    <string name="permdesc_bluetooth" product="default" msgid="1202135959389935958">"Admite una aplicación que ve la configuración del teléfono Bluetooth local, y realiza y acepta conexiones con dispositivos vinculados."</string>
+    <!-- XL -->
+    <string name="policydesc_watchLogin" product="tablet" msgid="7927990389488709968">"Supervisar el número de contraseñas incorrectas ingresadas al desbloquear la pantalla, y bloquear la tableta o eliminar todos los datos del teléfono si se ingresan demasiadas contraseñas incorrectas."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="4998594853332798741">"Supervisa el número de contraseñas incorrectas ingresadas al desbloquear la pantalla, y bloquee el teléfono o elimine todos los datos del teléfono si se ingresan demasiadas contraseñas incorrectas."</string>
+    <!-- XL -->
+    <string name="policydesc_wipeData" product="tablet" msgid="7871059407132175855">"Borrar los datos de la tableta sin advertencias, restableciendo la configuración de fábrica"</string>
+    <string name="policydesc_wipeData" product="default" msgid="6003127471292136411">"Borrar los datos del teléfono sin advertencias al restablecer la configuración original"</string>
+    <!-- XL -->
+  <string-array name="phoneTypes">
+    <item msgid="7066790683658405096">"Pantalla principal"</item>
+    <item msgid="5813675571320075289">"Teléfono móvil"</item>
+    <item msgid="1236863745322977021">"Trabajo"</item>
+    <item msgid="7018038125868933566">"Fax laboral"</item>
+    <item msgid="4280105707643078852">"Fax personal"</item>
+    <item msgid="6527083287534782580">"Localizador"</item>
+    <item msgid="706618935041239888">"Otro"</item>
+    <item msgid="8099625332540070724">"Personalizado"</item>
+  </string-array>
+    <!-- XL -->
+  <string-array name="emailAddressTypes">
+    <item msgid="8080673853442355385">"Pantalla principal"</item>
+    <item msgid="924798042157989715">"Trabajo"</item>
+    <item msgid="1959796935508361158">"Otro"</item>
+    <item msgid="756534161520555926">"Personalizado"</item>
+  </string-array>
+    <!-- XL -->
+  <string-array name="postalAddressTypes">
+    <item msgid="1166454994471190496">"Pantalla principal"</item>
+    <item msgid="3602955376664951787">"Trabajo"</item>
+    <item msgid="4646105398231575508">"Otro"</item>
+    <item msgid="8191179302220976184">"Personalizado"</item>
+  </string-array>
+    <!-- XL -->
+  <string-array name="imAddressTypes">
+    <item msgid="2528436635522549040">"Pantalla principal"</item>
+    <item msgid="5834207144511084508">"Trabajo"</item>
+    <item msgid="3796683891024584813">"Otro"</item>
+    <item msgid="6644316676098098833">"Personalizado"</item>
+  </string-array>
+    <!-- XL -->
+  <string-array name="organizationTypes">
+    <item msgid="6571823895277482483">"Trabajo"</item>
+    <item msgid="4013674940836786104">"Otro"</item>
+    <item msgid="8549998141814637453">"Personalizado"</item>
+  </string-array>
+    <!-- XL -->
+    <string name="phoneTypeHome" msgid="2087652870939635038">"Pantalla principal"</string>
+    <!-- XL -->
+    <string name="phoneTypeMobile" msgid="7084573626440935140">"Teléfono móvil"</string>
+    <!-- XL -->
+    <string name="emailTypeHome" msgid="1298773522695936612">"Pantalla principal"</string>
+    <!-- XL -->
+    <string name="emailTypeMobile" msgid="5515624509217674980">"Teléfono móvil"</string>
+    <!-- XL -->
+    <string name="postalTypeHome" msgid="7553888805834710738">"Pantalla principal"</string>
+    <!-- XL -->
+    <string name="imTypeHome" msgid="3732426015472142690">"Pantalla principal"</string>
+    <!-- XL -->
+    <string name="sipAddressTypeHome" msgid="8212230577724692911">"Pantalla principal"</string>
+    <!-- XL -->
+    <string name="lockscreen_pattern_instructions" msgid="9171665895877154059">"Extraer el patrón para desbloquear"</string>
+    <!-- XL -->
+    <string name="lockscreen_battery_short" msgid="891372653127247039">"Segmento <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <!-- XL -->
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="3961770350078423154">"No hay tarjeta SIM en la tableta."</string>
+    <string name="lockscreen_missing_sim_message" product="default" msgid="5997031739677800758">"No hay tarjeta SIM en el teléfono."</string>
+    <!-- XL -->
+    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="2429599468920598896">"Has establecido incorrectamente tu gráfico de desbloqueo <xliff:g id="NUMBER_0">%d</xliff:g> veces. "\n\n"Vuelve a intentarlo en <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+    <!-- XL -->
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="3211267232692817092">"Has establecido incorrectamente tu gráfico de desbloqueo <xliff:g id="NUMBER_0">%d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees tu tableta al acceder a Google."\n\n" Vuelve a intentarlo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="7097890594752816076">"Has establecido incorrectamente tu gráfico de desbloqueo <xliff:g id="NUMBER_0">%d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%d</xliff:g> intentos incorrectos, se te solicitará que desbloquees tu teléfono al acceder a Google. "\n\n" Vuelve a intentarlo en <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
+    <!-- XL -->
+    <string name="lockscreen_glogin_submit_button" msgid="4760302858316749698">"Acceder"</string>
+    <!-- XL -->
+    <string name="lockscreen_glogin_invalid_input" msgid="7265806099449246244">"Nombre de usuario o contraseña no válidos."</string>
+    <!-- XL -->
+    <string name="hour_ampm" msgid="6161399724998500216">"Segmento <xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <!-- XL -->
+    <string name="hour_cap_ampm" msgid="724197720606114012">"Segmento <xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <!-- XL -->
+    <string name="double_tap_toast" msgid="2893001600485832537">"Sugerencia: presiona dos veces para acercar y alejar"</string>
+    <!-- XL -->
+    <string name="autofill_address_name_separator" msgid="5171727678145785075">" Segmento "</string>
+    <!-- XL -->
+    <string name="permlab_readHistoryBookmarks" msgid="6148149152792104516">"leer historial y favoritos del navegador"</string>
+    <!-- XL -->
+    <string name="permdesc_readHistoryBookmarks" msgid="7371336472744100059">"Permite a la aplicación leer todas las URL que ha visitado el navegador y todos los favoritos del navegador."</string>
+    <!-- XL -->
+    <string name="permlab_writeHistoryBookmarks" msgid="1369319390968848231">"escribir historial y favoritos del navegador"</string>
+    <!-- XL -->
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="3870229397949634482">"Permite que una aplicación modifique el historial de navegación y los favoritos del navegador almacenados en tu tableta. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar los datos en tu navegador."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="6845659334691579933">"Permite a una aplicación modificar el historial y los favoritos del navegador almacenados en tu teléfono. Las aplicaciones maliciosas pueden utilizarlo para borrar o modificar tus datos."</string>
+    <!-- XL -->
+    <string name="permlab_setAlarm" msgid="8112208516527103653">"fija la alarma en el reloj de alarma"</string>
+    <!-- XL -->
+    <string name="permdesc_setAlarm" msgid="5454386032150297784">"Permite a la aplicación fijar una alarma en una aplicación de alarma. Es posible que algunas aplicaciones de alarma no implementen esta función."</string>
+    <!-- XL -->
+    <string name="menu_delete_shortcut_label" msgid="8482704027019632634">"eliminar"</string>
+    <!-- XL -->
+  <plurals name="num_minutes_ago">
+    <item quantity="one" msgid="468685153446407901">"hace 1 minuto"</item>
+    <item quantity="other" msgid="211907662145171054">"Hace <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
+  </plurals>
+    <!-- XL -->
+  <plurals name="num_hours_ago">
+    <item quantity="one" msgid="2172827344495633666">"hace 1 hora"</item>
+    <item quantity="other" msgid="6094391999921908511">"Hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
+  </plurals>
+    <!-- XL -->
+  <plurals name="num_days_ago">
+    <item quantity="one" msgid="3766494702684657165">"ayer"</item>
+    <item quantity="other" msgid="5030316952487658828">"Hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
+  </plurals>
+    <!-- XL -->
+  <plurals name="abbrev_num_seconds_ago">
+    <item quantity="one" msgid="1441918190525197797">"hace 1 s"</item>
+    <item quantity="other" msgid="3958332340802316933">"hace <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
+  </plurals>
+    <!-- XL -->
+  <plurals name="abbrev_num_minutes_ago">
+    <item quantity="one" msgid="3404245071272952255">"hace 1 min"</item>
+    <item quantity="other" msgid="6004808520903389765">"hace <xliff:g id="COUNT">%d</xliff:g> min"</item>
+  </plurals>
+    <!-- XL -->
+  <plurals name="abbrev_num_hours_ago">
+    <item quantity="one" msgid="806010152744475654">"hace 1 hora"</item>
+    <item quantity="other" msgid="7553525762196895290">"Hace <xliff:g id="COUNT">%d</xliff:g> horas"</item>
+  </plurals>
+    <!-- XL -->
+  <plurals name="abbrev_num_days_ago">
+    <item quantity="one" msgid="5819444260187611238">"ayer"</item>
+    <item quantity="other" msgid="1069986768190052012">"Hace <xliff:g id="COUNT">%d</xliff:g> días"</item>
+  </plurals>
+    <!-- XL -->
+    <string name="preposition_for_time" msgid="3606608741888559522">"a la/s <xliff:g id="TIME">%s</xliff:g>"</string>
+    <!-- XL -->
+    <string name="minutes" msgid="1486240209627391507">"min"</string>
+    <!-- XL -->
+    <string name="selectAll" msgid="847570914566450966">"Seleccionar todos"</string>
+    <!-- XL -->
+    <string name="low_internal_storage_view_text" product="tablet" msgid="6497548813789342134">"Está quedando poco espacio de almacenamiento en la tableta."</string>
+    <string name="low_internal_storage_view_text" product="default" msgid="2901569701336868928">"Hay poco espacio de almacenamiento en el teléfono."</string>
+    <!-- XL -->
+    <string name="capital_on" msgid="5705918046896729554">"ENCENDIDO"</string>
+    <!-- XL -->
+    <string name="wait" msgid="8036803866051401072">"Espera"</string>
+    <!-- XL -->
+    <string name="heavy_weight_notification" msgid="5762367358298413602">"<xliff:g id="APP">%1$s</xliff:g> se está ejecutando"</string>
+    <!-- XL -->
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="103298639852047758">"Preparando almacenamiento USB"</string>
+    <string name="ext_media_checking_notification_title" product="default" msgid="2111086053471573248">"Preparando la tarjeta SD"</string>
+    <!-- XL -->
+    <string name="ime_action_done" msgid="7200237418945571897">"Listo"</string>
+    <!-- XL -->
+    <string name="wallpaper_binding_label" msgid="6966627494441714436">"Fondo de pantalla"</string>
+    <!-- XL -->
+    <string name="websearch" msgid="904596193450917688">"Búsqueda web"</string>
+    <!-- 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>
+    <!-- XL -->
+    <string name="autofill_address_summary_name_format" msgid="7531610259426153850">"$1$2$3"</string>
+    <!-- XL -->
+    <string name="autofill_address_summary_format" msgid="8398158823767723887">"$1$2$3"</string>
+    <!-- XL -->
+    <string name="gpsNotifTicker" msgid="6612390321359669319">"Solicitud de ubicación de <xliff:g id="NAME">%s</xliff:g>"</string>
+    <!-- XL -->
+    <string name="gpsNotifTitle" msgid="7533028619350196545">"Solicitud de ubicación"</string>
+    <!-- XL -->
+    <string name="gpsNotifMessage" msgid="5592972401593755530">"Solicitado por <xliff:g id="NAME">%1$s</xliff:g> (<xliff:g id="SERVICE">%2$s</xliff:g>)"</string>
+    <!-- XL -->
+    <string name="gpsVerifYes" msgid="1511016393202739483">"Sí"</string>
+    <!-- XL -->
+    <string name="gpsVerifNo" msgid="661731239940896232">"No"</string>
+    <!-- XL -->
+    <string name="sync_too_many_deletes" msgid="6088394702274114202">"Eliminar el límite excedido"</string>
+    <!-- XL -->
+    <string name="sync_too_many_deletes_desc" msgid="4794082462774743277">"Existen <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> artículos eliminados para <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, cuenta <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>. ¿Qué te gustaría hacer?"</string>
+    <!-- XL -->
+    <string name="sync_really_delete" msgid="7782215155483034729">"Eliminar artículos."</string>
+    <!-- XL -->
+    <string name="sync_undo_deletes" msgid="6501390120900825477">"Deshacer eliminaciones."</string>
+    <!-- XL -->
+    <string name="sync_do_nothing" msgid="612038572646360281">"No hagas nada por el momento."</string>
+</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 1818af1..5e6645d 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -151,8 +151,10 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avión"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"El modo avión está Encendido"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"El modo avión está Apagado"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
-    <string name="android_system_label" msgid="6577375335728551336">"Sistema Androide"</string>
+    <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicios que te cuestan dinero"</string>
     <string name="permgroupdesc_costMoney" msgid="8193824940620517189">"Admite aplicaciones que realizan actividades que te pueden costar dinero."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Tus mensajes"</string>
@@ -211,7 +213,7 @@
     <string name="permdesc_enableCarMode" msgid="5673461159384850628">"Permite que una aplicación habilite el modo auto."</string>
     <string name="permlab_killBackgroundProcesses" msgid="8373714752793061963">"eliminar los procesos de fondo"</string>
     <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"Permite que una aplicación elimine los procesos de fondo de otras aplicaciones, aun si la memoria no es baja."</string>
-    <string name="permlab_forceStopPackages" msgid="1447830113260156236">"provocar la detención de otras aplicaciones"</string>
+    <string name="permlab_forceStopPackages" msgid="1447830113260156236">"forzar la detención de otras aplicaciones"</string>
     <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"Permite que una aplicación provoque la detención de otras aplicaciones."</string>
     <string name="permlab_forceBack" msgid="1804196839880393631">"provocar que la aplicación se acerque"</string>
     <string name="permdesc_forceBack" msgid="6534109744159919013">"Admite una aplicación que provoca que cualquier actividad del fondo se acerque y vuelva a alejarse. Se debe evitar utilizarlo en aplicaciones normales."</string>
@@ -360,6 +362,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Admite que la aplicación controle la linterna."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"acceder a dispositivos USB"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Permite que la aplicación acceda a dispositivos USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"probar el hardware"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Admite que la aplicación controle diversos periféricos con el fin de probar el hardware."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"llamar directamente a números de teléfono"</string>
@@ -373,8 +379,8 @@
     <string name="permdesc_locationUpdates" msgid="2300018303720930256">"Permite activar y desactivar las notificaciones de actualización de ubicación de la radio. Las aplicaciones normales no deben utilizarlo."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"acceder a las propiedades de protección"</string>
     <string name="permdesc_checkinProperties" msgid="7150307006141883832">"Admite el acceso de lectura y escritura a las propiedades subidas por el servicio de protección. Las aplicaciones normales no deben utilizarlo."</string>
-    <string name="permlab_bindGadget" msgid="776905339015863471">"elegir controles"</string>
-    <string name="permdesc_bindGadget" msgid="2098697834497452046">"Admite que la aplicación indique al sistema cuáles controles puede utilizar cada aplicación. Con este permiso, las aplicaciones pueden brindar acceso a los datos personales a otras aplicaciones. Las aplicaciones normales no deben utilizarlo."</string>
+    <string name="permlab_bindGadget" msgid="776905339015863471">"elegir widgets"</string>
+    <string name="permdesc_bindGadget" msgid="2098697834497452046">"Admite que la aplicación indique al sistema qué widgets puede utilizar cada aplicación. Con este permiso, las aplicaciones pueden brindar acceso a los datos personales a otras aplicaciones. Las aplicaciones normales no deben utilizarlo."</string>
     <string name="permlab_modifyPhoneState" msgid="8423923777659292228">"modificar el estado del teléfono"</string>
     <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Admite que la aplicación controle las funciones telefónicas del dispositivo. Una aplicación con este permiso puede cambiar las redes, encender y apagar la radio del teléfono y funciones similares sin notificarte en ningún momento."</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"leer el estado del teléfono y la identidad"</string>
@@ -606,7 +612,7 @@
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Pantalla bloqueada."</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Presiona el Menú para desbloquear o realizar una llamada de emergencia."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Presionar Menú para desbloquear."</string>
-    <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Extraer el patrón para desbloquear"</string>
+    <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Dibujar el patrón de desbloqueo"</string>
     <string name="lockscreen_emergency_call" msgid="5347633784401285225">"Llamada de emergencia"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Regresar a llamada"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Correcto"</string>
@@ -614,7 +620,7 @@
     <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Lo sentimos, vuelve a intentarlo"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Cargada."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"Segmento <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta tu cargador."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"No hay tarjeta SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hay tarjeta SIM en el tablet."</string>
@@ -657,7 +663,7 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"¿Deseas salir de esta página?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Selecciona Aceptar para continuar o Cancelar para permanecer en la página actual."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Confirmar"</string>
-    <string name="double_tap_toast" msgid="1068216937244567247">"Sugerencia: presiona dos veces para acercar y alejar"</string>
+    <string name="double_tap_toast" msgid="1068216937244567247">"Sugerencia: presiona dos veces para acercar o alejar (zoom)"</string>
     <string name="autofill_this_form" msgid="1272247532604569872">"Autocompl."</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Conf func Autocompl"</string>
     <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
@@ -784,7 +790,7 @@
     <string name="Midnight" msgid="5630806906897892201">"Medianoche"</string>
     <string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
     <string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
-    <string name="selectAll" msgid="6876518925844129331">"Seleccionar todos"</string>
+    <string name="selectAll" msgid="6876518925844129331">"Seleccionar todo"</string>
     <string name="cut" msgid="3092569408438626261">"Cortar"</string>
     <string name="copy" msgid="2681946229533511987">"Copiar"</string>
     <string name="paste" msgid="5629880836805036433">"Pegar"</string>
@@ -820,7 +826,7 @@
     <string name="anr_process" msgid="1246866008169975783">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> no responde."</string>
     <string name="force_close" msgid="3653416315450806396">"Forzar cierre"</string>
     <string name="report" msgid="4060218260984795706">"Notificar"</string>
-    <string name="wait" msgid="7147118217226317732">"Espera"</string>
+    <string name="wait" msgid="7147118217226317732">"Esperar"</string>
     <string name="launch_warning_title" msgid="8323761616052121936">"Se redirigió la aplicación"</string>
     <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> se está ejecutando ahora."</string>
     <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> se inició originalmente."</string>
@@ -995,8 +1001,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Medios externos en estado desconocido."</string>
     <string name="share" msgid="1778686618230011964">"Compartir"</string>
     <string name="find" msgid="4808270900322985960">"Buscar"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Buscar en la Web"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1007,4 +1012,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index da06dab..4f02c4b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avión"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modo avión activado. Desactivar."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modo avión desactivado. Activar."</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicios por los que tienes que pagar"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permite que la aplicación controle la función de linterna."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"acceso a dispositivos USB"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"La aplicación puede acceder a dispositivos USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"probar hardware"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Permite que la aplicación controle distintos periféricos con fines de prueba del hardware."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"llamar directamente a números de teléfono"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Estado de medio externo desconocido"</string>
     <string name="share" msgid="1778686618230011964">"Compartir"</string>
     <string name="find" msgid="4808270900322985960">"Buscar"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Búsqueda web"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 7e00ebd..95871a4 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"پست صوتی"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"مشکل در اتصال یا کد MMI نامعتبر."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"عملکرد فقط به شماره های شماره گیری ثابت محدود است."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"سرویس فعال شد."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"سرویس فعال شد برای:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"سرویس غیرفعال شده است."</string>
@@ -126,7 +125,7 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"همگام سازی"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"همگام سازی"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"تعداد موارد حذف شده <xliff:g id="CONTENT_TYPE">%s</xliff:g> بسیار زیاد است."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"محل ذخیره رایانه لوحی پر است! برخی از فایل ها را حذف کنید تا فضا خالی شود."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"حافظه رایانه لوحی پر است! برخی از فایل ها را حذف کنید تا فضا خالی شود."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"محل ذخیره تلفن پر است! برخی از فایل ها را حذف کنید تا فضا خالی شود."</string>
     <string name="me" msgid="6545696007631404292">"من"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"گزینه های رایانه لوحی"</string>
@@ -139,8 +138,7 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"خاموش کردن..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"رایانه لوحی شما خاموش می شود."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"گوشی شما خاموش می شود."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"آیا می خواهید دستگاه را خاموش کنید؟"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"اخیر"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"برنامه اخیری موجود نیست."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"گزینه های رایانه لوحی"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"حالت هواپیما"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"حالت هواپیما روشن است"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"حالت هواپیما خاموش است"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"سیستم Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"سرویس های غیر رایگان"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"ابزارهای توسعه"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"ویژگی ها فقط برای برنامه نویسان برنامه کاربردی لازم است."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"ذخیره سازی"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"به کارت SD دسترسی داشته باشید."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"به حافظه USB دسترسی پیدا کنید."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"به کارت SD دسترسی داشته باشید."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"غیرفعال کردن یا تغییر نوار وضعیت"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"به برنامه کاربردی اجازه می دهد نوار وضعیت را غیرفعال کرده یا نمادهای سیستم را اضافه کرده و حذف کند."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"نوار وضعیت"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"به برنامه کاربردی اجازه می دهد که نوار وضعیت شود."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"گسترش دادن/جمع کردن نوار وضعیت"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"به برنامه کاربردی اجازه می دهد نوار وضعیت را کوچک یا بزرگ کند."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"توقف تماس های خروجی"</string>
@@ -196,7 +194,7 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"ارسال پیامک ها"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"به برنامه کاربردی اجازه می دهد پیامک ارسال کند. برنامه های مضر ممکن است با ارسال پیام هایی بدون تأیید شما، هزینه هایی را برای شما ایجاد کنند."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"خواندن پیامک یا MMS"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"به برنامه کاربردی اجازه می دهد پیامک های ذخیره شده در رایانه لوحی شما یا سیم کارت را بخواند. برنامه های مضر می توانند پیام های محرمانه شما را بخوانند."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"به برنامه اجازه می دهد پیامک های ذخیره شده در رایانه لوحی شما یا سیم کارت را بخواند. برنامه های مضر می توانند پیام های محرمانه شما را بخوانند."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"به برنامه کاربردی اجازه می دهد پیامک های ذخیره شده در گوشی شما یا سیم کارت را بخواند. برنامه های مضر می توانند پیام های محرمانه شما را بخوانند."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"ویرایش پیامک یا MMS"</string>
     <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"به برنامه کاربردی اجازه می دهد در پیامک های ذخیره شده در رایانه لوحی شما یا سیم کارت بنویسد. برنامه های مضر می توانند پیام های شما را حذف کنند."</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ممانعت از جابجایی برنامه"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"مانع از جابجایی کاربر به یک برنامه دیگر می شود."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"نظارت و بررسی تمام راه اندازی های برنامه کاربردی"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"به یک برنامه کاربردی امکان می دهد نحوه راه اندازی فعالیت ها توسط سیستم را کنترل و نظارت کند. برنامه های مضر ممکن است به طور کامل سیستم را تحت کنترل بگیرند. این مجوز تنها برای بهبود لازم است و هرگز برای استفاده های معمولی کاربرد ندارد."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"به یک برنامه کاربردی اجازه می دهد نحوه راه اندازی فعالیت ها توسط سیستم را کنترل و نظارت کند. برنامه های مضر ممکن است به طور کامل سیستم را تحت کنترل بگیرند. این مجوز تنها برای بهبود لازم است و هرگز برای استفاده های معمولی تلفن کاربرد ندارد."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"ارسال پخش بسته حذف شده"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"به یک برنامه کاربردی اجازه می دهد اعلانی را پخش کند که یک بسته برنامه آن را حذف کرده است. برنامه های مضر از این امکان برای از بین بردن سایر برنامه های در حال اجرا استفاده می کنند."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"ارسال پخش دریافت شده توسط پیامک"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"نمایش پنجره های غیرمجاز"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"اجازه می دهد پنجره هایی ایجاد شوند که برای استفاده توسط رابط کاربر سیستم داخلی در نظر گرفته شده است. برای استفاده با برنامه های معمولی در نظر گرفته نشده است."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"هشدارهای سطح سیستم نمایش"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"به یک برنامه کاربردی اجازه می دهد پنجره های هشدار سیستم را نمایش دهد. برنامه های مضر می توانند کنترل کل صفحه را در دست بگیرند."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"به یک برنامه کاربردی اجازه می دهد پنجره های هشدار سیستم را نمایش دهد. برنامه های مضر می توانند کنترل تمام صفحه را در دست بگیرند."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"اصلاح سرعت انیمیشن کلی"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"به یک برنامه کاربردی اجازه می دهد تا کل سرعت انیمیشن را در هر زمان تغییر دهد (انیمیشن هایی سریعتر یا آرام تر)."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"مدیریت کدهای برنامه"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"به برنامه های کاربردی اجازه می دهد کدهای خود را ایجاد کرده و مدیریت کنند و همچنین ترتیب بندی Z خود را تأیید کنند. هرگز برای برنامه های معمولی مورد نیاز نیست."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"کلیدها و دکمه های کنترل را فشار دهید"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"به یک برنامه کاربردی اجازه می دهد رویدادهای ورودی خود (فشارهای کلید و سایر موارد) را به دیگر برنامه ها تحویل دهد. برنامه های مضر از این امکان می توانند برای کنترل رایانه لوحی استفاده کنند."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"به یک برنامه کاربردی اجازه می دهد رویدادهای ورودی خود (فشارهای کلید و سایر موارد) را به دیگر برنامه ها تحویل دهد. برنامه های مضر از این امکان می توانند برای مسلط شدن بر رایانه لوحی استفاده کنند."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"به یک برنامه کاربردی اجازه می دهد رویدادهای ورودی خود (فشارهای کلید و سایر موارد) را به دیگر برنامه ها تحویل دهد. برنامه های مضر از این امکان می توانند برای مسلط شدن بر گوشی استفاده کنند."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"مواردی که می نویسید و کارهایی که انجام می دهید را ضبط کنید"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"به برنامه های کاربردی اجازه می دهد حتی زمانی که با برنامه دیگری در حال ارتباط هستید (مانند وارد کردن یک رمز ورود)، بتوانند کلیدهایی را که فشار می دهید ببینند. هرگز برای برنامه های معمولی مورد نیاز نیست."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"نصب مستقیم برنامه های کاربردی"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"به یک برنامه کاربردی اجازه می دهد تا بسته های Android جدید یا به روز شده را نصب کند. برنامه های مضر می توانند از این امکان برای افزودن برنامه های جدید با مجوزهای خودسرانه قدرتمند استفاده کنند."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"حذف کل داده های حافظه پنهان برنامه"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"به یک برنامه کاربردی اجازه می دهد با حذف فایل ها در دایرکتوری حافظه پنهان برنامه، فضای آزاد در محل ذخیره سازی رایانه لوحی ایجاد کند. دسترسی به فرآیندهای سیستم معمولاً بسیار محدود است."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"به یک برنامه کاربردی اجازه می دهد با حذف فایل ها در دایرکتوری حافظه پنهان برنامه، فضای آزاد در محل ذخیره سازی گوشی ایجاد کند. دسترسی به فرآیندهای سیستم معمولاً بسیار محدود است."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"به یک برنامه کاربردی اجازه می دهد با حذف فایل ها در دایرکتوری حافظه پنهان برنامه، فضای آزاد در محل ذخیره سازی گوشی ایجاد کند. دسترسی به فرآیندهای سیستم معمولاً بسیار محدود است."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"انتقال منابع برنامه کاربردی"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"به یک برنامه کاربردی اجازه می دهد منابع برنامه را از رسانه داخلی به رسانه خارجی منتقل کرده و بالعکس."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"خواندن فایل های گزارش سیستم"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"به یک برنامه کاربردی اجازه می دهد فایل های مختلف گزارش سیستم را بخواند. با این کار، اطلاعات کلی مربوط به کاری که با رایانه لوحی انجام می دهید مشخص می شود که ممکن است شامل حاوی اطلاعات شخصی و خصوصی باشند."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"به یک برنامه کاربردی اجازه می دهد فایل های مختلف گزارش سیستم را بخواند. با این کار، اطلاعات کلی مربوط به کاری که با رایانه لوحی انجام می دهید مشخص می شود که ممکن است شامل حاوی اطلاعات شخصی و خصوصی باشند."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"مطالعه داده های گزارش حساس"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"به یک برنامه کاربردی اجازه می دهد فایل های مختلف گزارش سیستم را بخواند. با این کار، اطلاعات کلی مربوط به کاری که با رایانه لوحی انجام می دهید را کشف می کند، که ممکن است حاوی اطلاعات شخصی و خصوصی باشند."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"به یک برنامه کاربردی اجازه می دهد فایل های مختلف گزارش سیستم را بخواند. با این کار، اطلاعات کلی مربوط به کاری که با گوشی انجام می دهید را کشف می کند، که ممکن است حاوی اطلاعات شخصی و خصوصی باشند."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"خواندن/نوشتن منابع متعلق به تشخیص"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"به یک برنامه کاربردی امکان می دهد هر منبع متعلق به گروه تشخیص را بخواند یا بنویسد، مانند فایل های موجود در /dev. این امر می تواند بصورت بالقوه بر ثبات و امنیت سیستم تأثیر بگذارد. از این امکان تنها باید برای شناسایی مشکلات مخصوص سخت افزار توسط سازنده یا اپراتور استفاده شود."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"فعال یا غیرفعال کردن مؤلفه های برنامه"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"به یک برنامه کاربردی اجازه می دهد تا فعال شدن یا فعال نشدن مؤلفه یک برنامه دیگر را تغییر دهد. برنامه های مضر می توانند از این امکان برای غیرفعال کردن قابلیت های مهم رایانه لوحی استفاده کنند. در مورد مجوزها دقت بیشتری داشته باشید، زیرا امکان دارد مؤلفه های یک برنامه را به حالت بلااستفاده، ناسازگار یا بدون ثبات تبدیل کند."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"به یک برنامه کاربردی اجازه می دهد تا فعال شدن یا فعال نشدن مؤلفه یک برنامه دیگر را تغییر دهد. برنامه های مضر می توانند از این امکان برای غیرفعال کردن قابلیت های مهم رایانه لوحی استفاده کنند. در مورد مجوزها دقت بیشتری داشته باشید، زیرا امکان دارد مؤلفه های یک برنامه را به حالت بلااستفاده، ناسازگار یا بدون ثبات تبدیل کند."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"به یک برنامه کاربردی اجازه می دهد تا فعال شدن یا فعال نشدن مؤلفه یک برنامه دیگر را تغییر دهد. برنامه های مضر می توانند از این امکان برای غیرفعال کردن قابلیت های مهم رایانه لوحی استفاده کنند. در استفاده از این مجوز دقت کنید، زیرا امکان دارد مؤلفه های یک برنامه را به حالت بلااستفاده، ناسازگار یا بدون ثبات تبدیل کند."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"به یک برنامه کاربردی اجازه می دهد تا فعال شدن یا فعال نشدن مؤلفه یک برنامه دیگر را تغییر دهد. برنامه های مضر می توانند از این امکان برای غیرفعال کردن قابلیت های مهم گوشی استفاده کنند. این مجوز باید به دقت استفاده شود، زیرا امکان دارد مؤلفه های یک برنامه را به حالت بلااستفاده، ناسازگار یا بدون ثبات تبدیل کند."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"تنظیم برنامه های برگزیده"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"به یک برنامه کاربردی اجازه می دهد برنامه های برگزیده شما را تغییر دهد. این امر به برنامه های مضر امکان می دهد تا به آرامی برنامه های در حال اجرا را تغییر دهند و سبب جمع آوری اطلاعات شخصی و خصوصی شما توسط برنامه های موجود شوند."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"اصلاح کردن تنظیمات سیستم کلی"</string>
@@ -301,7 +299,7 @@
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"به یک برنامه کاربردی اجازه می دهد با پایان راه اندازی سیستم، به طور خودکار شروع به کار کند. این امر سبب می شود مدت بیشتری طول بکشد تا رایانه لوحی شروع به کار کند و به برنامه اجازه می دهد تا با اجرای دائمی، سرعت کلی رایانه لوحی را کم کند."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"به یک برنامه کاربردی اجازه می دهد با پایان راه اندازی سیستم، به طور خودکار شروع به کار کند. این امر سبب می شود مدت بیشتری طول بکشد تا گوشی شروع به کار کند و به برنامه اجازه می دهد تا با اجرای دائمی، سرعت کلی تلفن را کم کند."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"ارسال پخش چسبنده"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"به یک برنامه کاربردی اجازه می دهد پخش های چسبنده را ارسال کند که پس از پایان پخش همچنان باقی می مانند. برنامه های مضر می توانند با وادار کردن رایانه لوحی به استفاده بیش از حد حافظه، رایانه لوحی را کند کرده یا ناپایدار کنند."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"به یک برنامه کاربردی اجازه می دهد پخش های چسبنده را ارسال کند که پس از پایان پخش همچنان باقی می مانند. برنامه های مضر می توانند با وادار کردن رایانه لوحی به استفاده بیش از حد حافظه، تلفن را کند کرده یا ناپایدار کنند."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"به یک برنامه کاربردی اجازه می دهد پخش های چسبنده را ارسال کند که پس از پایان پخش همچنان باقی می مانند. برنامه های مضر می توانند با وادار کردن تلفن به استفاده بیش از حد حافظه، تلفن را کند کرده یا ناپایدار کنند."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"خواندن اطلاعات تماس"</string>
     <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"به یک برنامه کاربردی اجازه می دهد تمام اطلاعات تماس (آدرس) ذخیره شده در رایانه لوحی شما را بخواند. برنامه های مضر می توانند از این امکان برای ارسال اطلاعات شما به دیگر افراد استفاده کنند."</string>
@@ -310,7 +308,7 @@
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"به یک برنامه کاربردی اجازه می دهد اطلاعات تماس (آدرس) ذخیره شده در رایانه لوحی شما را تغییر دهد. برنامه های مضر می توانند از این امکان برای حذف یا تغییر اطلاعات تماس شما استفاده کنند."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"به یک برنامه کاربردی اجازه می دهد اطلاعات تماس (آدرس) ذخیره شده در گوشی شما را تغییر دهد. برنامه های مضر می توانند از این امکان برای حذف یا تغییر اطلاعات تماس شما استفاده کنند."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"خواندن رویدادهای تقویم"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"به یک برنامه کاربردی اجازه می دهد که تمام رویدادهای تقویم ذخیره شده در رایانه لوحی شما را بخواند. برنامه های کاربردی مضر می توانند از این ویژگی برای ارسال رویدادهای تقویم شما به سایر افراد استفاده کنند."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"به یک برنامه کاربردی اجازه می دهد که تمام رویدادهای تقویم ذخیره شده در رایانه لوحی شما را بخواند. برنامه های مضر می توانند از این ویژگی برای ارسال رویدادهای تقویم شما به سایر افراد استفاده کنند."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"به یک برنامه کاربردی اجازه می دهد که تمام رویدادهای تقویم ذخیره شده در گوشی شما را بخواند. برنامه های کاربردی مضر می توانند از این ویژگی برای ارسال رویدادهای تقویم شما به سایر افراد استفاده کنند."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"افزودن یا اصلاح رویدادهای تقویم و ارسال ایمیل به مهمانان"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"به یک برنامه کاربردی اجازه می دهد که رویدادهای تقویم شما را، که ممکن است برای مهمانان ایمیل ارسال کند، اضافه کرده یا حذف کند. برنامه های مضر می توانند از این امکان برای پاک کردن یا تغییر رویدادهای تقویم و یا ارسال ایمیل به مهمانان استفاده کنند."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"مجوز برای نصب یک ارائه دهنده مکان"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"منابع مکان کاذب را برای تست ایجاد کنید. برنامه های مضر می توانند از این امکان برای لغو مکان و وضعیت بازگردانده شده توسط منابع مکان واقعی مانند GPS یا ارائه دهندگان شبکه استفاده کنند، یا مکان شما را کنترل کرده و آن را به یک منبع خارجی گزارش دهند."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"مکان مناسب (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"به منابع مکان دقیق مانند سیستم موقعیت یابی جهانی، در صورت وجود، در گوشی خود متصل شوید. برنامه های مضر می توانند از آن برای تعیین محل شما استفاده کنند، و ممکن است مقدار بیشتری باتری مصرف کنند."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"به منابع مکانی دقیق مانند سیستم موقعیت یابی جهانی، در صورت وجود، در رایانه لوحی خود متصل شوید. برنامه های مضر می توانند از این برنامه برای تعیین محل شما استفاده کنند و مقدار بیشتری باتری مصرف کنند."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"به منابع مناسب مکان مانند سیستم موقعیت یابی جهانی،در صورت وجود، در گوشی خود متصل شوید. برنامه های مضر می توانند از این برنامه برای تعیین محل شما استفاده کننده و مقدار بیشتری باتری مصرف کنند."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"مکان نامشخص (وابسته به شبکه)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"برای تعیین مکان تقریبی رایانه لوحی، در صورت وجود، به منابع مکان نامشخص مانند پایگاه داده شبکه سلولی دسترسی پیدا کنید. برنامه های مضر می توانند از آن برای تعیین محل تقریبی شما استفاده کنند."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"برای تعیین مکان تقریبی رایانه لوحی در صورت وجود، به منابع مکان نامشخص مانند پایگاه داده شبکه تلفن همراه دسترسی پیدا کنید. برنامه های مضر می توانند از این مورد برای تعیین محل تقریبی شما استفاده کنند."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"برای تعیین مکان تقریبی گوشی، در صورت وجود، به منابع مکان نامشخص مانند پایگاه داده شبکه سلولی دسترسی پیدا کنید. برنامه های مضر می توانند از این مورد برای تعیین محل تقریبی شما استفاده کنند."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"دسترسی به SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"به برنامه کاربردی اجازه می دهد از ویژگی های سطح پایین SurfaceFlinger استفاده کند."</string>
@@ -334,13 +332,13 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"به برنامه کاربردی اجازه می دهد تنظیمات صوتی کلی را اصلاح کند، مانند میزان صدا و مسیریابی."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ضبط صدا"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"به برنامه کاربردی اجازه می دهد به مسیر ضبط صدا دسترسی داشته باشد."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"گرفتن عکس ها"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"به برنامه کاربردی اجازه می دهد تصاویری را با دوربین ضبط کند. با این کار برنامه در هر زمان می تواند تصاویر قابل مشاهده توسط دوربین را ببیند."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"غیر فعال کردن رایانه لوحی بصورت دائم"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"عکسبرداری و فیلمبرداری"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"به برنامه کاربردی اجازه می دهد با دوربین عکسبرداری و فیلمبرداری کند. با این کار به برنامه امکان داده می شود در هر زمان تصاویری که دوربین مشاهده می کند را جمع آوری کند."</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"غیر فعال کردن دائم رایانه لوحی"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"تلفن بطور دائمی غیرفعال شود"</string>
     <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"به برنامه کاربردی اجازه می دهد تا رایانه لوحی را به طور کلی و دائمی غیرفعال کند. این کار بسیار خطرناک است."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"به برنامه کاربردی اجازه می دهد تا گوشی را به طور کلی و دائمی غیرفعال کند. این کار بسیار خطرناک است."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"راه اندازی مجدد رایانه لوحی به اجبار"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"راه اندازی مجدد اجباری رایانه لوحی"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"اجبار برنامه برای راه اندازی مجدد"</string>
     <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"به برنامه کاربردی اجازه می دهد تا سبب راه اندازی مجدد رایانه لوحی شود."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"به برنامه کاربردی اجازه می دهد تا سبب راه اندازی مجدد گوشی شود."</string>
@@ -348,23 +346,25 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"به برنامه کاربردی اجازه می دهد تا فایل سیستم ها را برای دستگاه ذخیره سازی جداشدنی نصب کرده یا جدا کند."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"فرمت کردن دستگاه ذخیره سازی خارجی"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"به برنامه کاربردی اجازه می دهد تا دستگاه ذخیره سازی جداشدنی را فرمت کند."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"دریافت اطلاعات مربوط به ذخیره سازی ایمن"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"به برنامه کاربردی اجازه می دهد تا اطلاعات مربوط به ذخیره سازی ایمن را دریافت کند."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"ایجاد محل ذخیره سازی ایمن"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"به برنامه کاربردی اجازه می دهد تا ذخیره سازی ایمن را ایجاد کند."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"از بین بردن ذخیره ایمن"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"به برنامه کاربردی اجازه می دهد تا ذخیره سازی ایمن را از بین ببرد."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"نصب/باز کردن محل ذخیره ایمن"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"به برنامه کاربردی اجازه می دهد تا دستگاه ذخیره سازی ایمن را نصب کرده یا جدا کند."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"تغییر نام ذخیره سازی ایمن"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"به برنامه کاربردی اجازه می دهد تا نام دستگاه ذخیره سازی ایمن را تغییر دهد."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"دریافت اطلاعات مربوط به حافظه داخلی"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"به برنامه کاربردی اجازه می دهد تا اطلاعات مربوط به حافظه داخلی را دریافت کند."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"ایجاد حافظه داخلی"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"به برنامه کاربردی اجازه می دهد تا حافظه داخلی را ایجاد کند."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"خراب کردن حافظه داخلی"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"به برنامه کاربردی اجازه می دهد تا حافظه داخلی را از بین ببرد."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"نصب/باز کردن حافظه داخلی"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"به برنامه کاربردی اجازه می دهد تا حافظه داخلی را نصب کرده یا جدا کند."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"نامگذاری مجدد دستگاه ذخیره داخلی"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"به برنامه کاربردی اجازه می دهد تا نام حافظه داخلی را تغییر دهد."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"کنترل لرزاننده"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"به برنامه کاربردی اجازه می دهد لرزاننده را کنترل کند."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"کنترل چراغ قوه"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"به برنامه کاربردی اجازه می دهد چراغ قوه را کنترل کند."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"دسترسی به دستگاه های USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"به برنامه کاربردی اجازه می دهد به دستگاه های USB دسترسی پیدا کند."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"تست سخت افزار"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"به برنامه کاربردی اجازه می دهد سایر برنامه های جانبی را برای تست سخت افزاری کنترل کند."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"به برنامه کاربردی اجازه می دهد تا بدون دخالت شما با هر شماره تلفنی تماس بگیرد. برنامه های مضر ممکن است باعث تماس های غیرمنتظره ای در صورتحساب تلفن شما شوند. توجه داشته باشید که این ویژگی به برنامه کاربردی اجازه نمی دهد با شماره های اضطراری تماس بگیرد."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"تماس مستقیم با هر شماره تلفنی"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"به برنامه کاربردی اجازه می دهد تا بدون دخالت شما با هر شماره تلفنی، از جمله شماره های اضطراری تماس بگیرد. برنامه های مضر می توانند تماس های غیرقانونی و غیرضروری با شماره های اضطراری برقرار کنند."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"شروع مستقیم راه اندازی رایانه لوحی CDMA"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"راه اندازی مستقیم تنظیم رایانه لوحی CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"شروع مستقیم راه اندازی تلفن CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"به برنامه کاربردی اجازه می دهد تا ارائه مجوز CDMA را آغاز کند. برنامه های مضر ممکن است ارائه مجوز CDMA را بدون ضرورت شروع کنند."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"کنترل اعلان های به روز رسانی مکان"</string>
@@ -411,7 +411,7 @@
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"عملکرد به عنوان AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"به یک برنامه کاربردی امکان می دهد با تأیید کنندگان اعتبار حساب تماس بگیرند"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"یافتن حساب های شناخته شده"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"به یک برنامه کاربردی امکان می دهد لیستی از حساب های شناخته شده توسط رایانه لوحی را دریافت کند."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"به یک برنامه کاربردی اجازه می دهد لیستی از حساب های شناخته شده توسط رایانه لوحی را دریافت کند."</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"به یک برنامه کاربردی امکان می دهد لیستی از حساب های شناخته شده توسط گوشی را دریافت کند."</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"عملکرد به عنوان تأیید کننده اعتبار حساب"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"به یک برنامه کاربردی اجازه می دهد از قابلیت های تأیید کننده اعتبار حساب مربوط به مدیر حساب استفاده کند، از جمله ایجاد چندین حساب و دریافت و تنظیم رمزهای ورود آنها."</string>
@@ -441,12 +441,10 @@
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"به یک برنامه کاربردی اجازه می دهد تا رایانه لوحی محلی بلوتوث را پیکربندی کرده، دستگاه های راه دور را شناسایی کرده و با آنها جفت شود."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"به یک برنامه کاربردی اجازه می دهد تا تلفن محلی بلوتوث را پیکربندی کرده، دستگاه های راه دور را شناسایی کرده و با آنها جفت شود."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"ایجاد اتصال های بلوتوث"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"به یک برنامه کاربردی اجازه می دهد تا پیکربندی رایانه لوحی بلوتوث محلی را مشاهده کند، اتصال ها را با دستگاه های جفت شده برقرار کرده، آنها را بپذیرد."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"به یک برنامه کاربردی اجازه می دهد تا پیکربندی تلفن لوحی بلوتوث محلی را مشاهده کند، اتصال ها را با دستگاه های جفت شده برقرار کرده، آنها را بپذیرد."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"به یک برنامه کاربردی اجازه می دهد تا پیکربندی تلفن بلوتوث محلی را مشاهده کند، اتصال ها را با دستگاه های جفت شده برقرار کرده، آنها را بپذیرد."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"کنترل ارتباط راه نزدیک"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"به یک برنامه کاربردی برای ارتباط با برچسب های ارتباط راه نزدیک (NFC)، کارت ها و خواننده ها اجازه می دهد."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"غیرفعال کردن قفل کلید"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"به یک برنامه کاربردی اجازه می دهد قفل کلید و حفاظت رمز ورود همراه با کلیه کلیدها را غیرفعال کند. یک نمونه قانونی از این مورد، غیرفعال شدن قفل کلید در هنگام دریافت تماس تلفنی و سپس فعال کردن قفل کلید پس از پایان تماس است."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"خواندن تنظیمات همگام سازی"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"به یک برنامه کاربردی امکان می دهد که تمام کلمات شخصی، نام ها و عباراتی که ممکن است کاربر در فرهنگ لغت کاربر ذخیره کرده باشد را بخواند."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"نوشتن در فرهنگ لغت تعریف شده توسط کاربر"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"به یک برنامه کاربردی اجازه می دهد کلمات جدیدی را در فرهنگ لغت کاربر بنویسد."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"اصلاح کردن/حذف محتویات کارت SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"اصلاح/حذف محتواهای حافظه USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"اصلاح کردن/حذف محتویات کارت SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"به یک برنامه کاربردی اجازه می دهد در کارت SD رایت کند."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"به یک برنامه کاربردی اجازه می دهد تا دستگاه USB را بنویسید."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"به یک برنامه کاربردی اجازه می دهد در کارت SD رایت کند."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"اصلاح/حذف محتواهای ذخیره سازی رسانه داخلی"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"به یک برنامه کاربردی برای اصلاح محتواهای حافظه رسانه داخلی اجازه می دهد."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"دسترسی به سیستم فایل حافظه پنهان"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"به یک برنامه کاربردی امکان می دهد سیستم فایل حافظه پنهان را بخواند و بنویسد."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"محدود کردن رمز ورود"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"انواع رمز ورود که مجاز به استفاده از آنها هستید را محدود کنید."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"تعداد دفعات ورود به سیستم برای مشاهده"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"تعداد رمز ورودهای نادرست وارد شده هنگام بازکردن قفل را نظارت کنید، و رایانه لوحی را قفل کنید یا در صورتی که تعداد زیادی رمز ورود نادرست وارد شده، کلیه داده های رایانه لوحی را حذف کنید"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"تعداد رمز ورودهای نادرست وارد شده هنگام بازکردن قفل را نظارت کنید، و رایانه لوحی را قفل کنید یا در صورتی که تعداد زیادی رمز ورود نادرست وارد شده، کلیه داده های رایانه لوحی را حذف کنید"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"بازنشانی رمز ورود"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"رمز ورود شما را به اجبار به یک مورد جدید تبدیل می کند، سرپرست را ملزم می کند قبل از ورود به برنامه، آن را به شما تحویل دهد."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"قفل اجباری"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"کنترل هنگام قفل شدن دستگاه و الزام شما به وارد کردن دوباره رمز ورود."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"علامتگذاری/دریافت تماس های اینترنتی"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"به یک برنامه کاربردی اجازخ می دهد از سرویس SIP جهت برقراری یا دریافت تماس های اینترنتی استفاده کند."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"کنترل طول و نویسه های مجاز رمزهای ورود قفل گشایی صفحه"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاش های قفل گشایی صفحه"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"تعداد رمزهای ورود نادرست وارد شده هنگام قفل گشایی صفحه نشان داده می شود و در صورتی که رمز ورودهای نادرست بسیاری وارد شود، گوشی قفل شده یا همه داده های رایانه لوحی پاک می شود."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"تعداد رمزهای ورود نادرست وارد شده هنگام قفل گشایی صفحه نشان داده می شود و در صورتی که رمز ورودهای نادرست بسیاری وارد شود، گوشی قفل شده یا همه داده های گوشی پاک می شود."</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"تغییر رمز ورود قفل گشایی صفحه"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"تغییر رمز ورود قفل گشایی صفحه"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"قفل کردن صفحه"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"کنترل نحوه قفل شدن صفحه و زمان آن"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"پاک کردن تمام داده ها"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"پاک کردن داده رایانه لوحی بدون اخطار، با اجرای یک بازنشانی به داده های کارخانه"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"پاک کردن داده رایانه لوحی بدون اخطار، با اجرای یک بازنشانی به داده های کارخانه"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"پاک کردن داده های رایانه لوحی بدون هشدار با انجام یک عملکرد بازنشانی داده های کارخانه"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"پاک کردن داده های گوشی بدون هشدار با انجام یک عملکرد بازنشانی داده های کارخانه"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"تنظیم پروکسی جهانی دستگاه"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"پروکسی جهانی دستگاه مورد نظر را جهت استفاده هنگام فعال بودن خط مشی تنظیم کنید. فقط اولین سرپرست دستگاه پروکسی جهانی مفید را تنظیم می کند."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"تنظیم زمان انقضای رمز ورود"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"کنترل مدت زمانی که رمز ورود صفحه قفل قبل از تغییر یافتن لازم دارد"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"خانه"</item>
     <item msgid="869923650527136615">"تلفن همراه"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"پیجوی محل کار"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"دستیار"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"سفارشی"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"تاریخ تولد"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"سالگرد"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"رویداد"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"سایر موارد"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"سفارشی"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"خانه"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"محل کار"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"محل کار"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"سایر موارد"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"سفارشی"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"سفارشی"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"دستیار"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"برادر"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"کودک"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"شریک محلی"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"پدر"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"دوست"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"مدیر"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"مادر"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"والدین"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"شریک"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"ارجاع توسط"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"خویشاوند"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"خواهر"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"همسر"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"سفارشی"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"صفحه اصلی"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"محل کار"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"سایر موارد"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"کد پین را وارد کنید"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"رمز ورود را برای بازگشایی قفل وارد کنید"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"کد پین را برای بازگشایی قفل وارد کنید"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"پین کد اشتباه است!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"برای بازگشایی قفل، منو را فشار دهید و سپس 0 را فشار دهید."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"شماره اضطراری"</string>
@@ -646,8 +615,7 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"بازگشت به تماس"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"صحیح است!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"متأسفیم، دوباره امتحان کنید"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"متأسفیم، دوباره امتحان کنید"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"شارژ کردن (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"شارژ شد."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"سیم کارت قفل شد."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"بازگشایی قفل سیم کارت..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده اید. "\n\n"لطفاً پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده اید. <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق دیگر سبب می شود از شما خواسته شود که برای بازگشایی قفل رایانه لوحی خود به برنامه Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"شما رمز ورود خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه وارد کرده اید. "\n\n"لطفاً پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"شما کد پین خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه وارد کرده اید. "\n\n"لطفاً پس از <xliff:g id="NUMBER_1">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده اید. بعد از <xliff:g id="NUMBER_1">%d</xliff:g> تلاش ناموفق، از شما خواسته می شود که برای بازگشایی قفل رایانه لوحی خود به Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%d</xliff:g> بار اشتباه کشیده اید. <xliff:g id="NUMBER_1">%d</xliff:g> تلاش های ناموفق بیشتر سبب می شود از شما خواسته شود که برای بازگشایی قفل گوشی خود به برنامه Google وارد شوید."\n\n" لطفاً پس از <xliff:g id="NUMBER_2">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"در <xliff:g id="NUMBER">%d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"الگو را فراموش کرده اید؟"</string>
@@ -698,23 +664,17 @@
     <string name="double_tap_toast" msgid="1068216937244567247">"نکته: برای انجام بزرگنمایی مثبت و منفی، دو بار ضربه بزنید."</string>
     <string name="autofill_this_form" msgid="1272247532604569872">"تکمیل خودکار"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"تنظیم تکمیل خودکار"</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">"، "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"خواندن سابقه و نشانک های مرورگر"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"به برنامه کاربردی اجازه می دهد تا تمام URL های بازدید شده توسط مرورگر و تمام نشانک های آن را بخواند."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"نوشتن سابقه مرورگر و نشانک ها"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"به یک برنامه کاربردی اجازه می دهد سابقه مرورگر یا نشانک ذخیره شده در رایانه لوحی شما را تغییر دهد. برنامه های مضر می توانند از این امکان برای حذف یا تغییر داده های مرورگر شما استفاده کنند."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"به یک برنامه کاربردی اجازه می دهد سابقه مرورگر یا نشانک ذخیره شده در گوشی شما را تغییر دهد. برنامه های مضر می توانند از این امکان برای حذف یا تغییر داده های مرورگر شما استفاده کنند."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"تنظیم هشدار در ساعت زنگ دار"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"به برنامه کاربردی برای تنظیم یک هشدار در یک برنامه ساعت زنگ دار نصب شده اجازه می دهد. در برخی از برنامه های ساعت زنگ دار ممکن است این ویژگی اجرا نشود."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"اصلاح کردن مجوزهای مکان جغرافیایی مرورگر"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"به یک برنامه کاربردی اجازه می دهد مجوزهای مکان جغرافیایی مرورگر را تغییر دهد. برنامه های مضر می توانند از این گزینه استفاده کرده و اطلاعات مربوط به مکان را به وب سایت های غیر قانونی ارسال کنند."</string>
     <string name="save_password_message" msgid="767344687139195790">"می خواهید مرورگر این رمز ورود را به خاطر داشته باشد؟"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"برش"</string>
     <string name="copy" msgid="2681946229533511987">"کپی"</string>
     <string name="paste" msgid="5629880836805036433">"جای گذاری"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"چیزی برای جای گذاری نیست"</string>
     <string name="copyUrl" msgid="2538211579596067402">"کپی URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"انتخاب متن..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"انتخاب متن"</string>
     <string name="inputMethod" msgid="1653630062304567879">"روش ورودی"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"ویرایش متن"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"عملکردهای متنی"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"فضا کم است"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"فضای ذخیره سازی رایانه لوحی در حال کم شدن است."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"فضای ذخیره رایانه لوحی در حال کم شدن است."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"فضای ذخیره سازی تلفن در حال کم شدن است."</string>
     <string name="ok" msgid="5970060430562524910">"تأیید"</string>
     <string name="cancel" msgid="6442560571259935130">"لغو"</string>
     <string name="yes" msgid="5362982303337969312">"تأیید"</string>
     <string name="no" msgid="5141531044935541497">"لغو"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"توجه"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"در حال بارگیری..."</string>
     <string name="capital_on" msgid="1544682755514494298">"روشن"</string>
     <string name="capital_off" msgid="6815870386972805832">"خاموش"</string>
     <string name="whichApplication" msgid="4533185947064773386">"تکمیل عملکرد با استفاده از"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"بستن اجباری"</string>
     <string name="report" msgid="4060218260984795706">"گزارش"</string>
     <string name="wait" msgid="7147118217226317732">"منتظر بمانید"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"برنامه هدایت مجدد شد"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> اکنون در حال اجرا است."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> از ابتدا راه اندازی شد."</string>
+    <string name="smv_application" msgid="295583804361236288">"برنامه <xliff:g id="APPLICATION">%1$s</xliff:g> (پردازش <xliff:g id="PROCESS">%2$s</xliff:g>) خط مشی StrictMode اجرای خودکار را نقض کرده است."</string>
+    <string name="smv_process" msgid="5120397012047462446">"فرآیند <xliff:g id="PROCESS">%1$s</xliff:g> خط مشی StrictMode اجرای خودکار خود را نقض کرده است."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> در حال اجرا"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"انتخاب برای رفتن به برنامه"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"جابجایی در برنامه ها؟"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"برنامه دیگری در حال حاضر در حال اجرا است که قبل از شروع برنامه جدید دیگری باید متوقف شود."</string>
+    <string name="old_app_action" msgid="493129172238566282">"بازگشت به <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"برنامه جدید راه اندازی نشود."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"شروع <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"برنامه قدیمی بدون ذخیره متوقف شود."</string>
     <string name="sendText" msgid="5132506121645618310">"انتخاب یک عملکرد برای متن"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"میزان صدای زنگ"</string>
     <string name="volume_music" msgid="5421651157138628171">"میزان صدای رسانه"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"نمایش همه"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"دستگاه ذخیره سازی انبوه USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB متصل شد"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"شما گوشی خود را از طریق USB به رایانه متصل کرده اید. اگر می خواهید فایل ها را بین رایانه خود و کارت SD کپی کنید، دکمه زیر را انتخاب کنید."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"شما گوشی خود را از طریق USB به رایانه متصل کرده اید. اگر می خواهید فایل ها را بین رایانه خود و کارت SD کپی کنید، دکمه زیر را انتخاب کنید."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"شما از طریق USB به رایانه متصل شده اید. اگر می خواهید فایل ها را بین رایانه خود و حافظه USB در Android کپی کنید، دکمه زیر را لمس کنید."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"شما از طریق USB به رایانه متصل شده اید. اگر می خواهید فایل ها را بین رایانه خود و کارت SD در Android کپی کنید، دکمه زیر را لمس کنید."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"روشن کردن دستگاه ذخیره سازی USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"مشکلی در استفاده از کارت SD برای دستگاه ذخیره سازی USB وجود دارد."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"مشکلی در استفاده از کارت SD برای دستگاه ذخیره سازی USB وجود دارد."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"مشکلی در استفاده از حافظه USB برای ذخیره سازی انبوه USB وجود دارد."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"مشکلی در استفاده از کارت SD برای حافظه انبوه USB وجود دارد."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB متصل شد"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"انتخاب کنید تا فایل ها در/از رایانه شما کپی شود."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"خاموش کردن دستگاه ذخیره سازی USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"برای خاموش کردن دستگاه ذخیره سازی USB انتخاب کنید."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"دستگاه ذخیره سازی USB در حال استفاده است"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"قبل از خاموش کردن دستگاه ذخیره سازی USB، بررسی کنید که کارت SD Android را از رایانه خود جدا کرده باشید."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"قبل از خاموش کردن حافظه USB، مطمئن شوید که دستگاه ذخیره سازی Android USB خود را از رایانه خود جدا کرده باشید."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"قبل از خاموش کردن دستگاه ذخیره سازی USB، بررسی کنید که کارت SD Android را از رایانه خود جدا کرده باشید."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"خاموش کردن دستگاه ذخیره سازی USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"مشکلی در خاموش کردن دستگاه ذخیره سازی USB وجود داشت. بررسی کنید که میزبان USB را جدا کرده باشید و سپس دوباره امتحان کنید."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"در صورت روشن کردن دستگاه ذخیره سازی USB، برخی از برنامه هایی که از آنها استفاده می کنید متوقف می شوند و تا زمانی که دستگاه ذخیره سازی USB را خاموش نکنید امکان استفاده از آنها وجود نخواهد داشت."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"عملکرد USB انجام نشد"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"تأیید"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"فرمت کردن کارت SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"فرمت کردن حافظه USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"فرمت کردن کارت SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"مطمئن هستید که می خواهید این کارت SD را فرمت کنید؟ تمام اطلاعات موجود در کارت شما از بین می رود."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"فرمت کردن حافظه USB، همه فایل های ذخیره شده در آنجا پاک شود؟ عملکرد قابل بازگشت نیست!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"مطمئن هستید که می خواهید این کارت SD را فرمت کنید؟ تمام اطلاعات موجود در کارت شما از بین می رود."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"قالب"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"رفع عیب USB متصل شد"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"داوطلبین"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"آماده کردن کارت SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"آماده سازی حافظه USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"آماده کردن کارت SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"بررسی خطاها."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"کارت SD خالی"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"حافظه USB خالی"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"کارت SD خالی"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"کارت SD خالی است یا سیستم فایل آن پشتیبانی نمی شود."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"حافظه USB خالی است یا از سیستم فایل پشتیبانی نشده ای برخوردار است."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"کارت SD خالی است یا سیستم فایل آن پشتیبانی نمی شود."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"کارت SD آسیب دیده"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"حافظه USB خراب شده"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"کارت SD آسیب دیده"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"کارت SD خراب است. لازم است که آن را دوباره فرمت کنید."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"حافظه USB خراب است. لازم است که آن را دوباره فرمت کنید."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"کارت SD خراب است. لازم است که آن را دوباره فرمت کنید."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"کارت SD به صورت غیر منتظره ای جدا شد"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"حافظه USB به صورت غیر منتظره جدا شد"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"کارت SD به صورت غیر منتظره ای جدا شد"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"کارت SD را قبل از بیرون آوردن جدا کنید تا سبب از بین رفتن داده ها نشود."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"اتصال حافظه USB را قبل از بیرون آوردن قطع کنید تا سبب از بین رفتن داده ها نشود."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"کارت SD را قبل از بیرون آوردن جدا کنید تا سبب از بین رفتن داده ها نشود."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"کارت SD را می توان با امنیت کامل جدا کرد"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"حافظه USB را می توانید با ایمنی جدا کنید"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"کارت SD را می توان با امنیت کامل جدا کرد"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"کارت SD را می توانید با امنیت کامل خارج کنید."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"شما می توانید حافظه USB را با اطمینان جدا کنید."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"کارت SD را می توانید با امنیت کامل خارج کنید."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"کارت SD حذف شده"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"جدا کردن حافظه USB"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"کارت SD حذف شده"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"کارت SD جدا شد. یک کارت جدید وارد کنید."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"حافظه USB جدا شد. یک رسانه جدید متصل کنید."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"کارت SD جدا شد. یک کارت جدید وارد کنید."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"فعالیتی مطابق با این مورد یافت نشد"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"به روزرسانی آمار مربوط به استفاده مؤلفه"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"ارسال"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"بعدی"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"انجام شد"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"قبلی"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"اجرا کردن"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"شماره گیری "\n"با استفاده از <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"ایجاد مخاطب"\n"با استفاده از <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN بر پایه کلید از پیش مشترک شده"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN وابسته به گواهی"</string>
     <string name="upload_file" msgid="2897957172366730416">"انتخاب فایل"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"هیچ فایلی انتخاب نشد"</string>
     <string name="reset" msgid="2448168080964209908">"بازنشانی"</string>
     <string name="submit" msgid="1602335572089911941">"ارسال"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"حالت خودرو فعال شد"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"برای خروج از حالت خودرو انتخاب کنید."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"اتصال داده با سیم یا نقطه اتصال فعال"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"برای پیکربندی، لمس کنید"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"برگشت"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"بعدی"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"پرش"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"استفاده زیاد از داده های تلفن همراه"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"برای کسب اطلاعات بیشتر درباره استفاده از داده های تلفن همراه، لمس کنید"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"داده های تلفن همراه از مقدار مجاز بیشتر است"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"برای کسب اطلاعات بیشتر درباره استفاده از داده های تلفن همراه، لمس کنید"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"مورد منطبقی موجود نیست"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"یافتن در صفحه"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 مورد منطبق"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> از <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"انجام شد"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"قطع اتصال حافظه USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"قطع اتصال کارت SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"در حال پاک کردن حافظه USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"در حال پاک کردن کارت SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"حافظه USB پاک نشد."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"کارت SD پاک نشد."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"کارت SD قبل از قطع اتصال از دستگاه خارج شد."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"حافظه USB اکنون در حال بررسی شدن است."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"کارت SD در حال حاضر در حال بررسی است."</string>
+    <string name="media_removed" msgid="7001526905057952097">"کارت SD حذف شده است."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"حافظه در حال حاضر توسط رایانه دیگری استفاده می شود."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"کارت SD در حال حاضر توسط یک رایانه در حال استفاده است."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"رسانه خارجی در حالت ناشناس است."</string>
+    <string name="share" msgid="1778686618230011964">"اشتراک گذاری"</string>
+    <string name="find" msgid="4808270900322985960">"یافتن"</string>
+    <string name="websearch" msgid="4337157977400211589">"جستجوی وب"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index ff8c464..1392ebb 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Vastaaja"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Yhteysongelma tai virheellinen MMI-koodi."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Voit suorittaa toiminnon vain sallitut puhelut -numeroihin."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Palvelu otettiin käyttöön."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Palvelu käytössä luokalle:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Palvelu on poistettu käytöstä."</string>
@@ -139,8 +138,7 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"Suljetaan..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet-laitteesi sammutetaan."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Puhelin suljetaan."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Haluatko sammuttaa laitteen?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Viimeisimmät"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Ei viimeaikaisia sovelluksia."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Tablet-laitteen asetukset"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lentokonetila"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Lentokonetila on KÄYTÖSSÄ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Lentokonetila on POIS KÄYTÖSTÄ"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Maksulliset palvelut"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Kehittäjätyökalut"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Ominaisuudet, joita vain sovellusten kehittäjät tarvitsevat."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Tallennustila"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Käytä SD-korttia."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Käytä USB-tallennustilaa."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Käytä SD-korttia."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"poista tilapalkki käytöstä tai muokkaa tilapalkkia"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Antaa sovelluksen poistaa tilapalkin käytöstä tai lisätä ja poistaa järjestelmäkuvakkeita."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"tilapalkki"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Antaa sovelluksen sijaita tilapalkissa."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"laajentaa/tiivistää tilarivin"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Antaa sovelluksen laajentaa tai tiivistää tilapalkin."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"katkaise soitettavia puheluita"</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"estä sovellusten vaihto"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Estää käyttäjää vaihtamasta toiseen sovellukseen."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"tarkkaile ja hallitse kaikkien sovelluksien käynnistämistä"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Antaa sovelluksen tarkkailla ja hallita järjestelmän käynnistämiä toimintoja. Haittasovellukset saattavat vaarantaa järjestelmän täysin. Tätä lupaa tarvitaan vain kehitykseen, ei tavalliseen käyttöön."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Antaa sovelluksen tarkkailla ja hallita järjestelmän käynnistämiä toimintoja. Haitalliset sovellukset saattavat vaarantaa järjestelmän täysin. Tätä lupaa tarvitaan vain kehitykseen, ei tavalliseen laitteen käyttöön."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"lähetä paketeista poistettuja lähetyksiä"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Antaa sovelluksen lähettää ilmoituksen, että sovelluspaketti on poistettu. Haitalliset sovellukset saattavat sulkea käynnissä olevia sovelluksia."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"lähetä tekstiviestillä vastaanotettuja lähetyksiä"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"näytä luvattomia ikkunoita"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Antaa sovelluksen luoda ikkunoita, jotka on tarkoitettu sisäisen järjestelmän käyttöliittymän käyttöön. Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"näytä järjestelmätason ilmoituksia"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Antaa sovelluksen näyttää järjestelmäilmoitusikkunoita. Haittasovellukset saattavat kaapata käyttöönsä koko ruudun."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Antaa sovelluksen näyttää järjestelmävaroitusikkunoita. Haittasovellukset voivat kaapata käyttöönsä koko ruudun."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"muokkaa yleistä animaationopeutta"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Antaa sovelluksen muuttaa yleistä animaationopeutta (nopeammaksi tai hitaammaksi) milloin tahansa."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"hallitse sovellustunnuksia"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Antaa sovelluksen luoda ja hallinnoida omia tunnisteitaan ja ohittaa tavallisen Z-järjestyksen. Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"painaa näppäimiä ja hallintapainikkeita"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Antaa sovelluksen toimittaa omia syöttötapahtumiaan (näppäimen painalluksia jne.) muille sovelluksille. Haittasovellukset voivat ottaa tämän avulla tablet-laitteen haltuunsa."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Antaa sovelluksen lähettää omia syöttötapahtumia (näppäimen painalluksia jne.) muille sovelluksille. Haittasovellukset voivat ottaa koko tablet-laitteen haltuunsa."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Antaa sovelluksen toimittaa omia syöttötapahtumiaan (näppäimen painalluksia jne.) muille sovelluksille. Haitalliset sovellukset saattavat ottaa tämän avulla puhelimen haltuunsa."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"tallenna kirjoittamiasi merkkejä ja suorittamiasi toimintoja"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Antaa sovelluksien tarkkailla painamiasi näppäimiä jopa toisten sovellusten käytön yhteydessä (kuten salasanoja syötettäessä). Ei tavallisten sovelluksien käyttöön."</string>
@@ -281,14 +279,14 @@
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Antaa sovelluksen vapauttaa puhelimesta tallennustilaa poistamalla sovelluksen välimuistihakemistossa olevia tiedostoja. Käyttöoikeus myönnetään yleensä vain järjestelmäprosesseille."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Siirrä sovellusresursseja"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Antaa sovelluksen siirtää sovellusresursseja sisäisistä medioista ulkoisiin ja päin vastoin."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"lue järjestelmälokitiedostoja"</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"lukea arkaluonteisia lokitietoja"</string>
     <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Antaa sovelluksen lukea järjestelmän lokitiedostoja. Näin sovellus saa tietoonsa tietoja siitä, mitä teet tablet-laitteella, ja mahdollisia yksityisiä tai arkaluonteisia tietoja."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Antaa sovelluksen lukea järjestelmän lokitiedostoja. Näin sovellus saa tietoonsa tietoja siitä, mitä teet tablet-laitteella, ja mahdollisia yksityisiä tai arkaluonteisia tietoja."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Antaa sovelluksen lukea järjestelmän lokitiedostoja. Näin sovellus saa tietoonsa tietoja siitä, mitä teet puhelimella, ja mahdollisia yksityisiä tai arkaluonteisia tietoja."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lue diag:in omistamia resursseja / kirjoita resursseihin"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Antaa sovelluksen lukea ja kirjoittaa kaikkiin diag-ryhmän omistamiin resursseihin, esimerkiksi /dev-hakemistossa oleviin tiedostoihin. Tämä saattaa mahdollisesti vaikuttaa järjestelmän vakauteen ja tietosuojaan. Suositellaan käytettäväksi VAIN operaattorin tai valmistajan laitteistodiagnooseihin."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"ota sovelluskomponentteja käyttöön tai poista niitä käytöstä"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Antaa sovelluksen päättää, onko toisen sovelluksen komponentti käytössä vai ei. Haittasovellukset saattavat käyttää tätä tärkeiden tablet-laitteen ominaisuuksien käytöstä poistamiseen. Mieti tarkkaan ennen tämän luvan myöntämistä, etteivät sovellusten komponentit mene käyttämättömään, yhteensopimattomaan tai epävakaaseen tilaan."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Antaa sovelluksen päättää, onko toisen sovelluksen komponentti käytössä vai ei. Haittasovellukset saattavat käyttää tätä tärkeiden tablet-laitteen ominaisuuksien käytöstä poistamiseen. Mieti tarkkaan ennen tämän luvan myöntämistä, etteivät sovellusten komponentit mene käyttämättömään, yhteensopimattomaan tai epävakaaseen tilaan."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Antaa sovelluksen päättää, onko toisen sovelluksen komponentti käytössä vai ei. Haittasovellukset saattavat käyttää tätä tärkeiden puhelimen ominaisuuksien käytöstä poistamiseen. Mieti tarkkaan ennen tämän luvan myöntämistä, etteivät sovellusten komponentit mene käyttämättömään, yhteensopimattomaan tai epävakaaseen tilaan."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"aseta ensisijaisia sovelluksia"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Antaa sovelluksen muokata ensisijaisia sovelluksiasi. Haitalliset sovellukset saattavat muuttaa käynnissä olevia sovelluksia ja huijata olemassa olevia sovelluksiasi keräämään sinulta yksityisiä tietoja."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"muokkaa yleisiä järjestelmän asetuksia"</string>
@@ -301,10 +299,10 @@
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Antaa sovelluksen käynnistää itsensä heti, kun järjestelmä on käynnistynyt uudelleen. Tämä voi hidastaa tablet-laitteen käynnistymistä ja sallia sovelluksen hidastaa tablet-laitetta yleisesti olemalla aina käynnissä."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Antaa sovelluksen käynnistää itsensä, kun järjestelmä on käynnistynyt uudelleen. Tämä voi pitkittää puhelimen käynnistysaikaa, ja sovellus voi hidastaa puhelimen toimintaa olemalla aina käynnissä."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"lähetä tärkeä lähetys"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Antaa sovelluksen lähettää tärkeitä lähetyksiä, jotka jäävät voimaan lähetyksen päätyttyä. Haittasovellukset voivat hidastaa tablet-laitteen toimintaa tai tehdä siitä epävakaan lisäämällä sen muistin käyttöä."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Antaa sovelluksen lähettää tärkeitä lähetyksiä, jotka jäävät voimaan lähetyksen päätyttyä. Haittasovellukset saattavat hidastaa puhelimen toimintaa tai tehdä siitä epävakaan lisäämällä sen muistin käyttöä."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Antaa sovelluksen lähettää tärkeitä lähetyksiä, jotka jäävät voimaan lähetyksen päätyttyä. Haitalliset sovellukset saattavat hidastaa puhelimen toimintaa tai tehdä siitä epävakaan lisäämällä sen muistin käyttöä."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"lue yhteystietoja"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Antaa sovelluksen tarkastella kaikkia tablet-laitteellesi tallennettuja yhteystietoja (osoitteita). Haittasovellukset voivat käyttää tätä tietojesi lähettämiseen muille"</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Antaa sovelluksen tarkastella kaikkia tablet-laitteellesi tallennettuja yhteystietoja (osoitteita). Haittasovellukset voivat käyttää tätä tietojesi lähettämiseen muille ihmisille."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Antaa sovelluksen lukea kaikki puhelimeesi tallennetut yhteystiedot (osoitteet). Haitalliset sovellukset saattavat käyttää tätä tietojesi lähettämiseen muille."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"kirjoita yhteystietoja"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Antaa sovelluksen muokata tablet-laitteellesi tallennettuja yhteystietoja (osoitteita). Haittasovellukset voivat käyttää tätä yhteystietojesi pyyhkimiseen tai muokkaamiseen."</string>
@@ -324,7 +322,7 @@
     <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Käytä sijaintilähteitä, kuten GPS-järjestelmää tablet-laitteella, jos saatavilla. Haittasovellukset voivat käyttää tätä sijaintisi määrittämiseen ja voivat kuluttaa akkuasi tavallista enemmän."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Käyttää tarkkoja sijaintilähteitä kuten GPS:ää puhelimella, jos saatavilla. Haitalliset sovellukset saattavat käyttää tätä määrittääkseen sijaintisi, ja ne saattavat myös kuluttaa enemmän akkua."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"summittainen (verkkopohjainen) sijainti"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Käytä summittaisia sijaintilähteitä, kuten matkapuhelinverkon tietokantaa, määrittääkseen likimääräisen tablet-laitteen sijainnin, jos saatavilla. Haittasovellukset saattavat käyttää tätä likimääräisen sijaintisi määrittämiseen."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Käytä summittaisia sijaintilähteitä kuten matkapuhelinverkon tietokantaa likimääräisen tablet-laitteen sijainnin määrittämiseen, jos saatavilla. Haittasovellukset saattavat käyttää tätä likimääräisen sijaintisi määrittämiseen."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Käyttää summittaisia sijaintilähteitä, kuten matkapuhelinverkon tietokantaa, määrittääkseen likimääräisen puhelimen sijainnin, jos saatavilla. Haitalliset sovellukset saattavat käyttää tätä likimääräisen sijaintisi määrittämiseen."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"käytä SurfaceFlinger-sovellusta"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Antaa sovelluksen käyttää SurfaceFlinger-sovelluksen alatason ominaisuuksia."</string>
@@ -334,8 +332,8 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Antaa sovelluksen muokata yleisiä ääniasetuksia, kuten äänenvoimakkuutta ja reititystä."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"tallentaa ääntä"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Antaa sovelluksen käyttää äänitallennepolkua."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"ota kuvia"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Antaa sovelluksen ottaa kuvia kameralla. Sovellus saa siis käyttöönsä kaikki kameran näkemät kohteet."</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"ota kuvia ja videoita"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Antaa sovelluksen tallentaa kuvia ja videoita kameralla. Näin sovellus voi aina kerätä kameran näkemät kuvat."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"poista tablet-laite käytöstä lopullisesti"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"poista puhelin käytöstä pysyvästi"</string>
     <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Antaa sovelluksen poistaa koko tablet-laitteen käytöstä lopullisesti. Tämä on hyvin vaarallista."</string>
@@ -348,23 +346,25 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Antaa sovelluksen ottaa käyttöön ja poistaa käytöstä tiedostojärjestelmiä siirrettäviin tallennuslaitteisiin."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"alusta ulkoinen tallennustila"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Antaa sovelluksen muokata siirrettävää tallennuslaitetta."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"saa tietoja suojatusta tallennustilasta"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Antaa sovelluksen hankkia suojatussa tallennustilassa olevia tietoja."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"luo suojattua tallennustilaa"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Antaa sovelluksen luoda suojattua tallennustilaa."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"tuhoa suojattua tallennustilaa"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Antaa sovelluksen tuhota suojattua tallennustilaa."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"ota käyttöön / poista käytöstä suojattua tallennustilaa"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Antaa sovelluksen ottaa käyttöön / poistaa käytöstä suojattua tallennustilaa."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"nimeä suojatun tallennustilan uudelleen"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Antaa sovelluksen nimetä suojattua tallennustilaa uudelleen."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"hae tietoja sisäisestä tallennustilasta"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Antaa sovelluksen hakea tietoja sisäisestä tallennustilasta."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"luo sisäistä tallennustilaa"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Antaa sovelluksen luoda sisäistä tallennustilaa."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"tuhoa sisäistä tallennustilaa"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Antaa sovelluksen tuhota sisäistä tallennustilaa."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"ota käyttöön tai poista käytöstä sisäistä tallennustilaa"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Antaa sovelluksen ottaa käyttöön tai poistaa käytöstä sisäistä tallennustilaa."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"nimeä sisäistä tallennustilaa uudelleen"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Antaa sovelluksen nimetä sisäistä tallennustilaa uudelleen."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"hallitse värinää"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Antaa sovelluksen hallita värinää."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"hallitse taskulamppua"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Antaa sovelluksen hallita lamppua."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"käytä USB-tiloja"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Antaa sovelluksen käyttää USB-tiloja."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testaa laitteistoa"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Antaa sovelluksen hallita useita liitännäislaitteita laitteistotestaustarkoituksessa."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"Antaa sovelluksen soittaa puhelinnumeroihin ilman omaa hallintaasi. Haitalliset sovellukset saattavat soittaa odottamattomia puheluita ja kasvattaa puhelinlaskuasi. Huomaa, että tämä ei anna sovellukselle lupaa soittaa hätänumeroihin."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"soita mihin tahansa puhelinnumeroon suoraan"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Antaa sovelluksen soittaa mihin tahansa numeroon, myös hätänumeroihin, ilman omaa hallintaasi. Haitalliset sovellukset saattavat soittaa hätänumeroihin laittomia ja tarpeettomia puheluita."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"aloita CDMA-tabletin asetuksien määrittäminen"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"käynnistä CDMA-tablet-laitteen asetukset"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"aloita CDMA-puhelimen asetuksien määrittäminen"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Antaa sovelluksen aloittaa CDMA-määrityksen. Haitalliset sovellukset saattavat aloittaa CDMA-määrityksen tarpeettomasti."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"hallitse sijaintien päivitysilmoituksia"</string>
@@ -443,10 +443,8 @@
     <string name="permlab_bluetooth" msgid="8361038707857018732">"luo Bluetooth-yhteyksiä"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Antaa sovelluksen tarkastella paikallisen Bluetooth-tabletin asetuksia sekä muodostaa ja hyväksyä laitepariyhteyksiä."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Antaa sovelluksen tarkastella paikallisen Bluetooth-puhelimen asetuksia sekä muodostaa ja hyväksyä laitepariyhteyksiä muihin laitteisiin."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"hallitse Near Field Communication -tunnistusta"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Antaa sovelluksen viestiä Near Field Communication (NFC) -tunnisteiden, -korttien ja -lukijoiden kanssa."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"poista näppäinlukitus käytöstä"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Antaa sovelluksen poistaa näppäinlukituksen ja siihen liittyvän salasanasuojauksen käytöstä. Esimerkki: puhelin poistaa näppäinlukituksen käytöstä saapuvan puhelun yhteydessä ja ottaa näppäinlukituksen takaisin käyttöön puhelun päätyttyä."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lue synkronointiasetuksia"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Antaa sovelluksen lukea yksityisiä sanoja, nimiä ja ilmauksia, joita käyttäjä on tallentanut sanakirjaan."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"kirjoita käyttäjän määrittämään sanakirjaan"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Antaa sovelluksen kirjoittaa uusia sanoja käyttäjän sanakirjaan."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"muokkaa/poista SD-kortin sisältöä"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"muokkaa/poista USB-sisältöä"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"muokkaa/poista SD-kortin sisältöä"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Antaa sovelluksen kirjoittaa SD-kortille."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Antaa sovelluksen kirjoittaa USB-tallennustilaan."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Antaa sovelluksen kirjoittaa SD-kortille."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"muokkaa/poista säilytystilan sisältöä"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Antaa sovelluksen muokata sisäisen tallennustilan sisältöä."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"käytä välimuistin tiedostojärjestelmää"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Antaa sovelluksen lukea välimuistin tiedostojärjestelmää ja kirjoittaa sinne."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Rajoita salasanaa"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Rajaa käytettävien salasanojen tyyppejä."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Tarkkaile kirjautumisyrityksiä"</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"soita/vastaanota internetpuheluita"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Antaa sovelluksen käyttää SIP-palvelua internetpuheluiden soittamiseen/vastaanottamiseen."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Aseta salasanasäännöt"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Hallinnoi ruudun lukituksenpoistosalasanoissa sallittuja merkkejä ja salasanan pituutta"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Tarkkaile ruudun lukituksen poistoyrityksiä"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Tarkkaile ruudun lukitusta poistettaessa annettujen virheellisten salasanojen lukumäärää ja lukitse tablet-laite tai tyhjennä kaikki tabletin tiedot, jos virheellisiä salasanoja annetaan liian monta."</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Tarkkaile ruudun lukitusta poistettaessa annettujen virheellisten salasanojen lukumäärää ja lukitse tablet-laite tai tyhjennä kaikki tabletin tiedot, jos virheellisiä salasanoja annetaan liian monta."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Palauta salasana"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Pakota salasanalle uusi arvo ja vaadi järjestelmänvalvojaa antamaan se sinulle ennen kuin voit kirjautua sisään."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Pakota lukitus"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Hallitse laitteen lukittumista, sinun täytyy antaa salasana uudelleen."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Tarkkaile ruudun lukitusta poistettaessa annettujen virheellisten salasanojen lukumäärää ja lukitse puhelin tai tyhjennä kaikki puhelimen tiedot, jos virheellisiä salasanoja annetaan liian monta."</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Vaihda ruudunlukituksen poiston salasanaa"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Vaihda ruudunlukituksen poiston salasanaa"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Lukitse ruutu"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Hallinnoi, milloin ja miten ruutu lukittuu"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Pyyhi kaikki tiedot"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Tyhjennä tablet-laitteen tiedot varoituksetta palauttamalla tehdasasetukset."</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Tyhjennä tablet-laitteen tiedot varoituksetta palauttamalla tehdasasetukset."</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Tyhjennä puhelimen tiedot varoituksetta palauttamalla tehdasasetukset."</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Aseta laitteen yleinen välityspalvelin"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Aseta laitteen yleinen välityspalvelin käyttöön, kun käytäntö on käytössä. Vain ensimmäinen laitteen järjestelmänhallitsija voi asettaa käytettävän yleisen välityspalvelimen."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Aseta salasanan umpeutuminen"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Valitse, kuinka pian ruudunlukituksen poiston salasana tulee vaihtaa"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Puhelinnumero (koti)"</item>
     <item msgid="869923650527136615">"Mobiili"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Hakulaite (työ)"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Avustaja"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"Multimediaviesti"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Oma"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Syntymäpäivä"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Vuosipäivä"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Tapahtuma"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Muu"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Muokattu"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Sähköposti (koti)"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Työ"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Työ"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Muu"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Muokattu"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Muokattu"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Avustaja"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Veli"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Lapsi"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Avopuoliso"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Isä"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Ystävä"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Johtaja"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Äiti"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Vanhempi"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Kumppani"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Suosittelija"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Sukulainen"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Sisko"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Puoliso"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Muokattu"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Koti"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Työ"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Muu"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Anna PIN-koodi"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Poista lukitus antamalla salasana"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Poista lukitus antamalla PIN-koodi"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Virheellinen PIN-koodi!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Poista lukitus painamalla Valikko-painiketta ja 0-näppäintä."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Hätänumero"</string>
@@ -646,8 +615,7 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Palaa puheluun"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Oikein!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Yritä uudelleen"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Yritä uudelleen"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Ladataan (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Muutettu."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM-kortti on lukittu."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM-kortin lukitusta poistetaan…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Olet piirtänyt lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. "\n\n"Yritä uudelleen <xliff:g id="NUMBER_1">%d</xliff:g> sekunnin kuluttua."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%d</xliff:g> kertaa, sinua pyydetään poistamaan tablet-laitteesi lukitus Google-sisäänkirjautumisen avulla."\n\n" Yritä uudelleen <xliff:g id="NUMBER_2">%d</xliff:g> sekunnin kuluttua."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Olet antanut salasanasi väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. "\n\n"Yritä uudelleen <xliff:g id="NUMBER_1">%d</xliff:g> sekunnin kuluttua."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Olet antanut PIN-koodisi väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. "\n\n"Yritä uudelleen <xliff:g id="NUMBER_1">%d</xliff:g> sekunnin kuluttua."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Piirsit lukituksenpoistokuvin väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%d</xliff:g> kertaa, sinua pyydetään poistamaan tablet-laitteesi lukitus Google-sisäänkirjautumisen avulla."\n\n" Yritä uudelleen <xliff:g id="NUMBER_2">%d</xliff:g> sekunnin kuluttua."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%d</xliff:g> kertaa, sinua pyydetään poistamaan puhelimesi lukitus Google-sisäänkirjautumisen avulla."\n\n" Yritä uudelleen <xliff:g id="NUMBER_2">%d</xliff:g> sekunnin kuluttua."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Yritä uudelleen <xliff:g id="NUMBER">%d</xliff:g> sekunnin kuluttua."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Unohditko mallin?"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Siirrytäänkö pois tältä sivulta?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Valitse OK, jos haluat jatkaa, tai Peruuta, jos et halua siirtyä pois sivulta."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Vahvista"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Vinkki: lähennä ja loitonna kaksoisnapauttamalla"</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"Aut. täyt."</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"Automaattinen täyttö"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Autom. täyttö"</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lue selaimen historiaa ja kirjanmerkkejä"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Antaa sovelluksen lukea kaikki selaimen käyttämät URL-osoitteet ja selaimen kirjanmerkit."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"kirjoita selaimen historiaa ja kirjanmerkkejä"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Antaa sovelluksen muokata selaimen historiaa tai tablet-laitteellesi tallennettuja kirjanmerkkejä. Haittasovellukset voivat käyttää tätä selaimen tietojen pyyhkimiseen tai muokkaamiseen."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Antaa sovelluksen muokata puhelimeen tallennettuja selaimen historia- ja kirjanmerkkitietoja. Haitalliset sovellukset voivat käyttää tätä pyyhkiäkseen tai muokatakseen selaimen tietoja."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"aseta herätys herätyskelloon"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Antaa sovelluksen asettaa herätyksen asennettuun herätyskellosovellukseen. Kaikki herätyskellosovellukset eivät välttämättä käytä tätä ominaisuutta."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"muokkaa selaimen maantieteellisen sijainnin lupia"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Antaa sovelluksen muokata selaimen maantieteellisen sijainnin lupia. Haitalliset sovellukset saattavat käyttää tätä sijaintitietojen lähettämiseen satunnaisiin verkkosivustoihin."</string>
     <string name="save_password_message" msgid="767344687139195790">"Haluatko selaimen muistavan tämän salasanan?"</string>
@@ -830,15 +790,12 @@
     <string name="cut" msgid="3092569408438626261">"Leikkaa"</string>
     <string name="copy" msgid="2681946229533511987">"Kopioi"</string>
     <string name="paste" msgid="5629880836805036433">"Liitä"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Ei mitään liitettävää"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Kopioi URL-osoite"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Tekstin valinta..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Tekstin valinta"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Syöttötapa"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Muokkaa tekstiä"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Tekstitoiminnot"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Tila vähissä"</string>
     <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Tablet-laitteen tallennustila on vähissä."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Puhelimen tallennustila on vähissä."</string>
@@ -847,8 +804,7 @@
     <string name="yes" msgid="5362982303337969312">"OK"</string>
     <string name="no" msgid="5141531044935541497">"Peruuta"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Huomio"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Ladataan..."</string>
     <string name="capital_on" msgid="1544682755514494298">"OTA KÄYTTÖÖN"</string>
     <string name="capital_off" msgid="6815870386972805832">"POISTA KÄYTÖSTÄ"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Tee toiminto käyttäen sovellusta"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Pakota sulkeutumaan"</string>
     <string name="report" msgid="4060218260984795706">"Ilmoita"</string>
     <string name="wait" msgid="7147118217226317732">"Odota"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Sovellus uudelleenohjasi"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> on nyt käynnissä."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> käynnistettiin alun perin."</string>
+    <string name="smv_application" msgid="295583804361236288">"Sovellus <xliff:g id="APPLICATION">%1$s</xliff:g> (prosessi <xliff:g id="PROCESS">%2$s</xliff:g>) on rikkonut itse käyttöön ottamaansa StrictMode-käytäntöä."</string>
+    <string name="smv_process" msgid="5120397012047462446">"Prosessi <xliff:g id="PROCESS">%1$s</xliff:g> on rikkonut itse käyttöön ottamaansa StrictMode-käytäntöä."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> käynnissä"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Vaihda sovellusta"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Vaihdetaanko sovellusta?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Toinen sovellus on jo käynnissä. Sulje kyseinen sovellus, ennen kuin käynnistät uuden."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Palaa kohteeseen <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Älä käynnistä uutta sovellusta."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Käynnistä <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Pysäytä vanha sovellus tallentamatta."</string>
     <string name="sendText" msgid="5132506121645618310">"Valitse tekstille toiminto"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Soittoäänen voimakkuus"</string>
     <string name="volume_music" msgid="5421651157138628171">"Median äänenvoimakkuus"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Näytä kaikki"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-massamuisti"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB yhdistetty"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Olet yhdistänyt puhelimesi tietokoneeseesi USB-yhteyden kautta. Valitse alla oleva painike, jos haluat kopioida tiedostoja tietokoneesi ja Androidin SD-korttisi välillä."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Olet yhdistänyt puhelimesi tietokoneeseesi USB-yhteyden kautta. Valitse alla oleva painike, jos haluat kopioida tiedostoja tietokoneesi ja Androidin SD-korttisi välillä."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Olet yhdistänyt laitteesi tietokoneeseesi USB-kaapelin kautta. Kosketa alla olevaa painiketta, jos haluat kopioida tiedostoja tietokoneesi ja Androidin USB-tallennustilan välillä"</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Olet yhdistänyt laitteesi tietokoneeseesi USB-kaapelin kautta. Kosketa alla olevaa painiketta, jos haluat kopioida tiedostoja tietokoneesi ja Androidin SD-kortin välillä."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Ota USB-tallennustila käyttöön"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"SD-kortin käyttämisessä USB-tallennustilana esiintyi ongelma."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"SD-kortin käyttämisessä USB-tallennustilana esiintyi ongelma."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Ongelma käytettäessä USB-tilaa USB-massamuistina."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Ongelma käytettäessä SD-korttia USB-massamuistina."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB yhdistetty"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Kopioi tiedostoja tietokoneelle tai tietokoneelta valitsemalla tämä."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Poista USB-tallennustila käytöstä"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Poista USB-tallennustila käytöstä valitsemalla tämä."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-tallennustila käytössä"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Varmista ennen USB-tallennustilan käytöstä poistoa, että olet poistanut Androidin SD-kortin käytöstä tietokoneestasi."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Varmista ennen USB-tallennustilan kytkemistä pois päältä, että olet poistanut Androidin USB-tallennustilan käytöstä tietokoneellasi."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Varmista ennen USB-tallennustilan käytöstä poistoa, että olet poistanut Androidin SD-kortin käytöstä tietokoneestasi."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Poista USB-tallennustila käytöstä"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Ongelma USB-tallennustilan käytöstä poistamisessa. Tarkista, että olet poistanut USB-laitteen käytöstä ja yritä uudelleen."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jos otat USB-tallennustilan käyttöön, osa käyttämistäsi sovelluksista pysähtyy eivätkä ne välttämättä ole käytössä kunnes poistat USB-tallennustilan käytöstä."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB-toiminto epäonnistui"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Alusta SD-kortti"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Alusta USB-tila"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Alusta SD-kortti"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Haluatko varmasti alustaa SD-kortin? Kaikki kortilla olevat tiedot menetetään."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Haluatko alustaa USB-tilan ja poistaa kaikki siellä olevat tiedostot? Toimintoa ei voi peruuttaa!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Haluatko varmasti alustaa SD-kortin? Kaikki kortilla olevat tiedot menetetään."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Muoto"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-vianetsintä yhdistetty"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidaatit"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Valmistellaan SD-korttia"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Valmistellaan USB-tilaa"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Valmistellaan SD-korttia"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Tarkistetaan virheiden varalta."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Tyhjä SD-kortti"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Tyhjä USB-tallennustila"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tyhjä SD-kortti"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"SD-kortti on tyhjä tai sen tiedostojärjestelmää ei tueta."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB-tallennustila on tyhjä tai sen tiedostojärjestelmää ei tueta."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD-kortti on tyhjä tai sen tiedostojärjestelmää ei tueta."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Vahingoittunut SD-kortti"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"USB-tila vahingoittunut"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Vahingoittunut SD-kortti"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"SD-kortti vioittunut. Saatat joutua alustamaan kortin."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB-tallennustila on vahingoittunut. Voit joutua alustamaan sen uudelleen."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD-kortti vioittunut. Saatat joutua alustamaan kortin."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"SD-kortti poistettiin yllättäen"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-tila poistettiin yllättäen"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD-kortti poistettiin yllättäen"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Poista SD-kortti käytöstä ennen kuin poistat sen, jotta tietoja ei katoa."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Poista USB-tallennustila käytöstä ennen sen irrottamista estääksesi tietoja katoamasta."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Poista SD-kortti käytöstä ennen kuin poistat sen, jotta tietoja ei katoa."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"SD-kortti voidaan poistaa"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Voit nyt poistaa USB-tilan"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD-kortti voidaan poistaa"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Voit nyt poistaa SD-kortin."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Voit nyt poistaa USB-tallennustilan turvallisesti."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Voit nyt poistaa SD-kortin."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"SD-kortti poistettu"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB-tallennustila on poistettu"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD-kortti poistettu"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"SD-kortti poistettu. Aseta uusi kortti."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB-tallennustila poistettu. Lisää uusi laite."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD-kortti poistettu. Aseta uusi kortti."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Osuvia toimintoja ei löytynyt"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"päivitä komponenttien käyttötietoja"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Lähetä"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Seuraava"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Valmis"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Edell."</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Suorita"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Valitse numero"\n" <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Luo yhteystieto"\n"käyttäen numeroa <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Esijaettuun avaimeen perustuva L2TP/IPSec-suojattu VPN-verkko"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Varmenteeseen perustuva L2TP/IPSec-suojattu VPN-verkko"</string>
     <string name="upload_file" msgid="2897957172366730416">"Valitse tiedosto"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Ei valittua tiedostoa"</string>
     <string name="reset" msgid="2448168080964209908">"Palauta"</string>
     <string name="submit" msgid="1602335572089911941">"Lähetä"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Autotila käytössä"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Poistu autotilasta valitsemalla tämä."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Internetyhteyden jakaminen tai yhteyspiste käytössä"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Kosketa ja tee määritykset"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Takaisin"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Seuraava"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Ohita"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Paljon mobiilitiedonsiirtoa"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Saat lisätietoja mobiilitiedonsiirrosta koskettamalla"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Mobiilitiedonsiirtoraja ylitetty"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Saat lisätietoja mobiilitiedonsiirrosta koskettamalla"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Ei tuloksia"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Etsi sivulta"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 tulos"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g>/<xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Valmis"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Poistetaan USB-tallennustilaa käytöstä..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Poistetaan SD-korttia käytöstä..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Tyhjennetään USB-tallennustilaa..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Tyhjennetään SD-korttia..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">" USB-tallennustilan tyhjentäminen epäonnistui."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"SD-kortin tyhjentäminen epäonnistui."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD-kortti irrotettiin ennen sen käytöstä poistamista."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB-tallennustilaa tarkistetaan."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"SD-korttia tarkistetaan."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD-kortti on poistettu."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB-tallennustila on tietokoneen käytössä."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"SD-kortti on tietokoneen käytössä."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Ulkoinen media tuntemattomassa tilassa."</string>
+    <string name="share" msgid="1778686618230011964">"Jaa"</string>
+    <string name="find" msgid="4808270900322985960">"Etsi"</string>
+    <string name="websearch" msgid="4337157977400211589">"Verkkohaku"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 9ec5675..361d193 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode Avion"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Le mode Avion est activé."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Le mode Avion est désactivé."</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services payants"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permet à l\'application de contrôler la lampe de poche."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"accéder aux périphériques USB"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Autorise l\'application à accéder aux périphériques USB"</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"Tests du matériel"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Permet à l\'application de contrôler différents périphériques à des fins de test matériel."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"Appel direct des numéros de téléphone"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"État du support externe inconnu"</string>
     <string name="share" msgid="1778686618230011964">"Partager"</string>
     <string name="find" msgid="4808270900322985960">"Rechercher"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Recherche Web"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 2c07d41..befb526 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Govorna pošta"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Problem s vezom ili nevažeći MMI kôd."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Operacija je ograničena samo na brojeve s fiksnim biranjem."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Usluga nije omogućena."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Usluga je omogućena za korisnika:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Usluga je onemogućena."</string>
@@ -126,10 +125,10 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"Sinkronizacija"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinkronizacija"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Previše brisanja stavki <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Prostor za pohranu na tablet računalo pun je! Izbrišite dio datoteka da biste oslobodili prostor."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Pohrana tabletnog uređaja je puna! Izbrišite neke datoteke da biste oslobodili prostor."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"Prostor za pohranu na telefonu pun je! Izbrišite dio datoteka da biste oslobodili prostor."</string>
     <string name="me" msgid="6545696007631404292">"Ja"</string>
-    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opcije tablet računala"</string>
+    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opcije tabletnog uređaja"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"Opcije telefona"</string>
     <string name="silent_mode" msgid="7167703389802618663">"Bešumni način"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"Uključi bežični prijenos"</string>
@@ -137,13 +136,12 @@
     <string name="screen_lock" msgid="799094655496098153">"Zaključavanje zaslona"</string>
     <string name="power_off" msgid="4266614107412865048">"Isključi"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Isključivanje..."</string>
-    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Vaše će se tablet računalo isključiti."</string>
+    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Vaš tabletni uređaj će se isključiti."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Vaš će se telefon ipak isključiti"</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Želite li isključiti uređaj?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Nedavni"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Nema nedavnih aplikacija."</string>
-    <string name="global_actions" product="tablet" msgid="408477140088053665">"Opcije tablet računala"</string>
+    <string name="global_actions" product="tablet" msgid="408477140088053665">"Opcije tabletnog uređaja"</string>
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcije telefona"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Zaključavanje zaslona"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Isključi"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Način rada u zrakoplovu"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uključen je način rada u zrakoplovu"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Isključen je način rada u zrakoplovu"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Usluge koje se plaćaju"</string>
@@ -160,7 +160,7 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vaše poruke"</string>
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"Čitajte i pišite SMS-ove, poruke e-pošte i ostale poruke."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Vaši osobni podaci"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Izravan pristup kontaktima i kalendaru pohranjenom na tablet računalu."</string>
+    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Izravan pristup kontaktima i kalendaru pohranjenima na tabletnom uređaju."</string>
     <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Izravan pristup kontaktima i kalendaru pohranjenom na telefonu."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Vaša lokacija"</string>
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Praćenje vaše fizičke lokacije"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Razvojni alati"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Značajke potrebne samo za razvojne programere aplikacija."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Prostor za pohranu"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Pristup SD kartici."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Pristupi memoriji USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Pristup SD kartici."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"onemogućavanje ili izmjena trake statusa"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Aplikaciji omogućuje isključivanje trake statusa i uklanjanje sistemskih ikona."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"traka statusa"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Aplikaciji omogućuje da bude traka statusa."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"proširivanje/sažimanje trake statusa"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Aplikaciji omogućuje širenje ili sažimanje na traci statusa."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"prekini izlazne pozive"</string>
@@ -196,10 +194,10 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"slanje SMS poruka"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Aplikaciji omogućuje slanje SMS poruka. Zlonamjerne aplikacije mogu stvarati troškove slanjem poruka bez vaše potvrde."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"čitanje SMS-a ili MMS-a"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Aplikaciji omogućuje čitanje SMS poruka pohranjenih na tablet računalu ili SIM kartici. Zlonamjerne aplikacije mogu čitati vaše povjerljive poruke."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Aplikaciji omogućuje čitanje SMS poruka pohranjenih na tabletnom uređaju ili SIM kartici. Zlonamjerne aplikacije mogu čitati vaše povjerljive poruke."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Aplikaciji omogućuje čitanje SMS poruka pohranjenih na telefonu ili SIM kartici. Zlonamjerne aplikacije mogu čitati vaše povjerljive poruke."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"uređivanje SMS-a ili MMS-a"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Aplikaciji omogućuje pisanje na SMS poruke pohranjene na tablet računalu ili SIM kartici. Zlonamjerne aplikacije mogu izbrisati vaše poruke."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Aplikaciji omogućuje pisanje u SMS poruke pohranjene na tabletnom uređaju ili SIM kartici. Zlonamjerne aplikacije mogu izbrisati vaše poruke."</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Aplikaciji omogućuje pisanje SMS poruka za pohranjivanje na telefonu ili SIM kartici. Zlonamjerne aplikacije mogu izbrisati vaše poruke."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"primanje WAP-a"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Aplikaciji omogućuje primanje i obradu WAP poruka. Zlonamjerne aplikacije mogu pratiti vaše poruke ili ih izbrisati prije nego što ih vi vidite."</string>
@@ -250,7 +248,7 @@
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"upravljanje tokenima aplikacije"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Aplikacijama omogućuje stvaranje tokena i upravljanje tokenima, zaobilaženjem uobičajenog z-rasporeda. Nikad ne bi trebalo koristiti za uobičajene aplikacije."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"pritisnite tipke i gumbe za nadzor"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Aplikaciji omogućuje isporuku vlastitih događaja unosa (pritisci tipki itd.) u drugu aplikaciju. Zlonamjerne aplikacije mogu to upotrijebiti za preuzimanje tablet računala."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Aplikaciji omogućuje isporuku vlastitih događaja unosa (pritisaka tipki itd.) u drugu aplikaciju. Zlonamjerne aplikacije to mogu upotrijebiti za preuzimanje tabletnog uređaja."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Aplikaciji omogućuje isporuku vlastitih unosa događaja (pritiskom tipke itd.) u drugu aplikaciju. Zlonamjerne aplikacije to mogu koristiti za preuzimanje telefona."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"bilježi što pišete i koje radnje poduzimate"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Aplikacijama omogućuje praćenje pritisnutih tipki kod interakcije s drugom aplikacijom (primjerice kod unosa zaporke). Nikad ne bi trebalo koristiti za uobičajene aplikacije."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"izravno instaliranje aplikacija"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Aplikaciji omogućuje instaliranje novih ili ažuriranih paketa sustava Android. Zlonamjerne aplikacije mogu to upotrijebiti za dodavanje aplikacija uz moćna, samovoljna dopuštenja."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"brisanje svih podataka iz predmemorije aplikacije"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Aplikaciji omogućuje oslobađanje mjesta za pohranu na tablet računalu brisanjem datoteka u direktoriju predmemorije aplikacije. Pristup je veoma ograničen obično na sistemski postupak."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Aplikaciji omogućuje oslobađanje mjesta za pohranu na tabletnom uređaju brisanjem datoteka u direktoriju predmemorije aplikacije. Pristup je veoma ograničen obično sistemskom postupku."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Aplikaciji omogućuje oslobađanje mjesta za pohranu na telefonu brisanjem datoteka u direktoriju predmemorije aplikacije. Pristup je veoma ograničen obično sistemskim postupkom."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Premjesti izvore aplikacije"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Aplikaciji omogućuje premještanje resursa aplikacije iz internih na vanjske medije i obratno."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"čitanje datoteka dnevnika sustava"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Aplikaciji omogućuje čitanje raznih sistemskih datoteka dnevnika. Tako možemo otkriti opće informacije o tome što radite na tablet računalu, što potencijalno uključuje osobne i privatne podatke."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Aplikaciji omogućuje čitanje raznih sistemskih datoteka dnevnika. Tako možemo otkriti opće informacije o tome što radite na tablet računalu, što potencijalno uključuje osobne i privatne podatke."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"čitaj osjetljive podatke dnevnika"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Aplikaciji omogućuje čitanje raznih sistemskih datoteka dnevnika. Tako može otkriti opće informacije o tome što radite na tabletnom uređaju, što potencijalno uključuje osobne ili privatne informacije."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Aplikaciji omogućuje čitanje raznih sistemskih datoteka dnevnika. Tako može otkriti opće informacije o tome što radite na telefonu, što potencijalno uključuje osobne ili privatne informacije."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"pisanje/čitanje u resursima čije je vlasnik dijagnostika"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Aplikaciji omogućuje čitanje i pisanje u bilo koji resurs u vlasništvu dijagnostičke grupe; na primjer, datoteke u stavci /dev. To potencijalno može utjecati na stabilnost i sigurnost sustava. To se treba koristiti SAMO za dijagnostiku koja se posebno odnosi na hardver od strane proizvođača ili operatera."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"omogućavanje ili onemogućavanje komponenti aplikacije"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Aplikaciji omogućuje promjenu postavke omogućavanja ili onemogućavanja komponente druge aplikacije. Zlonamjerne aplikacije mogu to upotrijebiti kako bi onemogućile važne mogućnosti tablet računala. Pažljivo upotrebljavajte to dopuštenje jer postoji mogućnost dobivanja komponenata u beskorisnom, nekonzistentnom ili nestabilnom stanju."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Aplikaciji omogućuje promjenu postavke omogućavanja ili onemogućavanja komponente druge aplikacije. Zlonamjerne aplikacije mogu to upotrijebiti kako bi onemogućile važne mogućnosti tablet računala. Pažljivo upotrebljavajte to dopuštenje jer postoji mogućnost dobivanja komponenata u beskorisnom, nekonzistentnom ili nestabilnom stanju."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Aplikaciji omogućuje promjenu postavke omogućavanja ili onemogućavanja komponente druge aplikacije. Zlonamjerne aplikacije mogu to upotrijebiti kako bi onemogućile važne mogućnosti tabletnog uređaja. Pažljivo upotrebljavajte to dopuštenje jer postoji mogućnost dobivanja komponenata u beskorisnom, nekonzistentnom ili nestabilnom stanju."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Aplikaciji omogućuje promjenu postavke omogućavanja ili onemogućavanja komponente druge aplikacije. Zlonamjerne aplikacije mogu to upotrijebiti kako bi onemogućile važne mogućnosti telefona. Pažljivo upotrebljavajte to dopuštenje jer postoji mogućnost dobivanja komponenata u beskorisnom, nekonzistentnom ili nestabilnom stanju."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"postavljanje željene lokacije"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Aplikaciji omogućuje izmjenu željenih aplikacija. To zlonamjernim aplikacijama može omogućiti da neprimjetno mijenjaju pokrenute aplikacije uz preobrazbu postojećih aplikacija na način da prikupljaju vaše osobne podatke."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"izmjena postavki globalnog sustava"</string>
@@ -298,19 +296,19 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"izmjena karte Google usluga"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"Aplikaciji omogućuje izmjenu karte Google usluga. Nije za upotrebu na uobičajenim aplikacijama."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"automatski pokreni ponovno pokretanje"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Aplikacijama omogućuje samopokretanje odmah nakon završetka ponovnog pokretanja sustava. To može uzrokovati duže pokretanje tablet uređaja, a aplikacija može usporiti ukupan rad tablet uređaja."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Aplikaciji omogućuje samopokretanje odmah nakon završetka pokretanja sustava. To može uzrokovati duže pokretanje tabletnog uređaja, a aplikacija ga može usporiti svojim neprekidnim radom."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Aplikacijama omogućuje samopokretanje odmah nakon završetka ponovnog pokretanja sustava. To može uzrokovati duže pokretanje telefona, a aplikacija može usporiti ukupan rad telefona."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"slanje privlačnih prijenosa"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Aplikaciji omogućuje slanje privlačnih prijenosa, koji se zadržavaju nakon završetka prijenosa. Zlonamjerne aplikacije mogu usporiti rad tablet računala ili ga učiniti nestabilnim uz upotrebu previše memorije."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Aplikaciji omogućuje slanje privlačnih prijenosa, koji se zadržavaju nakon završetka prijenosa. Zlonamjerne aplikacije mogu usporiti rad tabletnog uređaja ili ga učiniti nestabilnim uz upotrebu previše memorije."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Aplikaciji omogućuje slanje privlačnih prijenosa, koji se zadržavaju nakon završetka prijenosa. Zlonamjerne aplikacije mogu usporiti rad telefona ili ga učiniti nestabilnim uz upotrebu previše memorije."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"čitanje kontaktnih podataka"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Aplikaciji omogućuje čitanje svih podataka o kontaktima (adrese) koji su pohranjeni na tablet računalu. Zlonamjerne aplikacije mogu to upotrijebiti za slanje podataka drugim ljudima."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Aplikaciji omogućuje čitanje svih podataka o kontaktima (adrese) koji su pohranjeni na tabletnom uređaju. Zlonamjerne aplikacije to mogu upotrijebiti za slanje podataka drugim ljudima."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Aplikaciji omogućuje čitanje svih podataka o kontaktima (adrese) koji su pohranjeni na računalu. Zlonamjerne aplikacije to mogu koristiti za slanje podataka drugim ljudima."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"pisanje kontaktnih podataka"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Aplikaciji omogućuje izmjenu kontaktnih podataka (adrese) koji su pohranjeni na vašem tablet računalu. Zlonamjerne aplikacije mogu to upotrijebiti za brisanje ili izmjenu vaših kontaktnih podataka."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Aplikaciji omogućuje izmjenu kontaktnih podataka (adrese) koji su pohranjeni na vašem tabletnom uređaju. Zlonamjerne aplikacije mogu to upotrijebiti za brisanje ili izmjenu kontaktnih podataka."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Aplikaciji omogućuje izmjenu kontaktnih podataka (adrese) koji su pohranjeni na vašem telefonu. Zlonamjerne aplikacije to mogu koristiti za brisanje ili izmjenu vaših kontaktnih podataka."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"čitanje kalendarskih događaja"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Aplikaciji omogućuje čitanje svih kalendarskih događaja pohranjenih na tablet računalu. Zlonamjerne aplikacije mogu to upotrijebiti za slanje kalendarskih događaja drugim ljudima."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Aplikaciji omogućuje čitanje svih događaja na kalendaru koji su pohranjeni na tabletnom uređaju. Zlonamjerne aplikacije to mogu upotrijebiti za slanje događaja na kalendaru drugim ljudima."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Aplikaciji omogućuje čitanje svih kalendarskih događaja pohranjenih na računalu. Zlonamjerne aplikacije to mogu koristiti za slanje kalendarskih događaja drugim ljudima."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"dodavanje ili izmjena kalendarskih događaja i slanje e-pošte gostima"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Aplikaciji omogućuje dodavanje i promjenu događaja na kalendaru, čime se mogu slati poruke e-pošte gostima. Zlonamjerne aplikacije to mogu koristiti za brisanje ili izmjenu kalendarskih događaja ili za slanje poruka e-pošte gostima."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"dopuštenje za instaliranje davatelja usluge lociranja"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Stvorite izvore približnih lokacija za testiranje. Zlonamjerne aplikacije to mogu koristiti za poništavanje lokacije i/ili statusa koji prikazuju pravi izvori lokacija poput GPS-a ili mrežnih davatelja ili mogu pratiti i prijavljivati vašu lokaciju vanjskom izvoru."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"ispravna (GPS) lokacija"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Pristupite preciznim izvorima lokacije kao što je Global Positioning System na tablet računalu, ako je to dostupno. Zlonamjerne aplikacije mogu to upotrijebiti kako bi utvrdile vaš položaj i mogu dodatno crpiti baterijsku energiju."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Pristupite preciznim izvorima lokacije kao što je Global Positioning System na tabletnom uređaju, gdje je to dostupno. Zlonamjerne aplikacije mogu to upotrijebiti kako bi utvrdile vaš položaj i mogu dodatno crpiti baterijsku energiju."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Pristupite izvorima lokacije kao što je Global Positioning System na telefonu, ako je to dostupno. Zlonamjerne aplikacije mogu to upotrijebiti kako bi utvrdile vaš položaj i mogu dodatno crpiti baterijsku energiju."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"široka (mrežno temeljena) lokacija"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Pristupite općim izvorima lokacije poput podatkovne baze mobilne mreže kako biste utvrdili približnu lokaciju tablet računala, ako je to dostupno. Zlonamjerne aplikacije mogu to upotrijebiti za približno utvrđivanje vašeg položaja."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Pristupite općim izvorima lokacije poput podatkovne baze mobilne mreže kako biste utvrdili približnu lokaciju telefona, ako je to dostupno. Zlonamjerne aplikacije mogu to upotrijebiti za približno utvrđivanje vašeg položaja."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Pristupite općim izvorima lokacije poput podatkovne baze mobilne mreže kako biste utvrdili približnu lokaciju telefona, ako je to dostupno. Zlonamjerne aplikacije to mogu koristiti za približno utvrđivanje vašeg položaja."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"pristup značajci SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Aplikacijama omogućuje upotrebu niskorazinskih usluga SurfaceFlinger."</string>
@@ -334,37 +332,39 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Aplikaciji omogućuje izmjenu globalnih zvučnih postavki, poput glasnoće i usmjeravanja."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"snimanje zvuka"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Aplikaciji omogućuje pristup putu za snimanje zvuka."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"snimanje slika"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Aplikacijama omogućuje snimanje slika fotoaparatom. To aplikaciji omogućuje prikupljanje slika s fotoaparata u bilo kojem trenutku."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"trajno onemogući tablet računalo"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"snimi fotografije i videozapise"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Aplikacijama omogućuje snimanje slika i videozapisa fotoaparatom. To aplikaciji omogućuje prikupljanje slika s fotoaparata u bilo kojem trenutku."</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"trajno onemogući tabletni uređaj"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"trajno onemogućavanje telefona"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Aplikaciji omogućuje trajno isključivanje cijelog tablet računala. To je veoma opasno."</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Aplikaciji omogućuje trajno isključivanje cijelog tabletnog uređaja. To je veoma opasno."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Aplikaciji omogućuje trajno isključivanje cijelog telefona. To je veoma opasno."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"prisilno ponovno pokreni tablet računalo"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"prisilno ponovno pokretanje tabletnog uređaja"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"prisilno ponovno pokretanje telefona"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Aplikaciji omogućuje prisilno ponovno pokretanje tablet računala."</string>
+    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Aplikaciji omogućuje prisilno ponovno pokretanje tabletnog uređaja."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Aplikaciji omogućuje prisilno ponovno pokretanje telefona."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"učitavanje i skidanje datotečnih sustava"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Aplikaciji omogućuje uključivanje i isključivanje sustava datoteka prijenosnih uređaja za pohranjivanje."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formatiranje vanjske pohrane"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Aplikaciji omogućuje formatiranje prijenosnog uređaja za pohranjivanje."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"dobivanje informacija iz sigurnog mjesta za pohranu"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Aplikaciji omogućuje dobivanje informacija o sigurnom pohranjivanju."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"stvaranje sigurnog pohranjivanja"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Aplikaciji omogućuje stvaranje sigurno pohranjivanje."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"uništavanje sigurnog pohranjivanja"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Aplikaciji omogućuje uklanjanje prostora za sigurno pohranjivanje."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"uključivanje/isključivanje sigurnog pohranjivanja"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Aplikaciji omogućuje uključivanje/isključivanje sigurnog pohranjivanja."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"promjena naziva sigurnog pohranjivanja"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Aplikaciji omogućuje promjenu naziva za sigurno pohranjivanje."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"dohvati informacije o unutarnjoj pohrani"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Omogućuje aplikaciji dohvaćanje informacija o unutarnjoj pohrani."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"stvori unutarnju pohranu"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Aplikaciji omogućuje stvaranje unutarnjeg pohranjivanja."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"uništi unutarnju pohranu"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Aplikaciji omogućuje uništavanje unutarnjeg pohranjivanja."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"uključi/isključi unutarnju pohranu"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Aplikaciji omogućuje uključivanje/isključivanje unutarnjeg pohranjivanja."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"preimenuj unutarnju pohranu"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Aplikaciji omogućuje preimenovanje unutarnjeg pohranjivanja."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"nadzor nad vibracijom"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Aplikaciji omogućuje nadzor nad vibracijom."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"nadzor bljeskalice"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Aplikaciji omogućuje nadzor nad bljeskalicom."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"pristupi USB uređajima"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Omogućuje aplikaciji pristup USB uređajima."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testiranje hardvera"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Aplikacijama omogućuje nadzor nad raznim vanjskim jedinicama u svrhu hardverskog testiranja."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"Aplikaciji omogućuje pozivanje telefonskih brojeva bez vašeg znanja. Zlonamjerne aplikacije mogu uspostavljati neočekivane pozive i opteretiti telefonski račun. Napominjemo da ovime ne omogućujete aplikaciji pozivanje hitnih službi."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"izravno pozivanje bilo kojeg telefonskog broja"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Aplikacijama omogućuje pozivanje bilo kojeg telefonskog broja, uključujući brojeve hitnih službi, bez vašeg znanja. Zlonamjerne aplikacije mogu upućivati nepotrebne i nedopuštene pozive hitnim službama."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"izravno pokretanje postavke CDMA tablet računala"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"izravno pokreni postavljanje CDMA tabletnog uređaja"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"izravno pokretanje postavke CDMA telefona"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Aplikaciji omogućuje pokretanje dobivanja značajke CDMA. Zlonamjerne aplikacije mogu nepotrebno pokrenuti dobivanje značajke CDMA"</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"obavijesti o ažuriranju kontrolne lokacije"</string>
@@ -385,16 +385,16 @@
     <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Aplikaciji omogućuje nadzor nad telefonskim značajkama na uređaju. Aplikacija s tim dopuštenjem može mijenjati mreže, uključivati i isključivati radio na telefonu i slične stvari bez vašeg znanja."</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"čitanje stanja i identiteta računala"</string>
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"Aplikaciji omogućuje da pristupi telefonskim značajkama uređaja. Aplikacija s tim dopuštenjem može utvrditi telefonski broj i serijski broj telefona, može utvrditi je li poziv aktivan, broj pozivatelja i slične značajke."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"spriječi tablet računalo da prijeđe u stanje mirovanja"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"spriječi mirovanje tabletnog uređaja"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"sprečava telefon da prijeđe u stanje mirovanja"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Aplikaciji omogućuje da spriječi prelazak tablet računala u mirovanje."</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Aplikaciji omogućuje da spriječi prelazak tabletnog uređaja u mirovanje."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Aplikaciji omogućuje da spriječi prelazak telefona u mirovanje."</string>
-    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"uključivanje ili isključivanje tablet računala"</string>
+    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"uključivanje ili isključivanje tabletnog uređaja"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"uključivanje ili isključivanje telefona"</string>
-    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Aplikaciji omogućuje uključivanje ili isključivanje tablet računala."</string>
+    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Aplikaciji omogućuje uključivanje i isključivanje tabletnog uređaja."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Aplikaciji omogućuje uključivanje ili isključivanje telefona."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"pokretanje u tvorničkom testnom načinu rada"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Pokrenite kao niskorazinski proizvođački test, uz omogućavanje potpunog pristupa hardveru tablet računala. Dostupno je samo ako tablet računalo radi u proizvođačkom testnom načinu rada."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Pokrenite kao niskorazinski proizvođački test, uz omogućavanje potpunog pristupa hardveru tabletnog uređaja. Dostupno je samo ako tabletni uređaj radi u proizvođačkom testnom načinu rada."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Pokrenite kao niskorazinski proizvođački test, uz omogućavanje potpunog pristupa telefonskom hardveru. Dostupno je samo ako telefon radi u proizvođačkom testnom načinu rada."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"postavi pozadinsku sliku"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Aplikaciji omogućuje postavljanje sistemske pozadinske slike."</string>
@@ -403,15 +403,15 @@
     <string name="permlab_masterClear" msgid="2315750423139697397">"poništavanje sustava na tvornički zadane postavke"</string>
     <string name="permdesc_masterClear" msgid="5033465107545174514">"Aplikaciji omogućuje da potpuno poništi rad sustava na tvorničke postavke brisanjem svih podataka, konfiguracije i instaliranih aplikacija."</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"postavljanje vremena"</string>
-    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Aplikaciji omogućuje promjenu vremena na satu tablet računala."</string>
+    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Aplikaciji omogućuje promjenu vremena na satu tabletnog uređaja."</string>
     <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Aplikaciji omogućuje promjenu vremena na satu telefona."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"postavljanje vremenske zone"</string>
-    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Aplikaciji omogućuje promjenu vremenske zone na tablet računalu."</string>
+    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Aplikaciji omogućuje promjenu vremenske zone na tabletnom uređaju."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Aplikaciji omogućuje promjenu vremenske zone na telefonu."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"ima ulogu Usluge voditelja računa"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Aplikaciji omogućuje pozivanje kontrolora autentičnosti računa"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"otkrivanje poznatih računa"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Aplikaciji omogućuje dobivanje popisa računa koje poznaje tablet računalo."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Aplikaciji omogućuje dobivanje popisa računa koje tabletni uređaj poznaje."</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Aplikaciji omogućuje dobivanje popisa računa koje poznaje telefon."</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"ima ulogu kontrolora autentičnosti računa"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Aplikaciji omogućuje upotrebu mogućnosti za provjeru vjerodostojnosti računa koja je dio značajke AccountManager, uključujući stvaranje računa te dobivanje i postavljanje zaporki."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"omogući višenamjenski Wi-Fi prijem"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Aplikaciji omogućuje primanje paketa koji nisu izravno upućeni na vaš uređaj. To može biti korisno za otkrivanje obližnjih usluge. Koristi više energije od višenamjenskog načina rada."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"bluetooth administracija"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Aplikaciji omogućuje konfiguraciju lokalnog Bluetooth tablet računala te otkrivanje i sparivanje s udaljenim uređajima."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Aplikaciji omogućuje konfiguraciju lokalnog tabletnog uređaja s Bluetoothom te otkrivanje i sparivanje s udaljenim uređajima."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Aplikaciji omogućuje konfiguraciju lokalnog Bluetooth telefona i otkrivanje i sparivanje s udaljenim uređajima."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"stvaranje Bluetooth veza"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Aplikaciji omogućuje pregled konfiguracije lokalnog Bluetooth tablet računala i uspostavljanje i prihvaćanje veza sa sparenim uređajima."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Aplikaciji omogućuje pregled konfiguracije lokalnog Bluetooth tabletnog uređaja i uspostavljanje i prihvaćanje veza sa sparenim uređajima."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Aplikaciji omogućuje pregled konfiguracije lokalnog Bluetooth telefona i uspostavljanje i prihvaćanje veza sa sparenim uređajima."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"upravljaj beskontaktnom (NFC) komunikacijom"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Aplikaciji omogućuje komunikaciju s Near Field Communication (NFC) oznakama, karticama i čitačima."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"onemogući zaključavanje tipkovnice"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Aplikaciji omogućuje isključivanje zaključavanja tipkovnice i svih povezanih sigurnosnih zaporki. Jasan primjer toga daje isključivanje zaključavanja telefona kod primanja poziva, koje se ponovno aktivira nakon završetka poziva."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čitanje postavki sinkronizacije"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Aplikaciji omogućuje čitanje osobnih riječi, imena i izraza koje je korisnik možda spremio u korisničkom rječniku."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"pisanje u korisnički definiran rječnik"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Aplikaciji omogućuje pisanje novih riječi u korisnički rječnik."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"izmjena/brisanje sadržaja SD kartice"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"izmjeni/briši sadržaje memorije USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"izmjena/brisanje sadržaja SD kartice"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Aplikaciji omogućuje pisanje na SD karticu."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Omog. pisanje na USB memoriju."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Aplikaciji omogućuje pisanje na SD karticu."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"izmijeni/briši sadržaje unutarnjih medija pohrane"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Omogućuje aplikaciji izmjenu sadržaja pohrane unutarnjih medija."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"pristup sustavu datoteka predmemorije"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Aplikaciji omogućuje čitanje i pisanje u sustav datoteka predmemorije."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ograniči zaporku"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Ograničite vrste zaporki koje smijete koristiti."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Prati pokušaje prijave"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Nadziri broj netočnih zaporki unesenih pri otključavanju zaslona i zaključaj tablet računalo ili izbriši sve podatke s njega ako je uneseno previše netočnih zaporki"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Nadziri broj netočnih zaporki unesenih pri otključavanju zaslona i zaključaj tablet računalo ili izbriši sve podatke s njega ako je uneseno previše netočnih zaporki"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Poništi zaporku"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Promijenite zaporku koju vam je prethodno trebao dati administrator."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Pokreni zaključavanje"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Nadzire trenutak zaključavanja uređaja, zahtijeva ponovni unos zaporke."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"zovi/primaj internetske pozive"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Aplikaciji omogućuje upotrebu SIP usluge za nazivanje/primanje internetskih poziva."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Nadziri duljinu i znakove dopuštene u zaporci za otključavanje zaslona"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledaj pokušaje otključavanja zaslona"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Nadgledaj broj pogrešno unesenih zaporki za otključavanje zaslona i zaključaj tabletni uređaj ili izbriši sve podatke ako je uneseno previše pogrešnih zaporki"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Nadgledaj broj pogrešno unesenih zaporki za otključavanje zaslona i zaključaj telefon ili izbriši sve podatke ako je uneseno previše pogrešnih zaporki"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Promijeni zaporku za otključavanje zaslona"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Promijeni zaporku za otključavanje zaslona"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Zaključaj zaslon"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Nadziri kako se i kada zaslon zaključava"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Izbriši sve podatke"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Izbriši podatke tablet računala bez upozorenja, vraćanjem na tvorničko stanje"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Izbriši podatke tablet računala bez upozorenja, vraćanjem na tvorničko stanje"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Izbriši podatke tabletnog uređaja bez upozorenja vraćanjem u tvorničko stanje"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Izbriši podatke telefona bez upozorenja vraćanjem u tvorničko stanje"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"postavi globalni proxy uređaja"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Postavi globalni proxy uređaja za upotrebu dok su pravila omogućena. Samo prvi administrator uređaja postavlja djelotvoran globalni proxy."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Postavi istek zaporke"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Nadzirite za koliko vremena zaporka za zaključani zaslon treba biti promijenjena"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Početna"</item>
     <item msgid="869923650527136615">"Mobilni"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Poslovni dojavljivač"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Pomoćnik"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Prilagođeno"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Rođendan"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Godišnjica"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Događaj"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Drugo"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Prilagođeno"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Početna"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Posao"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Posao"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Ostalo"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Prilagođeno"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Prilagođeno"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Pomoćnik"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Brat"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Dijete"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Partner u kućanstvu"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Otac"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Prijatelj"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Voditelj"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Majka"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Roditelj"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Partner"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Preporučuje"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Rođak"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Sestra"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Bračni partner"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Prilagođeno"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Početna"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Posao"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Drugo"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Unesite PIN kôd"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Unesite zaporku za otključavanje"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Unesite PIN za otključavanje"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Netočan PIN kôd!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Za otključavanje pritisnite Izbornik pa 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Broj hitne službe"</string>
@@ -646,14 +615,13 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Uzvrati poziv"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Ispravno!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Žao nam je, pokušajte ponovo"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Pokušajte ponovno"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Punjenje (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Napunjeno."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Priključite punjač."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nema SIM kartice."</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"U tablet računalu nema SIM kartice."</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"U tabletnom uređaju nema SIM kartice."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"U telefonu nema SIM kartice."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Umetnite SIM karticu."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Samo hitni pozivi"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM kartica je zaključana."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Otključavanje SIM kartice…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Netočno ste iscrtali uzorak <xliff:g id="NUMBER_0">%d</xliff:g> puta. "\n\n"Pokušajte ponovo za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%d</xliff:g> puta. Nakon još <xliff:g id="NUMBER_1">%d</xliff:g> neuspješnih pokušaja, morat ćete otključati telefon pomoću Google prijave."\n\n" Pokušajte ponovo za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Netočno ste unijeli zaporku <xliff:g id="NUMBER_0">%d</xliff:g> puta. "\n\n"Pokušajte ponovno za <xliff:g id="NUMBER_1">%d</xliff:g> sekunda."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Netočno ste unijeli PIN <xliff:g id="NUMBER_0">%d</xliff:g> puta. "\n\n"Pokušajte ponovno za <xliff:g id="NUMBER_1">%d</xliff:g> sekunda."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%d</xliff:g> puta. Nakon još <xliff:g id="NUMBER_1">%d</xliff:g> neuspješna pokušaja, zamolit ćemo vas da otključate tabletni uređaj pomoću Google prijave."\n\n" Pokušajte ponovno za <xliff:g id="NUMBER_2">%d</xliff:g> sekunda."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%d</xliff:g> puta. Nakon još <xliff:g id="NUMBER_1">%d</xliff:g> neuspješna pokušaja, morat ćete otključati telefon pomoću Google prijave."\n\n" Pokušajte ponovo za <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Pokušajte ponovno za <xliff:g id="NUMBER">%d</xliff:g> s."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Zaboravili ste uzorak?"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Želite otići s ove lokacije?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Za nastavak odaberite U redu ili da biste ostali na trenutačnoj stranici odaberite Odustani."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Potvrdi"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Savjet: Dvaput dotaknite za povećanje i smanjivanje."</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"AutoFill"</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"Automatsko popunjavanje"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Postavi autopop."</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"čitanje povijesti i oznaka preglednika"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Aplikaciji omogućuje čitanje svih URL-ova koje je preglednik posjetio i svih oznaka iz preglednika."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"pisanje povijesti i oznaka preglednika"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Aplikaciji omogućuje izmjenu povijesti ili oznaka preglednika koji su pohranjeni na vašem tablet računalu. Zlonamjerne aplikacije mogu to upotrijebiti za brisanje ili izmjenu podataka o pregledniku."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Aplikaciji omogućuje izmjenu povijesti ili oznaka preglednika koji su pohranjeni na vašem telefonu. Zlonamjerne aplikacije to mogu upotrijebiti za brisanje ili izmjenu podataka o pregledniku."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Aplikaciji omogućuje izmjenu povijesti ili oznaka preglednika koji su pohranjeni na vašem telefonu. Zlonamjerne aplikacije to mogu koristiti za brisanje ili izmjenu podataka o pregledniku."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"namjesti alarm na budilici"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Omogućuje aplikaciji da namjesti alarm u instaliranoj aplikaciji budilice. Neke aplikacije budilice možda neće primijeniti ovu značajku."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Izmijeni dopuštenja za geo-lociranje u pregledniku"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Aplikaciji omogućuje izmjenu dopuštenja za geolokaciju u pregledniku. Zlonamjerne aplikacije to mogu koristiti za omogućavanje slanja informacija o lokaciji na proizvoljne web-lokacije."</string>
     <string name="save_password_message" msgid="767344687139195790">"Želite li da preglednik zapamti ovu zaporku?"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"Izreži"</string>
     <string name="copy" msgid="2681946229533511987">"Kopiraj"</string>
     <string name="paste" msgid="5629880836805036433">"Zalijepi"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Ništa za lijepljenje"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Kopiraj URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Odabir teksta..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Odabir teksta"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Način unosa"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Uredi tekst"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Radnje s tekstom"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Prostora ima sve manje"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Prostora za pohranjivanje na tablet računalu ima sve manje."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Prostora za pohranjivanje na tabletnom uređaju ima sve manje."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Prostora za pohranjivanje na telefonu ima sve manje."</string>
     <string name="ok" msgid="5970060430562524910">"U redu"</string>
     <string name="cancel" msgid="6442560571259935130">"Odustani"</string>
     <string name="yes" msgid="5362982303337969312">"U redu"</string>
     <string name="no" msgid="5141531044935541497">"Odustani"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Pažnja"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Učitavanje..."</string>
     <string name="capital_on" msgid="1544682755514494298">"Uključeno"</string>
     <string name="capital_off" msgid="6815870386972805832">"Isključeno"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Radnju dovrši pomoću stavke"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Prisilno zatvori"</string>
     <string name="report" msgid="4060218260984795706">"Izvješće"</string>
     <string name="wait" msgid="7147118217226317732">"Pričekaj"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Aplikacija preusmjerena"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> se izvodi sada."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> pokrenuta je prva."</string>
+    <string name="smv_application" msgid="295583804361236288">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) prekršila je svoje vlastito pravilo StrictMode."</string>
+    <string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> prekršio je svoje vlastito pravilo StrictMode."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"Izvodi se <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Odaberite za izmjenu aplikacije"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Izmjena aplikacija?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Već se izvodi neka druga aplikacija koja se mora zaustaviti prije pokretanje nove."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Natrag na <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Ne pokreći novu aplikaciju."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Pokreni <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Zaustavi staru aplikaciju bez spremanja."</string>
     <string name="sendText" msgid="5132506121645618310">"Odaberite radnju za tekst"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Glasnoća zvona"</string>
     <string name="volume_music" msgid="5421651157138628171">"Glasnoća medija"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Pokaži sve"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB masovno pohranjivanje"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB povezan"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Povezali ste računalo preko USB-a. Odaberite donji gumb ako želite kopirati datoteke s jednog računala na drugi i na SD karticu Androida."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Povezali ste računalo preko USB-a. Odaberite donji gumb ako želite kopirati datoteke s jednog računala na drugi i na SD karticu Androida."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Povezali ste se s računalom putem USB-a. Dodirnite donji gumb ako želite kopirati datoteke s računala na USB memoriju svojeg Androida ili obrnuto."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Povezali ste se s računalom putem USB-a. Dodirnite donji gumb ako želite kopirati datoteke s računala na karticu SD svojeg Androida ili obrnuto."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Uključi USB pohranjivanje"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Došlo je do problema s upotrebom SD kartice za USB pohranjivanje."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Došlo je do problema s upotrebom SD kartice za USB pohranjivanje."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Došlo je do problema s upotrebom USB memorije za za masovnu pohranu putem USB-a."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Došlo je do problema s upotrebom SD kartice za USB masovnu pohranu."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB povezan"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Odaberite za kopiranje datoteka na računalo ili s računala."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Isključi USB pohranjivanje"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Odaberite za isključivanje USB pohrane."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB pohrana se koristi"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Prije isključivanja USB pohranjivanja, morate izvaditi (“izbaciti”) SD karticu uređaja Android iz računala."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Prije isključivanja USB pohranjivanja, morate izvaditi (“izbaciti”) USB memoriju uređaja Android iz računala."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Prije isključivanja USB pohranjivanja, morate izvaditi (“izbaciti”) SD karticu uređaja Android iz računala."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Isključi USB pohranjivanje"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Došlo je do problema kod isključivanja USB pohranjivanja. Provjerite jeste li odspojili USB host, a zatim pokušajte ponovo."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ako uključite USB pohranjivanje, neke aplikacije koje koristite zaustavit će se i možda neće biti dostupne sve dok ne isključite USB pohranjivanje."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Rad USB-a nije uspio"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"U redu"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatiraj SD karticu"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format. USB memoriju"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatiraj SD karticu"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Jeste li sigurni da želite formatirati SD karticu? Svi podaci na kartici bit će izgubljeni."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatirati USB memoriju uz brisanje svih pohranjenih datoteka? Radnja se ne može poništiti!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Jeste li sigurni da želite formatirati SD karticu? Svi podaci na kartici bit će izgubljeni."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Priključen je alat za uklanjanje programske pogreške USB-a"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Priprema SD kartice"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Pripremanje memorije USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Priprema SD kartice"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Traženje pogrešaka."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Prazna SD kartica"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Prazna memorija USB"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Prazna SD kartica"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"SD kartica je prazna ili ima nepodržani sustav datoteka."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Memorija USB je prazna ili ima nepodržan sustav datoteka."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD kartica je prazna ili ima nepodržani sustav datoteka."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Oštećena SD kartica"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Oštećena USB memorija"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Oštećena SD kartica"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Oštećena je SD kartica. Možda biste je trebali preformatirati."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Oštećena je memorija USB. Možda biste je trebali preformatirati."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Oštećena je SD kartica. Možda biste je trebali preformatirati."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"SD kartica neočekivano je uklonjena"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Memorija USB nenadano uklonjena"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD kartica neočekivano je uklonjena"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"SD karticu isključite na siguran način prije uklanjanja kako biste izbjegli gubitak podataka."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Isključite USB memoriju na siguran način prije uklanjanja kako biste izbjegli gubitak podataka."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"SD karticu isključite na siguran način prije uklanjanja kako biste izbjegli gubitak podataka."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"SD kartica može se ukloniti na siguran način"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Sigurno uklanjanje memorije USB"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD kartica može se ukloniti na siguran način"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Možete ukloniti SD karticu na siguran način."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"USB memoriju možete sigurno ukloniti."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Možete ukloniti SD karticu na siguran način."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Uklonjena SD kartica"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Memorija USB uklonjena"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Uklonjena SD kartica"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"SD kartica je uklonjena. Umetnite novu."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Memorija USB uklonjena. Umetnite novi medij."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD kartica je uklonjena. Umetnite novu."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nisu pronađene podudarne radnje"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"statistika o upotrebi ažurirane komponente"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Pošalji"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Dalje"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Gotovo"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Preth."</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Pokreni"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Biraj broj"\n"koristeći <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Stvori kontakt"\n"koristeći <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Unaprijed dijeljeni L2TP/IPSec VPN temeljen na ključu"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN temeljen na certifikatu"</string>
     <string name="upload_file" msgid="2897957172366730416">"Odaberite datoteku"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Nema odabranih datoteka"</string>
     <string name="reset" msgid="2448168080964209908">"Ponovo postavi"</string>
     <string name="submit" msgid="1602335572089911941">"Pošalji"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Omogućen je način rada za automobil"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Odaberite za izlaz iz načina rada za automobil."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Ograničenje ili aktivan hotspot"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Dodirnite za konfiguraciju:"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Natrag"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Dalje"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Preskoči"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Upotreba velike količine mobilnih podataka"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Dotaknite da biste saznali više o upotrebi mobilnih podataka"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Prekoračeno je ograničenje za podatke na mobilnom uređaju"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Dotaknite da biste saznali više o upotrebi mobilnih podataka"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Nema rezultata"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Pronađi na stranici"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 podudaranje"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> od <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Gotovo"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Isključivanje memorije USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Isključivanje SD kartice..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Brisanje memorije USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Brisanje SD kartice..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Brisanje memorije USB nije uspjelo."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Brisanje SD kartice nije uspjelo."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Kartica SD uklonjena je prije isključivanja."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Memorija USB trenutačno se provjerava."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Kartica SD trenutno se provjerava."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Kartica SD uklonjena je."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB memoriju trenutačno upotrebljava računalo."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Karticu SD trenutačno upotrebljava računalo."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Vanjski mediji u nepoznatom stanju."</string>
+    <string name="share" msgid="1778686618230011964">"Dijeli"</string>
+    <string name="find" msgid="4808270900322985960">"Pronađi"</string>
+    <string name="websearch" msgid="4337157977400211589">"Pretraž. weba"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 017e837..0ee1bbc 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Hangposta"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Kapcsolódási probléma vagy érvénytelen MMI-kód."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"A művelet fix hívószámokra van korlátozva."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"A szolgáltatás engedélyezésre került."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Engedélyezett szolgáltatás(ok):"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"A szolgáltatás ki van kapcsolva."</string>
@@ -126,10 +125,10 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"Szinkronizálás"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Szinkronizálás"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Túl sok <xliff:g id="CONTENT_TYPE">%s</xliff:g> törlés."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"A táblagép tárhelye megtelt. Töröljön néhány fájlt."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"A táblagép tárhelye tele van. Szabadítson fel helyet néhány fájl törlésével."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"A telefon tárhelye megtelt! Hely felszabadításához töröljön néhány fájlt."</string>
     <string name="me" msgid="6545696007631404292">"Saját"</string>
-    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"A táblagép lehetőségei"</string>
+    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Táblagép beállításai"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"Telefonbeállítások"</string>
     <string name="silent_mode" msgid="7167703389802618663">"Néma üzemmód"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"Vezeték nélküli eszköz bekapcsolása"</string>
@@ -137,13 +136,12 @@
     <string name="screen_lock" msgid="799094655496098153">"Képernyő lezárása"</string>
     <string name="power_off" msgid="4266614107412865048">"Kikapcsolás"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Leállítás..."</string>
-    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"A táblagép le fog állni."</string>
+    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"A táblagép ki fog kapcsolni."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"A telefon le fog állni."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Kikapcsolja?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Legutóbbiak"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Nincs új alkalmazás."</string>
-    <string name="global_actions" product="tablet" msgid="408477140088053665">"A táblagép lehetőségei"</string>
+    <string name="global_actions" product="tablet" msgid="408477140088053665">"Táblagép beállításait"</string>
     <string name="global_actions" product="default" msgid="2406416831541615258">"Telefonbeállítások"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Képernyő lezárása"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Kikapcsolás"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Repülőgép üzemmód"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Repülőgép üzemmód bekapcsolva"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Repülőgép üzemmód kikapcsolva"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Fizetős szolgáltatások"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Fejlesztői eszközök"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Csak az alkalmazásfejlesztők számára fontos funkciók."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Tárhely"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Az SD-kártya elérése."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Az USB-tár elérése."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Az SD-kártya elérése."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"állapotsor kikapcsolása vagy módosítása"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Lehetővé teszi az alkalmazás számára az állapotsor kikapcsolását és a rendszerikonok hozzáadását, illetve eltávolítását."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"állapotsor"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Lehetővé teszi az alkalmazások számára, hogy az állapotsoron legyenek."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"állapotsáv részletes- és listanézete"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Lehetővé teszi az alkalmazások számára az állapotsor lista-, illetve részletes nézete közti váltást."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"kimenő hívások elfogása"</string>
@@ -196,10 +194,10 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"SMS-ek küldése"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Lehetővé teszi az alkalmazás számára SMS küldését. A rosszindulatú alkalmazások az Ön engedélye nélkül küldhetnek üzenetet, ami megnövelheti a kiadásait."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"SMS vagy MMS olvasása"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Lehetővé teszi az alkalmazás számára a táblagépen és a SIM-kártyán tárolt SMS-ek olvasását. A rosszindulatú alkalmazások elolvashatják a bizalmas üzeneteket."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Lehetővé teszi az alkalmazások számára, hogy olvassák a táblagépen vagy a SIM-kártyán lévő SMS-eket. A rosszindulatú alkalmazások elolvashatják a bizalmas üzeneteket."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Lehetővé teszi az alkalmazás számára a telefonon és a SIM-kártyán tárolt SMS-ek olvasását. A rosszindulatú alkalmazások elolvashatják a bizalmas üzeneteket."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"SMS vagy MMS szerkesztése"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Lehetővé teszi az alkalmazás számára, hogy írjon a táblagépen és a SIM-kártyán tárolt SMS-ekbe. A rosszindulatú alkalmazások törölhetik az üzeneteket."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Lehetővé teszi az alkalmazások számára, hogy írjanak a táblagépen vagy a SIM-kártyán lévő SMS-ekbe. A rosszindulatú alkalmazások törölhetik az üzeneteket."</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Lehetővé teszi az alkalmazás számára, hogy írjon a telefonon és a SIM-kártyán tárolt SMS-ekbe. A rosszindulatú alkalmazások törölhetik az üzeneteket."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"WAP fogadása"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Lehetővé teszi az alkalmazás számára a WAP-üzenetek fogadását és feldolgozását. A rosszindulatú alkalmazások megfigyelhetik vagy törölhetik az üzeneteket anélkül, hogy Ön látná."</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"alkalmazásváltás megakadályozása"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Megakadályozza, hogy a felhasználó másik alkalmazásra váltson."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"minden alkalmazásindítás figyelése és vezérlése"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Lehetővé teszi egy alkalmazás számára, hogy figyelje és vezérelje, hogy a rendszer hogyan indít el tevékenységeket. A rosszindulatú alkalmazások teljesen megfertőzhetik a rendszert. Ez az engedély csak fejlesztéshez szükséges, normál használathoz sosem."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Lehetővé teszi az alkalmazások számára, hogy megfigyeljék és vezéreljék, hogy a rendszer hogyan indít el tevékenységeket. A rosszindulatú alkalmazások teljesen tönkretehetik a rendszert. Ez az engedély csak fejlesztés céljára lehet szükséges, mindennapi használatra nem."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"eltávolított csomagú üzenetek küldése"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Lehetővé teszi egy alkalmazás számára, hogy üzenetet küldjön, ha egy alkalmazáscsomag eltávolításra került. A rosszindulatú alkalmazások ezáltal leállíthatnak más futó alkalmazásokat."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"SMS alapú üzenetek küldése"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"azonosítatlan ablakok megjelenítése"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Lehetővé teszi olyan ablakok létrehozását, amelyeket a belső rendszer felhasználói felülete általi használatra szántak. A normál alkalmazások nem használják ezt."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"rendszerszintű riasztások megjelenítése"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Lehetővé teszi egy alkalmazás számára a rendszerriasztási ablakok megjelenítését. A rosszindulatú alkalmazások elfoglalhatják a teljes képernyőt."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Lehetővé teszi az alkalmazások számára rendszerriasztás-ablakok megjelenítését. A rosszindulatú alkalmazások elfoglalhatják az egész képernyőt."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"animáció általános sebességének módosítása"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Lehetővé teszi egy alkalmazás számára az animációk általános sebességének (gyorsabb vagy lassabb) módosítását."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"alkalmazástokenek kezelése"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Lehetővé teszi az alkalmazások számára saját tokenek létrehozását és kezelését, kihagyva a szokásos Z-sorrendet. A normál alkalmazásoknak erre soha nincs szüksége."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"billentyűk és gombok megnyomása"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Lehetővé teszi egy alkalmazás számára saját beviteli eseményeinek (billentyűlenyomások stb.) elküldését más alkalmazásoknak. A rosszindulatú alkalmazások átvehetik a táblagép irányítását."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Lehetővé teszi az alkalmazások számára, hogy átadják saját beviteli eseményeiket (billentyűk megnyomása stb.) más alkalmazásoknak. A rosszindulatú alkalmazások ezt felhasználhatják arra, hogy átvegyék a táblagép irányítását."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Lehetővé teszi egy alkalmazás számára saját beviteli eseményeinek (billentyűlenyomások stb.) elküldését más alkalmazásoknak. A rosszindulatú alkalmazások átvehetik a telefon irányítását."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"a lenyomott billentyűk és a végrehajtott műveletek figyelése"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Lehetővé teszi az alkalmazások számára, hogy figyeljék a lenyomott billentyűket még másik alkalmazás használata esetén is (például jelszó beírásakor). A normál alkalmazásoknak erre soha nincs szüksége."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"alkalmazások közvetlen telepítése"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Lehetővé teszi egy alkalmazás számára új vagy frissített Android-csomagok telepítését. A rosszindulatú alkalmazások ezáltal önkényesen hozzáadhatnak hatékony engedélyekkel rendelkező alkalmazásokat."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"összes alkalmazás gyorsítótár-adatainak törlése"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Lehetővé teszi egy alkalmazás számára, hogy az alkalmazás-gyorsítótár könyvtárából töröljön fájlokat a táblagép memóriájának felszabadításához. A hozzáférés erősen korlátozott, főleg rendszerfolyamatokra."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Lehetővé teszi az alkalmazások számára, hogy helyet szabadítsanak fel a táblagépen az alkalmazás-gyorsítótár könyvtárban lévő fájlok törlésével. A hozzáférés nagyon korlátozott, általában rendszerfolyamatok kapnak."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Lehetővé teszi egy alkalmazás számára, hogy az alkalmazás-gyorsítótár könyvtárából töröljön fájlokat a telefon memóriájának felszabadításához. A hozzáférés erősen korlátozott, főleg rendszerfolyamatokra."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"További alkalmazás-erőforrások"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Lehetővé teszi egy alkalmazás számára alkalmazás-erőforrások áthelyezését a belső tárolóról egy külső tárolóra, és fordítva."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"rendszernapló-fájlok olvasása"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Lehetővé teszi egy alkalmazás számára, hogy elolvassa a rendszer különböző naplófájljait. Ezáltal általános információkat kaphat arról, hogy Ön miket csinált a táblagépén, és fennáll a lehetősége, hogy személyes vagy privát adatokhoz is hozzájut."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Lehetővé teszi egy alkalmazás számára, hogy elolvassa a rendszer különböző naplófájljait. Ezáltal általános információkat kaphat arról, hogy Ön miket csinált a táblagépén, és fennáll a lehetősége, hogy személyes vagy privát adatokhoz is hozzájut."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"érzékeny naplóadatok olvasása"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Lehetővé teszi az alkalmazások számára, hogy olvassák a rendszer különböző naplófájljait. Ezáltal általános információkat deríthetnek ki arról, hogy mire használja a táblagépét, valamint személyes, magánjellegű adatokhoz is hozzájuthatnak."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Lehetővé teszi az alkalmazások számára, hogy olvassák a rendszer különböző naplófájljait. Ezáltal általános információkat deríthetnek ki arról, hogy mire használja a telefonját, valamint személyes, magánjellegű adatokhoz is hozzájuthatnak."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"a diag tulajdonában lévő erőforrások olvasása és írása"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Lehetővé teszi egy alkalmazás számára, hogy olvassa és írja a diag csoport által birtokolt erőforrásokat; például a /dev könyvtár fájljait. Ez esetleg hatással lehet a rendszer stabilitására és biztonságára. Ezt CSAK a gyártó vagy a szolgáltató használhatja hardverspecifikus hibakeresésre."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"alkalmazáskomponensek be- és kikapcsolása"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Lehetővé teszi egy alkalmazás számára annak módosítását, hogy más alkalmazások komponensei engedélyezve vannak-e vagy sem. A rosszindulatú alkalmazások ezt a táblagép fontos képességeinek kikapcsolására használhatják. Óvatosan kell eljárni az engedély megadásával, mert lehetséges, hogy a komponensek használhatatlanok, inkonzisztensek vagy instabilak lesznek."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Lehetővé teszi egy alkalmazás számára annak módosítását, hogy más alkalmazások komponensei engedélyezve vannak-e vagy sem. A rosszindulatú alkalmazások ezt a táblagép fontos képességeinek kikapcsolására használhatják. Óvatosan kell eljárni az engedély megadásával, mert lehetséges, hogy a komponensek használhatatlanok, inkonzisztensek vagy instabilak lesznek."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Lehetővé teszi az alkalmazások számára, hogy megváltoztassák azt, hogy egy másik alkalmazás összetevője engedélyezve legyen-e vagy sem. A rosszindulatú alkalmazások ezt arra használhatják fel, hogy kikapcsolják a táblagép fontos funkcióit. Ezzel az engedéllyel óvatosan kell bánni, mivel egyes alkalmazáskomponensek használhatatlanná, inkonzisztenssé vagy instabillá válhatnak."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Lehetővé teszi az alkalmazások számára, hogy megváltoztassák azt, hogy egy másik alkalmazás összetevője engedélyezve legyen-e vagy sem. A rosszindulatú alkalmazások ezt arra használhatják fel, hogy kikapcsolják a telefon fontos funkcióit. Ezzel az engedéllyel óvatosan kell bánni, mivel egyes alkalmazáskomponensek használhatatlanná, inkonzisztenssé vagy instabillá válhatnak."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"preferált alkalmazások beállítása"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Lehetővé teszi egy alkalmazás számára a preferált alkalmazások módosítását. A rosszindulatú alkalmazások ezáltal észrevétlenül megváltoztathatják a futó alkalmazásokat, személyes adatokat gyűjtve Öntől."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"rendszer globális beállításainak módosítása"</string>
@@ -298,19 +296,19 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"Google-szolgáltatások térképének módosítása"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a Google-szolgáltatások térképét. A normál alkalmazások nem használják ezt."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"automatikus indítás rendszerindításkor"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Lehetővé teszi egy alkalmazás számára, hogy elindítsa magát a rendszerindítás után. Ez meghosszabbíthatja a táblagép elindításának idejét, az állandó futás miatt pedig lelassíthatja a táblagépet."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Lehetővé teszik az alkalmazások számára, hogy elindítsák magukat a rendszerindítás befejezése után. Emiatt tovább tarthat a táblagép elindulása, emellett az alkalmazás általánosságban is lelassíthatja a gépet, ha folyamatosan fut."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Lehetővé teszi egy alkalmazás számára, hogy elindítsa magát a rendszerindítás után. Ez meghosszabbíthatja a telefon elindításának idejét, az állandó futás miatt pedig lelassíthatja a telefont."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"ragadós üzenet küldése"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Lehetővé teszi egy alkalmazás számára ragadós üzenetek küldését, amelyek a sugárzás után is megmaradnak. A rosszindulatú alkalmazások lelassíthatják vagy instabillá tehetik a táblagépet a túlzott memóriahasználattal."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Lehetővé teszi egy alkalmazás számára \"ragadós üzenetek\" küldését, amelyek a sugárzás után is megmaradnak. A rosszindulatú alkalmazások lelassíthatják vagy instabillá tehetik a táblagépet a túlzott memóriahasználattal."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Lehetővé teszi egy alkalmazás számára ragadós üzenetek küldését, amelyek a sugárzás után is megmaradnak. A rosszindulatú alkalmazások lelassíthatják vagy instabillá tehetik a telefont a túlzott memóriahasználattal."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"névjegyadatok olvasása"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Lehetővé teszi egy alkalmazás számára, hogy elolvassa a táblagépen található összes felhasználói adatot (címet). A rosszindulatú alkalmazások kihasználhatják ezt arra, hogy elküldjék az adatokat másoknak."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Lehetővé teszi egy alkalmazás számára, hogy beolvassa a táblagépen tárolt összes névjegyadatot (címet). A rosszindulatú alkalmazások ezt felhasználhatják arra, hogy elküldjék adatait másoknak."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Lehetővé teszi egy alkalmazás számára, hogy elolvassa a telefonban található összes felhasználói adatot (címet). A rosszindulatú alkalmazások kihasználhatják ezt arra, hogy elküldjék az adatokat másoknak."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"névjegyadatok írása"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a táblagépen tárolt névjegy- (cím-) adatokat. A rosszindulatú alkalmazások felhasználhatják ezt a névjegyadatok törlésére vagy módosítására."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Lehetővé teszi az alkalmazások számára, hogy módosítsák a táblagépen tárolt névjegyadatokat (címeket). A rosszindulatú alkalmazások ezt felhasználhatják arra, hogy töröljék vagy módosítsák a névjegyadatokat."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a telefonon tárolt névjegy- (cím-) adatokat. A rosszindulatú alkalmazások felhasználhatják ezt a névjegyadatok törlésére vagy módosítására."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"naptári események olvasása"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Lehetővé teszi az alkalmazás számára, hogy elolvassa a táblagép naptárában lévő összes bejegyzést. A rosszindulatú alkalmazások ezt kihasználva másoknak is elküldhetik a naptárbejegyzéseket."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Lehetővé teszi az alkalmazások számára, hogy elolvassák a telefon naptárában lévő összes eseményt. A rosszindulatú alkalmazások ezt felhasználhatják arra, hogy elküldjék az eseményeket másoknak."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Lehetővé teszi az alkalmazás számára, hogy elolvassa a telefon naptárában lévő összes eseményt. A rosszindulatú alkalmazások ezt az események mások részére való elküldésére használhatják fel."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"naptári események hozzáadása vagy módosítása és e-mailek küldése vendégeknek"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Lehetővé teszi egy alkalmazás számára a naptári események hozzáadását és módosítását, valamint e-mailek küldését a vendégeknek. A rosszindulatú alkalmazások felhasználhatják ezt a naptárban levő események törlésére vagy módosítására, illetve e-mailek küldésére."</string>
@@ -321,7 +319,7 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"engedély helyszolgáltató telepítésére"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Helyforrás-utánzatok létrehozása tesztelés céljából. A rosszindulatú alkalmazások kihasználhatják ezt az olyan valódi helyforrások által megadott hely- és/vagy állapotadatok felülírására, mint a GPS vagy a mobilszolgáltatók, illetve az Ön tartózkodási helyének figyelésére és jelentésére külső forrásoknak."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"pontos (GPS) helymeghatározás"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Hozzáférés a táblagépen levő olyan pontos helyforrásokhoz, mint a GPS. A rosszindulatú alkalmazások ennek segítségével megállapíthatják az Ön tartózkodási helyét és ez a beállítás extra energiát fogyaszthat."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Hozzáfér olyan helyadat-forrásokhoz, mint a táblagépen lévő Globális helymeghatározó rendszer (ahol az elérhető). A rosszindulatú alkalmazások ezt felhasználhatják arra, hogy megállapítsák, Ön éppen hol tartózkodik, és ezáltal tovább csökkentik az akkumulátor energiáját."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Hozzáférés a telefonon levő olyan pontos helyforrásokhoz, mint a GPS. A rosszindulatú alkalmazások ennek segítségével megállapíthatják az Ön tartózkodási helyét és extra energiát fogyaszthatnak."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"becsült (hálózat alapú) helymeghatározás"</string>
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Hozzáférés olyan becsült helyforrásokhoz, mint például a mobilhálózati adatbázis, amellyel -- ahol elérhető -- hozzávetőlegesen meg lehet becsülni a táblagép helyzetét. A rosszindulatú alkalmazások ezáltal felbecsülhetik, hogy Ön merre jár."</string>
@@ -334,37 +332,39 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Lehetővé teszi az alkalmazás számára, hogy módosítsa az általános hangbeállításokat, például a hangerőt és az útválasztást."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"hanganyag rögzítése"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Lehetővé teszi az alkalmazások számára, hogy hozzáférjenek a hangfelvétel elérési útjához."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"fotó készítése"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Lehetővé teszi az alkalmazás számára, hogy képeket készítsen a kamerával. Ezáltal bármikor készíthet felvételeket arról, amit a kamera lát."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"táblagép végleges kikapcsolása"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"fotók és videók készítése"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Lehetővé teszi az alkalmazások számára, hogy fényképeket és videókat készítsenek a kamerával, ezáltal bármikor gyűjthetnek képanyagot, ha a kamera be van kapcsolva."</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"a táblagép végleges deaktiválása"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"telefon végleges letiltása"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Lehetővé teszi az alkalmazás számára a teljes táblagép végleges letiltását. Ez nagyon veszélyes."</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Lehetővé teszi az alkalmazások számára, hogy teljesen deaktiválják a táblagépet. Ez nagyon veszélyes."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Lehetővé teszi az alkalmazás számára a teljes telefon végleges letiltását. Ez nagyon veszélyes."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"táblagép újraindításának kényszerítése"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"táblagép újraindításának kikényszerítése"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"telefon újraindításának kikényszerítése"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Lehetővé teszi az alkalmazás számára a táblagép kényszerített újraindítását."</string>
+    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Lehetővé teszi az alkalmazások számára, hogy újraindítsák a táblagépet."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Lehetővé teszi az alkalmazás számára a telefon kényszerített újraindítását."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"fájlrendszerek csatolása és leválasztása"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Lehetővé teszi az alkalmazás számára a cserélhető lemezek fájlrendszereinek csatolását és leválasztását."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"külső tárhely formázása"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Lehetővé teszi az alkalmazás számára a cserélhető lemez formázását."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"információ kérése biztonságos tárolóról"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Lehetővé teszi az alkalmazás számára, hogy információkat szerezzen a biztonságos tárolóról."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"biztonságos tároló létrehozása"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Lehetővé teszi az alkalmazás számára biztonságos tárhely létrehozását."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"biztonságos tároló megsemmisítése"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Lehetővé teszi az alkalmazás számára biztonságos tárhely törlését."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"biztonságos tároló csatolása és leválasztása"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Lehetővé teszi az alkalmazás számára biztonságos tárhely csatolását és leválasztását."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"biztonságos tárhely átnevezése"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Lehetővé teszi az alkalmazás számára biztonságos tárhely átnevezését."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"információkérés a belső tárhelyről"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Lehetővé teszi az alkalmazások számára, hogy információkat kérjenek a belső tárhelyről."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"belső tárhely létrehozása"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Lehetővé teszi az alkalmazások számára, hogy létrehozzanak belső tárhelyet."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"a belső tárhely törlése"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Lehetővé teszi az alkalmazások számára, hogy töröljék a belső tárhelyet."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"belső tárhely csatlakoztatása és leválasztása"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Lehetővé teszi az alkalmazások számára, hogy csatlakoztassák/leválasszák a belső tárhelyet."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"belső tárhely átnevezése"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Lehetővé teszi az alkalmazások számára, hogy átnevezzék a belső tárhelyet."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"rezgés vezérlése"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Lehetővé teszi az alkalmazás számára a rezgés vezérlését."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"vaku vezérlése"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Lehetővé teszi az alkalmazás számára a vaku vezérlését."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"USB-eszközök elérése"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Lehetővé teszi az alkalmazások számára az USB-eszközök elérését."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"hardver tesztelése"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Lehetővé teszi az alkalmazás számára különböző perifériák vezérlését hardvertesztelés céljából."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"Lehetővé teszi az alkalmazás számára, hogy az Ön közreműködése nélkül hívjon fel telefonszámokat. A rosszindulatú alkalmazások hatására váratlan hívások jelenhetnek meg a telefonszámláján. Nem teszi lehetővé segélyhívó számok hívását."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"bármilyen telefonszám közvetlen hívása"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Lehetővé teszi az alkalmazás számára, hogy az Ön közreműködése nélkül felhívjon bármilyen telefonszámot, köztük a segélyhívó számokat is. A rosszindulatú alkalmazások felesleges és jogsértő hívásokat kezdeményezhetnek ez utóbbiakra."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"CDMA táblagép-beállítás közvetlen elindítása"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"a táblagép CDMA-beállításának közvetlen indítása"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"CDMA-telefonbeállítás közvetlen elindítása"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Lehetővé teszi az alkalmazás számára a CDMA-szolgáltatás indítása. A rosszindulatú alkalmazások szükségtelenül is elindíthatják a CDMA-szolgáltatást"</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"helyaktualizálási értesítések vezérlése"</string>
@@ -385,16 +385,16 @@
     <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Lehetővé teszi az alkalmazás számára az eszköz telefonálási funkcióinak vezérlését. Ezzel az engedéllyel lehetséges a hálózatváltás, a rádió be- és kikapcsolása, stb. anélkül, hogy erről Ön értesítést kapna."</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"telefon állapotának és azonosságának olvasása"</string>
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"Lehetővé teszi az alkalmazás számára, hogy hozzáférjen az eszköz telefonálási funkcióihoz. Az engedéllyel rendelkező alkalmazás megállapíthatja a telefon sorozat- és telefonszámát, hívás során a másik fél telefonszámát stb."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"táblagép alvó üzemmódjának megakadályozása"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"táblagép alvás üzemmódjának megakadályozása"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"telefon alvó üzemmódjának megakadályozása"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Lehetővé teszi egy alkalmazás számára annak megakadályozását, hogy a táblagép alvó üzemmódra váltson."</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Lehetővé teszi az alkalmazások számára, hogy megakadályozzák, hogy a táblagép alvó üzemmódra váltson."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Lehetővé teszi egy alkalmazás számára annak megakadályozását, hogy a telefon alvó üzemmódra váltson."</string>
     <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"a táblagép be- és kikapcsolása"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"a telefon be- és kikapcsolása"</string>
-    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Lehetővé teszi az alkalmazás számára, hogy be- vagy kikapcsolja a táblagépet."</string>
+    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Lehetővé teszi az alkalmazások számára a táblagép be- és kikapcsolását."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Lehetővé teszi az alkalmazás számára, hogy be- vagy kikapcsolja a telefont."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"futtatás gyári tesztüzemmódban"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Futtatás alacsony szintű gyártói tesztként, lehetővé téve a táblagép hardverének teljes körű elérését. Csak akkor érhető el, ha a táblagép gyártói tesztüzemmódban van."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Alacsony szintű gyári tesztként fut, lehetővé téve a táblagép összes hardverének elérését. Csak akkor érhető el, ha a táblagép gyári teszt üzemmódban fut."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Futtatás alacsony szintű gyártói tesztként, lehetővé téve a telefon hardverének teljes körű elérését. Csak akkor érhető el, ha a telefon gyártói tesztüzemmódban van."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"háttérkép beállítása"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Lehetővé teszi az alkalmazás számára a rendszer-háttérkép beállítását."</string>
@@ -403,15 +403,15 @@
     <string name="permlab_masterClear" msgid="2315750423139697397">"rendszer visszaállítása a gyári beállításokra"</string>
     <string name="permdesc_masterClear" msgid="5033465107545174514">"Lehetővé teszi egy alkalmazás számára a gyári beállítások teljes visszaállítását, törölve minden adatot, beállítást és telepített alkalmazást."</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"idő beállítása"</string>
-    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Lehetővé teszi egy alkalmazás számára a táblagép órájának átállítását."</string>
+    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Lehetővé teszi az alkalmazások számára hogy átállítsák a táblagép óráját."</string>
     <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Lehetővé teszi egy alkalmazás számára a telefon órájának átállítását."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"időzóna beállítása"</string>
-    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Lehetővé teszi egy alkalmazás számára a táblagép időzónájának módosítását."</string>
+    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Lehetővé teszi az alkalmazások számára hogy módosítsák a táblagép időzónáját."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Lehetővé teszi egy alkalmazás számára a telefon időzónájának módosítását."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"fiókfelügyeleti szolgáltatásként szereplés"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Lehetővé teszi egy alkalmazás számára, hogy hívásokat kezdeményezzenek a fiókhitelesítők felé"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"ismert fiókok felderítése"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Lehetővé teszi egy alkalmazás számára, hogy lekérje a táblagép által ismert fiókok listáját."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Lehetővé teszi az alkalmazások számára, hogy lekérjék a táblagép által ismert fiókok listáját."</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Lehetővé teszi egy alkalmazás számára, hogy lekérje a telefon által ismert fiókok listáját."</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"fiókhitelesítőként szereplés"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Lehetővé teszi egy alkalmazás számára a fiókkezelő fiókhitelesítő képességeinek használatát, beleértve fiókok létrehozását, valamint a jelszavak lekérését és beállítását."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"Wi-Fi multicast vétel engedélyezése"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Lehetővé teszi egy alkalmazás számára, hogy nem közvetlenül az eszköznek küldött csomagokat is fogadjon. Ez a közeli szolgáltatások felderítésében nyújthat segítséget. Több energiát fogyaszt, mint a nem multicast mód."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"bluetooth felügyelet"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Lehetővé teszi egy alkalmazás számára a helyi Bluetooth táblagép konfigurálását, valamint a távoli eszközök felderítését és párosítását."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Lehetővé teszi az alkalmazások számára, hogy konfigurálják a helyi Bluetooth-t, valamint felfedezzenek és párosítsanak távoli eszközöket."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Lehetővé teszi egy alkalmazás számára a helyi Bluetooth telefon konfigurálását, valamint a távoli eszközök felderítését és párosítását."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"Bluetooth kapcsolatok létrehozása"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Lehetővé teszi egy alkalmazás számára a helyi Bluetooth táblagép konfigurációjának megtekintését, valamint kapcsolatok kezdeményezését és fogadását a párosított eszközökkel."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Lehetővé teszi az alkalmazások számára, hogy megnézzék a Bluetooth beállításokat, és kapcsolatot hozzanak létre a párosított eszközökkel."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Lehetővé teszi egy alkalmazás számára a helyi Bluetooth telefon konfigurációjának megtekintését, valamint kapcsolatok kezdeményezését és fogadását a párosított eszközökkel."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"NFC technológia vezérlése"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Lehetővé teszi az alkalmazások számára, hogy NFC (Near Field Communication - kis hatósugarú vezeték nélküli kommunikáció) technológiát használó címkékkel, kártyákkal és leolvasókkal kommunikáljanak."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"billentyűzár kikapcsolása"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Lehetővé teszi egy alkalmazás számára a billentyűzár és a kapcsolódó jelszavas biztonság kikapcsolását. Ennek egy szabályos példája, amikor a telefon kikapcsolja a billentyűzárat egy beérkező hívás fogadásakor, majd a hívás befejezése után újra bekapcsolja azt."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"szinkronizálási beállítások olvasása"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Lehetővé teszi az alkalmazások számára a felhasználó által a felhasználói szótárban tárolt privát szavak, nevek és szófordulato elolvasását."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"írás a felhasználó által meghatározott könyvtárba"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Lehetővé teszi egy alkalmazás számára, hogy új szavakat írjon a felhasználó szótárába."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"az SD-kártya tartalmának módosítása és törlése"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"USB-tár tartalmának módosítása és törlése"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"az SD-kártya tartalmának módosítása és törlése"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Lehetővé teszi egy alkalmazás számára, hogy írjon az SD-kártyára."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Lehetővé teszi az alkalmazások számára, hogy írjanak az USB-tárra."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Lehetővé teszi egy alkalmazás számára, hogy írjon az SD-kártyára."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"a belső médiatároló tartalmának módosítása és törlése"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Lehetővé teszi az alkalmazások számára, hogy módosítsák a belső tárhely tartalmát."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"hozzáférés a gyorsítótár fájlrendszeréhez"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Lehetővé teszi egy alkalmazás számára a gyorsítótár fájlrendszerének olvasását és írását."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszó korlátozása"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"A használható jelszótípusok korlátozása."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Bejelentkezési kísérletek figyelése"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"A helytelenül bevitt jelszavak számának figyelése a képernyő zárolásának feloldása során, és a táblagép lezárása vagy a táblagép összes adatának törlése túl sok sikertelen próbálkozás után."</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"A helytelenül bevitt jelszavak számának figyelése a képernyő zárolásának feloldása során, és a táblagép lezárása vagy a táblagép összes adatának törlése túl sok sikertelen próbálkozás után."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Jelszó visszaállítása"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Adjon meg új értéket jelszavának, és kérje meg a rendszergazdát, hogy adja meg Önnek, mielőtt bejelentkezne."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Kényszerű lezárás"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Vezérli az eszköz lezárását, amihez újra meg kell adni a jelszót."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"internetes hívások kezdeményezése és fogadása"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Lehetővé teszi az alkalmazások számára a SIP-szolgáltatás használatát internetes hívások kezdeményezésére és fogadására."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"A képernyőzár-feloldási jelszavakban engedélyezett karakterek és hosszúság vezérlése"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Képernyőzár-feloldási kísérletek figyelése"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Figyeli a helytelenül megadott jelszavak számát a képernyőzár feloldása során, és ha túl sok rossz jelszót adnak meg, lezárja a táblagépet vagy törli annak összes adatát."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Figyeli a helytelenül megadott jelszavak számát a képernyőzár feloldása során, és ha túl sok rossz jelszót adnak meg, lezárja a telefont vagy törli annak összes adatát."</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"A képernyőzárat feloldó jelszó módosítása"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"A képernyőzárat feloldó jelszó módosítása"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"A képernyő zárolása"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"A képernyőzárolás módjának és idejének vezérlése"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Minden adat törlése"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"A táblagép adatainak figyelmeztetés nélkül történő törlése, a gyári adatok visszaállításával"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"A táblagép adatainak figyelmeztetés nélkül történő törlése, a gyári adatok visszaállításával"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Figyelmeztetés nélkül törli a táblagép adatait, visszaállítva a gyári adatokat"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Figyelmeztetés nélkül törli a telefon összes adatát, visszaállítva a gyári adatokat"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Az eszköz globális proxyjának beállítása"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Az eszköz globális proxyja lesz használatban, amíg az irányelv engedélyezve van. Csak az eszköz első rendszergazdája állíthatja be a tényleges globális proxyt."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Jelszó lejáratának beállítása"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Azt vezérli, mennyi időnként kell módosítani a képernyőt zároló jelszót"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Otthoni"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Munkahelyi személyhívó"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Asszisztens"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Egyéni"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Születésnap"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Évforduló"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Esemény"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Egyéb"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Egyéni"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Otthoni"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Munkahelyi"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Munkahelyi"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Egyéb"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Egyéni"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Egyéni"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Asszisztens"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Fiútestvér"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Gyermek"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Élettárs"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Apa"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Ismerős"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Felettes"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Anya"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Szülő"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Partner"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Ajánlotta"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Rokon"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Lánytestvér"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Házastárs"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Egyéni"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Otthoni"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Munkahely"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Egyéb"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Adja meg a PIN-kódot"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"A feloldáshoz írja be a jelszót"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Feloldáshoz írja be a PIN kódot"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Helytelen PIN-kód."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"A feloldáshoz nyomja meg a Menü, majd a 0 gombot."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Segélyhívó szám"</string>
@@ -646,8 +615,7 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Hívás folytatása"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Helyes!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Sajnáljuk, próbálja újra"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Sajnáljuk, próbálja újra"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Töltés (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Feltöltve."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"A SIM-kártya le van zárva."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM-kártya feloldása..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal rosszul rajzolta le feloldási mintáját. "\n\n"Kérjük, <xliff:g id="NUMBER_1">%d</xliff:g> másodperc múlva próbálja újra."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Helytelenül rajzolta le a feloldási mintát <xliff:g id="NUMBER_0">%d</xliff:g> alkalommal. További <xliff:g id="NUMBER_1">%d</xliff:g> sikertelen kísérlet után a Google rendszerében használt bejelentkezési adataival kell feloldania a táblagépét."\n\n"Kérjük, próbálja újra <xliff:g id="NUMBER_2">%d</xliff:g> másodperc múlva."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal helytelenül adta meg jelszavát. "\n\n"Kérjük, próbálkozzon újra <xliff:g id="NUMBER_1">%d</xliff:g> másodperc múlva."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal helytelenül adta meg PIN kódját. "\n\n"Kérjük, próbálkozzon újra <xliff:g id="NUMBER_1">%d</xliff:g> másodperc múlva."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal rosszul rajzolta be a feloldó mintát. <xliff:g id="NUMBER_1">%d</xliff:g> további sikertelen kísérlet után táblagépe zárolását a Google bejelentkezési adataival kell feloldania."\n\n" Kérjük, próbálkozzon újra <xliff:g id="NUMBER_2">%d</xliff:g> másodperc múlva."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Helytelenül rajzolta le a feloldási mintát <xliff:g id="NUMBER_0">%d</xliff:g> alkalommal. További <xliff:g id="NUMBER_1">%d</xliff:g> sikertelen kísérlet után a Google rendszerében használt bejelentkezési adataival kell feloldania a telefonját."\n\n" Kérjük, próbálja újra <xliff:g id="NUMBER_2">%d</xliff:g> másodperc múlva."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Próbálkozzon újra <xliff:g id="NUMBER">%d</xliff:g> másodperc múlva."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Elfelejtette a mintát?"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Elhagyja ezt az oldalt?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"A folytatáshoz válassza az OK, a jelenlegi oldalon maradáshoz a Mégse lehetőséget."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Megerősítés"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Tipp: érintse meg kétszer a nagyításhoz és kicsinyítéshez."</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"Aut.kitölt"</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"Automatikus kitöltés"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Autom. kitöltés"</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"böngészési előzmények és könyvjelzők olvasása"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Lehetővé teszi az alkalmazás számára a böngésző által felkeresett összes URL, valamint az összes könyvjelző olvasását."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"böngészési előzmények és könyvjelzők írása"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a táblagépen tárolt böngészési előzményeket és könyvjelzőket. A rosszindulatú alkalmazások felhasználhatják ezt a böngésző adatainak törlésére vagy módosítására."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a telefonon tárolt böngészési előzményeket és könyvjelzőket. A rosszindulatú alkalmazások felhasználhatják ezt a böngésző adatainak törlésére vagy módosítására."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"ébresztő beállítása az ébresztőórában"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Lehetővé teszi az alkalmazások számára, hogy beállítsanak egy ébresztőt egy telepített ébresztőóra alkalmazásban. Egyes ilyen alkalmazásokban lehet, hogy nem működik ez a funkció."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"A böngésző helymeghatározási engedélyeinek módosítása"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a böngésző helymeghatározási engedélyeit. A rosszindulatú alkalmazások kihasználhatják ezt arra, hogy helyadatokat küldjenek tetszőleges webhelyeknek."</string>
     <string name="save_password_message" msgid="767344687139195790">"Szeretné, hogy a böngésző megjegyezze a jelszót?"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"Kivágás"</string>
     <string name="copy" msgid="2681946229533511987">"Másolás"</string>
     <string name="paste" msgid="5629880836805036433">"Beillesztés"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Nincs mit bemásolni"</string>
     <string name="copyUrl" msgid="2538211579596067402">"URL másolása"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Szöveg kijelölése..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Szöveg kijelölése"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Beviteli mód"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Szöveg szerkesztése"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Műveletek szöveggel"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Kevés a hely"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Kevés a szabad tárhely a táblagépen."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"A táblagép tárhelye kezd elfogyni."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Kevés a szabad tárhely a telefonban."</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Mégse"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
     <string name="no" msgid="5141531044935541497">"Mégse"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Figyelem"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Betöltés..."</string>
     <string name="capital_on" msgid="1544682755514494298">"Be"</string>
     <string name="capital_off" msgid="6815870386972805832">"Ki"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Művelet végrehajtása a következővel:"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Bezárás most"</string>
     <string name="report" msgid="4060218260984795706">"Jelentés"</string>
     <string name="wait" msgid="7147118217226317732">"Várakozás"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Alk. átirányítva"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> éppen fut."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> volt eredetileg elindítva."</string>
+    <string name="smv_application" msgid="295583804361236288">"<xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazás (<xliff:g id="PROCESS">%2$s</xliff:g> folyamat) megsértette az általa kényszerített Szigorú üzemmód irányelvet."</string>
+    <string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> folyamat megsértette az általa kényszerített Szigorú üzemmód irányelvet."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> fut"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Válassza ezt az alkalmazásra váltáshoz"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Alkalmazást vált?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Már fut egy másik alkalmazás, amelyet le kell állítania, mielőtt egy újat indíthatna el."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Visszatérés a(z) <xliff:g id="OLD_APP">%1$s</xliff:g> alkalmazáshoz"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Ne induljon el az új alkalmazás."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"<xliff:g id="OLD_APP">%1$s</xliff:g> indítása"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"A régi alkalmazás leállítása mentés nélkül."</string>
     <string name="sendText" msgid="5132506121645618310">"Válasszon egy műveletet"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Csengetés hangereje"</string>
     <string name="volume_music" msgid="5421651157138628171">"Média hangereje"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Az összes megjelenítése"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB-háttértár"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB-eszköz csatlakoztatva"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Telefonját USB-kábel segítségével csatlakoztatta a számítógéphez. Érintse meg az alábbi gombot, ha fájlokat szeretne másolni a számítógépe és az Android SD-kártyája között."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Telefonját USB-kábel segítségével csatlakoztatta a számítógéphez. Érintse meg az alábbi gombot, ha fájlokat szeretne másolni a számítógépe és az Android SD-kártyája között."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"USB-kapcsolaton keresztül csatlakozott a számítógéphez. Érintse meg a lenti gombot, ha fájlokat szeretne másolni a számítógép és az Android USB-tára között."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"USB-kapcsolaton keresztül csatlakozott a számítógéphez. Érintse meg a lenti gombot, ha fájlokat szeretne másolni a számítógép és az Android SD-kártyája között."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"USB-tár bekapcsolása"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Hiba történt az SD-kártya használata során az USB-tárban."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Hiba történt az SD-kártya használata során az USB-tárban."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Probléma van az USB-tár használatával."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Probléma van az SD-kártya használatával USB-tárként."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB-eszköz csatlakoztatva"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Válassza ezt fájlok másolásához."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB-tár kikapcsolása"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Válassza ezt az USB-tár kikapcsolásához."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB-tár használatban"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Az USB-tár kikapcsolása előtt mindenképpen válassza le (\"adassa ki\") az Android SD-kártyáját a számítógépről."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Az USB-tár kikapcsolása előtt győződjön meg róla, hogy leválasztotta (\"kiadta\") az Android készülék USB-tárát a számítógépen."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Az USB-tár kikapcsolása előtt mindenképpen válassza le (\"adassa ki\") az Android SD-kártyáját a számítógépről."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"USB-tár kikapcsolása"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Gond volt az USB-tár kikapcsolásával. Ellenőrizze, hogy leválasztotta-e az USB-gazdagépet, majd próbálja újra."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ha bekapcsolja az USB-tárat, egyes jelenleg használt alkalmazások leállnak és lehet, hogy nem lesznek elérhetők a tár újbóli kikapcsolásáig."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Az USB művelet sikertelen"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"SD-kártya formázása"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Az USB-tár formázása"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD-kártya formázása"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Biztosan megformázza az SD-kártyát? A kártyán lévő minden adat el fog veszni."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formázza az USB-tárat, törölve az összes ott tárolt fájlt? A művelet nem vonható vissza!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Biztosan megformázza az SD-kártyát? A kártyán lévő minden adat el fog veszni."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formázás"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB hibakereső csatlakoztatva"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"jelöltek"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"SD-kártya előkészítése"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Az USB-tár előkészítése"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD-kártya előkészítése"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Hibakeresés."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Üres SD-kártya"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Üres USB-tár"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Üres SD-kártya"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Az SD-kártya üres vagy nem támogatott a fájlrendszere."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Az USB-tár üres, vagy a fájlrendszere nem támogatott."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Az SD-kártya üres vagy nem támogatott a fájlrendszere."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Az SD-kártya sérült"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Sérült USB-tár"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Az SD-kártya sérült"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Az SD-kártya megsérült. Lehet, hogy újra kell formázni."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Az USB-tár károsodott. Lehet, hogy újra kell formáznia."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Az SD-kártya megsérült. Lehet, hogy újra kell formázni."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Az SD-kártya váratlanul eltávolításra került"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB-tár váratlanul eltávolítva"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Az SD-kártya váratlanul eltávolításra került"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Az adatvesztés elkerülése érdekében az eltávolítás előtt előbb válassza le az SD-kártyát."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Az adatvesztés elkerülése érdekében válassza le az USB-tárat, mielőtt kihúzná azt."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Az adatvesztés elkerülése érdekében az eltávolítás előtt előbb válassza le az SD-kártyát."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Az SD-kártya biztonságosan eltávolítható"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Az USB-tár biztonságosan eltávolítható"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Az SD-kártya biztonságosan eltávolítható"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Biztonságosan eltávolíthatja az SD-kártyát."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Biztonságosan eltávolíthatja az USB-tárat."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Biztonságosan eltávolíthatja az SD-kártyát."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"SD-kártya eltávolítva"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Hiányzó USB-tár"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD-kártya eltávolítva"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Az SD-kártya eltávolítva. Helyezzen be egy újat."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Az USB-tár eltávolítva. Helyezzen be új hordozóeszközt."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Az SD-kártya eltávolítva. Helyezzen be egy újat."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nincs megfelelő tevékenység"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"komponenshasználati statisztikák frissítése"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Küldés"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Tovább"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Kész"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Előző"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Végrehajtás"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Szám hívása"\n"ezzel: <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Névjegy létrehozása "\n"a(z) <xliff:g id="NUMBER">%s</xliff:g> szám használatával"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Osztott kulcs (PSK) alapú L2TP/IPSec VPN"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Tanúsítvány alapú L2TP/IPSec VPN"</string>
     <string name="upload_file" msgid="2897957172366730416">"Fájl kiválasztása"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Nincs fájl kiválasztva"</string>
     <string name="reset" msgid="2448168080964209908">"Alaphelyzet"</string>
     <string name="submit" msgid="1602335572089911941">"Elküldés"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Gépkocsi üzemmód bekapcsolva"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Válassza ezt a kilépéshez a gépkocsi üzemmódból."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Megosztás vagy aktív hotspot"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"A konfiguráláshoz érintse meg"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Vissza"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Tovább"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Kihagyás"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Nagymértékű adathasználat"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Érintse meg, ha többre kíváncsi a mobil adathasználattal kapcsolatban"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Elérte a mobil adatkorlátot"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Érintse meg, ha többre kíváncsi a mobil adathasználattal kapcsolatban"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Nincs találat"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Keresés az oldalon"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 találat"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="TOTAL">%d</xliff:g>/<xliff:g id="INDEX">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Kész"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Az USB-tár leválasztása..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"SD-kártya leválasztása..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Az USB-tár törlése..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Az SD-kártya törlése..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Nem sikerült törölni az USB-tárat."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Nem sikerült törölni az SD-kártyát."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Az SD-kártya nem lett lecsatolva, mielőtt eltávolították."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Az USB-tár ellenőrzése folyamatban van."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Az SD-kártya ellenőrzése folyamatban van."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Az SD-kártya eltávolításra került."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Az USB-tárat jelenleg a számítógép használja."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Az SD-kártyát jelenleg a számítógép használja."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"A külső meghajtó állapota ismeretlen."</string>
+    <string name="share" msgid="1778686618230011964">"Megosztás"</string>
+    <string name="find" msgid="4808270900322985960">"Keresés"</string>
+    <string name="websearch" msgid="4337157977400211589">"Webes keresés"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index a674ff1..304ef90 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Kotak Pesan"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Masalah sambungan atau kode MMI tidak valid."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Operasi dibatasi untuk nomor panggilan tetap saja."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Layanan telah diaktifkan."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Layanan diaktifkan untuk:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Layanan telah dinonaktifkan."</string>
@@ -126,7 +125,7 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"Sinkron"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinkron"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Terlalu banyak <xliff:g id="CONTENT_TYPE">%s</xliff:g> penghapusan."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Penyimpanan pada tablet penuh! Hapus beberapa berkas agar ada tempat kosong."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Penyimpanan tablet penuh! Hapus beberapa berkas untuk menambah ruang kosong."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"Penyimpanan di ponsel penuh! Hapus sebagian berkas untuk mendapatkan ruang."</string>
     <string name="me" msgid="6545696007631404292">"Saya"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opsi tablet"</string>
@@ -139,8 +138,7 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"Sedang mematikan..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet Anda akan dimatikan."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Ponsel Anda akan dimatikan."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Apakah Anda ingin mematikannya?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Terbaru"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Tidak ada aplikasi terkini."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Opsi tablet"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode pesawat"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mode pesawat HIDUP"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mode pesawat MATI"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Layanan berbayar"</string>
@@ -160,7 +160,7 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Pesan Anda"</string>
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"Baca dan tulis SMS, email, dan pesan lainnya."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Informasi pribadi Anda"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Akses langsung ke data kenalan dan kalender yang tersimpan pada tablet."</string>
+    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Akses langsung ke kenalan dan kalender yang disimpan di tablet."</string>
     <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"akses langsung pada data kenalan dan kalender yang tersimpan pada ponsel."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Lokasi Anda"</string>
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Monitor lokasi fisik Anda"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Peralatan pengembangan"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Fitur hanya dibutuhkan oleh pengembang aplikasi."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Penyimpanan"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Akses kartu SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Akses penyimpanan USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Akses kartu SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"nonaktifkan atau ubah bilah status"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Mengizinkan aplikasi mematikan bilah status atau menambahkan dan menghapus ikon sistem."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"bilah status"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Mengizinkan aplikasi menjadi bilah status."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"luaskan/ciutkan bilah status"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Mengizinkan aplikasi meluaskan atau menciutkan bilah status."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"cegat panggilan keluar"</string>
@@ -196,10 +194,10 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"kirim pesan SMS"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Mengizinkan aplikasi mengirim pesan SMS. Aplikasi hasad dapat membebankan biaya kepada Anda dengan mengirim pesan tanpa konfirmasi dari Anda."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"baca SMS atau MMS"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Mengizinkan aplikasi membaca pesan SMS yang tersimpan dalam tablet atau kartu SIM Anda. Aplikasi hasad dapat membaca pesan rahasia Anda."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Mengizinkan aplikasi untuk membaca pesan SMS yang disimpan di tablet atau kartu SIM. Aplikasi berbahaya dapat membaca pesan rahasia Anda."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Mengizinkan aplikasi membaca SMS yang tersimpan dalam ponsel atau kartu SIM Anda. Aplikasi hasad dapat membaca pesan rahasia Anda."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"edit SMS atau MMS"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Mengizinkan aplikasi untuk menulis pesan SMS yang tersimpan dalam tablet atau kartu SIM Anda. Aplikasi hasad dapat menghapus pesan Anda."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Mengizinkan aplikasi untuk menulis ke pesan SMS yang disimpan di tablet atau kartu SIM. Aplikasi berbahaya dapat menghapus pesan Anda."</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Mengizinkan aplikasi untuk menulis pesan SMS yang tersimpan dalam ponsel atau kartu SIM Anda. Aplikasi hasad dapat menghapus pesan Anda."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"terima WAP"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Mengizinkan aplikasi menerima dan memproses pesan WAP. Aplikasi hasad dapat memonitor pesan Anda atau menghapusnya tanpa menampilkannya kepada Anda."</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"cegah pergantian aplikasi"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Mencegah pengguna beralih ke aplikasi lain."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"memonitor dan mengontrol semua pengaktifan aplikasi"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Mengizinkan aplikasi memantau dan mengontrol cara sistem meluncurkan aktivitas. Aplikasi hasad dapat mengubah sistem sepenuhnya. Izin ini hanya diperlukan untuk pengembangan, tidak pernah diperlukan untuk penggunaan ponsel secara normal."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Mengizinkan aplikasi memonitor dan mengontrol cara sistem meluncurkan aktivitas. Aplikasi berbahaya dapat mengambil alih sistem sepenuhnya. Izin ini hanya diperlukan untuk pengembangan, jangan pernah digunakan untuk penggunaan normal."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"kirim siaran paket dihapus"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Mengizinkan aplikasi mengirimkan pemberitahuan bahwa paket aplikasi telah dihapus. Aplikasi hasad dapat menggunakan ini untuk menghentikan aplikasi yang sedang berjalan lainnya."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"kirim siaran SMS-diterima"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"tampilkan jendela yang tidak diizinkan"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Mengizinkan pembuatan jendela yang dimaksudkan untuk digunakan oleh antarmuka pengguna sistem internal. Bukan untuk digunakan oleh aplikasi normal."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"tampilkan lansiran tingkat sistem"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Memungkinkan suatu aplikasi menampilkan jendela peringatan sistem. Aplikasi hasad dapat mengambil alih seluruh layar."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Mengizinkan aplikasi menampilkan jendela lansiran sistem. Aplikasi berbahaya dapat mengambil alih seluruh layar."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"ubah kecepatan animasi global"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Mengizinkan aplikasi mengubah kecepatan animasi global (animasi lebih cepat atau lebih lambat) kapan saja."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"kelola token aplikasi"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Mengizinkan aplikasi untuk membuat dan mengelola tokennya sendiri, memintas pengurutan Z normalnya. Jangan pernah digunakan untuk aplikasi normal."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"tekan kunci dan tombol kontrol"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Mengizinkan aplikasi mengirimkan data masukannya sendiri (penekanan tombol, dll.) ke aplikasi lainnya. Aplikasi hasad dapat menggunakan ini untuk mengambil alih tablet."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Mengizinkan aplikasi untuk mengirim aktivitas masukan sendiri (penekanan tombol, dll.) ke aplikasi lain. Aplikasi berbahaya dapat menggunakan ini untuk mengambil alih tablet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Mengizinkan aplikasi mengirimkan data masukannya sendiri (penekanan tombol, dll.) ke aplikasi lainnya. Aplikasi hasad dapat menggunakan ini untuk mengambil alih ponsel."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"rekam apa yang diketik dan tindakan yang dilakukan"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Mengizinkan aplikasi melihat tombol yang Anda tekan bahkan ketika berinteraksi dengan aplikasi lain (seperti memasukkan sandi). Tidak pernah diperlukan untuk aplikasi normal."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"pasang aplikasi secara langsung"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Mengizinkan aplikasi memasang paket Android baru atau yang diperbarui. Aplikasi hasad dapat menggunakan ini untuk menambahkan aplikasi dengan izin yang kuat secara sembarangan."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"hapus semua data tembolok aplikasi"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Mengizinkan aplikasi mengosongkan penyimpanan tablet dengan menghapus berkas dalam direktori tembolok aplikasi. Akses sangat terbatas, biasanya hanya untuk proses sistem."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Mengizinkan aplikasi mengosongkan penyimpanan tablet dengan menghapus berkas dalam direktori tembolok aplikasi. Akses sangat dibatasi biasannya pada proses sistem."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Mengizinkan aplikasi mengosongkan penyimpanan ponsel dengan menghapus berkas dalam direktori tembolok aplikasi. Akses sangat terbatas, biasanya pada proses sistem."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Pindahkan sumber daya aplikasi"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Mengizinkan aplikasi memindah sumber daya aplikasi dari media internal ke eksternal dan sebaliknya."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"baca berkas log sistem"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Memungkinkan aplikasi membaca dari berbagai berkas log sistem. Ini memungkinkan aplikasi menemukan informasi umum tentang apa yang Anda lakukan dengan tablet, yang mungkin meliputi informasi pribadi."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Memungkinkan aplikasi membaca dari berbagai berkas log sistem. Ini memungkinkan aplikasi menemukan informasi umum tentang apa yang Anda lakukan dengan tablet, yang mungkin meliputi informasi pribadi."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"baca data log sensitif"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Mengizinkan aplikasi membaca dari berbagai berkas log sistem. Ini memungkinkan aplikasi menemukan informasi umum tentang apa yang Anda lakukan dengan tablet, kemungkinan termasuk informasi pribadi."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Mengizinkan aplikasi membaca dari berbagai berkas log sistem. Ini memungkinkan aplikasi menemukan informasi umum tentang apa yang Anda lakukan dengan ponsel, kemungkinan termasuk informasi pribadi."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"baca/tulis ke sumber daya yang dimiliki oleh diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Mengizinkan aplikasi membaca dan menulis ke sumber daya yang dimiliki oleh grup diag; misalnya, berkas dalam /dev. Ini berisiko mempengaruhi kestabilan dan keamanan sistem. Ini sebaiknya HANYA digunakan untuk diagnostik khusus perangkat keras oleh pabrik atau operator."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"aktifkan atau nonaktifkan komponen aplikasi"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Mengizinkan aplikasi mengubah pengaktifan dan penonaktifan komponen aplikasi lain. Aplikasi hasad dapat menggunakan ini untuk menonaktifkan kemampuan tablet yang penting. Berhati-hatilah dan gunakan dengan izin, karena hal ini berisiko menyebabkan komponen aplikasi menjadi tidak dapat digunakan, tidak konsisten, atau tidak stabil."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Mengizinkan aplikasi mengubah pengaktifan dan penonaktifan komponen aplikasi lain. Aplikasi hasad dapat menggunakan ini untuk menonaktifkan kemampuan tablet yang penting. Berhati-hatilah dan gunakan dengan izin, karena hal ini berisiko menyebabkan komponen aplikasi menjadi tidak dapat digunakan, tidak konsisten, atau tidak stabil."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Izinkan aplikasi mengubah apakah komponen aplikasi lain diaktifkan atau tidak. Aplikasi berbahaya dapat menggunakan ini untuk menonaktifkan kemampuan tablet penting. Hati-hatilah saat menggunakan izin ini, karena komponen aplikasi tidak akan dapat digunakan, tidak konsisten, atau tidak stabil."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Izinkan aplikasi mengubah apakah komponen aplikasi lain diaktifkan atau tidak. Aplikasi berbahaya dapat menggunakan ini untuk menonaktifkan kemampuan ponsel penting. Hati-hatilah saat menggunakan izin ini, karena komponen aplikasi tidak akan dapat digunakan, tidak konsisten, atau tidak stabil."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"atur aplikasi yang disukai"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Mengizinkan aplikasi memodifikasi aplikasi yang dipilih. Ini dapat dimanfaatkan aplikasi hasad untuk diam-diam mengubah aplikasi yang sedang berjalan, spoofing aplikasi yang ada untuk mengumpulkan data pribadi dari Anda."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"ubah setelan sistem global"</string>
@@ -298,19 +296,19 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"ubah peta layanan Google"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"Mengizinkan aplikasi mengubah peta layanan Google. Tidak untuk digunakan oleh aplikasi normal."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"mulai secara otomatis pada saat boot"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Memungkinkan aplikasi memulai secara otomatis segera setelah sistem selesai booting. Ini dapat memperlambat proses memulai tablet dan menyebabkan aplikasi memperlambat tablet secara keseluruhan karena terus-terusan aktif."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Mengizinkan aplikasi menyala sendiri segera setelah sistem selesai booting. Hal ini dapat memperlama waktu memulai tablet dan menyebabkan aplikasi memperlambat tablet secara keseluruhan jika terus berjalan."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Mengizinkan aplikasi memulai sendiri segera setelah sistem selesai booting. Ini dapat memperlambat proses memulai ponsel dan menyebabkan aplikasi memperlambat ponsel secara keseluruhan ketika terus berjalan."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"kirim siaran memikat"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Memungkinkan aplikasi mengirimkan siaran lengket, yang tetap ada setelah siaran berakhir. Aplikasi hasad dapat memperlambat tablet atau membuatnya tidak stabil dengan menyebabkannya menggunakan terlalu banyak memori."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Mengizinkan aplikasi mengirim siaran permanen, yang tetap ada setelah siaran berakhir. Aplikasi berbahaya dapat memperlambat tablet atau tidak stabil dengan menyebabkan terlalu banyaknya memori yang digunakan."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Mengizinkan aplikasi mengirimkan siaran memikat, yang tetap ada setelah siaran berakhir. Aplikasi hasad dapat memperlambat ponsel atau membuatnya tidak stabil dengan menyebabkannya menggunakan terlalu banyak memori."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"baca data kenalan"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Memungkinkan aplikasi membaca semua data (alamat) kenalan yang tersimpan pada tablet. Aplikasi hasad dapat menggunakan ini untuk mengirimkan data Anda kepada orang lain."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Mengizinkan aplikasi membaca semua data kenalan (alamat) yang disimpan pada tablet Anda. Aplikasi berbahaya dapat menggunakan ini untuk mengirim data ke orang lain."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Mengizinkan aplikasi membaca semua data kenalan (alamat) yang tersimpan pada ponsel. Aplikasi hasad dapat menggunakan ini untuk mengirimkan data Anda ke orang lain."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"tuliskan data kenalan"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Memungkinkan aplikasi mengubah data kenalan (alamat) yang tersimpan pada tablet. Aplikasi hasad dapat menggunakan ini untuk menghapus atau mengubah data kenalan Anda."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Mengizinkan aplikasi memodifikasi data kenalan (alamat) yang disimpan pada tablet Anda. Aplikasi berbahaya dapat menggunakan ini untuk menghapus atau mengubah data kenalan."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Mengizinkan aplikasi mengubah data kenalan (alamat) yang tersimpan pada ponsel. Aplikasi hasad dapat menggunakan ini untuk menghapus atau mengubah data kenalan Anda."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"membaca acara kalender."</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Mengizinkan aplikasi membaca semua acara kalender yang tersimpan pada tablet. Aplikasi hasad dapat menggunakan ini untuk mengirimkan acara kalender Anda kepada orang lain."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Mengizinkan aplikasi membaca semua acara kalender yang disimpan pada tablet Anda. Aplikasi berbahaya dapat menggunakan ini untuk mengirim acara kalender ke orang lain."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Mengizinkan aplikasi membaca semua acara kalender yang tersimpan pada ponsel. Aplikasi hasad dapat menggunakan ini untuk mengirimkan acara kalender ke orang lain."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"Tambahkan atau modifikasi acara kalender dan kirimkan email ke tamu"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Mengizinkan aplikasi menambahkan atau mengubah acara pada kalender Anda, yang dapat mengirikan email ke tamu. Aplikasi hasad dapat menggunakan ini untuk menghapus atau mengubah acara kalender Anda atau mengirim email ke tamu."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"izin untuk memasang suatu penyedia lokasi"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Buat sumber lokasi tiruan untuk menguji. Aplikasi hasad dapat menggunakan ini untuk mengganti lokasi dan/atau status yang dikembalikan oleh sumber lokasi asli seperti GPS atau penyedia Jaringan atau memonitor dan melaporkan lokasi Anda ke sumber eksternal."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"lokasi terperinci (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Akses sumber lokasi detail seperti GPS pada tablet, jika tersedia. Aplikasi hasad dapat menggunakan ini untuk menentukan lokasi Anda, dapat menguras daya baterai."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Sumber lokasi kualitas tinggi akses seperti Sistem Penentuan Posisi Global pada tablet, jika tersedia. Aplikasi berbahaya dapat menggunakan ini untuk menentukan perkiraan lokasi Anda, dan dapat menyedot daya baterai."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Akses sumber lokasi detail seperti GPS pada ponsel, jika tersedia. Aplikasi hasad dapat menggunakan ini untuk menentukan lokasi Anda, dapat menguras daya baterai."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"lokasi sementara (berdasarkan jaringan)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Akses sumber lokasi kasar seperti database jaringan seluler untuk menentukan perkiraan lokasi tablet terdekat, jika ada. Aplikasi hasad dapat menggunakan ini untuk memperkirakan lokasi Anda."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Sumber lokasi sementara akses seperti database jaringan seluler untuk menentukan perkiraan lokasi tablet, jika tersedia. Aplikasi berbahaya dapat menggunakan ini untuk menentukan perkiraan lokasi Anda."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Akses sumber lokasi sementara seperti database jaringan seluler untuk menentukan lokasi ponsel terdekat, jika ada. Aplikasi hasad dapat menggunakan ini untuk memperkirakan lokasi Anda."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"akses SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Izinkan aplikasi menggunakan fitur tingkat rendah SurfaceFlinger."</string>
@@ -334,37 +332,39 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Mengizinkan aplikasi mengubah setelan audio global seperti volume dan perutean."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"rekam audio"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Mengizinkan aplikasi mengakses jalur rekaman audio."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"ambil foto"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Mengizinkan aplikasi mengambil foto dengan kamera. Ini memungkinkan aplikasi kapan pun juga menangkap gambar yang dilihat kamera."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"nonaktifkan tablet secara permanen"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"ambil gambar dan video"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Mengizinkan aplikasi mengambil gambar dan video dengan kamera. Ini mengizinkan aplikasi kapan pun untuk mengumpulkan gambar yang dilihat kamera."</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"noaktifkan tablet secara permanen"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"nonaktifkan ponsel secara permanen"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Mengizinkan aplikasi untuk menonaktifkan seluruh tablet secara permanen. Hal ini sangat berbahaya."</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Mengizinkan aplikasi menonaktifkan seluruh tablet secara permanen. Ini sangat berbahaya."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Mengizinkan aplikasi untuk menonaktifkan seluruh ponsel secara permanen. Hal ini sangat berbahaya."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"paksa reboot tablet"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"reboot tablet secara paksa"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"paksa reboot ponsel"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Mengizinkan aplikasi memaksa tablet untuk melakukan reboot."</string>
+    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Mengizinkan aplikasi memaksa tablet dinyalakan ulang."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Mengizinkan aplikasi memaksa ponsel untuk melakukan reboot."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"pasang dan lepas filesystem"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Mengizinkan aplikasi memuat dan melepas sistem berkas untuk penyimpanan aman."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"format penyimpanan eksternal"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Mengizinkan aplikasi memformat penyimpanan aman."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"dapatkan informasi tentang penyimpanan aman"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Mengizinkan aplikasi mendapatkan informasi pada penyimpanan aman."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"buat penyimpanan aman"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Mengizinkan aplikasi membuat penyimpanan aman."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"hancurkan penyimpanan aman"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Mengizinkan aplikasi menghancurkan penyimpanan aman."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"pasang / lepas penyimpanan aman"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Mengizinkan aplikasi memuat / melepas penyimpanan aman."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"ubah nama penyimpanan aman"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Mengizinkan aplikasi mengubah nama penyimpanan aman."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"dapatkan informasi pada penyimpanan internal"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Mengizinkan aplikasi untuk mendapatkan informasi pada penyimpanan internal."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"buat penyimpanan internal"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Mengizinkan aplikasi untuk membuat penyimpanan internal."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"merusak penyimpanan internal"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Mengizinkan aplikasi untuk merusak penyimpanan internal."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"pasang / lepas penyimpanan internal"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Mengizinkan aplikasi untuk memasang / melepas penyimpanan internal."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"ubah nama penyimpanan internal"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Mengizinkan aplikasi untuk mengubah penyimpanan internal."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"mengontrol penggetar"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Mengizinkan aplikasi mengontrol penggetar."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"mengontrol lampu senter"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Mengizinkan aplikasi mengontrol lampu senter."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"akses perangkat USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Mengizinkan aplikasi untuk perangkat USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"uji perangkat keras"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Mengizinkan aplikasi mengontrol berbagai perangkat periferal untuk tujuan menguji perangkat keras."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"Mengizinkan aplikasi untuk memanggil nomor telepon tanpa campur tangan Anda. Aplikasi hasad dapat menyebabkan panggilan tak terduga pada tagihan ponsel Anda. Perhatikan bahwa hal ini tidak mengizinkan aplikasi tersebut memanggil nomor darurat."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"panggil nomor telepon apa pun secara langsung"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Mengizinkan aplikasi untuk memanggil nomor telepon apapun, termasuk nomor darurat, tanpa intervensi Anda. Aplikasi hasad dapat melakukan panggilan ilegal dan tidak perlu ke layanan darurat."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"mulai penyiapan tablet CDMA secara langsung"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"memulai penyiapan tablet CDMA secara langsung"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"mulai penyiapan ponsel CDMA secara langsung"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Mengizinkan aplikasi memulai penyediaan CDMA. Aplikasi hasad dapat tiba-tiba memulai penyediaan CDMA."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"mengontrol pemberitahuan pembaruan lokasi"</string>
@@ -385,16 +385,16 @@
     <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Mengizinkan aplikasi mengendalikan fitur ponsel pada perangkat. Suatu aplikasi dengan izin ini dapat beralih jaringan, menghidupkan dan mematikan radio ponsel dan semacamnya tanpa memberitahukan kepada Anda."</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"baca kondisi dan identitas ponsel"</string>
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"Mengizinkan aplikasi mengakses fitur ponsel yang ada pada perangkat. Suatu aplikasi dengan izin ini dapat menentukan nomor telepon dan nomor seri telepon, apakah panggilan telah aktif, nomor yang dipanggil, dan semacamnya."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"mencegah tablet masuk mode tidur"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"cegah tablet dari tidur"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"mencegah ponsel menjadi tidak aktif"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Memungkinkan aplikasi mencegah tablet masuk ke mode tidur."</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Izinkan aplikasi mencegah tablet tidur."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Mengizinkan aplikasi mencegah ponsel masuk ke mode tidur"</string>
-    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"daya tablet hidup atau mati"</string>
+    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"hidupkan atau matikan tablet"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"daya ponsel hidup atau mati"</string>
-    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Memungkinkan aplikasi mematikan dan menghidupkan tablet."</string>
+    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Mengizinkan aplikasi untuk menghidupkan atau mematikan tablet."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Mengizinkan aplikasi mematikan dan menghidupkan ponsel."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"jalankan pada mode uji pabrik"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Jalankan sebagai uji pabrik tingkat rendah, yang memungkinkan akses penuh pada perangkat keras tablet. Hanya tersedia ketika tablet berjalan pada mode uji pabrik."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Menjalankan sebagai uji pabrikan tingkat rendah, mengizinkan akses lengkap ke perangkat keras tablet. Hanya tersedia jika tablet berjalan dalam mode uji pabrikan."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Jalankan sebagai uji pabrik tingkat rendah, yang memungkinkan akses penuh pada perangkat keras ponsel. Hanya tersedia ketika ponsel berjalan pada mode uji pabrik."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"atur wallpaper"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Mengizinkan aplikasi mengatur wallpaper sistem."</string>
@@ -403,15 +403,15 @@
     <string name="permlab_masterClear" msgid="2315750423139697397">"setel ulang sistem ke setelan bawaan pabrik"</string>
     <string name="permdesc_masterClear" msgid="5033465107545174514">"Mengizinkan aplikasi menyetel ulang sistem sepenuhnya ke setelan pabriknya, menghapus semua data, konfigurasi, dan aplikasi yang terpasang."</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"atur waktu"</string>
-    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Mengizinkan aplikasi mengubah waktu jam tablet."</string>
+    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Izinkan aplikasi mengubah waktu jam pada tablet."</string>
     <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Mengizinkan aplikasi mengubah waktu jam ponsel."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"atur zona waktu"</string>
-    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Memungkinkan aplikasi mengubah zona waktu tablet."</string>
+    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Izinkan aplikasi mengubah zona waktu pada tablet."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Mengizinkan aplikasi mengubah zona waktu ponsel."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"bertindak sebagai AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Mengizinkan aplikasi melakukan panggilan ke AccountAuthenticators"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"menemukan akun yang diketahui"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Mengizinkan aplikasi mendapatkan daftar akun yang dikenali oleh tablet."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Mengizinkan aplikasi untuk mendaftar akun yang diketahui oleh tablet."</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Mengizinkan aplikasi mengubah mendapatkan daftar akun yang dikenali oleh ponsel."</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"bertindak sebagai autentikator akun"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Mengizinkan aplikasi menggunakan kemampuan autentikator akun pada AccountManager, termasuk di antaranya membuat akun dan mendapatkan dan mengatur sandi."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"Izinkan penerimaan Wi-Fi Multicast"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Mengizinkan aplikasi menerima paket yang tidak langsung dialamatkan ke perangkat Anda. Ini dapat bermanfaat ketika mencari perangkat yang ditawarkan di dekat Anda. Aplikasi ini menggunakan lebih banyak daya ketimbang mode selain multicast."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"Administrasi bluetooth"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Memungkinkan aplikasi mengonfigurasi tablet Bluetooth lokal, serta menemukan dan menyandingkannya dengan perangkat jarak jauh."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Mengizinkan aplikasi untuk mengonfigurasi tablet Bluetooth lokal, dan menemukan serta memasang dengan perangkat jarak jauh."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Mengizinkan aplikasi mengonfigurasi ponsel Bluetooth lokal, dan menemukan dan menyandingkan perangkat jarak jauh."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"buat sambungan Bluetooth"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Mengizinkan aplikasi melihat konfigurasi tablet Bluetooth lokal, serta melakukan dan menerima panggilan dengan perangkat yang disandingkan."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Mengizinkan aplikasi melihat konfigurasi tablet Bluetooth lokal, dan melakukan dan menerima koneksi dengan perangkat terpasang."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Mengizinkan aplikasi melihat konfigurasi ponsel Bluetooth lokal, dan membuat dan menerima panggilan dengan perangkat yang disandingkan."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"kontrol NFC"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Mengizinkan aplikasi berkomunikasi dengan tag, kartu, dan pembaca Near Field Communication (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"nonaktifkan kunci tombol"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Mengizinkan aplikasi menonaktifkan keylock dan keamanan sandi terkait mana pun. Contoh yang sah adalah ponsel menonaktifkan keylock ketika menerima panggilan telepon masuk, kemudian mengaktifkan keylock sekali lagi setelah panggilan selesai."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"baca setelan sinkron"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Mengizinkan aplikasi membaca kata, nama, dan frasa pribadi yang mungkin telah disimpan dalam kamus pengguna."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"tulis ke kamus buatan pengguna"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Mengizinkan aplikasi menuliskan kata-kata baru ke dalam kamus pengguna."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"ubah/hapus isi kartu SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"ubah/hapus konten penyimpanan USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"ubah/hapus isi kartu SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Mengizinkan aplikasi menulis ke kartu SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Mengizinkan aplikasi untuk menulis ke penyimpanan USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Mengizinkan aplikasi menulis ke kartu SD."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"ubah/hapus konten penyimpanan media internal"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Mengizinkan aplikasi mengubah konten penyimpanan media internal."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"akses sistem berkas tembolok."</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Mengizinkan aplikasi membaca dan menulis filesystem tembolok."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Batasi sandi"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Batasi jenis sandi yang Anda perbolehkan gunakan."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Awasi upaya masuk"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Memonitor jumlah sandi tidak benar yang dimasukkan saat membuka kunci layar, dan mengunci tablet atau menghapus semua data tablet jika sandi yang salah dimasukkan berkali-kali"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Memonitor jumlah sandi tidak benar yang dimasukkan saat membuka kunci layar, dan mengunci tablet atau menghapus semua data tablet jika sandi yang salah dimasukkan berkali-kali"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Setel ulang sandi"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Paksakan sandi ke nilai baru, administrator harus memberikannya kepada Anda sebelum dapat masuk."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Paksakan kunci"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Mengontrol ketika perangkat mengunci, Anda harus memasukkan sandi lagi."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"lakukan//terima panggilan internet"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Mengizinkan aplikasi menggunakan layanan SIP melakukan/menerima telepon internet"</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrol panjangnya dan karakter yang diizinkan dalam sandi pembuka layar"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Upaya pembukaan kunci layar monitor"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Monitor jumlah sandi yang salah dimasukkan ketika membuka kunci layar, dan mengunci tablet atau menghapus semua data tablet jika terlalu banyak sandi yang salah dimasukkan"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Monitor jumlah sandi yang salah dimasukkan ketika membuka kunci layar, dan mengunci ponsel atau menghapus semua data ponsel jika terlalu banyak sandi yang salah dimasukkan"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Ubah sandi pembuka kunci layar"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Ubah sandi pembuka kunci layar"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Kunci layar"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontrol cara dan kapan layar mengunci"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Hapus semua data"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Menghapus data tablet tanpa peringatan, dengan melakukan pengembalian ke setelan pabrik"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Menghapus data tablet tanpa peringatan, dengan melakukan pengembalian ke setelan pabrik"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Hapus data tablet tanpa peringatan, dengan menyetel ulang data pabrik"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Hapus data ponsel tanpa peringatan, dengan menyetel ulang data pabrik"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Setel proxy global perangkat"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Setel proxy global perangkat yang akandigunakan ketika kebijakan diaktifkan. Hanya admin perangkat pertama yang menyetel procy global yang berlaku."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Setel kedaluwarsa sandi"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Kontrol berapa lama sebelum sandi penguncian layar perlu diubah"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Rumah"</item>
     <item msgid="869923650527136615">"Seluler"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Pager Kantor"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Asisten"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Ubahsuaian"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Hari Ulang Tahun"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Hari Peringatan"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Acara"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Lainnya"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Ubahsuaian"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Rumah"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Kantor"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Kantor"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Lainnya"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Ubahsuaian"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Ubahsuaian"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Asisten"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Saudara laki-laki"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Anak"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Mitra Serumah"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Ayah"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Teman"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Manajer"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Ibu"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Orang tua"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Mitra"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Dirujuk oleh"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Sanak saudara"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Saudara perempuan"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Pasangan"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Ubahsuaian"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Beranda"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Kerjaan"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Lainnya"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Masukkan kode PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Masukkan sandi untuk membuka"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Masukkan PIN untuk membuka kunci"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Kode PIN salah!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Untuk membuka, tekan Menu lalu 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Nomor darurat"</string>
@@ -646,14 +615,13 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Kembali ke panggilan"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Perbaiki!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Maaf, coba lagi"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Maaf, harap coba lagi"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Mengisi daya (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Terisi."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Hubungkan pengisi daya."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Tidak ada kartu SIM."</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tidak ada Kartu SIM di dalam tablet."</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tidak ada kartu SIM dalam tablet."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Tidak ada Kartu SIM di dalam ponsel."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Masukkan kartu SIM"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Panggilan darurat saja"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Kartu SIM terkunci."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Membuka kartu SIM…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Anda telah salah menggambar pola pembuka kunci sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. "\n\n"Harap coba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> detik."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Anda telah salah menggambar pola pembuka kunci sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Bila gagal lagi <xliff:g id="NUMBER_1">%d</xliff:g> kali, Anda akan diminta membuka kunci tablet menggunakan info masuk Google."\n\n" Harap coba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> detik."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Anda telah salah memasukkan sandi <xliff:g id="NUMBER_0">%d</xliff:g> kali. "\n\n"Coba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> detik."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Anda telah salah memasukkan PIN <xliff:g id="NUMBER_0">%d</xliff:g> kali. "\n\n"Coba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> detik."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Anda telah salah menggambar pola pembuka kunci <xliff:g id="NUMBER_0">%d</xliff:g> kali. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> upaya yang gagal, Anda akan diminta membuka kunci tablet menggunakan info masuk Google."\n\n" Harap masuk lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> detik."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Anda telah salah menggambar pola pembuka kunci sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> upaya gagal lagi, Anda akan diminta membuka kunci ponsel menggunakan info masuk Google."\n\n" Harap coba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> detik."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Coba lagi dalam <xliff:g id="NUMBER">%d</xliff:g> detik."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Lupa pola?"</string>
@@ -698,23 +664,17 @@
     <string name="double_tap_toast" msgid="1068216937244567247">"Kiat: ketuk dua kali untuk memperbesar dan memperkecil."</string>
     <string name="autofill_this_form" msgid="1272247532604569872">"IsiOtomatis"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Penyiapan IsiOtomatis"</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"baca riwayat dan bookmark Peramban"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Izinkan aplikasi membaca semua URL yang telah dikunjungi Peramban, dam semua bookmark Peramban."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"tuliskan riwayat dan bookmark Peramban"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Memungkinkan aplikasi mengubah riwayat atau bookmark Peramban yang tersimpan pada ponsel. Aplikasi hasad dapat menggunakan ini untuk menghapus atau mengubah data Peramban."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Mengizinkan aplikasi memodifikasi riwayat atau bookmark Peramban yang disimpan pada tablet Anda. Aplikasi berbahaya dapat menggunakan ini untuk menghapus atau mengubah data Peramban."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Mengizinkan aplikasi mengubah riwayat atau bookmark Peramban yang tersimpan pada ponsel. Aplikasi hasad dapat menggunakan ini untuk menghapus atau mengubah data Peramban."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"setel alarm di jam alarm"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Perbolehkan aplikasi untuk menyetel alarm di aplikasi jam alarm yang terpasang. Beberapa aplikasi jam alarm tidak dapat menerapkan fitur ini."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Ubah izin geolokasi Peramban"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Mengizinkan aplikasi mengubah izin geolokasi Peramban. Aplikasi hasad dapat menggunakan ini untuk mengizinkan pengiriman informasi lokasi ke situs web sembarangan."</string>
     <string name="save_password_message" msgid="767344687139195790">"Apakah Anda ingin peramban menyimpan sandi ini?"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"Potong"</string>
     <string name="copy" msgid="2681946229533511987">"Salin"</string>
     <string name="paste" msgid="5629880836805036433">"Tempel"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Tidak ada yang disalin"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Salin URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Pilih teks..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Pemilihan teks"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metode masukan"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Edit teks"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Tindakan teks"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Ruang penyimpanan tinggal sedikit"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Ruang penyimpanan tablet hampir habis."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Ruang penyimpanan tablet semakin sedikit."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Ruang penyimpanan ponsel tersisa sedikit."</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Batal"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
     <string name="no" msgid="5141531044935541497">"Batal"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Perhatian"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Memuat..."</string>
     <string name="capital_on" msgid="1544682755514494298">"HIDUP"</string>
     <string name="capital_off" msgid="6815870386972805832">"MATI"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Tindakan lengkap menggunakan"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Tutup paksa"</string>
     <string name="report" msgid="4060218260984795706">"Laporkan sebagai"</string>
     <string name="wait" msgid="7147118217226317732">"Tunggu"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Aplikasi dialihkan"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang berjalan."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> telah diluncurkan aslinya."</string>
+    <string name="smv_application" msgid="295583804361236288">"Aplikasi <xliff:g id="APPLICATION">%1$s</xliff:g> (proses <xliff:g id="PROCESS">%2$s</xliff:g>) telah melanggar kebijakan StrictMode yang diberlakukan secara otomatis."</string>
+    <string name="smv_process" msgid="5120397012047462446">"Proses <xliff:g id="PROCESS">%1$s</xliff:g> telah melanggar kebijakan StrictMode yang diberlakukan secara otomatis."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> berjalan"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Pilih untuk beralih ke aplikasi"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Ubah aplikasi?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Aplikasi lain sudah berjalan yang harus dihentikan sebelum Anda dapat memulai yang baru."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Kembali ke<xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Jangan memulai aplikasi baru."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Mulai <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Hentikan aplikasi lama tanpa menyimpan."</string>
     <string name="sendText" msgid="5132506121645618310">"Pilih tindakan untuk teks"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Volume dering"</string>
     <string name="volume_music" msgid="5421651157138628171">"Volume media"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Tampilkan semua"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Penyimpanan Massal USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB terhubung"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Anda telah menyambungkan ponsel ke komputer melalui USB. Pilih tombol di bawah jika ingin menyalin berkas antar komputer dan kartu SD Android Anda."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Anda telah menyambungkan ponsel ke komputer melalui USB. Pilih tombol di bawah jika ingin menyalin berkas antar komputer dan kartu SD Android Anda."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Anda telah terhubung ke komputer melalui USB. Sentuh tombol di bawah jika Anda ingin menyalin berkas antara komputer dan penyimpanan USB Android Anda."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Anda telah terhubung ke komputer melalui USB. Sentuh tombol di bawah jika Anda ingin menyalin berkas antara komputer dan kartu SD Android Anda."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Hidupkan penyimpanan USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Ada masalah saat menggunakan kartu SD Anda untuk penyimpanan USB."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Ada masalah saat menggunakan kartu SD Anda untuk penyimpanan USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Tidak ada masalah menggunakan penyimpanan USB untuk penyimpanan massal USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Tidak ada masalah menggunakan kartu SD untuk penyimpanan massal USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB terhubung"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Pilih untuk menyalin berkas ke/dari komputer Anda."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Matikan penyimpanan USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Pilih untuk mematikan penyimpanan USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Penyimpanan USB sedang digunakan"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Sebelum mematikan penyimpanan USB, pastikan bahwa Anda telah melepas (“dikeluarkan”) kartu SD Android dari komputer."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Sebelum mematikan penyimpanan USB, pastikan Anda telah melepas (“dikeluarkan”) penyimpanan USB Android Anda dari komputer."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Sebelum mematikan penyimpanan USB, pastikan bahwa Anda telah melepas (“dikeluarkan”) kartu SD Android dari komputer."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Matikan penyimpanan USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Ada masalah ketika mematikan penyimpanan USB. Periksa untuk memastikan bahwa Anda telah melepaskan inang USB, lalu coba sekali lagi."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jika Anda menghidupkan penyimpanan USB, sebagian aplikasi yang Anda gunakan akan berhenti dan mungkin tidak tersedia sampai Anda mematikan penyimpanan USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operasi USB gagal"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format kartu SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format penyimpanan USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Format kartu SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Apakah Anda yakin ingin memformat kartu SD? Semua data pada kartu akan hilang."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Format penyimpanan USB, menghapus semua berkas yang disimpan di sana? Tindakan tidak dapat diurungkan!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Apakah Anda yakin ingin memformat kartu SD? Semua data pada kartu akan hilang."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Debugging USB terhubung"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"calon"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Menyiapkan kartu SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Menyiapkan penyimpanan USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Menyiapkan kartu SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Memeriksa galat."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Kartu SD kosong"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Penyimpanan USB kosong"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Kartu SD kosong"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Kartu SD kosong atau memiliki sistem berkas yang tidak didukung."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Penyimpanan USB kosong atau tidak memiliki sistem berkas yang tidak didukung."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Kartu SD kosong atau memiliki sistem berkas yang tidak didukung."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Kartu SD rusak"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Penyimpanan USB rusak"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Kartu SD rusak"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Kartu SD rusak. Anda mungkin harus memformatnya."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Penyimpanan USB rusak. Anda mungkin perlu memformat ulang."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Kartu SD rusak. Anda mungkin harus memformatnya."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Kartu SD tiba-tiba dicabut"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Penyimpanan USB dilepas secara tidak sengaja"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Kartu SD tiba-tiba dicabut"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Lepaskan kartu SD sebelum mencabutnya untuk mencegah hilangnya data."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Lepas penyimpanan USB sebelum menghapus untuk menghindari kehilangan data."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Lepaskan kartu SD sebelum mencabutnya untuk mencegah hilangnya data."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Kartu SD aman dicabut"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Penyimpanan USB aman untuk dilepas"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Kartu SD aman dicabut"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Anda dapat melepaskan kartu SD dengan aman."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Anda dapat melepas penyimpanan USB dengan aman."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Anda dapat melepaskan kartu SD dengan aman."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Cabut kartu SD"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Penyimpanan USB dihapus"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Cabut kartu SD"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Kartu SD dicabut. Masukkan yang baru."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Penyimpanan USB dihapus. Masukkan media baru."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Kartu SD dicabut. Masukkan yang baru."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Tidak ditemukan aktivitas yang sesuai"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"perbarui statistik penggunaan komponen"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Kirimkan"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Berikutnya"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Selesai"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Sebelumnya"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Lakukan"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Panggil nomor "\n"menggunakan<xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Buat kenalan "\n"menggunakan <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Kunci pra-bagi berbasis L2TP/IPSec VPN"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sertifikat berbasis L2TP/IPSec VPN"</string>
     <string name="upload_file" msgid="2897957172366730416">"Pilih berkas"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Tidak ada berkas yang dipilih"</string>
     <string name="reset" msgid="2448168080964209908">"Setel ulang"</string>
     <string name="submit" msgid="1602335572089911941">"Kirim"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Mode mobil diaktifkan"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Pilih untuk keluar mode mobil"</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering (Penambatan) atau hotspot aktif"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Sentuh untuk mengonfigurasikan"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Kembali"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Selanjutnya"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Lewati"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"penggunaan data seluler yang tinggi"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Sentuh untuk mengetahui penggunaan data seluler lebih lengkap"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Batas data seluler terlampaui"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Sentuh untuk mengetahui penggunaan data seluler lebih lengkap"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Tidak ada kecocokan"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Temukan pada laman"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 kecocokan"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> dari <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Selesai"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Melepas penyimpanan USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Melepas kartu SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Menghapus penyimpanan USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Menghapus kartu SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Gagal menghapus penyimpanan USB."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Gagal menghapus kartu SD."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Kartu SD dihapus sebelum dilepas."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Saat ini penyimpanan USB sedang diperiksa."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Kartu SD sedang diperiksa."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Kartu SD telah dihapus."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Saat ini penyimpanan USB sedang digunakan oleh komputer."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Kartu SD sedang digunakan oleh komputer."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Media eksternal dalam status tidak diketahui."</string>
+    <string name="share" msgid="1778686618230011964">"Bagikan"</string>
+    <string name="find" msgid="4808270900322985960">"Temukan"</string>
+    <string name="websearch" msgid="4337157977400211589">"Penelusuran Web"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index f472755..282d375 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modalità aereo"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modalità aereo attiva"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modalità aereo non attiva"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servizi che prevedono un costo"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Consente all\'applicazione di controllare il flash."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"accesso a dispositivi USB"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Consente all\'applicazione di accedere ai dispositivi USB"</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"esecuzione test hardware"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Consente all\'applicazione di controllare varie periferiche per il test dell\'hardware."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"chiamata diretta n. telefono"</string>
@@ -456,7 +462,7 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Consente a un\'applicazione di leggere parole, nomi e frasi private che l\'utente potrebbe aver memorizzato nel dizionario utente."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"scrittura nel dizionario definito dall\'utente"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Consente a un\'applicazione di scrivere nuove parole nel dizionario utente."</string>
-    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modifica/eliminaz. archivio USB"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modifica/eliminaz. contenuti archivio USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificare/eliminare i contenuti della scheda SD"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Consente di scrivere nell\'archivio USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Consente a un\'applicazione di scrivere sulla scheda SD."</string>
@@ -654,7 +660,7 @@
     <string name="factorytest_not_system" msgid="4435201656767276723">"L\'azione FACTORY_TEST è supportata soltanto per i pacchetti installati in /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nessun pacchetto trovato che fornisca l\'azione FACTORY_TEST."</string>
     <string name="factorytest_reboot" msgid="6320168203050791643">"Riavvia"</string>
-    <string name="js_dialog_title" msgid="8143918455087008109">"La pagina all\'indirizzo <xliff:g id="TITLE">%s</xliff:g> indica:"</string>
+    <string name="js_dialog_title" msgid="8143918455087008109">"Avviso relativo alla pagina <xliff:g id="TITLE">%s</xliff:g>:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Uscire da questa pagina?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Seleziona OK per continuare o Annulla per rimanere nella pagina corrente."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Conferma"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Stato dei supporti esterni sconosciuto."</string>
     <string name="share" msgid="1778686618230011964">"Condividi"</string>
     <string name="find" msgid="4808270900322985960">"Trova"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Ricerca Web"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 67a6403..ea48002 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"דואר קולי"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"בעיה בחיבור או קוד MMI לא תקין."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"הפעולה מוגבלת למספרי חיוג קבועים בלבד."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"השירות הופעל."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"השירות הופעל עבור:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"השירות הושבת."</string>
@@ -126,7 +125,7 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"סנכרון"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"סנכרן"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"יש מחיקות <xliff:g id="CONTENT_TYPE">%s</xliff:g> רבות מדי."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"שטח האחסון בטבלט מלא! מחק חלק מהקבצים כדי לפנות שטח."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"שטח האחסון בטבלט מלא! מחק קבצים כדי לפנות שטח."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"שטח האחסון בטלפון מלא! מחק חלק מהקבצים כדי לפנות שטח."</string>
     <string name="me" msgid="6545696007631404292">"אני"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"אפשרויות טבלט"</string>
@@ -137,13 +136,12 @@
     <string name="screen_lock" msgid="799094655496098153">"נעילת מסך"</string>
     <string name="power_off" msgid="4266614107412865048">"כיבוי"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"מבצע כיבוי..."</string>
-    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"הטבלט שלך יכובה."</string>
+    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"הטבלט שלך יכבה."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"הטלפון שלך יכובה."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"האם ברצונך לבצע כיבוי?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"אחרונות"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"לא הותקנו יישומים לאחרונה."</string>
-    <string name="global_actions" product="tablet" msgid="408477140088053665">"אפשרויות טבלט"</string>
+    <string name="global_actions" product="tablet" msgid="408477140088053665">"אפשרות של טבלט"</string>
     <string name="global_actions" product="default" msgid="2406416831541615258">"אפשרויות טלפון"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"נעילת מסך"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"כיבוי"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"מצב טיסה"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"מצב טיסה מופעל"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"מצב טיסה כבוי"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
     <string name="android_system_label" msgid="6577375335728551336">"מערכת Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"שירותים שעולים לך כסף"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"כלי פיתוח"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"תכונות הדרושות למפתחי יישומים בלבד."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"שטח אחסון"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"גישה לכרטיס ה-SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"גישה לאמצעי אחסון מסוג USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"גישה לכרטיס ה-SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"השבת או שנה את שורת המצב"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"מאפשר ליישום להשבית את שורת המצב או להוסיף ולהסיר סמלי מערכת."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"שורת מצב"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"מאפשר ליישום להיות שורת המצב."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"הרחב/כווץ את שורת המצב"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"מאפשר ליישום להרחיב או לכווץ את שורת המצב."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"עכב שיחות יוצאות"</string>
@@ -196,10 +194,10 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"שלח הודעות SMS"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"מאפשר ליישום לשלוח הודעות SMS. יישומים זדוניים עלולים לגרום לחיובים על ידי שליחת הודעות ללא אישורך."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"קריאת SMS או MMS"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"מאפשר ליישום לקרוא הודעות SMS המאוחסנות בטבלט או בכרטיס ה-SIM. יישומים זדוניים עלולים לקרוא את ההודעות הסודיות."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"מאפשר ליישום לקרוא הודעות SMS המאוחסנות בטבלט או בכרטיס ה-SIM. יישומים זדוניים עלולים למחוק את ההודעות שלך."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"מאפשר ליישום לקרוא הודעות SMS המאוחסנות בטלפון או בכרטיס ה-SIM. יישומים זדוניים עלולים לקרוא את ההודעות הסודיות."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"ערוך SMS או MMS"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"מאפשר ליישום לכתוב להודעות SMS המאוחסנות בטבלט או בכרטיס ה-SIM. יישומים זדוניים עלולים למחוק את ההודעות."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"מאפשר ליישום לכתוב להודעות SMS המאוחסנות בטבלט או בכרטיס ה-SIM. יישומים זדוניים עלולים למחוק את ההודעות שלך."</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"מאפשר ליישום לכתוב להודעות SMS המאוחסנות בטלפון או בכרטיס ה-SIM. יישומים זדוניים עלולים למחוק את ההודעות."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"קבל WAP"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"מאפשר ליישום לקבל ולעבד הודעות WAP. יישומים זדוניים עלולים לעקוב אחר ההודעות או למחוק אותן מבלי להציג אותן לך."</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"מנע החלפת יישומים"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"מונע מהמשתמש לעבור ליישום אחר."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"עקוב ושלוט בכל השקת היישומים"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"מאפשר ליישום לעקוב אחרי האופן שבו המערכת מפעילה פעילויות ולשלוט בו. יישומים זדוניים עלולים לפגוע לחלוטין במערכת. הרשאה זו דרושה רק לפיתוח, לעולם לא לשימוש רגיל."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"מאפשר ליישום לעקוב אחר האופן שבו המערכת מפעילה פעילויות ולשלוט בו. יישומים זדוניים עשויים לפגוע לגמרי במערכת. הרשאה זו דרושה רק לצורך פיתוח, לעולם לא לשימוש רגיל."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"שליחת שידור שהוסר מחבילה"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"מאפשר ליישום לשדר התראה שחבילת יישום הוסרה. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לסיים יישומים פועלים אחרים."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"שלח שידור שהתקבל ב-SMS"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"הצג חלונות לא מורשים"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"מאפשר יצירת חלונות המיועדים לשימוש של ממשק המשתמש במערכת הפנימית. לא לשימוש של יישומים רגילים."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"הצג התראות ברמת המערכת"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"מאפשר ליישום להציג חלונות התראה של המערכת. יישומים זדוניים עלולים להשתלט על המסך כולו."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"מאפשר ליישום להציג חלונות של התראות מערכת. יישומים זדוניים עלולים להשתלט על המסך כולו."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"שנה את מהירות ההנפשה הכללית"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"מאפשר ליישום לשנות את מהירות ההנפשה הכללית (הנפשות מהירות או איטיות יותר) בכל עת."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"נהל אסימוני יישום"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"מאפשר ליישומים ליצור ולנהל אסימונים משלהם, תוך עקיפת סידור ה-Z הרגיל שלהם. לא אמור להידרש לעולם ליישומים רגילים."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"לחיצה על מקשים ושליטה בלחצנים"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"מאפשר ליישום לספק אירועי קלט משלו (הקשות על מקשים וכדומה) ליישומים אחרים. יישומים זדוניים עלולים להשתמש ביכולת זו כדי להשתלט על הטבלט."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"מאפשר ליישום לספק אירועי קלט משלו (לחיצות על מקשים וכדומה) ליישומים אחרים. יישומים זדוניים עלולים להשתמש ביכולת זו כדי להשתלט על הטבלט."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"מאפשר ליישום לספק אירועי קלט משלו (הקשות על מקשים וכדומה) ליישומים אחרים. יישומים זדוניים עלולים להשתמש ביכולת זו כדי להשתלט על הטלפון."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"הקלט את מה שאתה מקליד ואת הפעולות שאתה מבצע"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"מאפשר ליישומים לצפות במקשים שעליהם אתה לוחץ בעת אינטראקציה עם יישום אחר (כגון הזנת סיסמה). לא אמור להיות דרוש לעולם ליישום רגילים."</string>
@@ -281,14 +279,14 @@
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"מאפשר ליישום לפנות שטח אחסון בטלפון על ידי מחיקת קבצים בספריית הקובץ השמור של היישום. הגישה מוגבלת מאוד בדרך כלל לתהליך מערכת."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"העבר משאבי יישום"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"מאפשר ליישום להעביר משאבי יישומים ממדיה פנימית לחיצונית ולהיפך."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"קריאת קובצי יומן מערכת"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"מאפשר ליישום לקרוא מקובצי היומן השונים של המערכת. יכולת זו מאפשרת לגלות מידע כללי על הפעולות שאתה מבצע בטבלט, שעשוי לכלול מידע אישי או פרטי."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"מאפשר ליישום לקרוא מקובצי היומן השונים של המערכת. יכולת זו מאפשרת לגלות מידע כללי על הפעולות שאתה מבצע בטבלט, שעשוי לכלול מידע אישי או פרטי."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"קרא נתונים רגישים של יומן רישום"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"מאפשר ליישום לקרוא מיומני הרישום השונים של המערכת. כך מתאפשר לו לגלות מידע כללי על הפעולות שלך בטבלט, מידע שעשוי לכלול מידע אישי או פרטי."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"מאפשר ליישום לקרוא מיומני הרישום השונים של המערכת. כך מתאפשר לו לגלות מידע כללי על הפעולות שלך בטלפון, מידע שעשוי לכלול מידע אישי או פרטי."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"קריאה/כתיבה למשאבים בבעלות diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"מאפשר ליישום לקרוא ולכתוב לכל משאב בבעלות קבוצת ה-diag; לדוגמה, קבצים ב-‎/dev. לפעולה זו יש פוטנציאל להשפיע על היציבות והאבטחה של המערכת. היצרן או המפעיל בלבד יכולים להשתמש ביכולת זו לצורך אבחונים ספציפיים בחומרה."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"הופך לפעיל או משבית רכיבי יישום"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"מאפשר ליישום לשנות ולקבוע אם רכיב של יישום אחר מופעל או לא. יישומים זדוניים עלולים להשתמש ביכולת זו כדי להשבית יכולות חשובות של הטבלט. יש להשתמש בזהירות בהרשאה זו, משום שהיא עלולה להעביר רכיבי יישום למצב לא שמיש, לא עקבי או לא יציב."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"מאפשר ליישום לשנות ולקבוע אם רכיב של יישום אחר מופעל או לא. יישומים זדוניים עלולים להשתמש ביכולת זו כדי להשבית יכולות חשובות של הטבלט. יש להשתמש בזהירות בהרשאה זו, משום שהיא עלולה להעביר רכיבי יישום למצב לא שמיש, לא עקבי או לא יציב."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"מאפשר ליישום להשתנות ללא קשר אם רכיב או יישום אחר מופעל או לא. יישומים זדוניים יכולים להשתמש ביכולת זו כדי להשבית יכולות חשובות של הטבלט. יש לנהוג בזהירות בהרשאה זו, כיוון שהיא עלולה להעביר רכיבי יישום למצב לא רגיל, לא עקבי או לא יציב."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"מאפשר ליישום להשתנות ללא קשר אם רכיב או יישום אחר מופעל או לא. יישומים זדוניים יכולים להשתמש ביכולת זו כדי להשבית יכולות חשובות של הטלפון. יש לנהוג בזהירות בהרשאה זו, כיוון שהיא עלולה להעביר רכיבי יישום למצב לא רגיל, לא עקבי או לא יציב."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"הגדר יישומים מועדפים"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"מאפשר ליישום לשנות את היישומים המועדפים. פעולה זו עלולה לאפשר ליישומים זדוניים לשנות באופן שקט את היישומים הפועלים, לזייף את היישומים הקיימים כדי לאסוף נתונים פרטיים ממך."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"שנה הגדרות מערכת כלליות"</string>
@@ -298,19 +296,19 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"שינוי מפת השירותים של Google"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"מאפשר ליישום לשנות את מפת השירותים של Google. לא לשימוש של יישומים רגילים."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"הפעל אוטומטית באתחול"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"מאפשר ליישום להפעיל את עצמו מחדש לאחר אתחול המערכת. פעולה זו עלולה להאריך את זמן הפעלת הטבלט, ומאפשרת ליישום להאט את הפעולה הכוללת של הטבלט כאשר היא פועלת תמיד."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"מאפשר ליישום להפעיל את עצמו ברגע שהמערכת מסיימת את האתחול. מצב זה עלול להאריך את הפעלת הטבלט ולאפשר ליישום להאט את הפעולה הכללית של הטבלט אם יפעל תמיד."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"מאפשר ליישום להפעיל את עצמו מחדש לאחר אתחול המערכת. פעולה זו עלולה להאריך את הפעלת הטלפון ומאפשר ליישום להאט את הפעולה הכוללת של הטלפון אם היא פועלת תמיד."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"שלח שידור דביק"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"מאפשר ליישום לשלוח שידורים דביקים, הנשארים לאחר סיום השידור. יישומים זדוניים עלולים להאט את פעולת הטבלט או להפוך אותו ללא יציב כיוון שהם גורמים לשימוש מופרז בזיכרון."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"מאפשר ליישום לשלוח שידורים דביקים שנותרים לאחר שהשידור מסתיים. יישומים זדוניים יכולים להאט את הטבלט או להפוך אותו ללא יציב בכך שיגרמו לו להשתמש בזיכרון רב מדי."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"מאפשר ליישום לשלוח שירותים דביקים, הנשארים לאחר סיום השידור. יישומים זדוניים עלולים להאט את פעולת הטלפון או להפוך אותו ללא יציג כיוון שהם גורמים לשימוש מופרז בזיכרון."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"קרא נתונים של אנשי קשר"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"מאפשר ליישום לקרוא את כל הנתונים של אנשי הקשר (כתובות) המאוחסנים בטבלט. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לשלוח את הנתונים שלך לאנשים אחרים."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"מאפשר ליישום לקרוא את כל נתוני אנשי הקשר (כתובות) בטבלט. יישומים זדוניים יכולים להשתמש ביכולת זו כדי לשלוח את הנתונים לאחרים."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"מאפשר ליישום לקרוא את כל הנתונים של אנשי הקשר (כתובות) המאוחסנים בטלפון. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לשלוח את הנתונים שלך לאנשים אחרים."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"כתוב נתוני איש קשר"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"מאפשר ליישום לשנות את הנתונים של אנשי הקשר (כתובות) המאוחסנים בטבלט. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את הנתונים של אנשי הקשר."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"מאפשר ליישום לשנות את נתוני הקשר (כתובות) המאוחסנים בטבלט. יישומים זדוניים יכולים להשתמש ביכולת זו כדי למחוק או לשנות את נתוני אנשי הקשר."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"מאפשר ליישום לשנות את הנתונים של אנשי הקשר (כתובות) המאוחסנים בטלפון. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את הנתונים של אנשי הקשר."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"קרא אירועי לוח שנה"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"מאפשר ליישום לקרוא את כל אירועי לוח השנה המאוחסנים בטבלט. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לשלוח את אירועי לוח השנה שלך לאנשים אחרים."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"מאפשר ליישום לקרוא את כל נתוני לוח השנה המאוחסנים בטבלט. יישומים זדוניים יכולים להשתמש ביכולת זו כדי לשלוח את אירועי לוח השנה לאנשים אחרים."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"מאפשר ליישום לקרוא את כל אירועי לוח השנה המאוחסנים בטלפון. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לשלוח את אירועי לוח השנה שלך לאנשים אחרים."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"הוסף או שנה אירועי לוח השנה ושלח דוא\"ל לאורחים"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"מאפשר ליישום להוסיף או לשנות את האירועים בלוח השנה, פעולה שעשויה לשלוח דוא\"ל לאורחים. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את האירועים בלוח השנה או כדי לשלוח דוא\"ל לאורחים."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"הרשאה להתקין ספק מיקום"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"צור מקורות מיקום מדומים לצורך בדיקה. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לעקוף את המקום ו/או המצב המוחזרים על ידי מקורות המיקום האמיתיים כגון GPS או ספקי רשת או לעקוב ולדווח על המיקום שלך למקור חיצוני."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"מיקום מדויק (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"קבל גישה למקורות מיקום מדויקים כגון מערכת מיקום גלובלית (GPS) בטבלט, כאשר הם זמינים. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לקבוע היכן אתה נמצא ולגרום לצריכת סוללה נוספת."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"קבל משאבי מיקומים מדויקים כגון \'מערכת מיקום גלובלית\' בטבלט בהתאם לזמינות. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לקבוע היכן אתה, ועשויים לצרוך כוח סוללה נוסף."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"קבל גישה למקורות מיקום מדויקים כגון מערכת מיקום גלובלית (GPS) בטלפון, כאשר הם זמינים. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לקבוע היכן אתה נמצא, ולגרום לצריכת סוללה נוספת."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"מיקום משוער (מבוסס רשת)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"קבל גישה למשאבי מיקום משוער כגון מסד הנתונים של הרשת הסלולרית כדי לקבוע את המיקום המשוער של הטבלט, כאשר הם זמינים. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לקבוע את מיקומך המשוער."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"קבל גישה למשאבי מיקום גולמיים כגון מסד הנתונים של רשת סלולרית כדי לקבוע מיקום משוער של הטבלט, כשהאפשרות זמינה. יישומים זדוניים עלולים להשתמש ביכולת זאת כדי לקבוע את מיקומך המשוער."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"קבל גישה למשאבי מיקום משוער כגון מסד הנתונים של הרשת הסלולרית כדי לקבוע את המיקום המשוער של הטלפון, כאשר ניתן. יישומים זדוניים עלולים להשתמש ביכולת זו כדי לקבוע את מיקומך המשוער."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"גישה ל-SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"מאפשר ליישומים להשתמש בתכונות SurfaceFlinger ברמה נמוכה."</string>
@@ -334,37 +332,39 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"מאפשר ליישום לשנות הגדרות אודיו כלליות כגון עוצמת קול וניתוב."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"הקלט אודיו"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"מאפשר ליישום לגשת לנתיב הקלטת אודיו."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"צלם תמונות"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"מאפשר ליישום לצלם תמונות בעזרת המצלמה. כך מתאפשר ליישום לאסוף תמונות שהמצלמה רואה בכל עת."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"השבת לצמיתות את הטבלט"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"צלם תמונות וסרטונים"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"מאפשר ליישום לצלם תמונות וסרטוני וידאו באמצעות המצלמה. כך יכול היישום לאסוף בכל עת תמונות שהמצלמה רואה."</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"השבת טבלט לצמיתות"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"השבת טלפון לצמיתות"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"מאפשר ליישום להשבית את הטבלט כולו לצמיתות. יכולת זו מסוכנת מאוד."</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"מאפשר ליישום להשבית את הטבלט כולו לצמיתות."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"מאפשר ליישום להשבית את הטלפון כולו לצמיתות. יכולת זו מסוכנת מאוד."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"אלץ אתחול מחדש של הטבלט"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"אלץ אתחול מחדש אל הטבלט"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"אלץ אתחול מחדש של הטלפון"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"מאפשר ליישום לאלץ את הטבלט לבצע אתחול מחדש."</string>
+    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"מאפשר ליישום לכפות על הטבלט לבצע אתחול מחדש."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"מאפשר ליישום לאלץ את הטלפון לבצע אתחול מחדש."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"טעינה וביטול טעינה של מערכות קבצים"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"מאפשר ליישום לטעון מערכות קבצים ולבטל את טעינתן עבור אחסון נשלף."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"פרמט אמצעי אחסון חיצוני"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"מאפשר ליישום לפרמט אחסון הניתן להסרה."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"קבלת מידע על אחסון מאובטח"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"מאפשר ליישום לקבל מידע על אחסון מאובטח."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"צור אחסון מאובטח"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"מאפשר ליישום ליצור אחסון מאובטח."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"השמד אחסון מאובטח"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"מאפשר ליישום להשמיד אחסון מאובטח."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"טען / בטל טעינה של אחסון מאובטח"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"מאפשר ליישום לטעון/להסיר טעינה של אחסון מאובטח."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"שנה את השם של אחסון מאובטח"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"מאפשר ליישום לשנות את השם של אחסון מאובטח."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"קבל מידע על אחסון פנימי"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"מאפשר ליישום לקבל מידע על אחסון פנימי."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"צור אחסון פנימי"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"מאפשר ליישום ליצור אחסון פנימי."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"השמד אחסון פנימי"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"מאפשר ליישום להשמיד אחסון פנימי."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"טען / בטל טעינה של אחסון פנימי"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"מאפשר ליישום לטעון/לבטל טעינה של אחסון פנימי."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"שנה שם של אחסון פנימי"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"מאפשר ליישום לשנות שם של אחסון פנימי."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"שליטה ברטט"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"מאפשר ליישום לשלוט ברטט."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"שליטה בפנס"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"מאפשר ליישום לשלוט בפנס."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"גישה להתקני USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"מאפשר ליישום גישה להתקני USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"בדוק חומרה"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"מאפשר ליישום לשלוט בציוד היקפי מסוגים שונים לצורך בדיקת חומרה."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"מאפשר ליישום להתקשר למספרי טלפון ללא התערבות מצידך. יישומים זדוניים עלולים לגרום לשיחות לא צפויות בחשבון הטלפון. לתשומת ליבך, אינו מאפשר ליישום להתקשר למספרי חירום."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"התקשר ישירות למספרי טלפון"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"מאפשר ליישום להתקשר לכל מספר טלפון, כולל מספרי חירום, ללא התערבות מצידך. יישומים זדוניים עלולים לבצע שיחות מיותרות ולא חוקיות לשירותי חירום."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"הפעל ישירות התקנת טבלט מסוג CDMA"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"הפעל ישירות הגדרת טבלט של CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"הפעל ישירות התקנה של טלפון CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"מאפשר ליישום להפעיל הקצאת CDMA. יישומים זדוניים עלולים להפעיל הקצאת CDMA ללא צורך"</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"שליטה בהתראות עדכון מיקום"</string>
@@ -385,16 +385,16 @@
     <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"מאפשר ליישום לשלוט בתכונות הטלפון של המכשיר. יישום עם הרשאה זו יכול להחליף רשתות, להפעיל ולכבות את הרדיו בטלפון וכדומה מבלי להודיע לך כלל."</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"קרא את המצב והזהות של הטלפון"</string>
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"מאפשר ליישום לגשת לתכונות טלפון של המכשיר.יישום עם הרשאה זו יכול לקבוע את מספר הטלפון והמספר הסידורי של טלפון זה, אם שיחה היא פעילה, המספר שאליו מחוברת שיחה זו וכדומה."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"מנע מעבר של הטבלט למצב שינה"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"מנע מהטבלט לעבור למצב שינה"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"מניעת מעבר הטלפון למצב שינה"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"מאפשר ליישום למנוע מעבר של הטבלט למצב שינה."</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"מאפשר ליישום למנוע מהטבלט לעבור למצב שינה."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"מאפשר ליישום למנוע מעבר של הטלפון למצב שינה."</string>
-    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"הדלק או כבה את הטבלט"</string>
+    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"הפעלה וכיבוי של טבלט"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"הדלק או כבה את הטלפון"</string>
-    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"מאפשר ליישום לכבות ולהדליק את הטבלט."</string>
+    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"מאפשר ליישום להפעיל או לכבות את הטבלט."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"מאפשר ליישום לכבות ולהדליק את הטלפון."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"הפעל במצב בדיקה של היצרן"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"הפעל כבדיקת יצרן ברמה נמוכה, המאפשרת גישה מלאה לחומרת הטבלט. זמין רק כאשר טבלט פועל במצב בדיקת יצרן."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"הפעל כבדיקת יצרן ברמה נמוכה, המאפשרת גישה מלאה לחומרה של הטבלט . זמין רק כאשר הטבלט  פועל במצב בדיקת יצרן."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"הפעל כבדיקת יצרן ברמה נמוכה, המאפשרת גישה מלאה לחומרת הטלפון. זמינה רק כאשר טלפון פועל במצב בדיקת יצרן."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"הגדר טפט"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"מאפשר ליישום להגדיר את טפט המערכת."</string>
@@ -411,7 +411,7 @@
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"פעל בתור ה-AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"מאפשר ליישום לבצע שיחות אל AccountAuthenticators"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"גלה חשבונות ידועים"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"מאפשר ליישום להגיע לרשימת החשבונות הידועים לטבלט."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"מאפשר ליישום לקבל רשימה של חשבונות הידועים לטבלט."</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"מאפשר ליישום להגיע לרשימת החשבונות הידועים לטלפון."</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"פעל כמאמת חשבון"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"מאפשר ליישום להשתמש ביכולות מאמת החשבון של מנהל החשבון, כולל יצירת חשבונות וקבלה והגדרה של הסיסמאות שלהם."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"אפשר קבלת שידורים מרובים ב-Wi-Fi"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"מאפשר ליישום לקבל חפיסות שלא ממוענות ישירות למכשיר שלך. יכולת זו שימושית בעת גילוי שירותים המוצעים בקרבת מקום. היא משתמשת במתח סוללה רב יותר לעומת מצב שאינו ריבוי שידורים."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"ניהול Bluetooth"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"מאפשר ליישום להגדיר את הטבלט המקומי מסוג Bluetooth ולגלות התקנים מרוחקים ולבצע התאמה איתם."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"מאפשר ליישום להגדיר את הטבלט המקומי עם Bluetooth ולגלות ולהתאים התקנים מרוחקים."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"מאפשר ליישום להגדיר את טלפון Bluetooth המקומי, ולגלות מכשירים מרוחקים ולבצע התאמה איתם."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"צור חיבורי Bluetooth"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"מאפשר ליישום להציג תצורה של הטבלט המקומי מסוג Bluetooth וליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"מאפשר ליישום להציג תצורה של טבלט Bluetooth מקומי וליצור ולקבל חיבורים עם התקנים מותאמים."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"מאפשר ליישום להציג תצורה של מכשיר Bluetooth המקומי, וליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"שלוט ב-Near Field Communication"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"מאפשר ליישום לקיים תקשורת עם תגיות, כרטיסים וקוראים מסוג Near Field Communication ‏(NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"השבת נעילת מקשים"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"מאפשר ליישום להשבית את נעילת המקשים ואבטחת סיסמה משויכת. דוגמה תקפה לכך היא טלפון המשבית את נעילת המקשים בעת קבלת שיחת טלפון נכנסת, ולאחר מכן מפעיל מחדש את נעילת המקשים עם סיום השיחה."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"קרא הגדרות סנכרון"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"מאפשר ליישום לקרוא מילים, שמות וביטויים פרטיים שהמשתמש אחסן במילון המשתמש."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"כתוב למילון בהגדרת המשתמש"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"מאפשר ליישום לכתוב מילים חדשות במילון המשתמש."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"שנה/מחק את התוכן של כרטיס SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"שנה/מחק תכנים באמצעי אחסון מסוג USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"שנה/מחק את התוכן של כרטיס SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"מאפשר ליישום לכתובת לכרטיס ה-SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"מאפשר ליישום לכתוב לאמצעי אחסון מסוג USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"מאפשר ליישום לכתובת לכרטיס ה-SD."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"שנה/מחק תכנים של מדיית אחסון פנימית"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"מאפשר ליישום לשנות את התכנים של אחסון המדיה הפנימי."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"גישה למערכת הקבצים של הקובץ השמור"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"מאפשר ליישום לקרוא ולכתוב במערכת הקבצים של הקובץ השמור."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"הגבל סיסמה"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"הגבל את סוגי הסיסמאות שבהן מותר לך להשתמש."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"צפה בניסיונות התחברות"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"עקוב אחר מספר הסיסמאות השגויות שהוזנו בעת ביטול נעילת המסך, ונעל את הטבלט, או מחק את כל הנתונים בטבלט אם הוזנו סיסמאות שגויות רבות מדי"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"עקוב אחר מספר הסיסמאות השגויות שהוזנו בעת ביטול נעילת המסך, ונעל את הטבלט, או מחק את כל הנתונים בטבלט אם הוזנו סיסמאות שגויות רבות מדי"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"אפס סיסמה"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"אלץ את הסיסמה שלך לערך חדש, דורש שמנהל המערכת ייתן לך את הסיסמה לפני שתוכל להיכנס."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"אלץ נעילה"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"שולט במועד נעילת ההתקן, דורש הזנה חוזרת של הסיסמה שלו."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"בצע/קבל שיחות אינטרנט"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"מאפשר ליישום להשתמש בשירות SIP כדי לבצע/לקבל שיחות אינטרנט."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"הגדר כללי סיסמה"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"שלוט באורך ובמספר התווים המותרים בסיסמאות לביטול נעילת מסך"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"עקוב אחר ניסיונות לביטול נעילת מסך"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"עקוב אחר מספר הסיסמאות השגויות שהוזנו בעת ביטול נעילת המסך, ונעל את הטבלט או מחק את כל נתוני הטבלט אם הוזנו סיסמאות שגויות רבות מדי"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"עקוב אחר מספר הסיסמאות השגויות שהוזנו בעת ביטול נעילת המסך, ונעל את הטלפון או מחק את כל נתוני הטלפון אם הוזנו סיסמאות שגויות רבות מדי"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"שנה את הסיסמה לביטול נעילת המסך"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"שנה את הסיסמה לביטול נעילת המסך"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"נעל את המסך"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"שלוט באופן ובמועד של נעילות מסך"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"מחק את כל הנתונים"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"מחק את הנתונים בטבלט ללא אזהרה על ידי איפוס נתוני יצרן"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"מחק את הנתונים בטבלט ללא אזהרה על ידי איפוס נתוני יצרן"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"מחק את נתוני הטבלט ללא אזהרה על ידי ביצוע איפוס נתוני יצרן"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"מחק את נתוני הטלפון ללא אזהרה, על ידי ביצוע איפוס נתוני יצרן"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"הגדר את שרת ה-proxy הגלובלי של ההתקן"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"הגדר את שרת proxy הגלובלי של ההתקן לשימוש כאשר המדיניות מופעלת. רק מנהל ההתקן הראשון מגדיר את שרת ה-proxy הגלובלי הפעיל."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"הגדר תפוגת תוקף של סיסמה"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"שלוט בפרק הזמן הדרוש לשינוי הסיסמה של נעילת המסך"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"דף הבית"</item>
     <item msgid="869923650527136615">"נייד"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"איתורית של העבודה"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"מסייע"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"מותאם אישית"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"יום הולדת"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"יום השנה"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"אירוע"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"אחר"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"מותאם אישית"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"דף הבית"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"עבודה"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"עבודה"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"אחר"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"מותאם אישית"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"מותאם אישית"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"עוזר"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"אח"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"צאצא"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"שותף לחיים"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"אב"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"חבר"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"מנהל"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"אם"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"הורה"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"שותף"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"הופנה על ידי"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"קרוב משפחה"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"אחות"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"בן/בת זוג"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"מותאם אישית"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"דף הבית"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"עבודה"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"אחר"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"הזן קוד PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"הזן סיסמה לביטול הנעילה"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"הזן PIN לביטול נעילה"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"קוד PIN שגוי!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"כדי לבטל את הנעילה, לחץ על \'תפריט\' ולאחר מכן על 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"מספר חירום"</string>
@@ -646,8 +615,7 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"חזרה לשיחה"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"נכון!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"מצטערים, נסה שוב"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"מצטערים, נסה שוב"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"טוען (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"נטען."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"כרטיס ה-SIM נעול."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"מבטל נעילת כרטיס SIM…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. "\n\n"נסה שוב בעוד <xliff:g id="NUMBER_1">%d</xliff:g> שניות."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"ציירת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטלפון באמצעות פרטי הכניסה שלך ב-Google‏."\n"‏ "\n" נסה שוב בעוד <xliff:g id="NUMBER_2">%d</xliff:g> שניות."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"הזנת סיסמה שגויה <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. "\n\n"נסה שוב בעוד <xliff:g id="NUMBER_1">%d</xliff:g> שניות."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"הזנת PIN שגוי <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. "\n\n"נסה שוב בעוד <xliff:g id="NUMBER_1">%d</xliff:g> שניות."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"שרטטת באופן שגוי את קו ביטול הנעילה <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטבלט באמצעות פרטי הכניסה שלך ל-Google."\n\n" נסה שוב בעוד <xliff:g id="NUMBER_2">%d</xliff:g> שניות."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"ציירת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילה הטלפון באמצעות פרטי הכניסה שלך ב-Google."\n\n" נסה שוב בעוד <xliff:g id="NUMBER_2">%d</xliff:g> שניות."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"נסה שוב בעוד <xliff:g id="NUMBER">%d</xliff:g> שניות."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"שכחת את הקו?"</string>
@@ -698,23 +664,17 @@
     <string name="double_tap_toast" msgid="1068216937244567247">"טיפש: הקש פעמיים כדי להתקרב ולהתרחק."</string>
     <string name="autofill_this_form" msgid="1272247532604569872">"מילוי אוטומטי"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"התקן \'מילוי אוטומטי\'"</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"קרא היסטוריה וסימניות של דפדפן"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"מאפשר ליישום לקרוא את כל כתובות האתרים שבהן ביקר הדפדפן, ואת כל הסימניות של הדפדפן."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"כתיבת היסטוריה וסימניות של דפדפן"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"מאפשר ליישום לשנות את ההיסטוריה או הסימניות של הדפדפן המאוחסנים בטבלט. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את נתוני הדפדפן."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"מאפשר ליישום לשנות את ההיסטוריה או הסימניות של הדפדפן המאוחסנות בטבלט. יישומים זדוניים יכולים להשתמש ביכולת זו כדי למחוק או לשנות את הנתונים בדפדפן."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"מאפשר ליישום לשנות את ההיסטוריה או הסימניות של הדפדפן המאוחסנים בטלפון. יישומים זדוניים עלולים להשתמש ביכולת זו כדי למחוק או לשנות את נתוני הדפדפן."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"הגדר התראה בשעון המעורר"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"מאפשר ליישום להגדיר התראה ביישום מותקן של שעון מעורר. חלק מיישומי השעון המעורר עשויים שלא ליישם תכונה זו."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"שנה את ההרשאות של מיקום גיאוגרפי בדפדפן"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"מאפשר ליישום לשנות את הרשאות היעד הגיאוגרפי של הדפדפן. יישומים זדוניים יכולים להשתמש ביכולת זו כדי לאפשר שליחה של פרטי מיקום לאתרי אינטרנט אקראיים."</string>
     <string name="save_password_message" msgid="767344687139195790">"האם ברצונך שהדפדפן יזכור סיסמה זו?"</string>
@@ -830,15 +790,12 @@
     <string name="cut" msgid="3092569408438626261">"גזור"</string>
     <string name="copy" msgid="2681946229533511987">"העתק"</string>
     <string name="paste" msgid="5629880836805036433">"הדבק"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"אין מה להדביק"</string>
     <string name="copyUrl" msgid="2538211579596067402">"העתק כתובת אתר"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"בחר טקסט..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"בחירת טקסט"</string>
     <string name="inputMethod" msgid="1653630062304567879">"שיטת קלט"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"ערוך טקסט"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"פעולות טקסט"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"חסר מקום"</string>
     <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"שטח האחסון בטבלט עומד להיגמר."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"שטח האחסון בטלפון עומד להיגמר."</string>
@@ -847,8 +804,7 @@
     <string name="yes" msgid="5362982303337969312">"אישור"</string>
     <string name="no" msgid="5141531044935541497">"ביטול"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"לידיעתך"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"טוען..."</string>
     <string name="capital_on" msgid="1544682755514494298">"הפעל"</string>
     <string name="capital_off" msgid="6815870386972805832">"כבוי"</string>
     <string name="whichApplication" msgid="4533185947064773386">"השלמת פעולה באמצעות"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"אלץ סגירה"</string>
     <string name="report" msgid="4060218260984795706">"דווח"</string>
     <string name="wait" msgid="7147118217226317732">"המתן"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"היישום נותב מחדש"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> פועל כעת."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> הופעל במקור."</string>
+    <string name="smv_application" msgid="295583804361236288">"היישום <xliff:g id="APPLICATION">%1$s</xliff:g> (תהליך <xliff:g id="PROCESS">%2$s</xliff:g>) הפר את מדיניות StrictMode באכיפה עצמית."</string>
+    <string name="smv_process" msgid="5120397012047462446">"התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הפר את מדיניות StrictMode באכיפה עצמית."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> פועל"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"בחר כדי לעבור ליישום"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"להחליף יישומים?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"יישום אחר כבר פועל ויש לעצור אותו לפני שתוכל להפעיל יישום חדש."</string>
+    <string name="old_app_action" msgid="493129172238566282">"חזרה אל <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"אל תפעיל את היישום החדש."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"הפעל את <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"הפסק את היישום הישן מבלי לשמור."</string>
     <string name="sendText" msgid="5132506121645618310">"בחר פעולה לטקסט"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"עוצמת הקול של הצלצול"</string>
     <string name="volume_music" msgid="5421651157138628171">"עוצמת קול של מדיה"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"הצג הכול"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"אחסון ב-USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB מחובר"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"חיברת את הטלפון למחשב באמצעות USB. בחר בלחצן בהמשך אם ברצונך להעתיק קבצים בין המחשב וכרטיס ה-SD של ה-Android."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"חיברת את הטלפון למחשב באמצעות USB. בחר בלחצן בהמשך אם ברצונך להעתיק קבצים בין המחשב וכרטיס ה-SD של ה-Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"התחברת למחשב באמצעות USB. גע בלחצן שבהמשך אם ברצונך להעתיק קבצים בין המחשב ואמצעי האחסון מסוג USB של התקן ה-Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"התחברת למחשב באמצעות USB. גע בלחצן שבהמשך אם ברצונך להעתיק קבצים בין המחשב וכרטיס ה-SD של התקן ה-Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"הפעל אחסון USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"יש בעיה בשימוש בכרטיס ה-SD שלך כאחסון USB."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"יש בעיה בשימוש בכרטיס ה-SD שלך כאחסון USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"קיימת בעיה בשימוש באמצעי אחסון מסוג USB לאחסון גדול ב-USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"יש בעיה בשימוש בכרטיס ה-SD לאחסון גדול ב-USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB מחובר"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"בחר כדי להעתיק קבצים מהמחשב/אל המחשב."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"כבה אחסון USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"בחר כדי לכבות אחסון USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"אחסון USB נמצא בשימוש"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"לפני כיבוי אחסון USB, ודא שהסרת (\"הוצאת\") את כרטיס ה-SD של Android מהמחשב."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"לפני כיבוי אמצעי אחסון מסוג USB, ודא שפרקת (\"הוצאת\") את אמצעי אחסון מסוג USB של Android מהמחשב."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"לפני כיבוי אחסון USB, ודא שהסרת (\"הוצאת\") את כרטיס ה-SD של Android מהמחשב."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"כבה אחסון USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"אירעה בעיה בכיבוי אחסון USB. בדוק כדי לוודא שלא ביטלת את טעינת מארח ה-USB, ולאחר מכן נסה שוב."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"אם תפעיל אחסון USB, חלק מהיישומים שבהם אתה משתמש יעצרו ולא יהיו זמינים עד שתכבה את אחסון ה-USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"הפעלת ה-USB נכשלה"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"אישור"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"פרמוט כרטיס SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"פרמט אמצעי אחסון מסוג USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"פרמוט כרטיס SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"האם אתה בטוח שברצונך לפרמט את כרטיס ה-SD? כל הנתונים בכרטיס יאבדו."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"לפרמט את אמצעי האחסון מסוג USB, תוך מחיקת כל הקבצים? הפעולה בלתי הפיכה!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"האם אתה בטוח שברצונך לפרמט את כרטיס ה-SD? כל הנתונים בכרטיס יאבדו."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"פורמט"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"ניקוי באגים של USB מחובר"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZאבגדהוזחטיכלמנסעפצקרשת"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ  0123456789אבגדהוזחטיכלמנסעפצקרשת"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"מועמדים"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"מכין את כרטיס ה-SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"מכין אמצעי אחסון מסוג USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"מכין את כרטיס ה-SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"בודק אם יש שגיאות."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"כרטיס SD ריק"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"אמצעי אחסון ריק מסוג USB"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"כרטיס SD ריק"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"כרטיס ה-SD ריק או שמערכת הקבצים שלו לא נתמכת."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"אמצעי אחסון ריק מסוג USB או עם מערכת קבצים לא נתמכת."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"כרטיס ה-SD ריק או שמערכת הקבצים שלו לא נתמכת."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"כרטיס SD פגום"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"אמצעי אחסון פגום מסוג USB"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"כרטיס SD פגום"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"כרטיס ה-SD פגום. ייתכן שיהיה עליך לפרמט אותו שוב."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"אמצעי אחסון מסוג USB נפגם. ייתכן שיהיה עליך לפרמט אותו שוב."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"כרטיס ה-SD פגום. ייתכן שיהיה עליך לפרמט אותו שוב."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"כרטיס SD הוסר באופן לא צפוי"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"אמצעי אחסון מסוג USB הוסר באופן בלתי צפוי"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"כרטיס SD הוסר באופן לא צפוי"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"בטל את טעינת כרטיס ה-SD לפני הסרתו כדי למנוע אובדן נתונים."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"בטל טעינת אמצעי אחסון מסוג USB לפני הסרתו כדי להימנע מאובדן נתונים."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"בטל את טעינת כרטיס ה-SD לפני הסרתו כדי למנוע אובדן נתונים."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"אפשר להסיר את כרטיס ה-SD"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"ניתן להסיר את אמצעי האחסון מסוג USB בבטחה"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"אפשר להסיר את כרטיס ה-SD"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"ניתן להסיר בבטחה את כרטיס ה-SD."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"אתה יכול להסיר בבטחה את אמצעי האחסון מסוג USB."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"ניתן להסיר בבטחה את כרטיס ה-SD."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"כרטיס ה-SD הוסר"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"אמצעי אחסון מסוג USB הוסר"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"כרטיס ה-SD הוסר"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"כרטיס SD הוסר. הכנס כרטיס חדש."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"אמצעי אחסון מסוג USB הוסר. הכנס מדיה חדשה."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"כרטיס SD הוסר. הכנס כרטיס חדש."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"לא נמצאו פעילויות תואמות"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"עדכון נתונים סטטיסטיים של שימוש ברכיב"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"שלח"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"הבא"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"בוצע"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"הקודם"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"בצע"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"חייג למספר"\n"באמצעות <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"צור איש קשר"\n"באמצעות <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN של L2TP/IPSec המבוסס על מפתח משותף מראש"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN המבוסס על אישור"</string>
     <string name="upload_file" msgid="2897957172366730416">"בחר קובץ"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"לא נבחר קובץ"</string>
     <string name="reset" msgid="2448168080964209908">"אפס"</string>
     <string name="submit" msgid="1602335572089911941">"שלח"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"מצב מכונית מופעל"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"בחר כדי לצאת ממצב מכונית."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"קשור או פעיל כנקודה חמה"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"גע כדי להגדיר"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"הקודם"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"הבא"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"דלג"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"שימוש רב בנתונים ניידים"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"גע למידע נוסף על שימוש בנתונים ניידים"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"אירעה חריגה ממגבלת הנתונים הניידים"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"גע למידע נוסף על שימוש נתונים ניידים"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"אין התאמות"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"מצא בדף"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"התאמה אחת"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> מתוך <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"בוצע"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"מבטל טעינה של אמצעי אחסון מסוג USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"מבטל טעינת כרטיס SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"מוחק אמצעי אחסון מסוג USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"מוחק כרטיס SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"נכשלה מחיקה של אמצעי אחסון מסוג USB."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"נכשלה מחיקת כרטיס SD."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"כרטיס ה-SD הוסר לפני שטעינתו בוטלה."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"אמצעי אחסון מסוג USB נבדק כעת."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"כרטיס SD נבדק כעת."</string>
+    <string name="media_removed" msgid="7001526905057952097">"כרטיס ה-SD הוסר."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"אמצעי אחסון מסוג USB נמצא כעת בשימוש של מחשב."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"כרטיס SD נמצא כעת בשימוש של מחשב."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"מדיה חיצונית במצב לא ידוע."</string>
+    <string name="share" msgid="1778686618230011964">"שתף"</string>
+    <string name="find" msgid="4808270900322985960">"חפש"</string>
+    <string name="websearch" msgid="4337157977400211589">"חיפוש Google"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index b94af31..6df5f3d 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"機内モード"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"機内モードON"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"機内モードOFF"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Androidシステム"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"料金の発生するサービス"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"ライトの制御をアプリケーションに許可します。"</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"USBデバイスへのアクセス"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"USBデバイスへのアクセスをアプリケーションに許可します。"</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"ハードウェアのテスト"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"ハードウェアのテストのためにさまざまな周辺機器を制御することをアプリケーションに許可します。"</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"電話番号発信"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"外部メディアの状態は不明です。"</string>
     <string name="share" msgid="1778686618230011964">"共有"</string>
     <string name="find" msgid="4808270900322985960">"検索"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"ウェブ検索"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 9c30604..10eba59 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"비행기 모드"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"비행기 모드 사용"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"비행기 모드 사용 안함"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 시스템"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"요금이 부과되는 서비스"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"애플리케이션이 카메라 플래시를 제어할 수 있도록 합니다."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"USB 장치 액세스"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"애플리케이션이 USB 장치에 액세스하도록 허용합니다."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"하드웨어 테스트"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"애플리케이션이 하드웨어를 테스트할 목적으로 다양한 주변장치를 제어할 수 있도록 합니다."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"전화번호 자동 연결"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"외부 미디어가 알 수 없는 상태입니다."</string>
     <string name="share" msgid="1778686618230011964">"공유"</string>
     <string name="find" msgid="4808270900322985960">"찾기"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"웹 검색"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index b1f12b5..fbfc3bf 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -22,5 +22,6 @@
     <dimen name="password_keyboard_key_height">47dip</dimen>
     <dimen name="password_keyboard_spacebar_vertical_correction">2dip</dimen>
     <dimen name="preference_screen_side_margin">96dp</dimen>
+    <dimen name="preference_screen_side_margin_negative">-100dp</dimen>
     <dimen name="preference_widget_width">72dp</dimen>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/core/res/res/values-large/dimens.xml b/core/res/res/values-large/dimens.xml
new file mode 100644
index 0000000..5691548
--- /dev/null
+++ b/core/res/res/values-large/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <item type="dimen" name="dialog_min_width_major">55%</item>
+    <item type="dimen" name="dialog_min_width_minor">80%</item>
+</resources>
diff --git a/core/res/res/values-large/themes.xml b/core/res/res/values-large/themes.xml
index 12257a1..9e3e0bb 100644
--- a/core/res/res/values-large/themes.xml
+++ b/core/res/res/values-large/themes.xml
@@ -18,15 +18,17 @@
 -->
 <resources>
     <style name="Theme.Holo.DialogWhenLarge"
-            parent="@android:style/Theme.Holo.Dialog">
+            parent="@android:style/Theme.Holo.Dialog.MinWidth">
+        <item name="preferencePanelStyle">@style/PreferencePanel.Dialog</item>
     </style>
     <style name="Theme.Holo.DialogWhenLarge.NoActionBar"
-            parent="@android:style/Theme.Holo.Dialog.NoActionBar">
+            parent="@android:style/Theme.Holo.Dialog.NoActionBar.MinWidth">
+        <item name="preferencePanelStyle">@style/PreferencePanel.Dialog</item>
     </style>
     <style name="Theme.Holo.Light.DialogWhenLarge"
-            parent="@android:style/Theme.Holo.Light.Dialog">
+            parent="@android:style/Theme.Holo.Light.Dialog.MinWidth">
     </style>
     <style name="Theme.Holo.Light.DialogWhenLarge.NoActionBar"
-            parent="@android:style/Theme.Holo.Light.Dialog.NoActionBar">
+            parent="@android:style/Theme.Holo.Light.Dialog.NoActionBar.MinWidth">
     </style>
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 2414675..bbb629d 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Balso paštas"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Ryšio problema arba neteisingas MMI kodas."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Operacija ribojama tik naudojant fiksuoto rinkimo numerius."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Paslauga įgalinta."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Paslauga buvo įgalinta:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Paslauga išjungta."</string>
@@ -139,8 +138,7 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"Išsijungia..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Planšetinio kompiuterio veikimas bus sustabdytas."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonas bus išjungtas."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Ar norite stabdyti?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Naujos"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Nėra naujų programų."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Planšetinio kompiuterio parinktys"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lėktuvo režimas"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ĮJUNGTAS lėktuvo režimas"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"lėktuvo režimas IŠJUNGTAS"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
     <string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Paslaugos, už kurias mokėjote"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Kūrėjo įrankiai"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funkcijos reikalingos tik programos kūrėjams."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Saugykla"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Pasiekite SD kortelę."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Pasiekti USB atmintinę."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Pasiekite SD kortelę."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"išjungti ar keisti būsenos juostą"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Leidžia programai išjungti būsenos juostą arba pridėti ir pašalinti sistemos piktogramas."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"būsenos juosta"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Leidžiama programai būti būsenos juosta."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"išskleisti / sutraukti būsenos juostą"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Leidžia programai išskleisti arba sutraukti būsenos juostą."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"sulaikyti išeinančius skambučius"</string>
@@ -281,14 +279,14 @@
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Leidžia programoms atlaisvinti vietos telefono saugykloje ištrinant failus, esančius programos talpyklos kataloge. Prieiga labai ribojama, dažniausiai dėl sistemos procesų."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Perkelti programos išteklius"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Leidžia programai perkelti programos išteklius iš vidinės į išorinę mediją ir atvirkščiai."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"skaityti sistemos žurnalo failus"</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"skaityti slaptus žurnalo duomenis"</string>
     <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Leidžiama programai skaityti iš įvairių sistemos žurnalų failų. Taip galima atrasti bendrą informaciją apie tai, ką darote naudodami planšetinį kompiuterį, galimai įtraukiant asmeninę ar privačią informaciją."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Leidžiama programai skaityti iš įvairių sistemos žurnalų failų. Taip galima atrasti bendrą informaciją apie tai, ką darote naudodami planšetinį kompiuterį, galimai įtraukiant asmeninę ar privačią informaciją."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Leidžiama programai skaityti iš įvairių sistemos žurnalų failų. Taip galima atrasti bendrą informaciją apie tai, ką darote telefonu, galimai įtraukiant asmeninę ar privačią informaciją."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"skaityti / rašyti ištekliuose, priklausančiuose diagnostikai"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Leidžia programai skaityti ir rašyti visuose diagnostikos grupei priklausančiuose ištekliuose, pvz., failuose, esančiuose /dev. Tai gali paveikti sistemos stabilumą ir saugą. Tai turėtų būti naudojama TIK aparatinės įrangos diagnostikai, atliekamai gamintojo ar operatoriaus."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"įgalinti ar išjungti programos komponentus"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Leidžiama programai keisti, ar įgalintas kitos programos komponentas, ar ne. Kenkėjiškos programos tai gali naudoti, kad neleistų svarbių planšetinio kompiuterio funkcijų. Priežiūros darbai turi būti atliekami tik gavus šį leidimą, nes programos komponentai gali būti paversti nenaudojamais, nenuosekliais ar nestabiliais."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Leidžiama programai keisti, ar įgalintas kitos programos komponentas, ar ne. Kenkėjiškos programos tai gali naudoti, kad neleistų svarbių planšetinio kompiuterio funkcijų. Priežiūros darbai turi būti atliekami tik gavus šį leidimą, nes programos komponentai gali būti paversti nenaudojamais, nenuosekliais ar nestabiliais."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Leidžiama programai keisti, ar įgalintas kitos programos komponentas, ar ne. Kenkėjiškos programos tai gali naudoti, kad neleistų svarbių telefono funkcijų. Priežiūros darbai turi būti atliekami tik gavus šį leidimą, nes programos komponentai gali būti paversti nenaudojamais, nenuosekliais ar nestabiliais."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"nustatyti pageidaujamas programas"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Leidžia programai keisti pageidaujamas programas. Tai gali leisti kenkėjiškoms programoms tyliai keisti paleistas programas, apsimetant, kad esamos jūsų programos renka duomenis iš jūsų."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"keisti visuotinius sistemos nustatymus"</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"leidimas įdiegti vietos teikimo įrankį"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Kurti imituojančius vietos šaltinius bandymui. Kenkėjiškos programos gali tai naudoti, kad panaikintų vietą ir (arba) būseną, kurią pateikė tikrieji vietos šaltiniai, pvz., GPS ar tinklo paslaugų teikėjai, ar stebėtų ir praneštų jūsų vietą išoriniam šaltiniui."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"išsami (GPS) vieta"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Pasiekite išsamius vietos šaltinius, pvz., pasaulinę pozicijos nustatymo sistemą, naudodami planšetinį kompiuterį, jei pasiekiama. Kenkėjiškos programos gali tai naudoti, kad nustatytų, kur jūs esate, ir tai gali naudoti papildomą akumuliatoriaus energiją."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Pasiekite išsamius vietos šaltinius, pvz., pasaulinę pozicijos nustatymo sistemą, naudodami planšetinį kompiuterį, jei pasiekiama. Kenkėjiškos programos gali tai naudoti, kad nustatytų, kur jūs esate, ir tai gali eikvoti papildomą akumuliatoriaus energiją."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Pasiekite išsamius vietos šaltinius, pvz., pasaulinę pozicijos nustatymo sistemą, telefone, jei galima. Kenkėjiškos programos gali tai naudoti, kad nustatytų, kur jūs esate, ir tai gali naudoti papildomą akumuliatoriaus energiją."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"apytikslė (pagrįsta pagal tinklą) vieta"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Pasiekite apytikslius vietos šaltinius, pvz., korinio tinklo duomenis, kad nustatytumėte apytikslę planšetinio kompiuterio vietą, jei pasiekiama. Kenkėjiškos programos gali tai naudoti, kad apytiksliai nustatytų, kur jūs esate."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Pasiekite apytikslius vietos šaltinius, pvz., korinio tinklo duomenis, kad nustatytumėte apytikslę planšetinio kompiuterio vietą, jei įmanoma. Kenkėjiškos programos gali tai naudoti, kad apytiksliai nustatytų, kur jūs esate."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Pasiekite apytikslius vietos šaltinius, pvz., korinio tinklo duomenys, kad nustatytumėte apytikslę telefono vietą, jei įmanoma. Kenkėjiškos programos gali tai naudoti, kad apytiksliai nustatytų, kur jūs esate."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"pasiekti „SurfaceFlinger“"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Leidžia programai naudoti „SurfaceFlinger“ žemo lygio funkcijose."</string>
@@ -334,8 +332,8 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Leidžia programai keisti visus garso nustatymus, pvz., garsumą ir kelvadą."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"įrašyti garsą"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Leidžia programai pasiekti garso įrašo kelią."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"fotografuoti"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Leidžia programai fotografuoti fotoaparatu. Tai leidžia programai bet kuriuo metu rinkti vaizdus, kurie matomi fotoaparate."</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"fotografuoti ir filmuoti"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Leidžiama programai fotografuoti ir filmuoti naudojant fotoaparatą. Taip programa gali bet kada rinkti fotoaparate pateikiamus vaizdus."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"visam laikui neleisti planšetinio kompiuterio"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"visam laikui išjungti telefoną"</string>
     <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Leidžiama programai visam laikui neleisti viso planšetinio kompiuterio. Tai labai pavojinga."</string>
@@ -348,23 +346,25 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Leidžia programai montuoti ir pašalinti keičiamos saugyklos failų sistemas."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formatuoti išorinę saugyklą"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Leidžia programai formatuoti keičiamą saugyklą."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"gauti informacijos apie saugią saugyklą"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Leidžia programai gauti informacijos apie saugią saugyklą."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"kurti saugią saugyklą"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Leidžia programai sukurti saugią saugyklą."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"naikinti saugią saugyklą"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Leidžia programai naikinti saugią saugyklą."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"montuoti / pašalinti saugią saugyklą"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Leidžia programai montuoti / pašalinti saugią saugyklą."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"pervadinti saugią saugyklą"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Leidžia programai iš naujo pavadinti saugią saugyklą."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"gauti informacijos apie vidinę atmintinę"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Leidžiama programai gauti informacijos apie vidinę atmintinę."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"kurti vidinę atmintinę"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Leidžiama programai sukurti vidinę atmintinę."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"sunaikinti vidinę atmintinę"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Leidžiama programai sunaikinti vidinę atmintinę."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"prijungti / atjungti vidinę atmintinę"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Leidžiama programai prijungti / atjungti vidinę atmintinę."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"iš naujo pavadinti vidinę atmintinę"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Leidžiama programai iš naujo pavadinti vidinę atmintinę."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"valdyti vibratorių"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Leidžia programai valdyti vibratorių."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"valdyti šviesos signalą"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Leidžia programai valdyti šviesos signalą."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"pasiekti USB įrenginius"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Leidžiama programai pasiekti USB įrenginius."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"bandyti aparatinę įrangą"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Leidžia programai valdyti įvairius išorinius įrenginius aparatinės įrangos bandymo tikslais."</string>
@@ -443,10 +443,8 @@
     <string name="permlab_bluetooth" msgid="8361038707857018732">"kurti „Bluetooth“ ryšius"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Leidžiama programai žiūrėti vietinio „Bluetooth“ planšetinio kompiuterio konfigūraciją ir užmegzti bei priimti susietų įrenginių ryšius."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Leidžia programai žiūrėti vietinio „Bluetooth“ telefono konfigūraciją ir užmegzti bei priimti susietų įrenginių ryšius."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"valdyti artimo lauko perdavimą (angl. „Near Field Communication“)"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Leidžiama programai perduoti artimo lauko perdavimo (angl. „Near Field Communication“, NFC) žymas, korteles ir skaitymo programas."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"išjungti užraktą"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Leidžia programai išjungti užraktą ir visą susijusią slaptažodžio apsaugą. Patikimas pavyzdys būtų užrakto išjungimas telefone gaunant įeinantį skambutį ir įgalinant jį vėl, kai skambutis baigtas."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"skaityti sinchronizavimo nustatymus"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Leidžia programai skaityti privačius žodžius, vardus ir frazes, kuriuos naudotojai išsaugojo naudotojo žodyne."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"rašyti naudotojo nustatytame žodyne"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Leidžia programai rašyti naujus žodžius į naudotojo žodyną."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"keisti / ištrinti SD kortelės turinį"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"keisti / ištrinti USB atmintinės turinį"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"keisti / ištrinti SD kortelės turinį"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Leidžia programai rašyti į SD kortelę."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Leidžiama programai įrašyti į USB atmintinę."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Leidžia programai rašyti į SD kortelę."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"keisti / ištrinti vidinės medijos atmintinės turinį"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Leidžiama programai keisti vidinės medijos atmintinės turinį."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"pasiekti talpyklos failų sistemą"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Leidžia programai skaityti ir rašyti į talpyklos failų sistemą."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Riboti slaptažodį"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Apriboti slaptažodžių tipus, kuriuos galite naudoti."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Žiūrėti bandymus prisijungti"</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"skambinti / priimti skambučius internetu"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Leidžiama programai naudoti SIP paslaugą norint skambinti / priimti skambučius internetu."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Nustatyti slaptažodžio taisykles"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Valdyti leidžiamą ekrano atrakinimo slaptažodžių ilgį ir juose leidžiamus naudoti simbolius"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Stebėti bandymus atrakinti ekraną"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Stebėti neteisingų slaptažodžių, įvestų atrakinant ekraną, skaičių ir, jei daug kartų įvedami neteisingi slaptažodžiai, užrakinti planšetinį kompiuterį ar ištrinti visus jo duomenis"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Stebėti neteisingų slaptažodžių, įvestų atrakinant ekraną, skaičių ir, jei daug kartų įvedami neteisingi slaptažodžiai, užrakinti planšetinį kompiuterį ar ištrinti visus jo duomenis"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Iš naujo nustatyti slaptažodį"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Pakeiskite slaptažodį į naują vertę, prašydami, kad administratorius suteiktų jums ją prieš prisijungiant."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Užrakinti"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Valdyti, kada įrenginys užsirakina, pareikalavęs iš naujo įvesti jo slaptažodį."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Stebėti neteisingų slaptažodžių, įvestų atrakinant ekraną, skaičių ir, jei daug kartų įvedami neteisingi slaptažodžiai, užrakinti telefoną ar ištrinti visus jo duomenis"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Pakeisti ekrano užrakinimo slaptažodį"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Pakeisti ekrano užrakinimo slaptažodį"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Užrakinti ekraną"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Valdyti, kaip ir kada užrakinamas ekranas"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Trinti visus duomenis"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Be įspėjimo ištrinti planšetinio kompiuterio duomenis iš naujo nustatant gamyklinius duomenis"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Be įspėjimo ištrinti planšetinio kompiuterio duomenis iš naujo nustatant gamyklinius duomenis"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Be įspėjimo ištrinti telefono duomenis iš naujo nustatant gamyklinius duomenis"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nustatyti įrenginio bendrąjį tarpinį serverį"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Nustatyti įrenginio bendrąjį tarpinį serverį, kad būtų naudojamas, kol įgalinta politika. Tik pirmasis įrenginio administratorius nustato efektyvų bendrąjį tarpinį serverį."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Nust. slaptaž. galiojimo pab."</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Valdyti, per kiek laiko iki ekrano užrakinimo turi būti pakeistas slaptažodis"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Pagrindinis"</item>
     <item msgid="869923650527136615">"Mobilusis"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Darbo pranešimų gaviklis"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Asistentas"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Priskirtas"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Gimimo diena"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Sukaktis"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Įvykis"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Kita"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Priskirtas"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Pagrindinis"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Darbo"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Darbo"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Kita"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Priskirtas"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Priskirtas"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Asistentas (-ė)"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Brolis"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Vaikas"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Civilinis partneris"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Tėvas"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Draugas (-ė)"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Vadovas (-ė)"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Motina"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Vienas iš tėvų"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Partneris (-ė)"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Rekomendavo"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Giminaitis (-ė)"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Sesuo"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Sutuoktinis (-ė)"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Priskirtas"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Pagrindinis"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Darbas"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Kita"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Įveskite PIN kodą"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Įveskite slaptažodį, kad atrakintumėte"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Jei norite atrakinti, įveskite PIN kodą"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Neteisingas PIN kodas!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Jei norite atrakinti, paspauskite „Meniu“ ir 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Pagalbos numeris"</string>
@@ -646,8 +615,7 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"grįžti prie skambučio"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Teisingai!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Apgailestaujame, bandykite dar kartą"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Apgailestaujame, bandykite dar kartą"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Įkraunama (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Įkrauta."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM kortelė užrakinta."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Atrakinama SD kortelė..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Neteisingai apibrėžėte atrakinimo modelį <xliff:g id="NUMBER_0">%d</xliff:g> kartus (-ų)."\n\n"Bandykite dar kartą po <xliff:g id="NUMBER_1">%d</xliff:g> sek."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"<xliff:g id="NUMBER_0">%d</xliff:g> k. neteisingai nubrėžėte atrakinimo šabloną. Dar po <xliff:g id="NUMBER_1">%d</xliff:g> nesėkm. band. būsite paprašyti atrakinti planšetinį kompiuterį naudodami „Google“ prisijungimo duomenis."\n\n" Po <xliff:g id="NUMBER_2">%d</xliff:g> sek. bandykite dar kartą."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"<xliff:g id="NUMBER_0">%d</xliff:g> k. netinkamai įvedėte slaptažodį. "\n\n"Po <xliff:g id="NUMBER_1">%d</xliff:g> sek. bandykite dar kartą."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"<xliff:g id="NUMBER_0">%d</xliff:g> k. netinkamai įvedėte PIN kodą. "\n\n"Po <xliff:g id="NUMBER_1">%d</xliff:g> sek. bandykite dar kartą."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"<xliff:g id="NUMBER_0">%d</xliff:g> k. neteisingai nubrėžėte atrakinimo šabloną. Dar po <xliff:g id="NUMBER_1">%d</xliff:g> nesėkmingų (-o) bandymų (-o) būsite paprašyti atrakinti planšetinį kompiuterį naudodami „Google“ prisijungimo duomenis."\n\n" Po <xliff:g id="NUMBER_2">%d</xliff:g> sek. bandykite dar kartą."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Neteisingai nurodėte savo atrakinimo modelį <xliff:g id="NUMBER_0">%d</xliff:g> kartus (-ų). Po dar <xliff:g id="NUMBER_1">%d</xliff:g> nesėkmingų bandymų būsite paprašyti atrakinti telefoną naudojant „Google“ prisijungimo duomenis."\n\n" Bandykite dar kartą po <xliff:g id="NUMBER_2">%d</xliff:g> sek."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Bandyti dar kartą po <xliff:g id="NUMBER">%d</xliff:g> sek."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Pamiršote modelį?"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Išeiti iš šio puslapio?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Pasirinkite „Gerai“, jei norite tęsti, arba pasirinkite Atšaukti“, jei norite likti dabartiniame puslapyje."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Patvirtinti"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Patarimas: bakstelėkite du kartus, kad padidintumėte ar sumažintumėte mastelį."</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"Automatinis užpildymas"</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"Automatinis pildymas"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Aut. pild. sąr."</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"skaityti naršyklės istoriją ir žymes"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Leidžia programai skaityti visus URL, kuriuose apsilankė naršyklė, ir visas naršyklės žymas."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"rašyti naršyklės istoriją ir žymes"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Leidžiama programai keisti naršyklės istoriją ar žymes, išsaugotas planšetiniame kompiuteryje. Kenkėjiškos programos gali tai naudoti, kad ištrintų ar keistų naršyklės duomenis."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Leidžia programai keisti naršyklės istoriją ar žymes, išsaugotus jūsų telefone. Kenkėjiškos programos gali tai naudoti, kad ištrintų ar keistų naršyklės duomenis."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"nustatyti žadintuvo signalą"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Leidžiama programai nustatyti signalą įdiegtoje žadintuvo programoje. Kai kuriose žadintuvo programose šios funkcijos gali nebūti."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Keisti naršyklės geografinės vietovės leidimus"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Leidžia programai keisti geografinių naršyklės vietų leidimus. Kenkėjiškos programos tai gali naudoti siunčiant vietos informaciją atsitiktinėms svetainėms."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ar norite, kad naršyklė atsimintų šį slaptažodį?"</string>
@@ -830,15 +790,12 @@
     <string name="cut" msgid="3092569408438626261">"Iškirpti"</string>
     <string name="copy" msgid="2681946229533511987">"Kopijuoti"</string>
     <string name="paste" msgid="5629880836805036433">"Įklijuoti"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Nėra, ką įklijuoti"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Kopijuoti URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Pasirinkti tekstą..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Teksto pasirinkimas"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Įvesties būdas"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Redaguoti tekstą"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksto veiksmai"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Mažai vietos"</string>
     <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Mažėja planšetinio kompiuterio atmintinės vietos."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Sparčiai mažėja vietos telefono saugykloje."</string>
@@ -847,8 +804,7 @@
     <string name="yes" msgid="5362982303337969312">"Gerai"</string>
     <string name="no" msgid="5141531044935541497">"Atšaukti"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Dėmesio"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Įkeliama..."</string>
     <string name="capital_on" msgid="1544682755514494298">"ĮJUNGTA"</string>
     <string name="capital_off" msgid="6815870386972805832">"IŠJUNGTA"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Užbaigti veiksmą naudojant"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Uždaryti"</string>
     <string name="report" msgid="4060218260984795706">"Ataskaita"</string>
     <string name="wait" msgid="7147118217226317732">"Palaukti"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Programa nukreipta"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ dabar vykdoma."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ buvo iš pradžių paleista."</string>
+    <string name="smv_application" msgid="295583804361236288">"Programa „<xliff:g id="APPLICATION">%1$s</xliff:g>“ (procesas „<xliff:g id="PROCESS">%2$s</xliff:g>“) pažeidė savo vykdomą „StrictMode“ politiką."</string>
+    <string name="smv_process" msgid="5120397012047462446">"„<xliff:g id="PROCESS">%1$s</xliff:g>“ procesas pažeidė savo vykdomą „StrictMode“ politiką."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"Vykdoma „<xliff:g id="APP">%1$s</xliff:g>“"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Pasirinkti perjungti į programą"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Perjungti programas?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Jau vykdoma kita programa, kurią reikia sustabdyti prieš paleidžiant naują."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Grįžti į <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Nepaleisti naujos programos."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Paleisti „<xliff:g id="OLD_APP">%1$s</xliff:g>“"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Sustabdyti seną programą neišsaugant."</string>
     <string name="sendText" msgid="5132506121645618310">"Pasirinkite teksto veiksmą"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Skambučio garsumas"</string>
     <string name="volume_music" msgid="5421651157138628171">"Medijos garsumas"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Rodyti viską"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB nuolatinė saugykla"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB prijungtas"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Naudodami USB, prijungėte savo telefoną prie kompiuterio. Pasirinkite toliau pateiktą mygtuką, jei norite kopijuoti failus iš kompiuterio į „Android“ SD kortelę ir atvirkščiai."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Naudodami USB, prijungėte savo telefoną prie kompiuterio. Pasirinkite toliau pateiktą mygtuką, jei norite kopijuoti failus iš kompiuterio į „Android“ SD kortelę ir atvirkščiai."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Prisijungėte prie kompiuterio per USB. Jei norite kopijuoti failus iš kompiuterio į „Android“ USB atmintinę ir atvirkščiai, palieskite toliau pateiktą mygtuką."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Prisijungėte prie kompiuterio per USB. Jei norite kopijuoti failus iš kompiuterio į „Android“ SD kortelę ir atvirkščiai, palieskite toliau pateiktą mygtuką."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Įjungti USB saugyklą"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Iškilo problema naudojant SD kortelę USB saugojimui."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Iškilo problema naudojant SD kortelę USB saugojimui."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Naudojant USB atmintinę didelės talpos USB atmintinei iškilo problema."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Naudojant SD kortelę didelės talpos USB atmintinei iškilo problema."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB prijungtas"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Pasirinkite į / iš kompiuterio kopijuojamus failus."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Išjungti USB saugyklą"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Pasirinkite, kad išjungtumėte USB saugyklą."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Naudojama USB saugykla"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Prieš išjungiant USB saugyklą, įsitikinkite, kad pašalinote („išstūmėte“) „Android“ SD kortelę iš kompiuterio."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Prieš išjungdami USB atmintinę, įsitikinkite, kad atjungėte („išstūmėte“) „Android“ USB atmintinę iš kompiuterio."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Prieš išjungiant USB saugyklą, įsitikinkite, kad pašalinote („išstūmėte“) „Android“ SD kortelę iš kompiuterio."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Išjungti USB saugyklą"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Išjungiant USB saugyklą iškilo problemų. Įsitikinkite, kad pašalinote USB prieglobą ir bandykite dar kartą."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Jei įjungiate USB saugyklą, kai kurios naudojamos programos sustos ir gali būti negalimos, kol išjungsite USB saugyklą."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB operacija nepavyko"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Gerai"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatuoti SD kortelę"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Format. USB atmint."</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatuoti SD kortelę"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Ar tikrai norite formatuoti SD kortelę? Bus prarasti visi kortelės duomenys."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formatuoti USB atmintinę ištrinant visus joje saugomus failus? Veiksmo nebus galima atšaukti!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Ar tikrai norite formatuoti SD kortelę? Bus prarasti visi kortelės duomenys."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatuoti"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB derinimas prijungtas"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidatai"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Ruošiama SD kortelė"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Ruošiama USB atmintinė"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Ruošiama SD kortelė"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Tikrinama, ar nėra klaidų."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Tuščia SD kortelė"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Tuščia USB atmintinė"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tuščia SD kortelė"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"SD kortelė tuščia arba joje yra nepalaikoma failų sistema."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB atmintinė tuščia arba yra nepalaikoma failų sistema."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD kortelė tuščia arba joje yra nepalaikoma failų sistema."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Pažeista SD kortelė"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Sugadinta USB atmintinė"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Pažeista SD kortelė"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"SD kortelė pažeista. Gali reikėti ją formatuoti iš naujo."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB atmintinė sugadinta. Gali reikėti iš naujo ją suformatuoti."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD kortelė pažeista. Gali reikėti ją formatuoti iš naujo."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"SD kortelė netikėtai pašalinta"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB atmintinė netikėtai pašal."</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD kortelė netikėtai pašalinta"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Išimti SD kortelę prieš pašalinant, kad nebūtų prarasti duomenys."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Kad neprarastumėte duomenų, prieš pašalindami atjunkite USB atmintinę."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Išimti SD kortelę prieš pašalinant, kad nebūtų prarasti duomenys."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Saugu pašalinti SD kortelę"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Galima pašalinti USB atmintinę"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Saugu pašalinti SD kortelę"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Galite saugiai pašalinti SD kortelę."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Galite saugiau pašalinti USB atmintinę."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Galite saugiai pašalinti SD kortelę."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Pašalinta SD kortelė"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Pašalinta USB atmintinė"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Pašalinta SD kortelė"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"SD kortelė pašalinta. Įdėkite naują."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB atmintinė pašalinta. Įdėti naują mediją."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD kortelė pašalinta. Įdėkite naują."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nerasta atitinkančios veiklos"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"atnaujinti komponento naudojimo statistiką"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Siųsti"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Kitas"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Atlikta"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Perž."</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Vykdyti"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Rinkti numerį "\n"naudojant <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Sukurti adresatą"\n"naudojant <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Iš anksto bendrinamas raktas, pagrįstas L2TP/IPSec VPT"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sertifikatas pagrįstas L2TP/IPSec VPT"</string>
     <string name="upload_file" msgid="2897957172366730416">"Pasirinkti failą"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Nepasirinktas joks failas"</string>
     <string name="reset" msgid="2448168080964209908">"Atstatyti"</string>
     <string name="submit" msgid="1602335572089911941">"Pateikti"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Įgalintas automobilio režimas"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Pasirinkite, kad išeitumėte iš automobilio režimo."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Susietas ar aktyvus"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Palieskite, kad galėtumėte konfigūruoti"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Atgal"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Kitas"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Praleisti"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Didelis mobiliųjų duomenų naudojimas"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Palieskite, kad sužinotumėte daugiau apie mobilių duomenų naudojimą"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Viršyta mobilių duomenų riba"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Palieskite, kad sužinotumėte daugiau apie mobilių duomenų naudojimą"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Nėra atitikčių"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Ieškoti puslapyje"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 atitiktis"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> iš <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Atlikta"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Atjungiama USB atmintinė..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Atjungiama SD kortelė..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Ištrinama USB atmintinė..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Ištrinama SD kortelė..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Nepavyko ištrinti USB atmintinės."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Nepavyko ištrinti SD kortelės."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD kortelė buvo pašalinta jos neatjungus."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Šiuo metu USB atmintinė tikrinama."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Šiuo metu SD kortelė tikrinama."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD kortelė pašalinta."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Šiuo metu USB atmintinė naudojama kompiuteryje."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Šiuo metu SD kortelė naudojama kompiuteryje."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Nežinomos būsenos išorinė medija."</string>
+    <string name="share" msgid="1778686618230011964">"Bendrinti"</string>
+    <string name="find" msgid="4808270900322985960">"Ieškoti"</string>
+    <string name="websearch" msgid="4337157977400211589">"Žiniat. paieška"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index dbe7180..7ef1e0a 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Balss pasts"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Savienojuma problēma vai nederīgs MMI kods."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Darbība ir atļauta tikai fiksēto numuru sastādīšanai."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Pakalpojums tika iespējots."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Pakalpojums tika iespējots šādai pakalpojumu klasei:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Pakalpojums ir atspējots."</string>
@@ -126,7 +125,7 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"Sinhronizācija"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinhronizācija"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Pārāk daudz <xliff:g id="CONTENT_TYPE">%s</xliff:g> dzēsto vienumu."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Planšetdatora atmiņa ir pilna. Dzēsiet dažus failus, lai atbrīvotu vietu."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Planšetdatora krātuve ir pilna! Dzēsiet dažus failus, lai atbrīvotu vietu."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"tālruņa krātuve ir pilna! Dzēsiet dažus failus, lai atbrīvotu vietu."</string>
     <string name="me" msgid="6545696007631404292">"Man"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Planšetdatora opcijas"</string>
@@ -137,10 +136,9 @@
     <string name="screen_lock" msgid="799094655496098153">"Bloķēt ekrānu"</string>
     <string name="power_off" msgid="4266614107412865048">"Strāvas padeve ir izslēgta."</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Notiek izslēgšana..."</string>
-    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Planšetdators tiks izslēgts."</string>
+    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Planšetdators tiks beidzēts."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Tālrunis tiks izslēgts."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Vai vēlaties beidzēt?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Nesens"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Nav nesen izmantotu lietojumprogrammu."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Planšetdatora opcijas"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lidojuma režīms"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Lidojuma režīms ir IESLĒGTS."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Lidojuma režīms ir IZSLĒGTS."</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Maksas pakalpojumi"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Izstrādes rīki"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Tikai lietojumprogrammu izstrādātājiem vajadzīgas funkcijas."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Krātuve"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Piekļūstiet SD kartei."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Piekļūst USB krātuvei."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Piekļūstiet SD kartei."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"atspējot vai pārveidot statusa joslu"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Ļauj lietojumprogrammai atspējot statusa joslu vai pievienot un noņemt sistēmas ikonas."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"statusa josla"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Ļauj lietojumprogrammai būt par statusa joslu."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"izvērst/sakļaut statusa joslu"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Ļauj lietojumprogrammai izvērst vai sakļaut statusa joslu."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"pārtvert izejošos zvanus"</string>
@@ -196,7 +194,7 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"sūtīt īsziņas"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Ļauj lietojumprogrammai sūtīt īsziņas. Ļaunprātīgas lietojumprogrammas var radīt jums izmaksas, bez apstiprinājuma sūtot īsziņas."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"lasīt īsziņu vai multiziņu"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Ļauj lietojumprogrammai lasīt planšetdatorā vai SIM kartē saglabātās īsziņas. Ļaunprātīgas lietojumprogrammas var lasīt jūsu konfidenciālos ziņojumus."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Ļauj lietojumprogrammai lasīt īsziņas, kas ir saglabātas planšetdatorā vai SIM kartē. Ļaunprātīgas lietojumprogrammas var lasīt jūsu konfidenciālos ziņojumus."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Ļauj lietojumprogrammai lasīt īsziņas, kas ir saglabātas jūsu tālrunī vai SIM kartē. Ļaunprātīgas lietojumprogrammas var lasīt konfidenciālos ziņojumus."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"rediģēt īsziņu vai multiziņu"</string>
     <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Ļauj lietojumprogrammai rakstīt īsziņās, kas ir saglabātas planšetdatorā vai SIM kartē. Ļaunprātīgas lietojumprogrammas var dzēst jūsu ziņojumus."</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"novērst lietojumprogrammu pārslēgšanu"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Neļauj lietotājam pārslēgties uz citu lietojumprogrammu."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"pārraudzīt un kontrolēt visu lietojumprogrammu palaišanu"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Ļauj lietojumprogrammai pārraudzīt un kontrolēt to, kā sistēma uzsāk darbības. Ļaunprātīgas lietojumprogrammas var pilnībā apdraudēt sistēmu. Šī atļauja ir nepieciešama tikai izstrādei (taču ne parastai ierīces lietošanai)."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Ļauj lietojumprogrammai pārraudzīt un kontrolēt, kā sistēma palaiž darbības. Ļaunprātīgas lietojumprogrammas var pilnībā uzlauzt sistēmu. Šī atļauja ir nepieciešama tikai izstrādei, bet ne parastai lietošanai."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"sūtīt apraidi par pakotnes noņemšanu"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Ļauj lietojumprogrammai raidīt paziņojumu, ka lietojumprogrammas pakotne ir noņemta. Ļaunprātīgas lietojumprogrammas var to izmantot, lai pārtrauktu jebkuras citas aktīvas lietojumprogrammas darbību."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"sūtīt īsziņā saņemtu apraidi"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"attēlot neautorizētus logus"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Ļauj izveidot logus, kas ir paredzēti izmantošanai iekšējās sistēmas lietotāja saskarnē. Nav paredzēts izmantošanai parastajās lietojumprogrammās."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"rādīt sistēmas līmeņa brīdinājumus"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Ļauj lietojumprogrammai rādīt sistēmas brīdinājumu logus. Ļaunprātīgas lietojumprogrammas var pārņemt visu planšetdatora ekrānu."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Ļauj lietojumprogrammai rādīt sistēmas brīdinājuma logus. Ļaunprātīgas lietojumprogrammas var pārņemt vadību pār visu ekrānu."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"pārveidot globālo animācijas ātrumu"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Ļauj lietojumprogrammai jebkurā brīdī mainīt globālo animācijas ātrumu (ātrākas vai lēnākas animācijas)."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"pārvaldīt lietojumprogrammas pilnvaras"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Ļauj lietojumprogrammām izveidot un pārvaldīt savas pilnvaras, apejot parasto Z secību. Nav nepieciešams parastajām lietojumprogrammām."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"nospiest taustiņus un vadības pogas"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Ļauj lietojumprogrammai piegādāt savus ievades notikumus (taustiņu spiedienus u.c.) citām lietojumprogrammām. Ļaunprātīgas lietojumprogrammas var to izmantot, lai pārņemtu vadību pār planšetdatoru."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Ļauj lietojumprogrammai rādīt savas ievades notikumus (nospiestos taustiņus u.tml.) citās lietojumprogrammās. Ļaunprātīgas lietojumprogrammas var to izmantot, lai pārņemtu planšetdatora vadību."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Ļauj lietojumprogrammai piegādāt savus ievades notikumus (taustiņu spiedienus u.c.) citām lietojumprogrammām. Ļaunprātīgas lietojumprogrammas var to izmantot, lai pārņemtu tālruni."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"reģistrēt rakstīto un veiktās darbības"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Ļauj lietojumprogrammām sekot līdzi nospiestajiem taustiņiem, mijiedarbojoties ar citu lietojumprogrammu (piemēram, ievadot paroli). Parastajām lietojumprogrammām nekad nav nepieciešama."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"tieši instalēt lietojumprogrammas"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Ļauj lietojumprogrammai instalēt jaunas vai atjauninātas Android pakotnes. Ļaunprātīgas lietojumprogrammas var to izmantot, lai pievienotu jaunas lietojumprogrammas ar nejauši jaudīgām atļaujām."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"dzēst visus lietojumprogrammas kešatmiņas datus"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Ļauj lietojumprogrammai atbrīvot vietu planšetdatora atmiņā, dzēšot failus lietojumprogrammas kešatmiņas katalogā. Piekļuve parasti ir pieejama tikai sistēmas procesā."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Ļauj lietojumprogrammai atbrīvot vietu planšetdatora krātuvē, dzēšot failus lietojumprogrammas kešatmiņas katalogā. Piekļuve parasti ir atļauta tikai sistēmas procesam."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Ļauj lietojumprogrammai atbrīvot vietu tālruņa krātuvē, dzēšot failus lietojumprogrammas kešatmiņas katalogā. Piekļuve parasti ir pieejama tikai sistēmas procesam."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Pārvietot lietojumprogrammas resursus"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Ļauj lietojumprogrammai pārvietot lietojumprogrammas resursus no iekšējā datu nesēja uz ārējo un otrādi."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"lasīt sistēmas žurnālfailus"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Ļauj lietojumprogrammai lasīt informāciju no dažādiem sistēmas žurnālfailiem. Tādējādi tā var atklāt vispārīgu informāciju par to, kādas darbības tiek veiktas ar planšetdatoru, iespējams, arī personas vai privātu informāciju."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Ļauj lietojumprogrammai lasīt informāciju no dažādiem sistēmas žurnālfailiem. Tādējādi tā var atklāt vispārīgu informāciju par to, kādas darbības tiek veiktas ar planšetdatoru, iespējams, arī personas vai privātu informāciju."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"lasīt sensitīvus žurnāla datus"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Ļauj lietojumprogrammai lasīt no sistēmas dažādiem žurnālfailiem. Šādi lietojumprogramma var atrast vispārīgu informāciju par jūsu darbībām planšetdatorā, tostarp, iespējams, arī personisku vai privātu informāciju."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Ļauj lietojumprogrammai lasīt no sistēmas dažādiem žurnālfailiem. Šādi lietojumprogramma var atrast vispārīgu informāciju par jūsu darbībām tālrunī, tostarp, iespējams, arī personisku vai privātu informāciju."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"lasīt grupas “diag” resursus un rakstīt tajos"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Ļauj lietojumprogrammai lasīt jebkuru resursu, kas pieder grupai “diag”, un rakstīt tajos; piemēram, failus direktorijā /dev. Tas var ietekmēt sistēmas stabilitāti un drošību. Tas ir jāizmanto TIKAI aparatūrai specifiskas diagnostikas veikšanai, ko izpilda ražotājs vai operators."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"iespējot vai atspējot lietojumprogrammas komponentus"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Ļauj lietojumprogrammai mainīt to, vai citas lietojumprogrammas komponents ir iespējots vai ne. Ļaunprātīgas lietojumprogrammas var to izmantot, lai atspējotu svarīgas planšetdatora iespējas. Atļauja ir jāizmanto uzmanīgi, jo pastāv iespēja, ka lietojumprogrammas komponenti būs neizmantojamā, nepastāvīgā vai nestabilā stāvoklī."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Ļauj lietojumprogrammai mainīt to, vai citas lietojumprogrammas komponents ir iespējots vai ne. Ļaunprātīgas lietojumprogrammas var to izmantot, lai atspējotu svarīgas planšetdatora iespējas. Atļauja ir jāizmanto uzmanīgi, jo pastāv iespēja, ka lietojumprogrammas komponenti būs neizmantojamā, nepastāvīgā vai nestabilā stāvoklī."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Ļauj lietojumprogrammai mainīt, vai tiek iespējots citas lietojumprogrammas komponents. Ļaunprātīgas lietojumprogrammas var to izmantot, lai atspējotu svarīgas planšetdatora iespējas. Izmantojiet šo atļauju uzmanīgi, jo pastāv iespēja, ka lietojumprogrammas komponentu stāvoklis kļūs neizmantojams, nekonsekvents vai nestabils."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Ļauj lietojumprogrammai mainīt to, vai tiek iespējots citas lietojumprogrammas komponents. Ļaunprātīgas lietojumprogrammas var to izmantot, lai atspējotu svarīgas tālruņa iespējas. Izmantojiet šo atļauju uzmanīgi, jo pastāv iespēja, ka lietojumprogrammas komponentu stāvoklis kļūs neizmantojams, nekonsekvents vai nestabils."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"iestatīt vēlamās lietojumprogrammas"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Ļauj lietojumprogrammai pārveidot vēlamās lietojumprogrammas. Šādi ļaunprātīgajām lietojumprogrammā var tikt atļauts nemanāmi mainīt darbinātās lietojumprogrammas, izmānot datus no esošajām lietojumprogrammām, lai apkopotu jūsu privātos datus."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"pārveidot globālos sistēmas iestatījumus"</string>
@@ -298,19 +296,19 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"pārveidot Google pakalpojumu karti"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"Ļauj lietojumprogrammai pārveidot Google pakalpojumu karti. Nav paredzēts izmantošanai parastajās lietojumprogrammās."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"automātiski sākt pēc palaišanas"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Ļauj startēt lietojumprogrammu, tiklīdz sistēma ir pabeigusi palaišanu. Tādējādi planšetdatora startēšanai var būt nepieciešams vairāk laika un lietojumprogrammai var tikt atļauts palēnināt vispārējo planšetdatora darbību."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Ļauj lietojumprogrammai startēt sevi, tiklīdz sistēma ir pabeigusi sāknēšanu. Šādi planšetdatoram var būt nepieciešams ilgāks startēšanas laiks, un var tikt atļauts lietojumprogrammai palēnināt vispārējo planšetdatora darbību, vienmēr darbojoties."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Ļauj startēt lietojumprogrammu, sevi tiklīdz sistēma ir pabeigusi palaišanu. Šādi tālruņa startēšana var būt ilgāka un lietojumprogrammai var tikt atļauts palēnināt vispārējo tālruņa darbību, vienmēr darbojoties."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"sūtīt piesaistošu apraidi"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ļauj lietojumprogrammai sūtīt piesaistošās apraides, kas saglabājas pēc apraides pabeigšanas. Ļaunprātīgas lietojumprogrammas var palēnināt planšetdatora darbību vai padarīt to nestabilu, tādējādi liekot izmantot pārāk daudz atmiņas."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Ļauj lietojumprogrammai sūtīt piesaistošas apraides, kas saglabājas pēc apraides beigām. Ļaunprātīgas lietojumprogrammas var palēnināt planšetdatora darbību vai padarīt tā darbību nestabilu, liekot izmantot pārāk daudz atmiņas."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Ļauj lietojumprogrammai sūtīt piesaistošās apraides, kas saglabājas pēc apraides pabeigšanas. Ļaunprātīgas lietojumprogrammas var palēnināt tālruņa darbību vai padarīt to nestabilu, tādējādi liekot izmantot pārāk daudz atmiņas."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"lasīt kontaktpersonu datus"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Ļauj lietojumprogrammai lasīt visus planšetdatorā saglabāto kontaktpersonu (adrešu) datus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai sūtītu jūsu datus citām personām."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Ļauj lietojumprogrammai lasīt visu planšetdatorā saglabāto kontaktpersonu (adrešu) datus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai sūtītu jūsu datus citām personām."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Ļauj lietojumprogrammai lasīt visus jūsu tālrunī saglabāto kontaktpersonu (adrešu) datus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai sūtītu jūsu datus citām personām."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"rakstīt kontaktpersonu datus"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Ļauj lietojumprogrammai pārveidot planšetdatorā saglabātos kontaktpersonu (adrešu) datus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai dzēstu vai pārveidotu jūsu kontaktpersonu datus."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Ļauj lietojumprogrammai pārveidot tālrunī saglabātos kontaktpersonu (adrešu) datus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai dzēstu vai pārveidotu jūsu kontaktpersonu datus."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"lasīt kalendāra pasākumus"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ļauj lietojumprogrammai lasīt visus planšetdatorā saglabātos kalendāra notikumus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai sūtītu kalendāra notikumus citām personām."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Ļauj lietojumprogrammai lasīt visus planšetdatorā saglabātos kalendāra notikumus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai sūtītu jūsu kalendāra notikumus citām personām."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Ļauj lietojumprogrammai lasīt visus tālrunī saglabātos kalendāra pasākumus. Ļaunprātīgas lietojumprogrammas var to izmantot, lai sūtītu kalendāra pasākumus citām personām."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"pievienot vai pārveidot kalendāra pasākumus un sūtīt e-pasta ziņojumus viesiem"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Ļauj lietojumprogrammai pievienot vai mainīt pasākumus jūsu kalendārā, kas var sūtīt e-pasta ziņojumus viesiem. Ļaunprātīgas lietojumprogrammas var to izmantot, lai dzēstu vai pārveidotu jūsu kalendāra pasākumus vai sūtītu e-pasta ziņojumus viesiem."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"atļauja instalēt atrašanās vietas sniedzēju"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Izveidojiet imitētas atrašanās vietas avotus pārbaudīšanai. Ļaunprātīgas lietojumprogrammas var to izmantot, lai ignorētu atrašanās vietu un/vai statusu, ko atgriež reālās atrašanās vietas avoti, piemēram, GPS vai tīkla nodrošinātāji, vai pārraudzītu un ziņotu par jūsu atrašanās vietu ārējam avotam."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"noteikt precīzu (GPS) atrašanās vietu"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Piekļūt precīziem atrašanās vietas avotiem, piemēram, globālās pozicionēšanas sistēmai planšetdatorā (ja pieejams). Ļaunprātīgas lietojumprogrammas var to izmantot, lai noteiktu jūsu atrašanās vietu, un var patērēt papildu akumulatora jaudu."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Piekļūst labas kvalitātes atrašanās vietas avotiem, piemēram, globālās pozicionēšanas sistēmai planšetdatorā, ja tā ir pieejama. Ļaunprātīgas lietojumprogrammas var to izmantot, lai noteiktu jūsu atrašanās vietu, un patērēt papildu akumulatora jaudu."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Piekļūstiet precīziem atrašanās vietas avotiem, piemēram, globālās pozicionēšanas sistēmai tālrunī (ja pieejams). Ļaunprātīgas lietojumprogrammas var to izmantot, lai noteiktu, kur jūs atrodaties, un var patērēt papildu akumulatora jaudu."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"noteikt aptuvenu (uz tīklu balstītu) atrašanās vietu"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Piekļūt tādiem zemas kvalitātes atrašanās vietas avotiem kā mobilā tīkla datu bāze, lai noteiktu aptuvenu planšetdatora atrašanās vietu (ja pieejams). Ļaunprātīgas lietojumprogrammas var to izmantot, lai noteiktu jūsu aptuveno atrašanās vietu."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Piekļūst zemas kvalitātes atrašanās vietas avotiem, piemēram, šūnu tīkla datu bāzei, lai noteiktu aptuvenu planšetdatora atrašanās vietu, ja tā ir pieejama. Ļaunprātīgas lietojumprogrammas var to izmantot, lai noteiktu aptuvenu jūsu atrašanās vietu."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Piekļūstiet tādiem zemas kvalitātes atrašanās vietas avotiem kā mobilā tīkla datu bāzei, lai noteiktu aptuvenu tālruņa atrašanās vietu (ja pieejams). Ļaunprātīgas lietojumprogrammas var to izmantot, lai noteiktu jūsu aptuveno atrašanās vietu."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"piekļūt SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Ļauj lietojumprogrammai izmantot SurfaceFlinger zemā līmeņa funkcijas."</string>
@@ -334,37 +332,39 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Ļauj lietojumprogrammai pārveidot globālos audio iestatījumus, piemēram, skaļumu un maršrutēšanu."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ierakstīt audio"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Ļauj lietojumprogrammai piekļūt audio ieraksta ceļam."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"uzņemt attēlus"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Ļauj lietojumprogrammai uzņemt attēlus ar kameru. Šādi lietojumprogramma jebkurā brīdī var apkopot attēlus, kas ir redzami ar kameru."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"neatgriezeniska planšetdatora atspējošana"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"uzņemt attēlus un videoklipus"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Ļauj lietojumprogrammai uzņemt attēlus un videoklipus ar kameru. Šādi lietojumprogramma jebkurā laikā var apkopot ar kameru redzamos attēlus."</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"neatgriezeniski atspējot planšetdatoru"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"neatgriezeniski atspējot tālruni"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Ļauj lietojumprogrammai neatgriezeniski atspējot visu planšetdatoru. Šāda darbība ir bīstama."</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Ļauj lietojumprogrammai neatgriezeniski atspējot visu planšetdatoru. Tas ir ļoti bīstami."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Ļauj lietojumprogrammai neatgriezeniski atspējot visu tālruni. Tas ir ļoti bīstami."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"planšetdatora piespiedu atsāknēšana"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"forsēt planšetdatora atsāknēšanu"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"atsāknēt tālruni"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Ļauj lietojumprogrammai atsāknēt planšetdatoru."</string>
+    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Ļauj lietojumprogrammai forsēt planšetdatora atsāknēšanu."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Ļauj lietojumprogrammai atsāknēt tālruni."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"uzlikt un noņemt failu sistēmas"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Ļauj lietojumprogrammai noņemt vai uzlikt noņemamu krātuvju failu sistēmas."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formatēt ārējo krātuvi"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Ļauj lietojumprogrammai formatēt noņemamo krātuvi."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"iegūt informāciju par drošo krātuvi"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Ļauj lietojumprogrammai iegūt informāciju par drošu krātuvi."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"izveidot drošu krātuvi"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Ļauj lietojumprogrammai izveidot drošu krātuvi."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"likvidēt drošo krātuvi"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Ļauj lietojumprogrammai likvidēt drošo krātuvi."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"uzlikt/noņemt drošo krātuvi"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Ļauj lietojumprogrammai uzlikt/noņemt drošu krātuvi."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"pārdēvēt drošo krātuvi"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Ļauj lietojumprogrammai pārdēvēt drošo krātuvi."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"iegūt informāciju par iekšējo krātuvi"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Ļauj lietojumprogrammai iegūt informāciju par iekšējo krātuvi."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"izveidot iekšēju krātuvi"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Ļauj lietojumprogrammai izveidot iekšējo krātuvi."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"likvidēt iekšējo krātuvi"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Ļauj lietojumprogrammai iznīcināt iekšējo krātuvi."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"uzstādīt/atvienot iekšējo krātuvi"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Ļauj lietojumprogrammai uzstādīt/atvienot iekšējo krātuvi."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"pārdēvēt iekšējo krātuvi"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Ļauj lietojumprogrammai pārdēvēt iekšējo krātuvi."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"kontrolēt vibrozvanu"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Ļauj lietojumprogrammai kontrolēt vibrozvanu."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"kontrolēt uzliesmojumu"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Ļauj lietojumprogrammai kontrolēt uzliesmojumu."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"piekļuve USB ierīcēm"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Ļauj lietojumprogrammai piekļūt USB ierīcēm."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"pārbaudīt aparatūru"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Ļauj lietojumprogrammai kontrolēt dažādas perifērijas ierīces aparatūras pārbaudīšanas nolūkos."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"Ļauj lietojumprogrammai zvanīt uz tālruņa numuriem bez jūsu iejaukšanās. Ļaunprātīgas lietojumprogrammas var radīt neparedzētu zvanu parādīšanos jūsu tālruņa rēķinā. Ņemiet vērā, ka lietojumprogramma nevar zvanīt uz ārkārtas numuriem."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"tieši zvanīt uz jebkuriem tālruņa numuriem"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Ļauj lietojumprogrammai zvanīt uz jebkuru tālruņa numuru, tostarp ārkārtas numuriem, bez jūsu iejaukšanās. Ļaunprātīgas lietojumprogrammas var veikt nevajadzīgus un pretlikumīgus zvanus uz ārkārtas pakalpojumiem."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"tiešā veidā sākt CDMA planšetdatora iestatīšanu"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"tieši sākt CDMA planšetdatora iestatīšanu"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"tiešā veidā sākt CDMA tālruņa iestatīšanu"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Ļauj lietojumprogrammai sākt CDMA nodrošināšanu. Ļaunprātīgas lietojumprogrammas var nevajadzīgi sākt CDMA nodrošināšanu."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"kontrolēt atrašanās vietas atjauninājumu paziņojumus"</string>
@@ -385,16 +385,16 @@
     <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Ļauj lietojumprogrammai kontrolēt ierīces tālruņa funkcijas. Lietojumprogramma ar šo atļauju var pārslēgt tīklus, ieslēgt un izslēgt tālruņa radio un veikt līdzīgas darbības, neinformējot par to jūs."</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"lasīt tālruņa stāvokli un identitāti"</string>
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"Ļauj lietojumprogrammai piekļūt ierīces tālruņa funkcijām. Lietojumprogramma ar šo atļauju var noteikt tālruņa numuru un šī tālruņa sērijas numuru, to, vai zvans ir aktīvs, numuru, ar kuru zvans ir savienots u.tml."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"planšetdatora pāriešanas miega režīmā novēršana"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"novērst planšetdatora pāriešanu miega režīmā"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"novērst tālruņa pāriešanu miega režīmā"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Ļauj lietojumprogrammai novērst planšetdatora pāriešanu miega režīmā."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Ļauj lietojumprogrammai novērst tālruņa pāriešanu miega režīmā."</string>
-    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"planšetdatora ieslēgšana vai izslēgšana"</string>
+    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"ieslēgt vai izslēgt planšetdatoru"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"ieslēgt vai izslēgt tālruni"</string>
     <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Ļauj lietojumprogrammai ieslēgt vai izslēgt planšetdatoru."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Ļauj lietojumprogrammai ieslēgt vai izslēgt tālruni."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"darbināt rūpnīcas pārbaudes režīmā"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Tiek palaista kā zema līmeņa ražotāja pārbaude, atļaujot pilnīgu piekļuvi tālruņa aparatūrai. Pieejama tikai tad, ja planšetdators darbojas ražotāja pārbaudes režīmā."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Darbina kā zema līmeņa ražotāja testu, atļaujot pilnīgu piekļuvi planšetdatora aparatūrai. Pieejama tikai tad, ja planšetdators darbojas ražotāja testa režīmā."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Darbiniet kā zema līmeņa ražotāja pārbaudi, atļaujot pilnīgu piekļuvi tālruņa aparatūrai. Pieejams tikai tad, ja tālrunis darbojas ražotāja pārbaudes režīmā."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"iestatīt tapeti"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Ļauj lietojumprogrammai iestatīt sistēmas tapeti."</string>
@@ -411,7 +411,7 @@
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"darboties kā AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Ļauj lietojumprogrammai veikt zvanus uz AccountAuthenticators"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"atklāt zināmus kontus"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Ļauj lietojumprogrammai iegūt ar planšetdatoru saistīto kontu sarakstu."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Ļauj lietojumprogrammai iegūt planšetdatoram zināmo kontu sarakstu."</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Ļauj lietojumprogrammai iegūt tālrunim zināmo kontu sarakstu."</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"darboties kā konta autentificētājam"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Ļauj lietojumprogrammai izmantot AccountManager konta autentificētāja iespējas, tostarp kontu izveidi un to paroļu iegūšanu un iestatīšanu."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"atļaut Wi-Fi multiraides uztveršanu"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Ļauj lietojumprogrammai saņemt paketes, kas nav tieši adresētas ierīcei. Tas var būt noderīgi, atklājot pakalpojumus, kas tiek piedāvāti tuvākajā apkārtnē. Tas izmanto vairāk jaudas nekā režīmā, kas nav multiraides režīms."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"Bluetooth administrēšana"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Ļauj lietojumprogrammai konfigurēt vietējo Bluetooth planšetdatoru, kā arī atklāt attālās ierīces un savienot tās pārī."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Ļauj lietojumprogrammai konfigurēt vietējo Bluetooth planšetdatoru, kā arī atklāt attālas ierīces un savienot tās pārī."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Ļauj lietojumprogrammai konfigurēt vietējo Bluetooth tālruni un atklāt attālās ierīces, un izveidot pāri ar tām."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"izveidot Bluetooth savienojumus"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Ļauj lietojumprogrammai skatīt vietējā Bluetooth planšetdatora konfigurāciju, kā arī veidot un pieņemt savienojumus ar pārī savienotām ierīcēm."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Ļauj lietojumprogrammai skatīt vietējā Bluetooth planšetdatora konfigurāciju un veidot savienojumus ar pārī savienotām ierīcēm."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Ļauj lietojumprogrammai skatīt vietējā Bluetooth tālruņa konfigurāciju, kā arī veidot un pieņemt savienojumus ar pārī savienotām ierīcēm."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"kontrolē tuvlauka saziņu"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Ļauj lietojumprogrammai sazināties ar tuvlauka saziņas (Near Field Communication — NFC) atzīmēm, kartēm un lasītājiem."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"atspējot atslēgas slēgu"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Ļauj lietojumprogrammai atspējot atslēgas slēgu un jebkādu saistīto paroles drošību. Atbilstošs tā piemērs: tālrunis atspējo atslēgas slēgu, saņemot ienākošu tālruņa zvanu, pēc tam atkārtoti iespējo atslēgas slēgu, kad saruna ir pabeigta."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lasīt sinhronizācijas iestatījumus"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Ļauj lietojumprogrammai lasīt jebkādus privātos vārdus, nosaukumus un frāzes, ko lietotājs, iespējams, ir saglabājis lietotāja vārdnīcā."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"rakstīt lietotāja definētajā vārdnīcā"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Ļauj lietojumprogrammai rakstīt jaunus vārdus lietotāja vārdnīcā."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"pārveidot/dzēst SD kartes saturu"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"pārveidot/dzēst USB kr. sat."</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"pārveidot/dzēst SD kartes saturu"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ļauj lietojumprogrammai rakstīt SD kartē."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ļauj lietoj. rakstīt USB kr."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Ļauj lietojumprogrammai rakstīt SD kartē."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"pārveidot/dzēst datu nesēja iekšējās krātuves saturu"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Ļauj lietojumprogrammai pārveidot iekšējas datu nesēja krātuves saturu."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"piekļūt kešatmiņas failu sistēmai"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Ļauj lietojumprogrammai lasīt kešatmiņas failu sistēmu un rakstīt tajā."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles ierobežošana"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Ierobežojiet izmantojamo paroļu veidus."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Pieteikšanās mēģinājumu vērošana"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Tiek pārraudzīts nepareizi ievadīto paroļu skaits, atbloķējot ekrānu, un tiek bloķēts planšetdators vai dzēsti visi planšetdatora dati, ja tiek ievadīts pārāk daudz nepareizu paroļu."</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Tiek pārraudzīts nepareizi ievadīto paroļu skaits, atbloķējot ekrānu, un tiek bloķēts planšetdators vai dzēsti visi planšetdatora dati, ja tiek ievadīts pārāk daudz nepareizu paroļu."</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Atiestatīt paroli"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Piespiedu kārtā mainīt paroli uz jaunu vērtību, pieprasot administratoram to jums piešķirt, lai varētu pieteikties."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Piespiedu bloķēšana"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontrolējiet, kad ierīce tiek bloķēta, pieprasot atkārtoti ievadīt tās paroli."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"veikt/saņemt interneta zvanus"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Ļauj lietojumprogrammai izmantot SIP pakalpojumu, vai veiktu/saņemtu interneta zvanus."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles kārtulu iestatīšana"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrolē ekrāna atbloķēšanas parolē atļautās rakstzīmes un garumu"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Pārrauga nepareizi ievadīto paroļu skaitu, atbloķējot ekrānu, un bloķē planšetdatoru vai dzēš visus planšetdatora datus, ja tiek ievadīts pārāk daudz nepareizu paroļu"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Pārrauga nepareizi ievadīto paroļu skaitu, atbloķējot ekrānu, un bloķē tālruni vai dzēš visus tālruņa datus, ja tiek ievadīts pārāk daudz nepareizu paroļu"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Ekrāna atbloķēšanas paroles maiņa"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Ekrāna atbloķēšanas paroles maiņa"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Ekrāna bloķēšana"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontrolē, kā un kur ekrāns tiek bloķēts"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Dzēst visus datus"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Atiestatot rūpnīcas datus, bez brīdinājuma tiek dzēsti visi planšetdatora dati"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Atiestatot rūpnīcas datus, bez brīdinājuma tiek dzēsti visi planšetdatora dati"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Dzēš planšetdatora datus bez brīdinājuma, veicot rūpnīcas datu atiestatīšanu"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Dzēš tālruņa datus bez brīdinājuma, veicot rūpnīcas datu atiestatīšanu"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Iestatīt ierīces globālo starpniekserveri"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Iestatiet izmantojamo ierīces globālo starpniekserveri, kad ir iespējota politika. Spēkā esošo globālo starpniekserveri iestata tikai pirmās ierīces administrators."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Paroles termiņa izb. iest."</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Kontrolē ekrāna bloķēšanas paroles maiņas intervālu"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Mājas"</item>
     <item msgid="869923650527136615">"Mobilais"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Peidžera numurs darbā"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Palīgs"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"Multiziņa"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Pielāgoti"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Dzimšanas diena"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Jubileja"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Pasākums"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Citi"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Pielāgots"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Mājas"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Darbā"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Darbā"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Cits"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Pielāgots"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Pielāgotas"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Palīgs"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Brālis"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Bērns"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Vietējais partneris"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Tēvs"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Draugs"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Pārvaldnieks"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Māte"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Vecāki"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Partneris"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Norādīja:"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Radinieks"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Māsa"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Laul. draugs/draudz."</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Pielāgotas"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Mājās"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Darbs"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Cits"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Ievadiet PIN kodu"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Lai atbloķētu, ievadiet paroli."</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Lai atbloķētu, ievadiet PIN"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"PIN kods nav pareizs."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Lai atbloķētu, nospiediet Izvēlne, pēc tam 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Ārkārtas numurs"</string>
@@ -646,8 +615,7 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Atpakaļ pie zvana"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Pareizi!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Neizdevās. Mēģiniet vēlreiz."</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Mēģiniet vēlreiz"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Notiek uzlāde (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Uzlādēts."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM karte ir bloķēta."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Notiek SIM kartes atbloķēšana..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Atbloķēšanas kombinācija tika nepareizi uzzīmēta <xliff:g id="NUMBER_0">%d</xliff:g> reizes. "\n\n"Lūdzu, mēģiniet vēlreiz pēc <xliff:g id="NUMBER_1">%d</xliff:g> sekundes(-ēm)."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Atbloķēšanas kombinācija tika nepareizi izveidota <xliff:g id="NUMBER_0">%d</xliff:g> reizi(-es). Pēc vēl <xliff:g id="NUMBER_1">%d</xliff:g> neveiksmīgiem mēģinājumiem planšetdators būs jāatbloķē, pierakstoties Google kontā."\n\n"Lūdzu, mēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%d</xliff:g> sekundes(-ēm)."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Parole tika nepareizi ievadīta <xliff:g id="NUMBER_0">%d</xliff:g> reizes. "\n\n"Lūdzu, mēģiniet vēlreiz pēc <xliff:g id="NUMBER_1">%d</xliff:g> sekundēm."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"PIN tika nepareizi ievadīts <xliff:g id="NUMBER_0">%d</xliff:g> reizes. "\n\n"Lūdzu, mēģiniet vēlreiz pēc <xliff:g id="NUMBER_1">%d</xliff:g> sekundēm."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Atbloķēšanas shēma tika nepareizi uzzīmēta <xliff:g id="NUMBER_0">%d</xliff:g> reizes. Vēl pēc <xliff:g id="NUMBER_1">%d</xliff:g> neveiksmīgiem mēģinājumiem tiks pieprasīts, lai atbloķējat planšetdatoru, izmantojot Google pierakstīšanos."\n\n" Lūdzu, mēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%d</xliff:g> sekundēm."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Atbloķēšanas kombinācija tika nepareizi uzzīmēta <xliff:g id="NUMBER_0">%d</xliff:g> reizi(-es). Pēc vēl <xliff:g id="NUMBER_1">%d</xliff:g> neveiksmīgiem mēģinājumiem tālrunis būs jāatbloķē, izmantojot Google pierakstīšanos."\n\n" Lūdzu, mēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%d</xliff:g> sekundes(-ēm)."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Mēģiniet vēlreiz pēc <xliff:g id="NUMBER">%d</xliff:g> sekundes(-ēm)."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Vai aizmirsāt kombināciju?"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Vai doties prom no šīs lapas?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Atlasiet Labi, lai turpinātu, vai Atcelt, lai paliktu pašreizējā lapā."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Apstiprināt"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Padoms: divreiz pieskarieties, lai tuvinātu un tālinātu."</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"Aut. aizp."</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"Aizpildīt automātiski"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Iest. aut. aizp."</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"lasīt pārlūkprogrammas vēsturi un grāmatzīmes"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Ļauj lietojumprogrammai lasīt visus URL, kas ir apmeklēti pārlūkprogrammā, un visas pārlūkprogrammas grāmatzīmes."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"rakstīt pārlūkprogrammas vēsturi un grāmatzīmes"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Ļauj lietojumprogrammai pārveidot planšetdatorā saglabāto pārlūkprogrammas vēsturi un grāmatzīmes. Ļaunprātīgas lietojumprogrammas var to izmantot, lai dzēstu vai pārveidotu pārlūkprogrammas datus."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Ļauj lietojumprogrammai pārveidot planšetdatorā saglabāto pārlūkprogrammas vēsturi vai grāmatzīmes. Ļaunprātīgas lietojumprogrammas var to izmantot, lai dzēstu vai pārveidotu jūsu pārlūkprogrammas datus."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Ļauj lietojumprogrammai pārveidot tālrunī saglabāto pārlūkprogrammas vēsturi un grāmatzīmes. Ļaunprātīgas lietojumprogrammas var to izmantot, lai dzēstu vai pārveidotu pārlūkprogrammas datus."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"iestatīt trauksmi modinātājpulkstenī"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Ļauj lietojumprogrammai iestatīt trauksmi instalētajā modinātājpulksteņa lietojumprogrammā. Dažās modinātājpulksteņu lietojumprogrammās šī funkcija var nebūt īstenojama."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Pārveidot pārlūkprogrammas ģeogrāfiskās atrašanās vietas atļaujas"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Ļauj lietojumprogrammai pārveidot pārlūkprogrammas ģeogrāfiskās atrašanās vietas atļaujas. Ļaunprātīgas lietojumprogrammas var to izmantot, lai atļautu atrašanās vietas informācijas sūtīšanu uz citām vietnēm."</string>
     <string name="save_password_message" msgid="767344687139195790">"Vai vēlaties, lai pārlūkprogrammā tiktu saglabāta šī parole?"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"Izgriezt"</string>
     <string name="copy" msgid="2681946229533511987">"Kopēt"</string>
     <string name="paste" msgid="5629880836805036433">"Ielīmēt"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Nav ielīmējamu vien."</string>
     <string name="copyUrl" msgid="2538211579596067402">"Kopēt URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Atlasīt tekstu..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Teksta atlase"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Ievades metode"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Rediģēt tekstu"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Teksta darbības"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Maz brīvas vietas"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Planšetdatora atmiņa ir gandrīz pilna."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Planšetdatora krātuve ir gandrīz pilna."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Tālruņa krātuvē kļūst maz vietas."</string>
     <string name="ok" msgid="5970060430562524910">"Labi"</string>
     <string name="cancel" msgid="6442560571259935130">"Atcelt"</string>
     <string name="yes" msgid="5362982303337969312">"Labi"</string>
     <string name="no" msgid="5141531044935541497">"Atcelt"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Uzmanību!"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Notiek ielāde..."</string>
     <string name="capital_on" msgid="1544682755514494298">"IESLĒGT"</string>
     <string name="capital_off" msgid="6815870386972805832">"IZSLĒGT"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Pabeigt darbību, izmantojot"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"aizvērt"</string>
     <string name="report" msgid="4060218260984795706">"Pārskats"</string>
     <string name="wait" msgid="7147118217226317732">"Gaidīt"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Lietojumpr. ir novirzīta"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> tagad darbojas."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Sākotnēji tika palaista lietojumprogramma <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="smv_application" msgid="295583804361236288">"Lietojumprogramma <xliff:g id="APPLICATION">%1$s</xliff:g> (process <xliff:g id="PROCESS">%2$s</xliff:g>) ir pārkāpusi savu pašieviesto StrictMode politiku."</string>
+    <string name="smv_process" msgid="5120397012047462446">"Process <xliff:g id="PROCESS">%1$s</xliff:g> ir pārkāpis savu pašieviesto StrictMode politiku."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> darbojas"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Atlasiet, lai pārietu uz lietojumprogrammu"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Vai pārslēgt lietojumprogrammas?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Jau darbojas cita lietojumprogramma. Tās darbība ir jāaptur, lai varētu startēt citu lietojumprogrammu."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Atgriezties: <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Nestartējiet jauno lietojumprogrammu."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Startēt: <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Aptur veco lietojumprogrammu, nesaglabājot."</string>
     <string name="sendText" msgid="5132506121645618310">"Atlasiet darbību tekstam"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Zvanītāja skaļums"</string>
     <string name="volume_music" msgid="5421651157138628171">"Multivides skaļums"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Rādīt visu"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB lielapjoma krātuve"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB ir pievienots."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Tālrunis ir pievienots datoram, izmantojot USB. Atlasiet tālāk norādīto pogu, ja vēlaties kopēt failus no datora uz Android SD karti vai otrādi."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Tālrunis ir pievienots datoram, izmantojot USB. Atlasiet tālāk norādīto pogu, ja vēlaties kopēt failus no datora uz Android SD karti vai otrādi."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Ir izveidots savienojums ar datoru, izmantojot USB. Pieskarieties tālāk esošajai pogai, ja vēlaties kopēt failus no datora Android USB atmiņā vai otrādi."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Ir izveidots savienojums ar datoru, izmantojot USB. Pieskarieties tālāk esošajai pogai, ja vēlaties kopēt failus no datora Android SD kartē vai otrādi."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Ieslēgt USB krātuvi"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Izmantojot SD karti kā USB krātuvi, rodas problēma."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Izmantojot SD karti kā USB krātuvi, rodas problēma."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Radās problēma, izmantojot USB krātuvi lielapjoma uzglabāšanai USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Radās problēma, izmantojot SD karti lielapjoma uzglabāšanai USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB ir pievienots."</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Atlasiet, lai kopētu failus datorā/no datora."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB krātuves izslēgšana"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Atlasiet, lai izslēgtu USB krātuvi."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB krātuve tiek izmantota"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Pirms USB krātuves izslēgšanas pārliecinieties, ka datorā ir noņemta (“izstumta”) Android SD karte."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Pirms USB krātuves izslēgšanas atvienojiet Android USB krātuvi no datora (tai jābūt “izstumtai”)."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Pirms USB krātuves izslēgšanas pārliecinieties, ka datorā ir noņemta (“izstumta”) Android SD karte."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Izslēgt USB krātuvi"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Izslēdzot USB krātuvi, radās problēma. Pārliecinieties, ka USB saimniekdators ir noņemts, pēc tam mēģiniet vēlreiz."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ja ieslēgsiet USB krātuvi, dažu joprojām lietoto lietojumprogrammu darbība tiks apturēta un tās, iespējams, nebūs pieejamas līdz brīdim, kad USB krātuve tiks izslēgta."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"USB darbība neizdevās."</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Labi"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"SD kartes formatēšana"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"USB kr. formatēšana"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"SD kartes formatēšana"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vai tiešām vēlaties formatēt SD karti? Visi kartē esošie dati tiks zaudēti."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Vai formatēt USB krātuvi, dzēšot visus tajā saglabātos failus? Šo darbību nevar atcelt."</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Vai tiešām vēlaties formatēt SD karti? Visi kartē esošie dati tiks zaudēti."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatēt"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB atkļūdošana ir pievienota."</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidāti"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"SD kartes sagatavošana"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Notiek USB kr. sagatavošana"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"SD kartes sagatavošana"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Notiek kļūdu meklēšana."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Tukša SD karte"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Tukša USB krātuve"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Tukša SD karte"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"SD karte ir tukša vai arī tajā ir neatbalstīta failu sistēma."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB krātuve ir tukša vai arī tajā ir neatbalstīta failu sistēma."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD karte ir tukša vai arī tajā ir neatbalstīta failu sistēma."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Bojāta SD karte"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Bojāta USB krātuve"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Bojāta SD karte"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"SD karte ir bojāta. Iespējams, tā būs atkārtoti jāformatē."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB krātuve ir bojāta. Iespējams, tā būs atkārtoti jāformatē."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD karte ir bojāta. Iespējams, tā būs atkārtoti jāformatē."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"SD karte tika negaidīti izņemta."</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB kr. tika negaidīti noņemta"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD karte tika negaidīti izņemta."</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Demontēt SD karti pirms tās izņemšanas, lai netiktu zaudēti dati."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Pirms noņemšanas atvienojiet USB krātuvi, lai nezaudētu datus."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Demontēt SD karti pirms tās izņemšanas, lai netiktu zaudēti dati."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"SD karti var droši noņemt."</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"USB krātuvi var droši noņemt"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD karti var droši noņemt."</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Varat droši noņemt SD karti."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Varat droši noņemt USB krātuvi."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Varat droši noņemt SD karti."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Izņemta SD karte"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Noņemta USB krātuve"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Izņemta SD karte"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"SD karte ir izņemta. Ievietojiet citu karti."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB krātuve ir noņemta. Ievietojiet jaunu datu nesēju."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD karte ir izņemta. Ievietojiet citu karti."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nav atrasta neviena atbilstoša darbība"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"atjaunināt komponenta lietojuma statistiku"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Sūtīt"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Tālāk"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Gatavs"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Iepr."</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Izpildīt"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Sastādiet numuru,"\n"izmantojot <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Izveidot kontaktpersonu,"\n"izmantojot šo numuru: <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Uz iepriekš koplietotas atslēgas balstīts L2TP/IPSec VPN"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Uz sertifikātu balstīts L2TP/IPSec VPN"</string>
     <string name="upload_file" msgid="2897957172366730416">"Izvēlēties failu"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Neviens fails nav izvēlēts"</string>
     <string name="reset" msgid="2448168080964209908">"Atiestatīt"</string>
     <string name="submit" msgid="1602335572089911941">"Iesniegt"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Automobiļa režīms ir iespējots."</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Atlasiet, lai izietu no automobiļa režīma."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Piesaiste vai tīklājs ir aktīvs."</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Pieskarieties, lai konfigurētu"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Atpakaļ"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Tālāk"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Izlaist"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Augsts mobilo datu lietojums"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Pieskarieties, lai uzzinātu vairāk par mobilo datu izmantošanu."</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Ir pārsniegts mobilo datu ierobežojums."</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Pieskarieties, lai uzzinātu vairāk par mobilo datu izmantošanu."</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Nav atbilstību"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Atrast lapā"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 atbilstība"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> no <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Gatavs"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Notiek USB krātuves atvienošana..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Notiek SD kartes atvienošana..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Notiek USB krātuves dzēšana..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Notiek SD kartes dzēšana..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Neizdevās dzēst USB krātuvi."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Neizdevās dzēst SD karti."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD karte pirms atvienošanas tika noņemta."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"USB atmiņa pašlaik tiek pārbaudīta."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"SD karte pašlaik tiek pārbaudīta."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD karte ir noņemta."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"USB krātuve pašlaik tiek izmantota datorā."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"SD karte pašlaik tiek izmantota datorā."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Ārējais datu nesējs ir nezināmā stāvoklī."</string>
+    <string name="share" msgid="1778686618230011964">"Kopīgot"</string>
+    <string name="find" msgid="4808270900322985960">"Atrast"</string>
+    <string name="websearch" msgid="4337157977400211589">"Meklēt tīmeklī"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 21a977d..83fd2d3c 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flymodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flymodus er på"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flymodus er av"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Betaltjenester"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Lar applikasjonen kontrollere lommelykten."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"tilgang til USB-enheter"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Tillater programmet å få tilgang til USB-enheter."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"teste maskinvare"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Lar applikasjonen styre diverse enheter med det formål å teste maskinvaren."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"ringe telefonnummer direkte"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Eksternt medium har ukjent tilstand."</string>
     <string name="share" msgid="1778686618230011964">"Del"</string>
     <string name="find" msgid="4808270900322985960">"Finn"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Nettsøk"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index be59831..3c03980 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Vliegmodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Vliegmodus is AAN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Vliegmodus is UIT"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services waarvoor u moet betalen"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Hiermee kan de toepassing de zaklamp bedienen."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"toegang krijgen tot USB-apparaten"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Hiermee kan de toepassing toegang krijgen tot USB-apparaten."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"hardware testen"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Hiermee kan de toepassing verschillende randapparaten beheren om de hardware te testen."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"telefoonnummers rechtstreeks bellen"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Extern medium heeft onbekende status."</string>
     <string name="share" msgid="1778686618230011964">"Delen"</string>
     <string name="find" msgid="4808270900322985960">"Vinden"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Online zoeken"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 567ef08..e82dbca 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Tryb samolotowy"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Tryb samolotowy jest włączony"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Tryb samolotowy jest wyłączony"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
     <string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Usługi płatne"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Pozwala aplikacji kontrolować latarkę."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"dostęp do urządzeń USB"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Zezwala aplikacji na dostęp do urządzeń USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testowanie sprzętu"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Pozwala aplikacji na kontrolowanie różnych urządzeń peryferyjnych w celu testowania sprzętu."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"bezpośrednie wybieranie numerów telefonów"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Nośnik zewnętrzny jest w nieznanym stanie."</string>
     <string name="share" msgid="1778686618230011964">"Udostępnij"</string>
     <string name="find" msgid="4808270900322985960">"Znajdź"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Wyszukiwarka"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 5756e96..41634f8 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo de avião"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"O modo de voo está activado"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"O modo de voo está desactivado"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serviços que implicam pagamento"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permite à aplicação controlar a lanterna."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"aceder a dispositivos USB"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Permite à aplicação aceder a dispositivos USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testar hardware"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Permite à aplicação controlar vários periféricos para fins de teste de hardware."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"marcar números de telefone directamente"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Suporte de dados externo em estado desconhecido."</string>
     <string name="share" msgid="1778686618230011964">"Partilhar"</string>
     <string name="find" msgid="4808270900322985960">"Localizar"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Pesquisar na Web"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index fa4d6aa..572cbce 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo de avião"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modo de avião ATIVADO"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modo de avião DESATIVADO"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serviços que geram gastos"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permite que o aplicativo controle a lanterna."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"acessar dispositivos USB"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Permitir que o aplicativo acesse dispositivos USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testar hardware"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Permite que o aplicativo controle diversos periféricos para teste do hardware."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"chamar diretamente os números de telefone"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Mídia externa em estado desconhecido."</string>
     <string name="share" msgid="1778686618230011964">"Compartilhar"</string>
     <string name="find" msgid="4808270900322985960">"Localizar"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Pesquisa na web do Google"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 679e2ee..9a879c7 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -154,6 +154,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modus d\'aviun"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Il modus d\'aviun è activà"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Il modus d\'aviun è deactivà."</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modus segirà"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servetschs che custan"</string>
@@ -363,6 +365,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permetta a l\'applicaziun da controllar la glischina."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"acceder ad apparats USB"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Permetta a l\'applicaziun dad acceder als apparats periferics USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testar la hardware"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Permetta ad ina applicaziun da controllar differents apparats periferics per motivs da test da hardware."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"telefonar directamain a numers da telefon"</string>
@@ -1067,4 +1073,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 19e300f..d0e1dc6 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Mesaj vocal"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Problemă de conexiune sau cod MMI nevalid."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Operaţia este limitată la numerele cu apelări restricţionate."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Serviciul a fost activat."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Serviciul a fost activat pentru:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Serviciul a fost dezactivat."</string>
@@ -126,10 +125,10 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"Sincronizare"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronizare"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Prea multe ştergeri <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Spaţiul de stocare al tabletei este plin! Ştergeţi fişiere pentru a elibera spaţiu."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Stocarea pe tabletă este plină! Ştergeţi câteva fişiere pentru a elibera spaţiul."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"Spaţiul de stocare al telefonului este plin! Ştergeţi fişiere pentru a elibera spaţiu."</string>
     <string name="me" msgid="6545696007631404292">"Eu"</string>
-    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opţiuni pentru tabletă"</string>
+    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opţiuni tablet PC"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"Opţiuni telefon"</string>
     <string name="silent_mode" msgid="7167703389802618663">"Mod Silenţios"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"Activaţi funcţia wireless"</string>
@@ -137,13 +136,12 @@
     <string name="screen_lock" msgid="799094655496098153">"Blocaţi ecranul"</string>
     <string name="power_off" msgid="4266614107412865048">"Opriţi alimentarea"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Se închide..."</string>
-    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tableta se va închide."</string>
+    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Computerul dvs. tablet PC se va închide."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonul dvs. se va închide."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Doriţi să închideţi?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Nicio aplicaţie recentă."</string>
-    <string name="global_actions" product="tablet" msgid="408477140088053665">"Opţiuni pentru tabletă"</string>
+    <string name="global_actions" product="tablet" msgid="408477140088053665">"Opţiuni tablet PC"</string>
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opţiuni telefon"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Blocaţi ecranul"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Opriţi alimentarea"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mod Avion"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modul Avion este ACTIVAT"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modul avion este DEZACTIVAT"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicii cu plată"</string>
@@ -160,7 +160,7 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Mesajele dvs."</string>
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"Citire şi scriere mesaje SMS, e-mailuri şi alte mesaje."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Informaţiile dvs. personale"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Acces direct la agenda şi la calendarul stocate pe tabletă."</string>
+    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Acces direct la agenda şi la calendarul stocate pe computerul dvs. tablet PC."</string>
     <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Acces direct la agenda şi la calendarul stocate pe telefonul dvs."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Locaţia dvs."</string>
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Monitorizare locaţie fizică"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Instrumente de dezvoltare"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funcţii necesare doar pentru dezvoltatorii de aplicaţii."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Stocare"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Accesează cardul SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Accesează stocarea USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Accesează cardul SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"dezactivare sau modificare bare de stare"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Permite aplicaţiei să dezactiveze bara de stare sau să adauge şi să elimine pictograme de sistem."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"bară de stare"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Permite aplicaţiei să fie bară de stare."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"extindere/restrângere bară de stare"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Permite aplicaţiei să extindă sau să restrângă bara de stare."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"interceptare apeluri trimise"</string>
@@ -196,10 +194,10 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"trimitere mesaje SMS"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Permite aplicaţiei să trimită mesaje SMS. Aplicaţiile rău-intenţionate ar putea să vă genereze costuri, deoarece trimit mesaje fără confirmarea dvs."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"citire mesaje SMS sau MMS"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Permite aplicaţiei să citească mesajele SMS stocate pe tabletă sau pe cardul SIM. Aplicaţiile rău-intenţionate ar putea să vă citească mesajele confidenţiale."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Permite aplicaţiei să citească mesajele SMS stocate pe computerul tablet PC sau pe cardul SIM. Aplicaţiile rău-intenţionate ar putea să vă citească mesajele confidenţiale."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Permite aplicaţiei să citească mesajele SMS stocate pe telefon sau pe cardul SIM. Aplicaţiile rău-intenţionate ar putea să vă citească mesajele confidenţiale."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"editare SMS sau MMS"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Permite aplicaţiei să scrie în mesajele SMS stocate pe tabletă sau pe cardul SIM. Aplicaţiile rău-intenţionate ar putea să vă şteargă mesajele."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Permite aplicaţiei să scrie în mesajele SMS stocate pe computerul tablet PC sau pe cardul SIM. Aplicaţiile rău-intenţionate ar putea să vă şteargă mesajele."</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Permite aplicaţiei să scrie în mesajele SMS stocate pe telefon sau pe cardul SIM. Aplicaţiile rău-intenţionate ar putea să vă şteargă mesajele."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"primire WAP"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Permite unei aplicaţii să primească şi să proceseze mesaje WAP. Aplicaţiile rău-intenţionate ar putea să monitorizeze mesajele sau să le şteargă fără să vi le arate."</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"împiedicare comutare între aplicaţii"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Împiedică trecerea utilizatorului la o altă aplicaţie."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"monitorizare şi control al lansării tuturor aplicaţiilor"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Permite unei aplicaţii să monitorizeze şi să controleze modul în care sistemul lansează activităţi. Aplicaţiile rău-intenţionate ar putea să compromită sistemul în întregime. Această permisiune este necesară doar pentru dezvoltare. Nu este niciodată necesară pentru utilizarea normală."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Permite unei aplicaţii să monitorizeze şi să controleze modul în care sistemul lansează activităţi. Aplicaţiile rău-intenţionate ar putea să compromită sistemul în întregime. Această permisiune este necesară numai pentru dezvoltare şi nu este niciodată necesară pentru utilizarea normală a telefonului."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"trimitere mesaj difuzat privind extragerea din pachet"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Permite unei aplicaţii să difuzeze o notificare de eliminare a unui pachet al aplicaţiei. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a opri alte aplicaţii în derulare."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"trimitere mesaj difuzat primit prin SMS"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"afişare ferestre neautorizate"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Permite crearea de ferestre menite să fie utilizate de interfaţa utilizatorului a sistemului intern. Nu se utilizează de aplicaţiile obişnuite."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"afişare alerte la nivel de sistem"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Permite unei aplicaţii să afişeze ferestre de alertă de sistem. Aplicaţiile rău-intenţionate ar putea să preia controlul asupra întregului ecran."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Permite unei aplicaţii să afişeze ferestre de alertă de sistem. Aplicaţiile rău-intenţionate ar putea să preia controlul asupra întregului ecran al telefonului."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"modificare viteză de animaţie globală"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Permite unei aplicaţii să modifice oricând viteza globală de animaţie (animaţii mai rapide sau mai lente)."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"gestionare simboluri aplicaţii"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Permite aplicaţiilor să creeze şi să gestioneze propriile simboluri, evitând ordinea lor Z normală. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"apăsare taste şi control butoane"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Permite unei aplicaţii să furnizeze propriile evenimente de intrare (apăsări de taste etc.) către alte aplicaţii. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a prelua controlul asupra tabletei."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Permite unei aplicaţii să furnizeze propriile evenimente (apăsări de taste etc.) către alte aplicaţii. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a prelua controlul asupra computerului tablet PC."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Permite unei aplicaţii să furnizeze propriile evenimente (apăsări de taste etc.) către alte aplicaţii. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a prelua controlul asupra telefonului."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"înregistrare a ceea ce tastaţi şi a operaţiunilor efectuate"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Permite unei aplicaţii să monitorizeze tastele pe care le apăsaţi când interacţionaţi cu o altă aplicaţie (cum ar fi introducerea unei parole). Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"instalare directă a aplicaţiilor"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Permite unei aplicaţii să instaleze pachete Android noi sau actualizate. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a adăuga aplicaţii noi cu permisiuni puternice alese la întâmplare."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"ştergere integrală date din cache ale aplicaţiei"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Permite unei aplicaţii să elibereze spaţiu de stocare pe tabletă, prin ştergerea fişierelor din directorul cache al aplicaţiei. De regulă, accesul este strict restricţionat la procesul de sistem."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Permite unei aplicaţii să golească stocarea pe computerul tablet PC prin ştergerea fişierelor din directorul cache al aplicaţiei. De regulă, accesul este strict restricţionat la procesul de sistem."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Permite unei aplicaţii să stocheze gratuit pe telefon, prin ştergerea fişierelor din directorul cache al aplicaţiei. De regulă, accesul este strict restricţionat la procesul de sistem."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"mutare resurse aplicaţie"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Permite unei aplicaţii să mute resursele aplicaţiei de pe suporturile fizice interne pe cele externe şi invers."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"citire fişiere din jurnalul sistemului"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Permite unei aplicaţii să citească din diverse fişiere jurnal ale sistemului. În acest mod poate descoperi informaţii generale cu privire la utilizarea tabletei de către dvs., incluzând potenţial informaţii personale sau confidenţiale."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Permite unei aplicaţii să citească din diverse fişiere jurnal ale sistemului. În acest mod poate descoperi informaţii generale cu privire la utilizarea tabletei de către dvs., incluzând potenţial informaţii personale sau confidenţiale."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"citire date de jurnal problematice"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Permite unei aplicaţii să citească din diverse fişiere jurnal ale sistemului. În acest mod poate descoperi informaţii generale cu privire la utilizarea computerului tablet PC de către dvs., şi probabil informaţii personale sau confidenţiale."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Permite unei aplicaţii să citească din diverse fişiere jurnal ale sistemului. În acest mod poate descoperi informaţii generale cu privire la utilizarea telefonului de către dvs., dar nu şi informaţii personale sau confidenţiale."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"citire/scriere în resursele deţinute de diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Permite unei aplicaţii să citească şi să scrie în orice resursă deţinută de grupul diag, de ex., fişierele din /dev. Această permisiune ar putea să afecteze stabilitatea şi securitatea sistemului. Permisiunea trebuie utilizată DOAR de producător sau de operator pentru diagnostice specifice pentru hardware."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"activare sau dezactivare a componentelor aplicaţiei"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Permite unei aplicaţii să modifice starea (activată sau dezactivată) a unei componente a altei aplicaţii. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a dezactiva funcţii importante ale tabletei. Este necesar să utilizaţi cu atenţie această permisiune, deoarece este posibil să aduceţi componentele aplicaţiei într-o stare inutilizabilă, inconsecventă sau instabilă."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Permite unei aplicaţii să modifice starea (activată sau dezactivată) a unei componente a altei aplicaţii. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a dezactiva funcţii importante ale tabletei. Este necesar să utilizaţi cu atenţie această permisiune, deoarece este posibil să aduceţi componentele aplicaţiei într-o stare inutilizabilă, inconsecventă sau instabilă."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Permite unei aplicaţii să modifice starea (activată sau dezactivată) a unei componente a altei aplicaţii. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a dezactiva funcţii importante ale computerului tablet PC. Este necesar să utilizaţi cu atenţie această permisiune, deoarece este posibil să aduceţi componentele aplicaţiei într-o stare inutilizabilă, inconsecventă sau instabilă."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Permite unei aplicaţii să modifice starea (activată sau dezactivată) a unei componente a altei aplicaţii. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a dezactiva funcţii importante ale telefonului. Este necesar să utilizaţi cu atenţie această permisiune, deoarece este posibil să aduceţi componentele aplicaţiei într-o stare inutilizabilă, inconsecventă sau instabilă."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"setare aplicaţii preferate"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Permite unei aplicaţii să modifice aplicaţiile dvs. preferate. Astfel li se poate permite aplicaţiilor rău-intenţionate să modifice fără a vă înştiinţa aplicaţiile care rulează, păcălind aplicaţiile existente să colecteze date confidenţiale de la dvs."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"modificare setări sistem globale"</string>
@@ -298,19 +296,19 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"modificare hartă servicii Google"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"Permite unei aplicaţii să modifice harta serviciilor Google. Nu se utilizează de aplicaţiile obişnuite."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"pornire automată la deschidere"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Permite unei aplicaţii să pornească imediat ce s-a terminat încărcarea sistemului. Din acest motiv, pornirea tabletei poate dura mai mult timp, iar rularea continuă a aplicaţiei poate încetini dispozitivul."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Permite unei aplicaţii să pornească imediat ce s-a terminat încărcarea sistemului. Din acest motiv, pornirea computerului tablet PC poate dura mai mult timp, iar rularea continuă a aplicaţiei îl poate încetini."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Permite unei aplicaţii să pornească imediat ce s-a terminat încărcarea sistemului. Din acest motiv, pornirea telefonului poate dura mai mult timp, iar rularea continuă a aplicaţiei poate încetini telefonul."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"trimitere mesaj difuzat persistent"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Permite unei aplicaţii să trimită mesaje difuzate persistente, care rămân după terminarea mesajului difuzat. Aplicaţiile rău-intenţionate ar putea să încetinească sau să destabilizeze tableta, determinând-o să utilizeze prea multă memorie."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Permite unei aplicaţii să trimită mesaje difuzate persistente, care rămân după terminarea mesajului difuzat. Aplicaţiile rău-intenţionate ar putea să încetinească sau să destabilizeze computerul tablet PC, determinându-l să utilizeze prea multă memorie."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Permite unei aplicaţii să trimită mesaje difuzate persistente, care rămân după terminarea mesajului difuzat. Aplicaţiile rău-intenţionate ar putea să încetinească sau să destabilizeze telefonul, determinându-l să utilizeze prea multă memorie."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"citire date de contact"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Permite unei aplicaţii să citească toate datele din agendă (adrese) stocate pe tabletă. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a trimite datele din agenda dvs. către alte persoane."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Permite unei aplicaţii să citească toate datele de contact (adrese) stocate pe computerul tablet PC. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a trimite datele dvs. către alte persoane."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Permite unei aplicaţii să citească toate datele de contact (adrese) stocate pe telefon. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a trimite datele dvs. către alte persoane."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"scriere date de contact"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite unei aplicaţii să modifice datele din agendă (adresele) stocate pe tabletă. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a şterge sau a modifica datele din agenda dvs."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Permite unei aplicaţii să modifice datele de contact (adresele) stocate pe computerul tablet PC. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a şterge sau a modifica datele dvs. de contact."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Permite unei aplicaţii să modifice datele de contact (adresele) stocate pe telefon. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a şterge sau a modifica datele dvs. de contact."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"citire evenimente din calendar"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite unei aplicaţii să citească toate evenimentele din calendar stocate pe tabletă. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a trimite evenimentele din calendar către alte persoane."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Permite unei aplicaţii să citească toate evenimentele din calendar stocate pe computerul tablet PC. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a trimite evenimentele din calendar către alte persoane."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Permite unei aplicaţii să citească toate evenimentele din calendar stocate pe telefon. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a trimite evenimentele din calendar către alte persoane."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"adăugare sau modificare de evenimente în calendar şi trimitere e-mailuri către invitaţi"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Permite unei aplicaţii să adauge sau să modifice evenimentele din calendar, prin care se pot trimite mesaje de e-mail către invitaţi. Aplicaţiile rău-intenţionate ar putea să utilizeze această aplicaţie pentru a şterge sau a modifica evenimentele din calendar ori pentru a trimite mesaje de e-mail către invitaţi."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"permisiune pentru instalarea unui furnizor de locaţii"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Creează surse de locaţii pentru testare. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a înlocui locaţia şi/sau starea returnată de sursele de locaţii reale, cum ar fi cele ale furnizorilor GPS sau de reţea, ori ar putea să monitorizeze şi să raporteze locaţia dvs. către o sursă externă."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"locaţie exactă (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Accesează de pe tabletă surse de localizare exacte, cum ar fi cele ale sistemului Global Positioning System, dacă este disponibil. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a stabili locul în care vă aflaţi. De asemenea, ar putea să consume mai multă energie a bateriei."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Accesează de pe computerul tablet PC surse de locaţii exacte, cum ar fi cele ale sistemului Global Positioning System, dacă este disponibil. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a stabili locul în care vă aflaţi. De asemenea, ar putea să consume mai multă energie a bateriei."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Accesează de pe telefon surse de locaţii exacte, cum ar fi cele ale sistemului Global Positioning System, dacă este disponibil. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a stabili locul în care vă aflaţi. De asemenea, ar putea să consume mai multă energie a bateriei."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"locaţie imprecisă (bazată pe reţea)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Accesează surse de locaţii imprecise, cum ar fi baza de date de telefonie mobilă, pentru a stabili cu aproximaţie locaţia tabletei, dacă acest lucru este disponibil. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a stabili cu aproximaţie locul unde vă aflaţi."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Accesează surse de locaţii imprecise, cum ar fi baza de date de telefonie mobilă, pentru a stabili cu aproximaţie locaţia computerului tablet PC, dacă acest lucru este disponibil. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a stabili cu aproximaţie locul unde vă aflaţi."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Accesează surse de locaţii imprecise, cum ar fi baza de date de telefonie mobilă, pentru a stabili cu aproximaţie locaţia telefonului, dacă acest lucru este disponibil. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a stabili cu aproximaţie locul unde vă aflaţi."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"accesare SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Permite unei aplicaţii să utilizeze funcţiile de nivel redus SurfaceFlinger."</string>
@@ -334,37 +332,39 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Permite aplicaţiei să modifice setările audio globale, cum ar fi volumul sau rutarea."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"înregistrare audio"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Permite aplicaţiei să acceseze calea către înregistrarea audio."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"fotografiere"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Permite unei aplicaţii să facă fotografii cu ajutorul camerei foto. Astfel i se permite aplicaţiei să colecteze oricând imaginile văzute de camera foto."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"dezactivare definitivă tabletă"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"realizarea de fotografii şi videoclipuri"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Permite unei aplicaţii să facă fotografii cu ajutorul camerei foto. Astfel i se permite aplicaţiei să colecteze oricând imaginile văzute de camera foto."</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"dezactivarea permanentă a computerului tablet PC"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"dezactivare permanentă a telefonului"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Permite aplicaţiei să dezactiveze definitiv întreaga tabletă. Acest lucru este foarte periculos."</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Permite aplicaţiei să dezactiveze definitiv întregul computer tablet PC. Acest lucru este foarte periculos."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Permite aplicaţiei să dezactiveze definitiv întregul telefon. Acest lucru este foarte periculos."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"forţare repornire tabletă"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"forţare repornire computer tablet PC"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"forţare repornire telefon"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Permite aplicaţiei să forţeze repornirea tabletei."</string>
+    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Permite aplicaţiei să forţeze repornirea computerului tablet PC."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Permite aplicaţiei să forţeze repornirea telefonului."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"montare şi demontare sisteme de fişiere"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Permite unei aplicaţii să monteze şi să demonteze sisteme de fişiere pentru stocarea pe suporturi amovibile."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formatare stocare externă"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Permite aplicaţiei să formateze stocarea pe suporturi amovibile."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"obţinere informaţii referitoare la stocarea securizată"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Permite unei aplicaţii să obţină informaţii referitoare la stocarea securizată."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"creare stocare securizată"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Permite aplicaţiei să creeze stocări securizate."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"distrugere stocare securizată"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Permite aplicaţiei să distrugă stocarea securizată."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"montare/demontare stocare securizată"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Permite aplicaţiei să monteze/demonteze stocarea securizată."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"redenumire stocare securizată"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Permite aplicaţiei să redenumească stocarea securizată."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"descărcare informaţii pe stocarea internă"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Permite aplicaţiei să primească informaţii pe stocarea internă."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"creare stocare internă"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Permite aplicaţiei să creeze stocare internă."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"distrugerea stocării interne"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Permite aplicaţiei să distrugă stocarea internă."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"montare/demontare stocare internă"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Permite aplicaţiei să monteze/demonteze stocarea internă."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"redenumire stocare internă"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Permite aplicaţiei să redenumească stocarea internă."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"controlare mecanism de vibrare"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Permite aplicaţiei să controleze mecanismul de vibrare."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"control lanternă"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Permite aplicaţiei să controleze lanterna."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"accesare dispozitive USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Permite aplicaţiei să acceseze dispozitive USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testare hardware"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Permite aplicaţiei să controleze diverse periferice în scopul testării componentelor hardware."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"Permite aplicaţiei să apeleze numere de telefon fără intervenţia dvs. Aplicaţiile rău-intenţionate ar putea să adauge apeluri neaşteptate pe factura dvs. de telefon. Reţineţi că această permisiune nu permite aplicaţiei să apeleze numere de urgenţă."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"apelare directă a oricărui număr de telefon"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Permite aplicaţiei să apeleze orice număr de telefon, inclusiv numere de urgenţă, fără intervenţia dvs. Aplicaţiile rău-intenţionate ar putea să efectueze apeluri inutile şi ilegale către serviciile de urgenţă."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"pornire directă a configuraţiei CDMA a tabletei"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"pornire directă a configurării computerului tablet PC pentru CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"pornire directă a configuraţiei CDMA a telefonului"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Permite aplicaţiei să pornească asigurarea accesului la CDMA. Aplicaţiile rău-intenţionate ar putea să pornească asigurarea accesului la CDMA, fără ca aceasta să fie necesară."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"controlare notificări de actualizare a locaţiei"</string>
@@ -385,16 +385,16 @@
     <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Permite aplicaţiei să controleze funcţiile de telefon ale dispozitivului. O aplicaţie cu această permisiune poate să comute reţelele, să închidă şi să deschidă radioul şi să efectueze alte acţiuni similare, fără să vă înştiinţeze."</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"citire stare şi identitate telefon"</string>
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"Permite aplicaţiei să acceseze funcţiile de telefon ale dispozitivului. O aplicaţie cu această permisiune poate regăsi numărul de telefon şi numărul serial al telefonului, dacă un apel este activ, numărul la care este conectat apelul şi alte aspecte similare."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"împiedicare intrare tabletă în repaus"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"împiedicarea computerului tablet PC să intre în repaus"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"împiedicare intrare telefon în repaus"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Permite unei aplicaţii să împiedice intrarea tabletei în starea de repaus."</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Permite unei aplicaţii să împiedice intrarea computerului tablet PC în stare de repaus."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Permite unei aplicaţii să împiedice intrarea telefonului în stare de repaus."</string>
-    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"pornire/oprire tabletă"</string>
+    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"pornire sau oprire computer tablet PC"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"telefon pornit sau oprit"</string>
-    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Permite aplicaţiei să activeze sau să dezactiveze tableta."</string>
+    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Permite aplicaţiei să pornească sau să oprească computerul tablet PC."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Permite aplicaţiei să activeze sau să dezactiveze telefonul."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"rulare în mod test de fabrică"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Rulează ca testare de producător la nivel redus, permiţând accesul complet la hardware-ul tabletei. Permisiune disponibilă doar când tableta rulează în modul de testare de producător."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Rulează ca test de nivel redus setat de producător, permiţând accesul complet la sistemul hardware al computerului tablet PC. Permisiune disponibilă doar când acesta rulează în modul de testare setat de producător."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Rulează ca testare de nivel redus al producătorului, permiţând accesul complet la hardware-ul telefonului. Permisiune disponibilă doar când telefonul rulează în modul de testare a producător."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"setare imagine de fundal"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Permite aplicaţiei să seteze imaginea de fundal a sistemului."</string>
@@ -403,15 +403,15 @@
     <string name="permlab_masterClear" msgid="2315750423139697397">"resetare sistem la setările prestabilite din fabrică"</string>
     <string name="permdesc_masterClear" msgid="5033465107545174514">"Permite unei aplicaţii să reseteze complet sistemul la setările din fabrică, ştergând toate datele, configurările şi aplicaţiile instalate."</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"setare dată/oră"</string>
-    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Permite unei aplicaţii să modifice ora tabletei."</string>
+    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Permite unei aplicaţii să schimbe ora computerului tablet PC."</string>
     <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Permite unei aplicaţii să modifice ora telefonului."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"setare fus orar"</string>
-    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Permite unei aplicaţii să modifice fusul orar al tabletei."</string>
+    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Permite unei aplicaţii să schimbe fusul orar al computerului tablet PC."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Permite unei aplicaţii să modifice fusul orar al telefonului."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"efectuare ca AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Permite unei aplicaţii să efectueze apeluri către AccountAuthenticators"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"descoperire conturi cunoscute"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Permite unei aplicaţii să obţină lista conturilor cunoscute de tabletă."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Permite unei aplicaţii să obţină lista conturilor cunoscute de computerul tablet PC."</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Permite unei aplicaţii să obţină lista conturilor cunoscute de telefon."</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"acţionare ca autentificator de cont"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Permite unei aplicaţii să utilizeze capacitatea autentificatorului de cont de către AccountManager, incluzând crearea conturilor şi obţinerea şi setarea parolelor."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"permitere recepţionare difuzare multiplă Wi-Fi"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Permite unei aplicaţii să primească pachete care nu sunt direct adresate dispozitivului dvs. Această permisiune poate fi utilă la descoperirea serviciilor oferite în apropiere. Consumă mai multă energie decât modul fără difuzare multiplă."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"administrare bluetooth"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Permite unei aplicaţii să configureze tableta Bluetooth local, să descopere şi să se asocieze cu dispozitive la distanţă."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Permite unei aplicaţii să configureze computerul tablet PC Bluetooth local, să descopere şi să se asocieze cu dispozitive la distanţă."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Permite unei aplicaţii să configureze telefonul Bluetooth local, să descopere şi să se asocieze cu dispozitive la distanţă."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"creare conexiuni Bluetooth"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Permite unei aplicaţii să vizualizeze configuraţia tabletei Bluetooth local, să efectueze şi să accepte conexiuni cu dispozitive pereche."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Permite unei aplicaţii să vizualizeze configuraţia computerului tablet PC Bluetooth local, să efectueze şi să accepte conexiuni cu dispozitive pereche."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Permite unei aplicaţii să vizualizeze configuraţia telefonului Bluetooth local, să efectueze şi să accepte conexiuni cu dispozitive pereche."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"controlare schimb de date prin Near Field Communication"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Permite unei aplicaţii să comunice cu etichetele, cardurile şi cititoarele NFC (Near Field Communication)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"dezactivare blocare taste"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite unei aplicaţii să dezactiveze blocarea tastelor şi orice modalitate asociată de securitate a parolelor. Un bun exemplu este deblocarea tastelor de către telefon atunci când se primeşte un apel şi reactivarea blocării tastelor la terminarea apelului."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"citire setări sincronizare"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Permite unei aplicaţii să citească cuvinte, nume şi expresii private stocate de utilizator în dicţionarul utilizatorului."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"scriere în dicţionarul definit de utilizator"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Permite unei aplicaţii să scrie cuvinte noi în dicţionarul utilizatorului."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modificare/ştergere conţinut card SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modificare/ştergere a conţinutului stocării USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modificare/ştergere conţinut card SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Permite unei aplicaţii să scrie pe cardul SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Permite unei apl. să scrie în stoc. USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Permite unei aplicaţii să scrie pe cardul SD."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"modificare/ştergere a conţinutului din stocarea media internă"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Permite unei aplicaţii să modifice conţinutul stocării media interne."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"accesare sistem de fişiere cache"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Permite unei aplicaţii să scrie şi să citească sistemul de fişiere cache."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Limitare parolă"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Restricţionează tipurile de parole pe care aveţi permisiunea să le utilizaţi."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Supraveghere încercări de conectare"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Monitorizaţi numărul de parole incorecte introduse la deblocarea ecranului şi blocaţi tableta sau ştergeţi datele acesteia dacă sunt introduse prea multe parole incorecte"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Monitorizaţi numărul de parole incorecte introduse la deblocarea ecranului şi blocaţi tableta sau ştergeţi datele acesteia dacă sunt introduse prea multe parole incorecte"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Resetare parolă"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Forţaţi o nouă valoare pentru parola dvs., obligându-l pe administrator să v-o comunice înainte de a vă conecta."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Forţare blocare"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Controlarea momentului în care dispozitivul se blochează, solicitând reintroducerea parolei."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"efectuare/primire apeluri prin internet"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Permite unei aplicaţii să utilizeze serviciul SIP pentru a efectua/primi apeluri prin internet."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Controlarea lungimii şi a tipului de caractere permise în parolele pentru deblocarea ecranului."</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizaţi încercările de deblocare a ecranului"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Monitorizaţi numărul parolelor incorecte introduse la deblocarea ecranului şi blocaţi computerul tablet PC sau ştergeţi toate datele stocate în acesta dacă au fost introduse prea multe parole incorecte"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Monitorizaţi numărul parolelor incorecte introduse la deblocarea ecranului şi blocaţi telefonul sau ştergeţi toate datele stocate în acesta dacă au fost introduse prea multe parole incorecte"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Editaţi parola de deblocare a ecranului"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Editaţi parola de deblocare a ecranului"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Blocaţi ecranul"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Controlarea modului şi a timpului în care se blochează ecranul"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Ştergere integrală date"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Ştergeţi datele tabletei fără avertisment, realizând o resetare la configuraţia din fabrică"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Ştergeţi datele tabletei fără avertisment, realizând o resetare la configuraţia din fabrică"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Ştergerea datelor de pe computerul tablet PC fără avertisment, efectuând resetarea configurării din fabrică"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Ştergeţi datele din telefon fără avertisment, efectuând resetarea configurării din fabrică"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Setaţi serverul proxy global pentru dispozitiv"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Setaţi serverul proxy global pentru dispozitiv care să fie utilizat cât timp politica este activă. Numai primul administrator al dispozitivului poate seta serverul proxy global activ."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Setaţi expirarea parolei"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Controlarea duratei până când parola de blocare a ecranului trebuie modificată"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domiciliu"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Pager serviciu"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Asistent"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Personalizate"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Zi de naştere"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Zi aniversară"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Eveniment"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Altul"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Personalizat"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Domiciliu"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Serviciu"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Serviciu"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Altele"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Personalizat"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Personalizată"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Asistent"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Frate"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Copil"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Partener domestic"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Tată"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Prieten"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Manager"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Mamă"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Părinte"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Partener"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Denumit după"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Rudă"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Soră"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Soţ/Soţie"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Personalizată"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Ecran pornire"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Serviciu"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Altul"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Introduceţi codul PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Introduceţi parola pentru a debloca"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Introduceţi PIN pentru deblocare"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Cod PIN incorect!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Pentru a debloca, apăsaţi Meniu, apoi 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Număr de urgenţă"</string>
@@ -646,14 +615,13 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Reveniţi la apel"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Corect!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Ne pare rău, încercaţi din nou"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Ne pare rău, încercaţi din nou"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Se încarcă (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Încărcată."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conectaţi încărcătorul."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Niciun card SIM."</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tableta nu are card SIM."</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nu există card SIM în computerul tablet PC."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Telefonul nu are card SIM."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Introduceţi un card SIM."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Numai apeluri de urgenţă"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Cardul SIM este blocat."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Se deblochează cardul SIM..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%d</xliff:g> ori. "\n\n"Încercaţi din nou în <xliff:g id="NUMBER_1">%d</xliff:g> (de) secunde."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%d</xliff:g> ori. După alte <xliff:g id="NUMBER_1">%d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi tableta cu ajutorul datelor de conectare la Google."\n\n"Încercaţi din nou peste <xliff:g id="NUMBER_2">%d</xliff:g> (de) secunde."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Aţi introdus în mod incorect parola de <xliff:g id="NUMBER_0">%d</xliff:g> (de) ori. "\n\n"Încercaţi din nou peste <xliff:g id="NUMBER_1">%d</xliff:g> (de) secunde."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Aţi introdus în mod incorect codul PIN de <xliff:g id="NUMBER_0">%d</xliff:g> (de) ori. "\n\n"Încercaţi din nou peste <xliff:g id="NUMBER_1">%d</xliff:g> (de) secunde."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%d</xliff:g> (de) ori. După încă <xliff:g id="NUMBER_1">%d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi computerul tablet PC cu ajutorul datelor de conectare la Google."\n\n" Încercaţi din nou peste <xliff:g id="NUMBER_2">%d</xliff:g> (de) secunde."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Aţi desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%d</xliff:g> de ori. După <xliff:g id="NUMBER_1">%d</xliff:g> încercări nereuşite, vi se va solicita să deblocaţi telefonul cu ajutorul datelor de conectare la Google."\n\n" Încercaţi din nou în <xliff:g id="NUMBER_2">%d</xliff:g> (de) secunde."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Încercaţi din nou peste <xliff:g id="NUMBER">%d</xliff:g> (de) secunde."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Aţi uitat modelul?"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Doriţi să părăsiţi această pagini?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Selectaţi OK pentru a continua sau Anulaţi pentru a rămâne pe pagina curentă."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Confirmaţi"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Sfat: apăsaţi de două ori pentru a mări şi a micşora."</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"Com.aut."</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"Completare automată"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Complet. autom."</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"citire istoric şi marcaje în browser"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Permite aplicaţiei să citească toate adresele URL vizitate din browser şi toate marcajele din acesta."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"citire istoric şi marcaje în browser"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Permite unei aplicaţii să modifice istoricul sau marcajele din browser stocate pe tabletă. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a şterge sau a modifica datele din browser."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Permite unei aplicaţii să modifice istoricul şi marcajele din browser, stocate pe computerul dvs. tablet PC. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a şterge sau a modifica datele din browser."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Permite unei aplicaţii să modifice istoricul şi marcajele din browser, stocate pe telefonul dvs. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a şterge sau a modifica datele din browser."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"setare alarmă pentru ceasul cu alarmă"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Permite aplicaţiei să seteze o alarmă într-o aplicaţie de ceas de alarmă instalată. Este posibil ca unele aplicaţii de ceas de alarmă să nu implementeze această funcţie."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Modificare permisiuni pentru locaţia geografică a browserului"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Permite unei aplicaţii să modifice permisiunile privind locaţia geografică a browserului. Aplicaţiile rău-intenţionate ar putea să utilizeze această permisiune pentru a permite trimiterea informaţiilor privind locaţia către site-uri Web arbitrare."</string>
     <string name="save_password_message" msgid="767344687139195790">"Doriţi ca browserul să reţină această parolă?"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"Decupaţi"</string>
     <string name="copy" msgid="2681946229533511987">"Copiaţi"</string>
     <string name="paste" msgid="5629880836805036433">"Inseraţi"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Nimic de inserat"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Copiaţi adresa URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Selectaţi text..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Selectare text"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metodă de intrare"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Editaţi text"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Acţiuni pentru text"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Spaţiu de stocare redus"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Spaţiul de stocare a tabletei se reduce."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Spaţiul de stocare de pe tabletă este scăzut."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Spaţiul de stocare a telefonului se reduce."</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Anulaţi"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
     <string name="no" msgid="5141531044935541497">"Anulaţi"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Atenţie"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Se încarcă..."</string>
     <string name="capital_on" msgid="1544682755514494298">"ACTIVAT"</string>
     <string name="capital_off" msgid="6815870386972805832">"DEZACTIVAT"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Finalizare acţiune utilizând"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Forţaţi închiderea"</string>
     <string name="report" msgid="4060218260984795706">"Raportaţi"</string>
     <string name="wait" msgid="7147118217226317732">"Aşteptaţi"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Aplicaţie redirecţionată"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> funcţionează acum."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> a fost lansată iniţial."</string>
+    <string name="smv_application" msgid="295583804361236288">"Aplicaţia <xliff:g id="APPLICATION">%1$s</xliff:g> (procesul <xliff:g id="PROCESS">%2$s</xliff:g>) a încălcat propria politică StrictMode."</string>
+    <string name="smv_process" msgid="5120397012047462446">"Procesul <xliff:g id="PROCESS">%1$s</xliff:g> a încălcat propria politică StrictMode."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"Rulează <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Selectaţi comutarea aplicaţiei"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Comutaţi între aplicaţii?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"O altă aplicaţie rulează deja şi trebuie oprită înainte a putea porni o aplicaţie nouă."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Reveniţi la <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Nu porniţi aplicaţia nouă."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Porniţi <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Opriţi vechea aplicaţie fără să salvaţi."</string>
     <string name="sendText" msgid="5132506121645618310">"Selectaţi o acţiune pentru text"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Volum sonerie"</string>
     <string name="volume_music" msgid="5421651157138628171">"Volum media"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Afişaţi-le pe toate"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Stocare masivă USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB conectat"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"V-aţi conectat telefonul la computer prin USB. Selectaţi butonul de mai jos dacă doriţi să copiaţi fişiere între computer şi cardul SD Android."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"V-aţi conectat telefonul la computer prin USB. Selectaţi butonul de mai jos dacă doriţi să copiaţi fişiere între computer şi cardul SD Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"V-aţi conectat la computer prin USB. Atingeţi butonul de mai jos dacă doriţi să copiaţi fişiere de pe computer pe stocarea USB Android sau invers."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"V-aţi conectat la computer prin USB. Atingeţi butonul de mai jos dacă doriţi să copiaţi fişiere de pe computer pe cardul SD Android sau invers."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Activaţi stocarea USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"A apărut o problemă la utilizarea cardului SD pentru stocarea USB."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"A apărut o problemă la utilizarea cardului SD pentru stocarea USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"A apărut o problemă la utilizarea stocării USB pentru stocarea masivă USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"A apărut o problemă la utilizarea cardului SD pentru stocarea masivă USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB conectat"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Selectaţi pentru a copia fişiere în/din computerul dvs."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Dezactivaţi stocarea USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Selectaţi dezactivarea stocării pe USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Stocarea USB este în curs de utilizare"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Înainte de a dezactiva stocarea USB, asiguraţi-vă că aţi demontat („aţi extras”) din computer cardul SD Android."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Înainte de a dezactiva stocarea USB, asiguraţi-vă că aţi demontat („aţi extras”) din computer stocarea USB Android."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Înainte de a dezactiva stocarea USB, asiguraţi-vă că aţi demontat („aţi extras”) din computer cardul SD Android."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Dezactivaţi stocarea USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Problemă la dezactivarea stocării pe USB. Verificaţi pentru a vă asigura că aţi demontat dispozitivul gazdă USB, apoi încercaţi din nou."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Dacă activaţi stocarea USB, unele aplicaţii pe care le utilizaţi în prezent se vor opri şi ar putea să nu fie disponibile până când dezactivaţi stocarea USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operaţie USB nereuşită"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formataţi cardul SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formataţi stoc. USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formataţi cardul SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Sigur doriţi să formataţi cardul SD? Veţi pierde toate datele de pe card."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Formataţi stocarea USB, ştergând toate fişierele stocate aici? Acţiunea nu poate fi anulată!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Sigur doriţi să formataţi cardul SD? Veţi pierde toate datele de pe card."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formataţi"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Depanarea USB este conectată"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"candidaţi"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Se pregăteşte cardul SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Se pregăteşte stocarea USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Se pregăteşte cardul SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Se verifică erorile."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Card SD gol"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Stocare USB goală"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Card SD gol"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Card SD gol sau cu un sistem de fişiere neacceptat."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Stocarea USB este goală sau are un sistem de fişiere neacceptat."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Card SD gol sau cu un sistem de fişiere neacceptat."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Card SD deteriorat"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Stocare USB deteriorată"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Card SD deteriorat"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Card SD deteriorat. Este posibil să fie necesară reformatarea sa."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Stocarea USB a fost deteriorată. Probabil este necesară reformatarea acesteia."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Card SD deteriorat. Este posibil să fie necesară reformatarea sa."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Card SD eliminat în mod neaşteptat"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Stoc. USB elim. în mod neaşt."</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Card SD eliminat în mod neaşteptat"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Pentru a evita pierderea datelor, demontaţi cardul SD înainte de a-l extrage."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Demontaţi stocarea USB înaintea eliminării, pentru a evita pierderea datelor."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Pentru a evita pierderea datelor, demontaţi cardul SD înainte de a-l extrage."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Se poate extrage cardul SD"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Puteţi elim. în sig. stoc. USB"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Se poate extrage cardul SD"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Puteţi extrage cardul SD în siguranţă."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Puteţi elimina în siguranţă stocarea USB."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Puteţi extrage cardul SD în siguranţă."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Card SD extras"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Stocarea USB a fost eliminată"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Card SD extras"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Card SD extras. Inseraţi un card nou."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Stocarea USB a fost eliminată. Inseraţi mediu de stocare nou."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Card SD extras. Inseraţi un card nou."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Nu s-a găsit nicio activitate potrivită"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"actualizare statistici referitoare la utilizarea componentelor"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Trimiteţi"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Înainte"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Terminat"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Înapoi"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Executaţi"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Formaţi numărul"\n"utilizând <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Creaţi contactul"\n"utilizând <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"VPN L2TP/IPSec bazat pe cheie prepartajată"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"VPN L2TP/IPSec bazat pe certificat"</string>
     <string name="upload_file" msgid="2897957172366730416">"Alegeţi un fişier"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Nu au fost găsite fişiere"</string>
     <string name="reset" msgid="2448168080964209908">"Resetaţi"</string>
     <string name="submit" msgid="1602335572089911941">"Trimiteţi"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Mod Maşină activat"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Selectaţi pentru a ieşi din modul Maşină."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering sau hotspot active"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Atingeţi pentru a configura"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Înapoi"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Înainte"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Omiteţi"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Utilizare intensivă de date"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Atingeţi pentru a afla mai multe despre utilizarea datelor mobile"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"S-a depăşit limita de date pentru telefonul mobil"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Atingeţi pentru a afla mai multe despre utilizarea datelor mobile"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Nicio potrivire"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Găsiţi pe pagină"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 potrivire"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> din <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Terminat"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Se demontează stocarea USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Se demontează cardul SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Se şterge stocarea USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Se şterge cardul SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Ştergerea stocării USB a eşuat."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Ştergerea cardului SD a eşuat."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Cardul SD a fost eliminat înainte de a fi demontat."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Stocarea USB este în curs de verificare."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Cardul SD este în curs de verificare."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Cardul SD a fost eliminat."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Stocarea USB este utilizată în prezent de un computer."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Cardul SD este utilizat în prezent de un computer."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Media externă în stare necunoscută."</string>
+    <string name="share" msgid="1778686618230011964">"Distribuiţi"</string>
+    <string name="find" msgid="4808270900322985960">"Găsiţi"</string>
+    <string name="websearch" msgid="4337157977400211589">"Căutare pe web"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index dcf2e7a..22ee02a 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим полета"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим полета ВКЛЮЧЕН"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим полета ВЫКЛЮЧЕН"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Платные услуги"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Позволяет приложению управлять вспышкой."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"доступ к USB-устройствам"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Позволяет приложению получать доступ к USB-устройствам."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"проверять аппаратное обеспечение"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Позволяет приложению управлять различными периферийными устройствами для проверки аппаратного обеспечения."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"посылать прямые вызовы на номера телефонов"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Неизвестно состояние внешнего носителя."</string>
     <string name="share" msgid="1778686618230011964">"Отправить"</string>
     <string name="find" msgid="4808270900322985960">"Найти"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Веб-поиск"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 1d5a276..397688d 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Hlasová schránka"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Problém s pripojením alebo neplatný kód MMI."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Operácia je obmedzená len na režim čísla pevného vytáčania."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Služba bola povolená."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Služba bola povolená pre:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Služba bola zakázaná."</string>
@@ -139,8 +138,7 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"Prebieha vypínanie..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Váš tablet bude vypnutý."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Váš telefón bude vypnutý."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Chcete zariadenie vypnúť?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Najnovšie"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Žiadne nedávno použité aplikácie."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Možnosti tabletu"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim V lietadle"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim V lietadle je ZAPNUTÝ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim V lietadle je VYPNUTÝ"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Spoplatnené služby"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Nástroje pre vývoj"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funkcie len pre vývojárov aplikácií."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Ukladací priestor"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Prístup na kartu SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Prístup do ukl. priestoru USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Prístup na kartu SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"zakázanie alebo zmeny stavového riadka"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Umožňuje aplikácii zakázať stavový riadok alebo pridať alebo odstrániť systémové ikony."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"stavový riadok"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Umožňuje aplikácii fungovať ako stavový riadok."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"rozbalenie a zbalenie stavového riadka"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Umožňuje aplikácii rozbaliť alebo zbaliť stavový riadok."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"zachytenie odchádzajúcich hovorov"</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabrániť prepínaniu aplikácií"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Zabráni používateľovi prepnúť na inú aplikáciu."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"sledovanie a ovládanie spúšťania všetkých aplikácií"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Umožňuje aplikácii sledovať a ovládať spúšťanie činností systémom. Škodlivé aplikácie môžu úplne ovládnuť systém. Toto povolenie je potrebné len na účely vývoja, nikdy nie na bežné používanie tabletu."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Umožňuje aplikácii sledovať a ovládať spúšťanie činností systémom. Škodlivé aplikácie môžu úplne ovládnuť systém. Toto oprávnenie je potrebné len na účely vývoja, nikdy nie na bežné používanie."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"odoslanie vysielania o odstránení balíčka"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Umožňuje aplikácii vysielať upozornenia o odstránení balíčka aplikácie. Škodlivé aplikácie môžu pomocou tohto nastavenia ukončiť ľubovoľnú ďalšiu spustenú aplikáciu."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"odoslanie vysielania o prijatej správe SMS"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"zobrazenie neoprávnených okien"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Umožňuje vytvorenie okien, ktoré majú byť použité interným systémom používateľského rozhrania. Bežné aplikácie toto nastavenie nepoužívajú."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"zobrazenie upozornení systémovej úrovne"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Umožňuje aplikácii zobraziť okná s výstrahami systému. Škodlivé aplikácie môžu prevziať kontrolu nad celou obrazovkou tabletu."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Umožňuje aplikácii zobraziť okná s výstrahami systému. Škodlivé aplikácie môžu prevziať kontrolu nad celou obrazovkou."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"globálne zmeny rýchlosti animácie"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Umožňuje aplikácii kedykoľvek globálne zmeniť rýchlosť animácie (rýchlejšia alebo pomalšia animácia)."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"správa tokenov aplikácií"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Umožňuje aplikácii vytvoriť a spravovať svoje vlastné tokeny a obísť ich obvyklé zoradenie typu Z. Bežné aplikácie by toto nastavenie vôbec nemali využívať."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"používanie kláves a tlačidiel"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Umožňuje aplikácii dodať svoje vlastné vstupné udalosti (stlačenia tlačidiel a pod.) ďalším aplikáciám. Škodlivé aplikácie môžu pomocou tohto nastavenia prevziať kontrolu nad tabletom."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Umožňuje aplikácii doručiť svoje vlastné vstupné udalosti (stlačenia tlačidiel a pod.) ďalším aplikáciám. Škodlivé aplikácie môžu pomocou tohto nastavenia prevziať kontrolu nad tabletom."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Umožňuje aplikácii doručiť svoje vlastné vstupné udalosti (stlačenia tlačidiel a pod.) ďalším aplikáciám. Škodlivé aplikácie môžu pomocou tohto nastavenia prevziať kontrolu nad telefónom."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"zaznamenanie písaného textu a realizovaných akcií"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Umožňuje aplikáciám sledovať, ktoré klávesy používate, a to aj pri práci s inými aplikáciami (napríklad pri zadávaní hesla). Bežné aplikácie by toto nastavenie nemali vôbec využívať."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"priama inštalácia aplikácií"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Umožňuje aplikácii nainštalovať nové alebo aktualizované balíčky systému Android. Škodlivé aplikácie môžu pomocou tohto nastavenia pridať nové aplikácie s ľubovoľnými oprávneniami."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"odstránenie všetkých údajov vo vyrovnávacej pamäti aplikácie"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Umožňuje aplikácii uvoľniť ukladací priestor tabletu odstránením súborov v adresári vyrovnávacej pamäte aplikácie. Prístup je veľmi obmedzený, väčšinou len pre systémové procesy."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Umožňuje aplikácii uvoľniť pamäť tabletu odstránením súborov v adresári vyrovnávacej pamäte aplikácie. Prístup je veľmi obmedzený, väčšinou len pre systémové procesy."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Umožňuje aplikácii uvoľniť pamäť telefónu odstránením súborov v adresári vyrovnávacej pamäte aplikácie. Prístup je veľmi obmedzený, väčšinou len pre systémové procesy."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Presun zdrojov aplikácie"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Umožňuje aplikácii presunúť svoje zdroje z internej pamäte na externé médium a naopak."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"čítanie systémových súborov denníka"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Umožňuje aplikácii čítať rôzne systémové súbory denníkov. Toto nastavenie aplikácie umožňuje získať všeobecné informácie o činnostiach s tabletom, nemali by však obsahovať žiadne osobné ani súkromné informácie."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Umožňuje aplikácii čítať rôzne systémové súbory denníkov. Toto nastavenie aplikácie umožňuje získať všeobecné informácie o činnostiach s tabletom, nemali by však obsahovať žiadne osobné ani súkromné informácie."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"čítať citlivé údaje denníkov"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Umožňuje aplikácii čítať rôzne systémové súbory denníkov. Toto nastavenie aplikácie umožňuje získať všeobecné informácie o činnostiach s tabletom, ktoré by mohli obsahovať osobné alebo súkromné informácie."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Umožňuje aplikácii čítať rôzne systémové súbory denníkov. Toto nastavenie aplikácii umožňuje získať všeobecné informácie o činnostiach s telefónom, ktoré by mohli obsahovať osobné alebo súkromné informácie."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"čítanie alebo zápis do prostriedkov funkcie diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Umožňuje aplikácii čítať ľubovoľné prostriedky v skupine diag, napr. súbory v priečinku /dev, a zapisovať do nich. Môže dôjsť k ovplyvneniu stability a bezpečnosti systému. Toto nastavenie by mal používať IBA výrobca či operátor na diagnostiku hardvéru."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"povolenie a zakázanie súčastí aplikácií"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Umožňuje aplikácii zmeniť, či je súčasť inej aplikácie povolená alebo nie. Škodlivé aplikácie môžu pomocou tohto nastavenia zakázať dôležité funkcie tabletu. V rámci tohto povolenia treba postupovať opatrne, pretože tu hrozí možnosť spôsobenia nepoužiteľnosti, nekonzistentnosti či nestability súčastí aplikácie."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Umožňuje aplikácii zmeniť, či je súčasť inej aplikácie povolená alebo nie. Škodlivé aplikácie môžu pomocou tohto nastavenia zakázať dôležité funkcie tabletu. V rámci tohto povolenia treba postupovať opatrne, pretože tu hrozí možnosť spôsobenia nepoužiteľnosti, nekonzistentnosti či nestability súčastí aplikácie."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Umožňuje aplikácii zmeniť, či je súčasť inej aplikácie povolená alebo nie. Škodlivé aplikácie môžu pomocou tohto nastavenia zakázať dôležité funkcie tabletu. Treba postupovať opatrne, pretože tu hrozí možnosť spôsobenia nepoužiteľnosti, nekonzistentnosti či nestability súčastí aplikácie."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Umožňuje aplikácii zmeniť povolenia súčastí iných aplikácií. Škodlivé aplikácie môžu pomocou tohto nastavenia zakázať dôležité funkcie telefónu. Je nutné postupovať opatrne, pretože tu hrozí možnosť spôsobenia nefunkčnosti, nekonzistentnosti či nestability súčastí aplikácie."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"nastavenie uprednostňovaných aplikácií"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Umožňuje aplikácii zmeniť vaše preferované aplikácie. Toto nastavenie môže škodlivým aplikáciám umožniť nepozorovane zmeniť spustené aplikácie a oklamať vaše existujúce aplikácie tak, aby zhromažďovali vaše súkromné údaje."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"zmeny globálnych nastavení systému"</string>
@@ -298,7 +296,7 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"zmeny mapy služieb Google"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"Umožňuje aplikácii zmeniť mapu služieb Google. Bežné aplikácie toto nastavenie nevyužívajú."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"automatické spustenie pri štarte"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Umožňuje aplikácii spustenie hneď po spustení systému. Toto nastavenie môže spomaliť spustenie tabletu a umožniť aplikácii celkovo spomaliť tablet, pretože bude neustále spustená."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Umožňuje aplikácii spustiť sa hneď po spustení systému. Toto nastavenie môže spomaliť spustenie tabletu a ako aj celkový výkon tabletu, pretože bude neustále spustená."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Umožňuje aplikácii spustenie hneď po spustení systému. Toto nastavenie môže spomaliť spustenie telefónu a umožniť aplikácii celkovo spomaliť telefón, pretože bude neustále spustená."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"odoslanie trvalého vysielania"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Umožňuje aplikácii odosielať trvalé vysielania, ktoré pretrvávajú aj po skončení vysielania. Škodlivé aplikácie môžu tablet spomaliť alebo spôsobiť jeho nestabilitu, pretože bude používať príliš veľa pamäte."</string>
@@ -324,7 +322,7 @@
     <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Umožňuje aplikácii prístup k zdrojom presnej polohy v tablete, ako je napríklad systém GPS (ak je k dispozícii). Škodlivé aplikácie môžu pomocou tohto nastavenia zistiť vašu polohu a môžu zvýšiť spotrebu batérie."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Umožňuje aplikácii prístup k zdrojom presnej polohy v telefóne, ako je napríklad systém GPS (ak je k dispozícii). Škodlivé aplikácie môžu pomocou tohto nastavenia zistiť vašu polohu a môžu zvýšiť spotrebu batérie."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"približná poloha (pomocou siete)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Umožňuje pristupovať k zdrojom približnej polohy, ako je napríklad databáza mobilnej siete (ak je k dispozícii), a určiť približnú polohu tabletu. Škodlivé aplikácie takto môžu zistiť, kde sa približne nachádzate."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Umožňuje pristupovať k zdrojom približnej polohy, ako je napríklad databáza mobilnej siete (pokiaľ je k dispozícii), a určiť približnú polohu tabletu. Škodlivé aplikácie takto môžu zistiť, kde sa približne nachádzate."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Umožňuje pristupovať k zdrojom približnej polohy, ako je napríklad databáza mobilnej siete (pokiaľ je k dispozícii), a určiť približnú polohu telefónu. Škodlivé aplikácie takto môžu zistiť, kde sa približne nachádzate."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"prístup k službe SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Umožňuje aplikácii používať nízkoúrovňové funkcie SurfaceFlinger."</string>
@@ -334,8 +332,8 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Umožňuje aplikácii zmeniť globálne nastavenie zvuku, napríklad hlasitosť alebo smerovanie."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"záznam zvuku"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Umožňuje aplikácii pristupovať k zaznamenávaniu zvuku."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"fotografovanie"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Umožňuje aplikácii fotografovať pomocou fotoaparátu. Toto nastavenie aplikácie umožní zhromažďovať fotografie vecí, na ktoré je práve fotoaparát namierený."</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"snímanie fotografií a natáčanie videí"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Umožňuje aplikácii fotografovať a natáčať videá pomocou fotoaparátu. Toto nastavenie aplikácie umožní zhromažďovať fotografie vecí, na ktoré je práve fotoaparát namierený."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"trvalé zakázanie tabletu"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"trvalé vypnutie telefónu"</string>
     <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Umožňuje aplikácii natrvalo vypnúť celý tablet. Toto je veľmi nebezpečné nastavenie."</string>
@@ -348,23 +346,25 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Umožňuje aplikácii pripojiť a odpojiť súborové systémy vo vymeniteľných ukladacích priestoroch."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formátovať externý ukladací priestor"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Umožňuje aplikácii formátovať vymeniteľný ukladací priestor."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"získať informácie o zabezpečenom ukladacom priestore"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Umožňuje aplikácii získať informácie o zabezpečenom ukladacom priestore."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"vytvoriť zabezpečený ukladací priestor"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Umožňuje aplikácii vytvoriť zabezpečený ukladací priestor."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"zničiť zabezpečený ukladací priestor"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Umožňuje aplikácii zničiť zabezpečený ukladací priestor."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"pripojiť alebo odpojiť zabezpečený ukladací priestor"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Umožňuje aplikácii pripojiť alebo odpojiť zabezpečený ukladací priestor."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"premenovať zabezpečený ukladací priestor"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Umožňuje aplikácii premenovať zabezpečený ukladací priestor."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"získať informácie o internom ukladacom priestore"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Umožňuje aplikácii získať informácie o internom ukladacom priestore."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"vytvoriť interný ukladací priestor"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Umožňuje aplikácii vytvoriť interný ukladací priestor"</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"zničiť interný ukladací priestor"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Umožňuje aplikácii zničiť interný ukladací priestor."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"pripojiť alebo odpojiť interný ukladací priestor"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Umožňuje aplikácii pripojiť alebo odpojiť interný ukladací priestor."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"premenovať interný ukladací priestor"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Umožňuje aplikácii premenovať interný ukladací priestor."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"ovládanie vibrácií"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Umožňuje aplikácii ovládať vibrácie."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"ovládanie kontrolky"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Umožňuje aplikácii ovládať kontrolku."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"prístup k zariadeniam USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Umožní aplikácii prístup k zariadeniam USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testovanie hardvéru"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Umožňuje aplikácii ovládať rôzne periférie na účely testovania hardvéru."</string>
@@ -441,12 +441,10 @@
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Umožňuje aplikácii konfigurovať miestny tablet s rozhraním Bluetooth a vyhľadávať a párovať vzdialené zariadenia."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Umožňuje aplikácii konfigurovať miestny telefón s rozhraním Bluetooth a vyhľadávať a párovať vzdialené zariadenia."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"vytvorenie pripojenia Bluetooth"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Umožňuje aplikácii zobraziť konfiguráciu miestneho tabletu s rozhraním Bluetooth, vytvárať pripojenia k spárovaným zariadeniam a prijímať tieto pripojenia."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Umožňuje aplikácii zobraziť konfiguráciu miestneho tabletu s rozhraním Bluetooth, vytvárať pripojenie na spárované zariadenia a prijímať tieto pripojenia."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Umožňuje aplikácii zobraziť konfiguráciu miestneho telefónu s rozhraním Bluetooth, vytvárať pripojenie na spárované zariadenia a prijímať tieto pripojenia."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"ovládať technológiu Near Field Communication"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Umožňuje aplikácii komunikovať so štítkami, kartami a čítačkami s podporou technológie Near Field Communication (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"zakázanie uzamknutia klávesnice"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Umožňuje aplikácii vypnúť uzamknutie klávesnice a súvisiace zabezpečenie heslom. Príkladom oprávneného použitia tejto funkcie je vypnutie uzamknutia klávesnice pri prichádzajúcom hovore a jej opätovné zapnutie po skončení hovoru."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čítanie nastavení synchronizácie"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Umožní aplikácii čítať súkromné slová, mená a frázy, ktoré mohol používateľ uložiť do svojho slovníka."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"zapisovať do slovníka definovaného používateľom"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Umožňuje aplikácii zapisovať nové slová do používateľského slovníka."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"Zmeniť/odstrániť obsah karty SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"upraviť/odstrániť obsah ukl. pr. USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"Zmeniť/odstrániť obsah karty SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Umožňuje aplikácii zápis na kartu SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Umožní zápis do ukl. priestoru USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Umožňuje aplikácii zápis na kartu SD."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"úprava alebo odstránenie obsahu interného ukladacieho priestoru média"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Umožňuje aplikácii upraviť obsah interného ukladacieho priestoru média."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"pristupovať do súborového systému vyrovnávacej pamäte"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Umožňuje aplikácii čítať a zapisovať do súborového systému vyrovnávacej pamäte."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Obmedzenie hesla"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Obmedzuje typ hesiel, ktoré je možné použiť."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovanie pokusov o prihlásenie"</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"uskutočňovať a prijímať internetové hovory"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Umožňuje aplikácii uskutočniť a prijímať internetové hovory pomocou služby SIP."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Ovládať dĺžku hesiel pre odomknutie obrazovky a v nich používané znaky"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Sledovať pokusy o odomknutie obrazovky"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Sledovať počet nesprávnych hesiel zadaných pri odomykaní obrazovky a uzamknúť tablet alebo odstrániť všetky údaje tabletu v prípade príliš veľkého počtu neplatných pokusov o zadanie hesla"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Sledovať počet nesprávnych hesiel zadaných pri odomykaní obrazovky a uzamknúť tablet alebo odstrániť všetky údaje tabletu v prípade príliš veľkého počtu neplatných pokusov o zadanie hesla"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Obnovenie hesla"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Vynúti nastavenie hesla na novú hodnotu, ktorú vám pred prihlásením musí oznámiť správca."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Vynútenie uzamknutia"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Určuje, kedy sa zariadenie uzamkne a bude vyžiadané opätovné zadanie hesla."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Sledovať počet nesprávnych hesiel zadaných pri odomykaní obrazovky a uzamknúť telefón alebo odstrániť všetky údaje telefónu v prípade príliš veľkého počtu neplatných pokusov o zadanie hesla"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Zmeniť heslo na odomknutie obrazovky"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Zmeniť heslo na odomknutie obrazovky"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Uzamknúť obrazovku"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Ovládať podmienky a spôsob uzamknutia obrazovky"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Vymazanie všetkých údajov"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Bez predchádzajúceho upozornenia zmazať všetky údaje tým, že sa obnovia továrenské nastavenia tabletu"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Bez predchádzajúceho upozornenia zmazať všetky údaje tým, že sa obnovia továrenské nastavenia tabletu"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Bez predchádzajúceho upozornenia zmazať všetky údaje tým, že sa obnovia továrenské nastavenia telefónu"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nastaviť globálny server proxy zariadenia"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Vyberte globálny server proxy, ktorý sa bude používať po aktivácii pravidiel. Platný globálny server proxy nastavuje iba prvý správca zariadenia."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Nastav. koniec platnosti hesla"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Ovládanie doby, po uplynutí ktorej treba zmeniť heslo na odomknutie obrazovky"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domovská stránka"</item>
     <item msgid="869923650527136615">"Mobil"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Pracovný pager"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Asistent"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Vlastné"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Narodeniny"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Výročie"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Udalosť"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Iné"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Vlastné"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Domovská stránka"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Práca"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Práca"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Iné"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Vlastné"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Vlastné"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Asistent"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Brat"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Dieťa"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Domáci partner"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Otec"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Priateľ"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Manažér"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Matka"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Rodič"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Partner(-ka)"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Referencie od"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Príbuzný(-á)"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Sestra"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Manžel(-ka)"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Vlastné"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Domovská stránka"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Práca"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Iné"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Zadajte kód PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Zadajte heslo pre odomknutie"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Zadajte kód PIN pre odomknutie"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Nesprávny kód PIN"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Ak chcete telefón odomknúť, stlačte Menu a následne 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Číslo tiesňového volania"</string>
@@ -646,8 +615,7 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Zavolať späť"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Správne!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Je nám ľúto, skúste to znova"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Je nám ľúto, skúste to znova"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Nabíjanie (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Nabité."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Karta SIM je uzamknutá."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Prebieha odomykanie karty SIM..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste použili nesprávny bezpečnostný vzor. "\n\n"Skúste to znova o <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po ďalších neúspešných pokusoch (<xliff:g id="NUMBER_1">%d</xliff:g>) budete požiadaní o odblokovanie tabletu pomocou prihlásenia do služby Google."\n\n"Skúste to znova o niekoľko sekúnd (<xliff:g id="NUMBER_2">%d</xliff:g>)."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste nesprávne zadali heslo. "\n\n"Skúste to znova o <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste nesprávne zadali kód PIN. "\n\n"Skúste to znova o <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po ďalších neúspešných pokusoch (<xliff:g id="NUMBER_1">%d</xliff:g>) budete požiadaní o odblokovanie tabletu pomocou prihlásenia do služby Google."\n\n" Skúste to znova o <xliff:g id="NUMBER_2">%d</xliff:g> sekúnd."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"<xliff:g id="NUMBER_0">%d</xliff:g>-krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po ďalších neúspešných pokusoch (<xliff:g id="NUMBER_1">%d</xliff:g>) budete požiadaní o odblokovanie telefónu pomocou prihlásenia do služby Google."\n\n" Skúste to znova o niekoľko sekúnd (<xliff:g id="NUMBER_2">%d</xliff:g>)."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Počet sekúnd zostávajúcich do ďalšieho pokusu: <xliff:g id="NUMBER">%d</xliff:g>."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Zabudli ste vzor?"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Chcete opustiť túto stránku?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Ak chcete pokračovať, vyberte OK. Ak chcete zostať na stránke, vyberte Zrušiť."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Potvrdiť"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Tip: Dvojitým klepnutím môžete zobrazenie priblížiť alebo oddialiť."</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"Aut. dop."</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"Automatické dopĺňanie"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Nast. Auto. dopĺň."</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"Čítanie histórie a záložiek prehliadača"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Umožňuje aplikácii čítať všetky adresy URL navštívené prehliadačom a záložky prehliadača."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"Zapisovať históriu a záložky prehliadača"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Umožňuje aplikácii zmeniť históriu prehliadača alebo záložky uložené v tablete. Škodlivé aplikácie môžu pomocou tohto nastavenia vymazať alebo pozmeniť údaje prehliadača."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Umožňuje aplikácii zmeniť históriu prehliadača alebo záložky uložené v telefóne. Škodlivé aplikácie môžu pomocou tohto nastavenia vymazať alebo pozmeniť údaje prehliadača."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"nastaviť budík"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Umožní aplikácii nastaviť budík v nainštalovanej aplikácii budíka. Niektoré aplikácie budíka nemusia túto funkciu obsahovať."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Zmeniť oprávnenia prehliadača poskytovať informácie o zemepisnej polohe"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Umožňuje aplikácii zmeniť oprávnenie prehliadača poskytovať informácie o zemepisnej polohe. Škodlivé aplikácie môžu toto nastavenie použiť na odosielanie informácií o umiestnení na ľubovoľné webové stránky."</string>
     <string name="save_password_message" msgid="767344687139195790">"Chcete, aby si prehliadač zapamätal toto heslo?"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"Vystrihnúť"</string>
     <string name="copy" msgid="2681946229533511987">"Kopírovať"</string>
     <string name="paste" msgid="5629880836805036433">"Prilepiť"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Nie je čo vložiť"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Skopírovať adresu URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Vybrať text..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Výber textu"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Metóda vstupu"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Upraviť text"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Operácie s textom"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Nedostatok pamäte"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"V tablete je málo miesta na ukladanie údajov."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"V ukladacom priestore tabletu je málo miesta."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"V telefóne je málo miesta na ukladanie údajov."</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Zrušiť"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
     <string name="no" msgid="5141531044935541497">"Zrušiť"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Pozor"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Prebieha načítavanie..."</string>
     <string name="capital_on" msgid="1544682755514494298">"ZAPNUTÉ"</string>
     <string name="capital_off" msgid="6815870386972805832">"VYPNUTÉ"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Dokončiť akciu pomocou aplikácie"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Vynútenie zavretia"</string>
     <string name="report" msgid="4060218260984795706">"Prehľad"</string>
     <string name="wait" msgid="7147118217226317732">"Čakajte"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Aplikácia bola presmerov."</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"Je spustená aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Pôvodne bola spustená aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="smv_application" msgid="295583804361236288">"Aplikácia <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) porušila svoje vlastné vynútené pravidlá StrictMode."</string>
+    <string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> porušil svoje vlastné vynútené pravidlá StrictMode."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"Spustená aplikácia: <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Túto možnosť vyberte, ak chcete prepnúť na aplikáciu."</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Prepnúť medzi aplikáciami?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Pred spustením novej aplikácie treba zastaviť inú spustenú aplikáciu."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Návrat k <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Nespúšťať novú aplikáciu."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Spustiť <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Zastaviť starú aplikáciu bez uloženia."</string>
     <string name="sendText" msgid="5132506121645618310">"Vyberte akciu pre text"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Hlasitosť vyzváňania"</string>
     <string name="volume_music" msgid="5421651157138628171">"Hlasitosť médií"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Zobraziť všetky"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Ukladací priestor USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Zariadenie USB pripojené"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Svoj telefón ste pripojili k počítaču pomocou USB. Ak chcete kopírovať súbory z počítača na kartu SD v zariadení so systémom Android alebo obrátene, vyberte nasledujúce tlačidlo."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Svoj telefón ste pripojili k počítaču pomocou USB. Ak chcete kopírovať súbory z počítača na kartu SD v zariadení so systémom Android alebo obrátene, vyberte nasledujúce tlačidlo."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Zariadenie ste pripojili k počítaču pomocou USB. Ak chcete kopírovať súbory z počítača do ukladacieho priestoru USB v zariadení so systémom Android alebo naopak, dotknite sa nasledujúceho tlačidla."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Zariadenie ste pripojili k počítaču pomocou USB. Ak chcete kopírovať súbory z počítača na kartu SD v zariadení so systémom Android alebo naopak, dotknite sa nasledujúceho tlačidla."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Zapnúť ukladací priestor USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Pri používaní vašej karty SD ako ukladacieho priestoru USB sa vyskytol problém."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Pri používaní vašej karty SD ako ukladacieho priestoru USB sa vyskytol problém."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Pri používaní vášho ukladacieho priestoru USB ako veľkokapacitného ukladacieho priestoru USB sa vyskytol problém."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Pri používaní vašej karty SD ako veľkokapacitného ukladacieho priestoru USB sa vyskytol problém."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Zariadenie USB pripojené"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Vyberte, ak chcete kopírovať súbory do/z počítača."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Vypnúť ukladací priestor USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Vyberte, ak chcete vypnúť ukladací priestor USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Ukladací priestor USB sa používa"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Pred vypnutím ukladacieho priestoru USB skontrolujte, či ste odpojili („vysunuli“) kartu SD zariadenia Android z počítača."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Pred vypnutím ukladacieho priestoru USB skontrolujte, či ste ho odpojili („vysunuli“) od počítača."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Pred vypnutím ukladacieho priestoru USB skontrolujte, či ste odpojili („vysunuli“) kartu SD zariadenia Android z počítača."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Vypnúť ukladací priestor USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Pri vypínaní ukladacieho priestoru USB sa vyskytol problém. Skontrolujte, či bol hostiteľ USB odpojený, a skúste to znova."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ak zapnete ukladací priestor USB, dôjde k zastaveniu niektorých používaných aplikácií. Tieto aplikácie pravdepodobne nebudú k dispozícii až do vypnutia ukladacieho priestoru USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Chyba operácie na rozhraní USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formátovať kartu SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formát. ukl. priestor USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formátovať kartu SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Naozaj chcete naformátovať kartu SD? Stratíte všetky údaje na karte."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Chcete ukladací priestor USB naformátovať a vymazať tak všetky súbory, ktoré sú v ňom uložené? Túto akciu nie je možné vrátiť späť."</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Naozaj chcete naformátovať kartu SD? Stratíte všetky údaje na karte."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formát"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Ladenie cez rozhranie USB pripojené"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁÄBCČDĎDZDŽEÉFGHCHIÍJKLĽMNŇOÓÔPRŔSŠTŤUÚVWXYÝZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidáti"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Príprava karty SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Príprava uklad. priestoru USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Príprava karty SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Kontrola chýb."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Prázdna karta SD"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Prázdny ukladací priestor USB"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Prázdna karta SD"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Karta SD je prázdna alebo obsahuje nepodporovaný systém súborov."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Ukladací priestor USB je prázdny alebo obsahuje nepodporovaný systém súborov."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Karta SD je prázdna alebo obsahuje nepodporovaný systém súborov."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Poškodená karta SD"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Ukl. priestor USB je poškodený"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Poškodená karta SD"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Karta SD je poškodená. Pravdepodobne ju bude treba znova naformátovať."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Ukladací priestor USB je poškodený. Pravdepodobne ho bude treba znova naformátovať."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Karta SD je poškodená. Pravdepodobne ju bude treba znova naformátovať."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Karta SD bola neočakávane odobraná"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Ukl. priestor USB nečakane odstránený"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Karta SD bola neočakávane odobraná"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Ak chcete zabrániť strate údajov, kartu SD pred odobratím odpojte."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Ak chcete zabrániť strate údajov, ukladací priestor USB pred odobratím odpojte."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Ak chcete zabrániť strate údajov, kartu SD pred odobratím odpojte."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Kartu SD je možné bezpečne odobrať"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Ukl. priestor USB môžete odobrať"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Kartu SD je možné bezpečne odobrať"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Kartu SD je možné bezpečne odobrať."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Ukladací priestor USB môžete bezpečne odstrániť."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Kartu SD je možné bezpečne odobrať."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Karta SD bola odobraná"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Ukl. priestor USB odstránený"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Karta SD bola odobraná"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Karta SD bola odobraná. Vložte novú kartu."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Ukladací priestor USB odstránený. Vložte nové médium."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Karta SD bola odobraná. Vložte novú kartu."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Neboli nájdené žiadne zodpovedajúce činnosti."</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"aktualizovať štatistiku použitia súčastí"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Odoslať"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Ďalej"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Hotovo"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Predch."</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Vykonať"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Vytočiť číslo"\n" <xliff:g id="NUMBER">%s</xliff:g>."</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Vytvoriť kontakt"\n"pre <xliff:g id="NUMBER">%s</xliff:g>."</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Sieť VPN L2TP/IPSec s vopred zdieľaným kľúčom"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Sieť VPN L2TP/IPSec s certifikátom"</string>
     <string name="upload_file" msgid="2897957172366730416">"Zvoliť súbor"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Nie je vybratý žiadny súbor"</string>
     <string name="reset" msgid="2448168080964209908">"Obnoviť"</string>
     <string name="submit" msgid="1602335572089911941">"Odoslať"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Aktivovaný režim V aute"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Vyberte, ak chcete ukončiť režim V aute."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Tethering alebo prístupový bod je aktívny"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Dotykom spustíte konfiguráciu"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Späť"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Ďalej"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Preskočiť"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Vysoké využitie mobilných údajov"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Dotykom zobrazíte viac informácií o využití mobilných údajov"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Bol prekročený limit mobilných údajov"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Dotykom zobrazíte viac informácií o využití mobilných údajov"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Žiadne zhody"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Vyhľadať na stránke"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"Počet zhôd: 1"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> z <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Hotovo"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Odpájanie ukladacieho priestoru USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Odpájanie karty SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Prebieha vymazávanie ukladacieho priestoru USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Prebieha vymazávanie karty SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Vymazanie ukladacieho priestoru USB zlyhalo."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Vymazanie karty SD zlyhalo."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Karta SD nebola pred odstránením odpojená."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Prebieha kontrola ukladacieho priestoru USB."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Prebieha kontrola karty SD."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Karta SD bola odstránená."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Ukladací priestor USB je momentálne používaný počítačom."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Karta SD sa momentálne používa počítačom."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Neznámy stav externého média."</string>
+    <string name="share" msgid="1778686618230011964">"Zdieľať"</string>
+    <string name="find" msgid="4808270900322985960">"Nájsť"</string>
+    <string name="websearch" msgid="4337157977400211589">"Hľadať na webe"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 43993d4..91c42a8 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Glasovna pošta"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Težava s povezavo ali neveljavna koda MMI."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Operacija je omejena na dovoljene telefonske številke, za katere ne velja zapora odhodnega klica."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Storitev je omogočena."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Storitev je bila omogočena za:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Storitev je onemogočena."</string>
@@ -126,7 +125,7 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"Sinhronizacija"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinhronizacija"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Preveč izbrisov vsebine <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Pomnilnik tabličnega računalnika je poln. Izbrišite nekaj datotek, da sprostite prostor."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Shramba tabličnega računalnika je polna. Izbrišite nekaj datotek, da sprostite prostor."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"Pomnilnik telefona je poln. Izbrišite nekaj datotek, da sprostite prostor."</string>
     <string name="me" msgid="6545696007631404292">"Jaz"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Možnosti tabličnega računalnika"</string>
@@ -137,10 +136,9 @@
     <string name="screen_lock" msgid="799094655496098153">"Zaklep zaslona"</string>
     <string name="power_off" msgid="4266614107412865048">"Izklopi"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Se zaustavlja ..."</string>
-    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablični računalnik bo zaustavljen."</string>
+    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablični računalnik se bo zaustavil."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefon bo zaustavljen."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Ali želite izklopiti telefon?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Nedavno"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Ni nedavnih programov."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Možnosti tabličnega računalnika"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Način za letalo"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Način za letalo je VKLOPLJEN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Način za letalo je IZKLOPLJEN"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Plačljive storitve"</string>
@@ -160,7 +160,7 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Vaša sporočila"</string>
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"Pisanje in branje sporočil SMS, e-pošte in drugih sporočil."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Osebni podatki"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Neposreden dostop do stikov in koledarja, shranjenih v tabličnem računalniku."</string>
+    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Neposreden dostop do stikov in koledarskih vnosov, shranjenih v tabličnem računalniku."</string>
     <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Neposreden dostop do stikov in koledarja, shranjenega v telefonu."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Vaša lokacija"</string>
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Spremljanje fizične lokacije"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Razvojna orodja"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Funkcije, ki jih potrebujejo le razvijalci programa."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Prostor za shranjevanje"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Dostop do kartice SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Dostop do pomnilnika USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Dostop do kartice SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"onemogočanje ali spreminjanje vrstice stanja"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Programom dovoljuje onemogočenje vrstice stanja ali dodajanje in odstranjevanje ikone sistema."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"vrstica stanja"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Programu omogoča, da postane vrstica stanja."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"razširjanje/strnjevanje vrstice stanja"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Programu dovoljuje razširjanje ali strjevanje vrstice stanja."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"prestrezanje odhodnih klicev"</string>
@@ -196,10 +194,10 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"pošiljanje sporočil SMS"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Programom dovoljuje pošiljanje sporočil SMS. Zlonamerni programi lahko pošiljajo sporočila brez vaše potrditve, kar vas lahko drago stane."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"branje sporočil SMS ali MMS"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Programu dovoljuje branje sporočil SMS, shranjenih v tabličnem računalniku ali na kartici SIM. Zlonamerni programi lahko berejo vaša zaupna sporočila."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Programu omogoča branje sporočil SMS, shranjenih v tabličnem računalniku ali na kartici SIM. Zlonamerni programi lahko preberejo vaša zaupna sporočila."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Programu dovoljuje branje sporočil SMS, shranjenih v telefonu ali na kartici SIM. Zlonamerni programi lahko berejo vaša zaupna sporočila."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"urejanje sporočil SMS ali MMS"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Programu dovoljuje pisanje v sporočila SMS, shranjena v tabličnem računalniku ali na kartici SIM. Zlonamerni programi lahko izbrišejo sporočila."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Programu omogoča zapisovanje v sporočila SMS, shranjena v tabličnem računalniku ali na kartici SIM. Zlonamerni programi lahko izbrišejo vaša sporočila."</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Programu dovoljuje pisanje v sporočila SMS, shranjena v telefonu ali na kartici SIM. Zlonamerni programi lahko izbrišejo sporočila."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"prejemanje sporočil WAP"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Programom dovoljuje sprejemanje in obdelavo sporočil WAP. Zlonamerni programi lahko spremljajo vaša sporočila ali jih izbrišejo, ne da bi vam jih pokazali."</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"preprečevanje preklopa programov"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Uporabniku preprečuje preklop v drug program."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"spremljanje in nadzor vseh zagonov programov"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Programu dovoljuje, da nadzira, kako sistem zaganja dejavnosti. Zlonamerni programi lahko ogrozijo celotno varnost sistema. To dovoljenje je potrebno le pri razvoju, nikoli pri navadni rabi."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Programu omogoča spremljanje in nadziranje načina, kako sistem zažene dejavnosti. Zlonamerni programi lahko v celoti ogrozijo varnost sistema. To dovoljenje je potrebno samo za razvoj, vendar ne za običajno uporabo."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"pošiljanje oddaje brez paketa"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Programu dovoljuje oddajanje obvestila, da je bil paket programa odstranjen. Zlonamerni programi lahko to uporabijo za zaustavitev morebitnih drugih programov, ki se izvajajo."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"pošiljanje oddaje, prejete prek SMS-a"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"prikazovanje nepooblaščenih oken"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Dovoljuje ustvarjanje oken, ki jih bo uporabljal uporabniški vmesnik notranjega sistema. Ni za uporabo z navadnimi programi."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"prikaz opozoril na ravni sistema"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Programu dovoljuje, da pokaže okna z opozorili sistema. Zlonamerni programi lahko prevzamejo celoten zaslon."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Programu omogoča prikaz oken s sistemskimi opozorili. Zlonamerni programi lahko zavzamejo celoten zaslon."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"spreminjanje splošne hitrosti animacij"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Dovoljuje, da program kadar koli spremeni splošno hitrost animacije (hitrejše ali počasnejše animacije)."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"upravljanje žetonov programa"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Dovoljuje, da programi ustvarijo in upravljajo svoje žetone ter obidejo navadno razvrščanje Z. Tega nikoli ni treba uporabiti za navadne programe."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"pritiskanje tipk in gumbov za nadzor"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Programu dovoljuje, da svoje dogodke vnosa (pritiske tipk ipd.) dostavi drugim programom. Zlonamerni programi lahko s tem prevzamejo nadzor nad tabličnim računalnikom."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Programu omogoča pošiljanje lastnih vnosov, na primer pritisnjene tipke in podobno, drugim programom. Zlonamerni program lahko s tem dovoljenjem prevzame nadzor nad tabličnim računalnikom."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Dovoljuje, da programi svoje dogodke vnosa (pritiske tipk ipd.) dostavijo drugim programom. Zlonamerni programi lahko s tem prevzamejo nadzor nad telefonom."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"snemanje vnesenega besedila in dejanj, ki jih izvedete"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Programu dovoljuje spremljanje tipk, ki jih pritisnete med interakcijo z drugim programom (na primer vnos gesla). Navadni programi tega nikoli ne potrebujejo."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"neposredno nameščanje programov"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Programu dovoljuje namestitev novih ali posodobljenih paketov sistema Android. Zlonamerni programi lahko to uporabijo za dodajanje novih programov s poljubnimi zmogljivimi dovoljenji."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"brisanje vseh podatkov predpomnilnika programa"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Programu dovoljuje sproščanje pomnilnika tabličnega računalnika z brisanjem datotek v imeniku predpomnilnika telefona. Dostop je zelo omejen, navadno le na sistemske procese."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Programu omogoča sprostitev shrambe tabličnega računalnika, tako da izbriše datoteke v predpomnilniškem imeniku programa. Dostop je običajno omejen na sistemske procese."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Programu dovoljuje sproščanje pomnilnika telefona z brisanjem datotek v imeniku predpomnilnika telefona. Dostop je zelo omejen, navadno le na sistemske procese."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Premikanje sredstev programa"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Dovoljuje, da programi sredstva programov z notranjih premaknejo na zunanje medije in obratno."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"branje dnevniških datotek sistema"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Programu dovoljuje branje iz različnih dnevniških datotek sistema. Tako lahko odkrije splošne informacije o tem, kaj počnete s tabličnim računalnikom, kar lahko vključuje tudi osebne ali zasebne informacije."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Programu dovoljuje branje iz različnih dnevniških datotek sistema. Tako lahko odkrije splošne informacije o tem, kaj počnete s tabličnim računalnikom, kar lahko vključuje tudi osebne ali zasebne informacije."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"branje občutljivih dnevniških podatkov"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Programu omogoča branje različnih sistemskih dnevniških datotek. To mu omogoča dostop do splošnih podatkov v tabličnem računalniku, lahko tudi do osebnih podatkov."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Programu omogoča branje različnih sistemskih dnevniških datotek. To mu omogoča dostop do splošnih podatkov v telefonu, lahko tudi do osebnih podatkov."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"branje/pisanje v sredstva, ki so v lasti skupine za diagnostiko"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Programu dovoljuje branje in pisanje na poljuben vir, ki je v lasti skupine za diagnostiko; na primer datoteke v mapi /dev. To lahko vpliva na stabilnost in varnost sistema. To naj uporablja SAMO izdelovalec ali operater za diagnostiko, specifično za strojno opremo."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"omogočanje ali onemogočanje komponent programa"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Programu dovoljuje, da spremeni, ali je komponenta drugega programa omogočena ali ne. Zlonamerni programi lahko to uporabijo za onemogočanje pomembnih zmožnosti tabličnega računalnika. Pri dodeljevanju dovoljenja je treba biti previden, saj lahko komponente programa nastavite tako, da jih ni mogoče uporabiti, da niso dosledne ali pa da postanejo nestabilne."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Programu dovoljuje, da spremeni, ali je komponenta drugega programa omogočena ali ne. Zlonamerni programi lahko to uporabijo za onemogočanje pomembnih zmožnosti tabličnega računalnika. Pri dodeljevanju dovoljenja je treba biti previden, saj lahko komponente programa nastavite tako, da jih ni mogoče uporabiti, da niso dosledne ali pa da postanejo nestabilne."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Omogoča, da program spremeni, ali je komponenta drugega programa omogočena ali ne. Zlonamerni programi lahko s tem dovoljenjem onemogočijo pomembne telefonske funkcije. To dovoljenje uporabljajte previdno, ker lahko programske komponente postanejo neuporabne, nedosledne ali nestabilne."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Omogoča, da program spremeni, ali je komponenta drugega programa omogočena ali ne. Zlonamerni programi lahko s tem dovoljenjem onemogočijo pomembne telefonske funkcije. To dovoljenje uporabljajte previdno, ker lahko programske komponente postanejo neuporabne, nedosledne ali nestabilne."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"nastavitev prednostnih programov"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Programom dovoljuje spreminjanje priljubljenih programov. Zlonamerni programi lahko s tem neopazno spremenijo programe, ki se izvajajo, tako da se izdajajo za obstoječe programe in zbirajo osebne podatke."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"spreminjanje splošnih nastavitev sistema"</string>
@@ -298,19 +296,19 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"spreminjanje zemljevidov Googlovih storitev"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"Programu dovoljuje spreminjanje zemljevidov Googlovih storitev. Ni za uporabo z navadnimi programi."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"samodejni začetek pri zagonu"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Programu dovoljuje, da se zažene takoj, ko sistem dokonča zagon. Zaradi tega lahko zagon tabličnega računalnika traja nekoliko dlje, program pa lahko upočasni splošno delovanje tabličnega računalnika, ker se vedno izvaja."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Omogoča, da se program samodejno zažene po zagonu sistema. To lahko povzroči daljši zagon tabličnega računalnika in programu omogoči, da s stalnim izvajanjem upočasni delovanje tabličnega računalnika."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Dovoljuje, da se program zažene takoj, ko sistem dokonča zagon. Zaradi tega lahko zagon telefona traja nekoliko dlje, program pa lahko upočasni splošno delovanje telefona, ker se vedno izvaja."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"pošiljanje fiksne oddaje"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Programu dovoljuje hitro pošiljanje fiksnih oddaj, ki ostanejo po koncu oddajanja. Zaradi zlonamernih programov je delovanje tabličnega računalnika lahko počasno ali nestabilno ali tablični računalnik zaradi njih porabi preveč pomnilnika."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Programu omogoča pošiljanje fiksnih oddaj, ki ostanejo po koncu oddajanja. Zlonamerni programi lahko upočasnijo ali oslabijo delovanje računalnika, tako da zasedejo preveč pomnilnika."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Programu dovoljuje hitro pošiljanje fiksnih oddaj, ki ostanejo po koncu oddajanja. Zaradi zlonamernih programov je delovanje telefona lahko počasno ali nestabilno ali telefon zaradi njih porabi preveč pomnilnika."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"branje podatkov stika"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Programu dovoljuje branje vseh podatkov stika (naslov), shranjenih v tabličnem računalniku. Zlonamerni programi lahko to uporabijo za pošiljanje podatkov drugim osebam."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Programu omogoča branje vseh podatkov (naslovov) o stikih, shranjenih v tabličnem računalniku. Zlonamerni programi lahko s tem dovoljenjem pošljejo vaše podatke drugim uporabnikom."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Programu dovoljuje branje vseh podatkov stika (naslov), shranjenih v telefonu. Zlonamerni programi lahko to uporabijo za pošiljanje podatkov drugim osebam."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"pisanje podatkov stika"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Programu dovoljuje spreminjanje podatkov stika (naslov), shranjenih v tabličnem računalniku. Zlonamerni programi lahko to uporabijo za brisanje ali spreminjanje podatkov stika."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Programu omogoča spreminjanje podatkov (naslovov), shranjenih v tabličnem računalniku. Zlonamerni programi lahko s tem dovoljenjem izbrišejo ali spremenijo podatke o stikih."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Programu dovoljuje spreminjanje podatkov stika (naslov), shranjenih v telefonu. Zlonamerni programi lahko to uporabijo za brisanje ali spreminjanje podatkov stika."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"branje koledarskih dogodkov"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Programu dovoljuje branje vseh dogodkov koledarja, shranjenih v tabličnem računalniku. Zlonamerni programi lahko to uporabijo za pošiljanje dogodkov koledarja drugim osebam."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Programu omogoča branje vseh koledarskih vnosov, shranjenih v tabličnem računalniku. Zlonamerni programi lahko s tem dovoljenjem pošljejo vnose drugim uporabnikom."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Programu dovoljuje branje vseh dogodkov koledarja, shranjenih v telefonu. Zlonamerni programi lahko to uporabijo za pošiljanje dogodkov koledarja drugim osebam."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"dodajanje ali spreminjanje koledarskih dogodkov in pošiljanje e-pošte gostom"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Dovoljuje, da program doda ali spremeni dogodke v koledarju, s čimer bodo gostom morda poslana e-poštna sporočila. Zlonamerni programi lahko to uporabijo za brisanje ali spreminjanje koledarskih dogodkov ali pošiljanje e-pošte gostom."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"dovoljenje za namestitev ponudnika lokacije"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Ustvarjanje simuliranih virov lokacije za preskušanje. Zlonamerni programi lahko to uporabijo za preglasitev lokacije in/ali stanja, ki ga vrnejo pravi viri lokacije, kot je GPS ali ponudniki omrežja, ali za spremljanje in pošiljanje vaše lokacije zunanjemu viru."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"natančna lokacija (GPS)"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Dostopa do podrobnih virov lokacije, kot je sistem GPS v tabličnem računalniku, kjer so na voljo. Zlonamerni programi lahko s tem določijo, kje ste, in še dodatno porabijo baterijo."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Dostop do virov natančne lokacije, kot je sistem GPS, v tabličnem računalniku. Zlonamerni programi lahko s tem dovoljenjem ugotovijo vašo lokacijo in dodatno porabljajo baterijo."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Dostopa do podrobnih virov lokacije, kot je sistem GPS v telefonu, kjer so na voljo. Zlonamerni programi lahko s tem dovoljenjem določijo, kje ste, in še dodatno porabijo baterijo."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"groba ocena lokacije (temelječa na omrežju)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Dostopa do grobih virov lokacij, kot je zbirka podatkov brezžičnega omrežja, s katerimi je mogoče določiti približno lokacijo tabličnega računalnika, kjer so na voljo. Zlonamerni programi lahko s tem določijo, kje približno ste."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Dostop do virov grobe lokacije, kot je zbirka podatkov brezžičnega omrežja, s katerimi je mogoče določiti približno lokacijo tabličnega računalnika. Zlonamerni programi lahko s tem dovoljenjem določijo vašo približno lokacijo."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Dostop do grobih virov lokacij, kot je zbirka podatkov brezžičnega omrežja, s katerimi je mogoče določiti približno lokacijo telefona, kjer je na voljo. Zlonamerni programi lahko s tem določijo, kje približno ste."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"dostop do storitve SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Programu dovoljuje uporabo funkcij nizke ravni SurfaceFlinger."</string>
@@ -334,37 +332,39 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Programu dovoljuje spreminjanje splošnih zvočnih nastavitev, kot sta glasnost in usmerjanje."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"snemanje zvoka"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Programu dovoljuje dostop do poti zvočnega posnetka."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"ustvarjanje slik"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Programu dovoljuje ustvarjanje slik s fotoaparatom. To pomeni, da lahko program kadar koli posname sliko, ki je v objektivu fotoaparata."</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"fotografiranje in snemanje videoposnetkov"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Programu omogoča snemanje slik in videoposnetkov, tako lahko program kadar koli posname slike, ki jih zajame fotoaparat."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"trajno onemogočenje tabličnega računalnika"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"trajno onemogočenje telefona"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Programu dovoljuje, da trajno onemogoči celoten tablični računalnik. To je zelo nevarno."</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Programu omogoča trajno onemogočenje celotnega tabličnega računalnika. To je zelo nevarno dejanje."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Programu dovoljuje trajno onemogočenje celotnega telefona. To je zelo nevarno."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"vsiljen vnovičen zagon tabličnega računalnika"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"vsiljeni vnovični zagon"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"vsiljevanje vnovičnega zagona telefona"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Programu dovoljuje, da vsili vnovični zagon tabličnega računalnika."</string>
+    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Programu omogoča vsiljenje vnovičnega zagona tabličnega računalnika."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Dovoljuje, da program vsili vnovični zagon telefona."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"vpenjanje in izpenjanje datotečnih sistemov"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Programu dovoljuje vpenjanje in izpenjanje datotečnih sistemov za izmenljive shrambe."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"formatiranje zunanje shrambe"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Programu dovoljuje formatiranje izmenljive shrambe."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"pridobivanje informacij o varni shrambi"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Programu dovoljuje pridobivanje informacij o varni shrambi."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"ustvarjanje varne shrambe"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Programu dovoljuje ustvarjanje varne shrambe."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"uničenje varne shrambe"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Dovoljuje, da program uniči varno shrambo."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"vpenjanje/izpenjanje varne shrambe"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Programu dovoljuje vpenjanje/izpenjanje varne shrambe."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"preimenovanje varne shrambe"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Programu dovoljuje preimenovanje varne shrambe."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"informacije o notranjem pomnilniku"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Programu omogoča pridobivanje podatkov o notranji shrambi."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"ustvarjanje notranje shrambe"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Programu omogoča ustvarjanje notranje shrambe."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"uničenje notranje shrambe"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Programu omogoča uničenje notranje shrambe."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"vpenjanje in izpenjanje notranjega pomnilnika"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Programu omogoča vpenjanje in izpenjanje notranje shrambe."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"preimenovanje notranje shrambe"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Programu omogoča preimenovanje notranje shrambe."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"nadzor vibriranja"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Programu dovoljuje nadzor vibriranja."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"nadzor svetilke"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Programu dovoljuje nadzor svetilke."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"dostop do naprav USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Programu omogoča dostop do naprav USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"preskušanje strojne opreme"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Programu dovoljuje nadzor različnih zunanjih naprav za preskušanje strojne opreme."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"Dovoljuje, da program brez vašega posredovanja kliče telefonske številke. Zaradi zlonamernih programov so na vašem telefonskem računu lahko nepričakovani klici. Programu to ne dovoljuje opravljanja klicev v sili."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"neposredno klicanje poljubnih telefonskih številk"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Dovoljuje, da program brez vašega posredovanja pokliče poljubno telefonsko številko, vključno s klici v sili. Zlonamerni programi lahko opravljajo nepotrebne in nezakonite klice v sili."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"neposredni zagon nastavitve tabličnega računalnika CDMA"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"neposredni zagon namestitve tabličnega računalnika CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"neposredni zagon nastavitve telefona CDMA"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Programu dovoljuje zagon omogočanja uporabe CDMA. Zlonamerni programi lahko po nepotrebnem zaženejo omogočanje uporabe CDMA"</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"nadzor obvestil o posodobitvi lokacije"</string>
@@ -385,16 +385,16 @@
     <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Programu dovoljuje nadzor telefonskih funkcij naprave. Program lahko s tem dovoljenjem brez obvestila preklaplja omrežja, vklopi in izklopi radio telefona in podobno."</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"branje stanja in identitete telefona"</string>
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"Programu dovoljuje dostop do funkcij telefona v napravi. Program lahko s tem dovoljenjem določi telefonsko številko in serijsko številko tega telefona, določi lahko tudi, ali je klic aktiven, številko, s katero je klic povezan, in podobno."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"preprečevanje, da bi tablični računalnik prešel v stanje pripravljenosti"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"preprečitev prehoda tabličnega računalnika v stanje pripravljenosti"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"preprečevanje prehod v stanje pripravljenosti telefona"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Programu dovoljuje, da tabličnemu računalniku prepreči prehod v stanje pripravljenosti."</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Omogoča, da program prepreči prehod tabličnega računalnika v stanje pripravljenosti."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Dovoljuje, da program telefonu prepreči prehod v stanje pripravljenosti."</string>
     <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"vklop ali izklop tabličnega računalnika"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"vklop ali izklop telefona"</string>
-    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Programu dovoljuje vklop ali izklop tabličnega računalnika."</string>
+    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Programu omogoča vklop ali izklop tabličnega računalnika."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Programu dovoljuje vklop ali izklop telefona."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"izvajanje v preskusnem načinu delovanja"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Se izvaja kot preskus izdelovalca nizke ravni, ki dovoljuje popoln dostop do strojne opreme tabličnega računalnika. Na voljo le, ko tablični računalnik deluje v načinu preskusa izdelovalca."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Izvajanje kot proizvajalčev preskus na najnižjem nivoju, kar omogoča popoln dostop do strojne opreme tabličnega računalnika. Dovoljenje je na voljo, samo če se tablični računalnik izvaja v načinu proizvajalčevega preskusa."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Se izvaja kot preskus izdelovalca nizke ravni, ki dovoljuje popoln dostop do strojne opreme telefona. Na voljo le, ko se telefon izvaja v načinu preskusa izdelovalca."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"nastavljanje ozadja"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Programu dovoljuje nastavitev ozadja sistema."</string>
@@ -403,15 +403,15 @@
     <string name="permlab_masterClear" msgid="2315750423139697397">"ponastavitev sistema na privzete tovarniške nastavitve"</string>
     <string name="permdesc_masterClear" msgid="5033465107545174514">"Dovoljuje, da program v celoti ponastavi sistem na tovarniške nastavitve, izbriše vse podatke, konfiguracijo in nameščene programe."</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"nastavljanje ure"</string>
-    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Programu dovoljuje spremembo ure tabličnega računalnika."</string>
+    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Programu omogoča spreminjanje ure v tabličnem računalniku."</string>
     <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Programu dovoljuje spremembo ure telefona."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"nastavitev časovnega pasu"</string>
-    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Programu dovoljuje spreminjanje časovnega pasu tabličnega računalnika."</string>
+    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Programu omogoča spreminjanje časovnega pasu v tabličnem računalniku."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Programu dovoljuje spreminjanje časovnega pasu telefona."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"opravljanje vloge AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Programu dovoljuje klicanje AccountAuthenticators"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"odkrivanje znanih računov"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Programu dovoljuje pridobivanje seznama računov, ki jih pozna tablični računalnik."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Programu omogoča dostop do seznama računov, ki jih pozna tablični računalnik."</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Programu dovoljuje pridobivanje seznama računov, ki jih pozna telefon."</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"opravlja vlogo overovitelja računa"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Dovoljuje, da program uporabi zmožnosti overovitelja računa storitve AccountManager, vključno z ustvarjanjem računov ter s pridobivanjem in nastavljanjem njihovih gesel."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"dovoljevanje sprejema večvrstnega brezžičnega oddajanja"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Programu dovoljuje prejemanje paketov, ki niso naslovljeni neposredno na vašo napravo. To je lahko uporabno, ko odkrivate storitve, ki so dane na voljo v bližini. Poraba je večja od načina delovanja brez večvrstnega oddajanja."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"skrbništvo storitve Bluetooth"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Programu dovoljuje konfiguriranje lokalnega tabličnega računalnika s tehnologijo Bluetooth ter odkrivanje oddaljenih naprav in povezovanje z njimi."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Programu omogoča konfiguriranje lokalnega tabličnega računalnika Bluetooth ter zaznavanje oddaljenih naprav in združevanje z njimi."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Programu dovoljuje konfiguriranje lokalnega telefona s tehnologijo Bluetooth ter odkrivanje oddaljenih naprav in povezovanje z njimi."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"ustvarjanje povezav Bluetooth"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Programu dovoljuje ogled konfiguracije lokalnega tabličnega računalnika s tehnologijo Bluetooth ter ustvarjanje in sprejemanje povezave s povezanimi napravami."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Programu omogoča ogled konfiguracije lokalnega tabličnega računalnika Bluetooth ter vzpostavljanje in sprejemanje povezave z združenimi napravami."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Programom dovoljuje ogled konfiguracije lokalnega telefona Bluetooth ter ustvarjanje in sprejemanje povezave s povezanimi napravami."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"nadzor nad komunikacijo s tehnologijo bližnjega polja"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Podpira komunikacijo med računalnikom in oznakami, karticami in bralniki komunikacije s tehnologijo bližnjega polja."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"onemogočanje zaklepa tipkovnice"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Dovoljuje, da program onemogoči zaklep tipk in morebitno povezano varnostno geslo. Legitimen primer je onemogočenje zaklepa tipkovnice pri dohodnem klicu ter vnovičnem omogočanju zaklepa, ko je klic dokončan."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"branje nastavitev sinhronizacije"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Programu dovoljuje branje morebitnih zasebnih besed, imen in izrazov, ki jih je uporabnik shranil v uporabniški slovar."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"pisanje v uporabniško določen slovar"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Programu dovoljuje pisanje nove besede v uporabniški slovar."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"spreminjanje/brisanje vsebine kartice SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"spreminjanje vsebine pomnilnika USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"spreminjanje/brisanje vsebine kartice SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Programu dovoljuje pisanje na kartico SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Programu omogoča zapisovanje na pomnilnik USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Programu dovoljuje pisanje na kartico SD."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"spreminjanje/brisanje vsebine notranje shrambe nosilca podatkov"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Programu omogoča spreminjanje vsebine notranje shrambe nosilca podatkov."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"dostop do datotečnega sistema predpomnilnika"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Programu dovoljuje branje in pisanje v datotečni sistem predpomnilnika."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Omejevanje gesla"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Omejevanje vrste gesel, ki jih lahko uporabite."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Spremljanje poskusov prijave"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Nadzoruje število nepravilno vnesenih gesel pri odklepanju zaslona in zaklene tablični računalnik ali izbriše vse podatke na njem, če je vnesenih preveč nepravilnih gesel"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Nadzoruje število nepravilno vnesenih gesel pri odklepanju zaslona in zaklene tablični računalnik ali izbriše vse podatke na njem, če je vnesenih preveč nepravilnih gesel"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Ponastavitev gesla"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Vsilite novo vrednost za geslo. Pred prijavo vam jo mora dati skrbnik."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Vsiljen zaklep"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Nadzor časa zaklepa naprave, pri tem morate znova vnesti geslo."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"opravljanje/sprejemanje internetnih klicev"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Programu omogoča uporabo storitve SIP za opravljanje in sprejemanje internetnih klicev."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih za odklepanje zaslona"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"nadzor nad poskusi odklepanja zaslona"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Spremljajte število vnesenih napačnih gesel, s katerimi želite odkleniti zaslon. Če je teh vnosov preveč, zaklenite tablični računalnik ali izbrišite vse podatke v njem."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Spremljajte število vnesenih napačnih gesel, s katerimi želite odkleniti zaslon. Če je teh vnosov preveč, zaklenite telefon ali izbrišite vse podatke v njem"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Spreminjanje gesla za odklepanje zaslona"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Spreminjanje gesla za odklepanje zaslona"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Zaklepanje zaslona"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Nadzor nad načinom in trenutkom zaklepa zaslona"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Brisanje vseh podatkov"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Brez opozorila zbriše podatke v tabličnem računalniku in obnovi tovarniške nastavitve"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Brez opozorila zbriše podatke v tabličnem računalniku in obnovi tovarniške nastavitve"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Brisanje (s tovarniško ponastavitvijo) vseh podatkov v tabličnem računalniku brez opozorila"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Brisanje (s tovarniško ponastavitvijo) vseh podatkov v telefonu brez opozorila"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nastavitev globalnega strežnika proxy za napravo"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Nastavite globalni strežnik proxy naprave, ki bo v uporabi, ko je pravilnik omogočen. Samo skrbnik prve naprave lahko nastavi veljaven globalni strežnik proxy."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Nastavitev poteka gesla"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Nastavite, koliko časa prej je treba spremeniti geslo za odklepanje zaslona"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Začetna stran"</item>
     <item msgid="869923650527136615">"Mobilni"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Službeni pozivnik"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Pomočnik"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Po meri"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Rojstni dan"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Obletnica"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Dogodek"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Drugo"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Po meri"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Začetna stran"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Služba"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Služba"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Drugo"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Po meri"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Po meri"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Pomočnik"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Brat"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Otrok"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Domači partner"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Oče"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Prijatelj"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Vodja"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Mati"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Starši"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Partner"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Predlagatelj:"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Sorodnik"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Sestra"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Zakonski partner"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Po meri"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Domov"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Služba"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Drugo"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Vnesite kodo PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Vnesite geslo za odklop"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Vnesite PIN za odklepanje"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Nepravilna koda PIN."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Če želite telefon odkleniti, pritisnite meni in nato 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Številka za klic v sili"</string>
@@ -646,8 +615,7 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Nazaj na klic"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Pravilno."</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Poskusite znova"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Poskusite znova"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Polnjenje (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Napolnjeno."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Kartica SIM je zaklenjena."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Odklepanje kartice SIM ..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Vzorec za odklepanje ste nepravilno narisali <xliff:g id="NUMBER_0">%d</xliff:g>-krat. "\n\n"Poskusite znova čez <xliff:g id="NUMBER_1">%d</xliff:g> sekund."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%d</xliff:g>-krat nepravilno vnesli. Po še <xliff:g id="NUMBER_1">%d</xliff:g> neuspešnih poskusih boste pozvani, da odklenete telefon z Googlovimi podatki za prijavo."\n\n" Poskusite znova čez <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"<xliff:g id="NUMBER_0">%d</xliff:g>-krat ste vnesli napačno geslo. "\n\n"Poskusite znova čez <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"<xliff:g id="NUMBER_0">%d</xliff:g>-krat ste vnesli napačen PIN. "\n\n"Poskusite znova čez <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"<xliff:g id="NUMBER_0">%d</xliff:g>-krat ste narisali napačen vzorec za odklepanje. Če vam tudi v <xliff:g id="NUMBER_1">%d</xliff:g>. ne uspe, boste tablični računalnik morali odkleniti s podatki za prijavo v Google."\n\n" Poskusite znova čez <xliff:g id="NUMBER_2">%d</xliff:g> s."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Vzorec za odklepanje ste nepravilno vnesli <xliff:g id="NUMBER_0">%d</xliff:g>-krat. Po <xliff:g id="NUMBER_1">%d</xliff:g> neuspešnih poskusih boste pozvani, da odklenete telefon z Googlovimi podatki za prijavo."\n\n" Poskusite znova čez <xliff:g id="NUMBER_2">%d</xliff:g> sekund."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Poskusite znova čez <xliff:g id="NUMBER">%d</xliff:g> sekund."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Ali ste pozabili vzorec?"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Ali se želite premakniti s te strani?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Če želite nadaljevati, izberite V redu, če želite ostati na trenutni strani, izberite Prekliči."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Potrdi"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Namig: tapnite dvakrat, če želite povečati ali pomanjšati."</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"Samodejno izpolnjevanje"</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"Samozapolni"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Nam. sam. izpoln."</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"branje zgodovine in zaznamkov brskalnika"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Programu dovoljuje branje vseh URL-jev, ki jih je brskalnik obiskal, in vseh brskalnikovih zaznamkov."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"pisanje zgodovine in zaznamkov brskalnika"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Programu dovoljuje spreminjanje zgodovine brskalnika ali zaznamkov, shranjenih v tabličnem računalniku. Zlonamerni programi lahko to uporabijo za brisanje ali spreminjanje podatkov brskalnika."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Programu omogoča spreminjanje brskalnikove zgodovine ali zaznamkov, shranjenih v tabličnem računalniku. Zlonamerni programi lahko s tem dovoljenjem izbrišejo ali spremenijo podatke brskalnika."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Programu dovoljuje spreminjanje zgodovine brskalnika ali zaznamkov, shranjenih v telefonu. Zlonamerni programi lahko to uporabijo za brisanje ali spreminjanje podatkov brskalnika."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"nastavitev alarma budilke"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Programu omogoča nastavitev alarma v nameščeni budilki. Nekatere budilke morda ne bodo uporabile te funkcije."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Spreminjanje dovoljenj za geolokacijo brskalnika"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Programu dovoljuje spreminjanje dovoljenja brskalnika za geografske lokacije. Zlonamerni programi lahko s tem dovoljenjem dovolijo pošiljanje podatkov o lokaciji poljubnim spletnim mestom."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ali želite, da si brskalnik zapomni to geslo?"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"Izreži"</string>
     <string name="copy" msgid="2681946229533511987">"Kopiraj"</string>
     <string name="paste" msgid="5629880836805036433">"Prilepi"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Ni elementov za lepljenje"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Kopiraj URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Izbiranje besedila ..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Izbrano besedilo"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Način vnosa"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Uredi besedilo"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Besedilna dejanja"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Zmanjkuje pomnilnika"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Primanjkuje pomnilnika tabličnega računalnika."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Pomanjkanje prostora v shrambi tabličnega računalnika."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Primanjkuje pomnilnika telefona."</string>
     <string name="ok" msgid="5970060430562524910">"V redu"</string>
     <string name="cancel" msgid="6442560571259935130">"Prekliči"</string>
     <string name="yes" msgid="5362982303337969312">"V redu"</string>
     <string name="no" msgid="5141531044935541497">"Prekliči"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Pozor"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Nalaganje ..."</string>
     <string name="capital_on" msgid="1544682755514494298">"VKLOPLJENO"</string>
     <string name="capital_off" msgid="6815870386972805832">"IZKLOPLJEN"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Dokončanje dejanja z"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Vsili zapiranje"</string>
     <string name="report" msgid="4060218260984795706">"Poročaj"</string>
     <string name="wait" msgid="7147118217226317732">"Čakaj"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Preusmeritev programa"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> se izvaja."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Prvotno je bil zagnan program <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="smv_application" msgid="295583804361236288">"Program <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) krši svoj samoizvedljivi pravilnik o strogem načinu."</string>
+    <string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> krši svoj samoizvedljivi pravilnik o strogem načinu."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> se izvaja"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Izberite za preklop na program"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Ali želite preklopiti program?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Preden zaženete nov program, ustavite izvajanega."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Vrni se na <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Ne zaženite novega programa."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Začni <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Ustavi prejšnji program brez shranjevanja."</string>
     <string name="sendText" msgid="5132506121645618310">"Izbiranje dejanja za besedilo"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Glasnost zvonjenja"</string>
     <string name="volume_music" msgid="5421651157138628171">"Glasnost predstavnosti"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Pokaži vse"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Masovni pomnilnik USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Povezava USB je vzpostavljena"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Telefon ste z računalnikom povezali s kablom USB. Če želite kopirati datoteke med računalnikom in kartico SD sistema Android, izberite spodnji gumb."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Telefon ste z računalnikom povezali s kablom USB. Če želite kopirati datoteke med računalnikom in kartico SD sistema Android, izberite spodnji gumb."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Z računalnikom ste vzpostavili povezavo prek povezave USB. Dotaknite se gumba spodaj, če želite kopirati datoteke med računalnikom in pomnilnikom USB za Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Z računalnikom ste vzpostavili povezavo prek povezave USB. Dotaknite se gumba spodaj, če želite kopirati datoteke med računalnikom in kartico SD za Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Vklop shrambe USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Pri uporabi kartice SD za shrambo USB je prišlo do napake."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Pri uporabi kartice SD za shrambo USB je prišlo do napake."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Težava z uporabo pomnilnika USB kot masovni pomnilnik USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Težava z uporabo kartice SD kot masovni pomnilnik USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Povezava USB je vzpostavljena"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Izberite, če želite kopirati datoteke v/iz računalnika."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Izklopi shrambo USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Izberite, če želite izklopiti shrambo USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Shramba USB je v uporabi"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Pred izklopom shrambe USB preverite, ali ste iz računalnika izpeli kartico SD sistema Android."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Preden izklopite pomnilnik USB, obvezno izpnite pomnilnik USB za Android iz računalnika."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Pred izklopom shrambe USB preverite, ali ste iz računalnika izpeli kartico SD sistema Android."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Izklopi shrambo USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Pri izklopu shrambe USB je prišlo do napake. Preverite, ali ste izpeli gostitelja USB, in poskusite znova."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Če vklopite shrambo USB, bodo nekateri programi, ki jih uporabljate, ustavljeni in morda ne bodo na voljo, dokler je ne izklopite."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Operacija USB ni uspela"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"V redu"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatiraj kartico SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Formatiranje pomnilnika USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Formatiraj kartico SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Ali ste prepričani, da želite formatirati kartico SD? Vsi podatki na kartici bodo izgubljeni."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Ali želite formatirati pomnilnik USB in izbrisati vse datoteke, shranjene na njem? Dejanje je dokončno."</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Ali ste prepričani, da želite formatirati kartico SD? Vsi podatki na kartici bodo izgubljeni."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Formatiraj"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"iskanje in odpravljanje napak USB je povezano"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Priprava kartice SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Pripravljanje pomnilnika USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Priprava kartice SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Iskanje napak."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Prazna kartica SD"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Prazen pomnilnik USB"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Prazna kartica SD"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Kartica SD je prazna ali ima nepodprt datotečni sistem."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Pomnilnik USB je prazen ali uporablja nepodprt datotečni sistem."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Kartica SD je prazna ali ima nepodprt datotečni sistem."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Poškodovana kartica SD"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Pomnilnik USB je poškodovan"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Poškodovana kartica SD"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Kartica SD je poškodovana. Morda jo boste morali znova formatirati."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Pomnilnik USB je poškodovan. Morda ga boste morali formatirati."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Kartica SD je poškodovana. Morda jo boste morali znova formatirati."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Kartica SD je bila nepričakovano odstranjena"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Pomnilnik USB je bil nepričakovano odstranjen"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Kartica SD je bila nepričakovano odstranjena"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Če se želite izogniti izgubi podatkov, pred odstranjevanjem izpnite kartico SD."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Pomnilnik USB najprej izpnite in šele nato odstranite, da ne pride do izgube podatkov."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Če se želite izogniti izgubi podatkov, pred odstranjevanjem izpnite kartico SD."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Kartico SD lahko varno odstranite"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Zdaj lahko varno odstranite pomnilnik USB"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Kartico SD lahko varno odstranite"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Kartico SD lahko varno odstranite."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Zdaj lahko varno odstranite pomnilnik USB."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Kartico SD lahko varno odstranite."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Kartica SD je odstranjena"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Ni pomnilnika USB"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Kartica SD je odstranjena"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Kartica SD je odstranjena. Vstavite novo."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Pomnilnik USB je odstranjen. Vstavite drug nosilec podatkov."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Kartica SD je odstranjena. Vstavite novo."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Ni bilo mogoče najti ujemajočih se dejavnosti"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"posodobitev statističnih podatkov uporabe komponent"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Pošlji"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Naprej"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Dokončano"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Nazaj"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Izvedi"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Pokliči številko"\n"s številko <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Ustvari stik"\n"s številko <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,62 +961,42 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN, ki temelji na ključu v vnaprejšnji skupni rabi"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN, ki temelji na potrdilu"</string>
     <string name="upload_file" msgid="2897957172366730416">"Izberi datoteko"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Nobena datoteka ni izbrana"</string>
     <string name="reset" msgid="2448168080964209908">"Ponastavi"</string>
     <string name="submit" msgid="1602335572089911941">"Pošlji"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Način delovanja za avtomobil je omogočen"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Izberite, če želite zapreti način za avtomobil."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Aktivna povezava z internetom ali dostopna točka sta aktivni"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Dotaknite se, če želite konfigurirati"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Nazaj"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Naprej"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Preskoči"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Velika uporaba podatkov v mobilni napravi"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Dotaknite se, če želite izvedeti več o uporabi podatkov v mobilni napravi."</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Omejitev za podatke v mobilni napravi je presežena"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Dotaknite se, če želite izvedeti več o uporabi podatkov v mobilni napravi."</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Ni ujemanj"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Najdi na strani"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 ujemanje"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> od <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Končano"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Izpenjanje pomnilnika USB ..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Izpenjanje kartice SD ..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Brisanje pomnilnika USB ..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Brisanje kartice SD ..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Brisanje pomnilnika USB ni uspelo."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Brisanje kartice SD ni uspelo."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Kartica SD je bila odstranjena, preden je bila izpeta."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Trenutno poteka preverjanje pomnilnika USB."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Poteka preverjanje kartice SD."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Kartica SD je odstranjena."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Pomnilnik USB trenutno uporablja računalnik."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Kartico SD trenutno uporablja računalnik."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Neznano stanje zunanjih nosilcev podatkov."</string>
+    <string name="share" msgid="1778686618230011964">"Deli z dr."</string>
+    <string name="find" msgid="4808270900322985960">"Najdi"</string>
     <!-- no translation found for websearch (4337157977400211589) -->
     <skip />
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
@@ -1087,4 +1009,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 6eaf100..c5c1e43 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Гласовна пошта"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Проблеми са везом или неважећи MMI кôд."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Рад је ограничен само на бројеве фиксног бирања."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Услуга је омогућена."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Услуга је омогућена за:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Услуга је онемогућена."</string>
@@ -129,7 +128,7 @@
     <string name="low_memory" product="tablet" msgid="2292820184396262278">"Меморија таблета је пуна! Избришите неке датотеке да бисте ослободили простор."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"Складиште телефона је пуно! Избришите неке датотеке како бисте ослободили простор."</string>
     <string name="me" msgid="6545696007631404292">"Ја"</string>
-    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Опције таблета"</string>
+    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Опције за таблет"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"Опције телефона"</string>
     <string name="silent_mode" msgid="7167703389802618663">"Нечујни режим"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"Укључи бежични сигнал"</string>
@@ -139,11 +138,10 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"Искључивање…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Таблет ће се искључити."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Телефон ће се искључити."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Желите ли да искључите телефон?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Недавно"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Нема недавно коришћених апликација."</string>
-    <string name="global_actions" product="tablet" msgid="408477140088053665">"Опције таблета"</string>
+    <string name="global_actions" product="tablet" msgid="408477140088053665">"Опције за таблет"</string>
     <string name="global_actions" product="default" msgid="2406416831541615258">"Опције телефона"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Закључај екран"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Искључи"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим рада у авиону"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим рада у авиону је УКЉУЧЕН"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим рада у авиону је ИСКЉУЧЕН"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android систем"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Услуге које се плаћају"</string>
@@ -160,7 +160,7 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Поруке"</string>
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"Читање и писање SMS порука, порука е-поште и осталих типова порука."</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"Личне информације"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Директан приступ контактима и календару сачуваним на таблету."</string>
+    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"Директни приступ контактима и календарима сачуваним на таблету."</string>
     <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"Директни приступ контактима и календару сачуваним на телефону."</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"Локација"</string>
     <string name="permgroupdesc_location" msgid="2430258821648348660">"Надгледа физичку локацију"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Алатке за програмирање"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Функције потребне само програмерима апликација."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Складиште"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Приступ SD картици."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Приступите USB меморији."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Приступ SD картици."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"онемогућавање или измена статусне траке"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Омогућава да апликација онемогући статусну траку или да додаје и уклања системске иконе."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"статусна трака"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Омогућава апликацији да функционише као статусна трака."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"проширење/скупљање статусне траке"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Омогућава да апликација прошири или скупи статусну траку."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"пресретање одлазних позива"</string>
@@ -196,10 +194,10 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"слање SMS порука"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Омогућава да апликација шаље SMS поруке. Злонамерне апликације могу да шаљу поруке без ваше потврде, што ће вам створити трошкове."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"читање SMS или MMS порука"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Омогућава да апликација чита SMS поруке сачуване на таблету или SIM картици. Злонамерне апликације могу да читају поверљиве поруке."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Омогућава апликацији да чита SMS поруке сачуване на таблету или SIM картици. Злонамерне апликације могу да читају ваше поверљиве поруке."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Омогућава да апликација чита SMS поруке сачуване на телефону или SIM картици. Злонамерне апликације могу да читају поверљиву преписку."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"измена SMS или MMS порука"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Омогућава да апликација уписује податке у SMS поруке сачуване на таблету или SIM картици. Злонамерне апликације могу да избришу поруке."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Омогућава апликацији да мења садржај SMS порука сачуваних на таблету или SIM картици. Злонамерне апликације могу да избришу ваше поруке."</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Омогућава да апликација уписује податке у SMS поруке сачуване на телефону или SIM картици. Злонамерне апликације могу да избришу поруке."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"пријем преко WAP-а"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Омогућава да апликација прима и обрађује WAP поруке. Злонамерне апликације могу да надгледају поруке или да их бришу, а да вам их не прикажу."</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"спречавање пребацивања са једне апликације на другу"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Спречава корисника да се пребаци на другу апликацију."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"надгледање и контрола покретања свих апликација"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Омогућава да апликација надгледа и контролише на који начин систем покреће активности. Злонамерне апликације могу у потпуности да угрозе систем. Ова дозвола је потребна само за програмирање, а никада за уобичајено коришћење."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Омогућава апликацији да надгледа и контролише начин на који систем покреће активности. Злонамерне апликације могу у потпуности да угрозе систем. Ова дозвола је потребна само за развој, а никада за стандардно коришћење."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"слање емитовања уклоњеног пакета"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Омогућава да апликација емитује обавештење да је пакет апликација уклоњен. Злонамерне апликације могу на тај начин да искључе све друге покренуте апликације."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"слање емитовања примљених путем SMS порука"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"приказ неовлашћених прозора"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Омогућава прављење прозора који су осмишљени за коришћење у корисничком интерфејсу интерног система. Не користе је обичне апликације."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"приказ упозорења на нивоу система"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Омогућава да апликација прикаже прозоре са системским упозорењима. Злонамерне апликације на тај начин могу да преузму цео екран."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Омогућава апликацији да приказује прозоре са системским упозорењима. Злонамерне апликације могу да преузму цео екран."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"измена глобалне брзине анимација"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Омогућава да апликација у сваком тренутку промени глобалну брзину анимација (брже или спорије анимације)."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"управљање токенима апликација"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Омогућава да апликације праве сопствене токене и управљају њима, заобилазећи уобичајени распоред по Z оси. Обичне апликације никада не би требало да је користе."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"притисци на тастере и контролну дугмад"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Омогућава да апликација испоручи сопствене догађаје уноса (притисци тастера итд.) другим апликацијама. Злонамерне апликације на тај начин могу да преузму контролу над таблетом."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Омогућава апликацији да другим апликацијама испоручи сопствене улазне догађаје (притисак на тастере итд.). Злонамерне апликације на тај начин могу да преузму контролу над таблетом."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Омогућава да апликација испоручи сопствене догађаје уноса (притисци тастера итд.) другим апликацијама. Злонамерне апликације на тај начин могу да преузму контролу над телефоном."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"снимање садржаја који куцате и радњи које предузимате"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Омогућава да апликације виде које тастере притискате чак и док радите у некој другој апликацији (нпр. када уносите лозинку). Нормалне апликације никада не би требало да је користе."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"директно инсталирање апликација"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Омогућава да апликација инсталира нове или ажуриране пакете оперативног система Android. Злонамерне апликације на тај начин могу да додају нове апликације са потенцијално моћним дозволама."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"брисање свих података из кеша апликације"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Омогућава да апликација ослободи меморију таблета брисањем датотека у каталогу кеша апликације. Приступ је обично строго ограничен само на системски процес."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Омогућава апликацији да ослободи меморију таблета брисањем датотека у директоријуму кеша апликације. Приступ је обично строго ограничен само на системске процесе."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Омогућава да апликација приступи бесплатном складишту телефона брисањем датотека у директоријуму кеша апликације. Приступ је обично строго ограничен само за системски процес."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Премештање ресурса апликације"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Омогућава да апликација премести ресурсе апликације са интерног на екстерни медијум и обратно."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"читање системских датотека евиденције"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Омогућава да апликација чита разне системске датотеке евиденције. То јој омогућава увид у опште информације о начину на који користите таблет, при чему могу да буду обухваћене личне или приватне информације."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Омогућава да апликација чита разне системске датотеке евиденције. То јој омогућава увид у опште информације о начину на који користите таблет, при чему могу да буду обухваћене личне или приватне информације."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"читање поверљивих података из евиденције"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Омогућава апликацији да чита разноврсне датотеке евиденције система. Захваљујући томе може да открије опште информације о томе за шта користите таблет, укључујући евентуално и личне или приватне информације."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Омогућава апликацији да чита разноврсне датотеке евиденције система. Захваљујући томе може да открије опште информације о томе за шта користите телефон, укључујући евентуално и личне или приватне информације."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"читање ресурса у власништву дијагностике и уписивање података у њих"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Омогућава да апликација чита и уписује податке у било који ресурс у власништву групе за дијагностиковање, на пример, датотеке у /dev. То може да угрози стабилност и безбедност система и треба да је користе САМО произвођач или оператер у сврхе дијагностиковање хардвера."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"омогућавање или онемогућавање компоненти апликација"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Омогућава да апликација промени да ли је компонента друге апликације омогућена или онемогућена. Злонамерне апликације могу то да искористе да онемогуће важне функције таблета. Треба бити опрезан при додељивању ове дозволе, јер компоненте апликација могу постати неупотребљиве, непоуздане или нестабилне."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Омогућава да апликација промени да ли је компонента друге апликације омогућена или онемогућена. Злонамерне апликације могу то да искористе да онемогуће важне функције таблета. Треба бити опрезан при додељивању ове дозволе, јер компоненте апликација могу постати неупотребљиве, непоуздане или нестабилне."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Омогућава апликацији да омогући или онемогући компоненту друге апликације. Злонамерне апликације то могу да злоупотребе и онемогуће важне функције таблета. Треба бити пажљив при додели ове дозволе јер постоји могућност да ће компоненте апликације постати неупотребљиве, неусаглашене или непостојане."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Омогућава апликацији да омогући или онемогући компоненту друге апликације. Злонамерне апликације то могу да злоупотребе и онемогуће важне функције телефона. Треба бити пажљив при додели ове дозволе јер постоји могућност да ће компоненте апликације постати неупотребљиве, неусаглашене или непостојане."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"подешавање жељених апликација"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Омогућава да апликација измени омиљене апликације. Услед тога злонамерне апликације могу кришом да промене апликације које су покренуте и да преко њих прикупљају ваше приватне податке."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"измена глобалних подешавања система"</string>
@@ -298,19 +296,19 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"измена мапе Google услуга"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"Омогућава да апликација измени мапу Google услуга. Не користе је обичне апликације."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"аутоматско покретање при покретању система"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Омогућава да се апликација покрене по довршетку покретања система. То може да успори укључивање таблета, при чему ова апликација може да успори целокупан рад таблета тиме што ће увек бити активна."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Омогућава апликацији да се покрене истовремено са системом. То може да услови спорије покретање таблета и омогући апликацији да успори целокупан рад уређаја тиме што ће увек бити активна."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Омогућава да се апликација покрене по довршетку покретања система. То може да успори укључивање телефона, при чему ова апликација може да успори целокупан рад телефона тиме што ће увек бити активна."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"слање пријемчивих емитовања"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Омогућава да апликација шаље пријемчиве преносе, који остају по завршетку емитовања. Злонамерне апликације могу да успоре или дестабилизују таблет тиме што ће трошити превише меморије."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Омогућава апликацији да шаље пријемчива емитовања, која остају и по завршетку емитовања. Злонамерне апликације могу да успоре таблет или да га учине нестабилним тиме што ће користити превише меморије."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Омогућава да апликација шаље пријемчиве преносе, који остају по завршетку емитовања. Злонамерне апликације на тај начин могу да успоравају и дестабилизују телефон тиме што ће трошити превише меморије."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"читање података о контактима"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Омогућава да апликација чита све податке о контактима (адресама) сачуване на таблету. Злонамерне апликације могу то да искористе за слање података другим особама."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Омогућава апликацији да чита све податке о контактима (адресама) сачуване на таблету. Злонамерне апликације то могу да злоупотребе и пошаљу ваше податке другим особама."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Омогућава да апликација чита све податке о контактима (адресама) сачуване на телефону. Злонамерне апликације могу то да искористе за слање ваших података другим особама."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"уписивање података о контактима"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Омогућава да апликација измени податке о контакту (адреси) сачуване на таблету. Злонамерне апликације могу то да искористе да би избрисале или измениле податке о контакту."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Омогућава апликацији да измени податке о контакту (адресу) сачуване на таблету. Злонамерне апликације на тај начин могу да избришу или измене податке о контакту."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Омогућава да апликација измени податке о контакту (адреси) сачуване на телефону. Злонамерне апликације могу то да злоупотребе и да избришу или измене податке о контакту."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"читање догађаја из календара"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Омогућава да апликација чита све догађаје из календара сачуване на таблету. Злонамерне апликације могу то да искористе за слање догађаја из календара другим људима."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Омогућава апликацији да чита све догађаје из календара сачуване на таблету. Злонамерне апликације то могу да злоупотребе и пошаљу ваше догађаје из календара другим особама."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Омогућава да апликација чита све догађаје из календара сачуване на телефону. Злонамерне апликације могу то да злоупотребе и искористе за слање догађаја из календара другим људима."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"додавање и измена догађаја из календара и слање порука е-поште гостима"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Омогућава да апликација додаје или мења догађаје у календару, услед чега гостима могу да се шаљу поруке е-поште. Злонамерне апликације могу на основу тога да избришу или измене догађаје из календара или да шаљу поруке е-поште гостима."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"дозвола за инсталирање добављача локације"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Прави лажне изворе локације у сврхе тестирања. Злонамерне апликације могу на основу тога да замене локацију и/или статус који пријављују прави извори локација, као што су GPS или добављачи мреже, односно да надгледају и пријављују локацију спољном извору."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"прецизна (GPS) локација"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Приступ изворима прецизне локације, као што је систем глобалног позиционирања на таблету, уколико је то доступно. Злонамерне апликације могу на основу тога да утврде вашу локацију и додатно троше батерију."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Приступ прецизним изворима информација, као што је глобални систем за позиционирање (Global Positioning System – GPS) на таблету, када су доступни. Злонамерне апликације то могу да злоупотребе како би утврдиле вашу локацију и на тај начин потроше додатно напајање батерије."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Приступ изворима прецизне локације, као што је систем глобалног позиционирања на телефону, уколико је то доступно. Злонамерне апликације могу на основу тога да утврде вашу локацију и да додатно троше батерију."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"оквирна локација (заснована на мрежи)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Приступ изворима оквирне локације, као што је база података мобилне мреже, ради утврђивања приближне локације таблета, уколико је то доступно. Злонамерне апликације могу на основу тога да утврде вашу приближну локацију."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Приступ непрецизним изворима локација, попут базе података мреже мобилне телефоније, ради одређивања приближне локације таблета, у случају да су доступни. Злонамерне апликације на тај начин могу да утврде вашу приближну локацију."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Приступ изворима оквирне локације, као што је база података мобилне мреже ради утврђивања приближне локације телефона, уколико је то доступно. Злонамерне апликације могу то да искористе за утврђивање ваше приближне локације."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"приступ функцији SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Омогућава да апликација користи SurfaceFlinger функције ниског нивоа."</string>
@@ -334,37 +332,39 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Омогућава да апликација измени глобалне поставке за аудио записе, попут јачине звука и усмеравања."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"снимање аудио записа"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Омогућава да апликација приступи путањи аудио записа."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"снимање фотографија"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Омогућава да апликација снима фотографије помоћу камере. То омогућава да апликација у сваком тренутку прикупља слике које су у кадру."</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"снимање фотографија и видео снимака"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Омогућава апликацији да снима фотографије и видео снимке преко камере. Захваљујући томе апликација може у сваком тренутку да прикупи слике приказане у склопу камере."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"трајно онемогућавање таблета"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"трајно онемогућавање телефона"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Омогућава да апликација трајно онемогући цео таблет. Ово је веома опасно."</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Омогућава апликацији да трајно онемогући цео таблет, што је веома опасно."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Омогућава да апликација трајно онемогући цео телефон. То је веома опасно."</string>
     <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"принудно поновно покретање таблета"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"принудно поновно покретање телефона"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Омогућава да апликација принудно поновно покрене таблет."</string>
+    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Омогућава апликацији да принудно поново покрене таблет."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Омогућава да апликација принудно поновно покрене телефон."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"прикључивање и искључивање система датотека"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Омогућава да апликација прикључи и искључи системе датотека преносивог складишта."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"форматирање екстерног складишта"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Омогућава да апликација форматира преносиво складиште."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"преузимање информација у безбедно складиште"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Омогућава да апликација преузме информације о безбедном складишту."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"прављење безбедног складишта"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Омогућава да апликација направи безбедно складиште."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"уништавање безбедног складишта"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Омогућава да апликација уништи безбедно складиште."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"прикључивање/искључивање безбедног складишта"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Омогућава да апликација прикључи/искључи безбедно складиште."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"преименовање безбедног складишта"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Омогућава да апликација преименује безбедно складиште."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"увид у информације о интерној меморији"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Омогућава апликацији увид у информације о интерној меморији."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"прављење интерне меморије"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Омогућава апликацији да направи интерну меморију."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"уништавање интерне меморије"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Омогућава апликацији да уништи интерну меморију."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"прикључивање/искључивање интерне меморије"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Омогућава апликацији да прикључи/искључи интерну меморију."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"преименовање интерне меморије"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Омогућава апликацији да преименује интерну меморију."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"контрола вибрације"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Омогућава да апликација контролише вибрације."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"контрола осветљења"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Омогућава да апликација контролише осветљење."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"приступ USB уређајима"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Омогућава апликацији приступ USB уређајима."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"тестирање хардвера"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Омогућава да апликација контролише разноврсне периферне уређаје у сврхе тестирања хардвера."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"Омогућава да апликација позива бројеве телефона не тражећи дозволу од вас. Злонамерне апликације на тај начин могу да задуже ваш телефонски рачун упућивањем непланираних позива. Имајте у виду да се апликацијама тиме не омогућава позивање бројева за хитне случајеве."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"директно позивање било ког броја телефона"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Омогућава да апликација позове било који број телефона, укључујући бројеве за хитне случајеве, не тражећи дозволу од вас. Злонамерне апликације на тај начин могу да упућују непотребне и забрањене позиве услугама за хитне случајеве."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"директно покретање подешавања CDMA таблета"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"директно покретање подешавања кодираног вишеструког приступа за таблет (Code Division Multiple Access – CDMA)"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"директно покретање подешавања CDMA телефона"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Омогућава да апликација покрене прибављање кодираног вишеструког приступа (CDMA). Злонамерне апликације могу без стварне потребе да покрену овај поступак."</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"контрола обавештења о ажурирању локације"</string>
@@ -387,14 +387,14 @@
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"Омогућава да апликација приступа функцијама телефона које уређај подржава. Ова дозвола омогућава да апликација утврди број телефона и серијски број телефона, те да ли је позив активан, са којим бројем је успостављена веза и слично."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"спречавање преласка таблета у стање спавања"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"спречавање преласка телефона у стање спавања"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Омогућава да апликација спречи прелазак таблета у стање спавања."</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Омогућава апликацији да спречи таблет да пређе у стање спавања."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Омогућава да апликација спречи прелазак телефона у стање спавања."</string>
     <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"укључивање или искључивање таблета"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"укључивање или искључивање телефона"</string>
-    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Омогућава да апликација укључи или искључи таблет."</string>
+    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Омогућава апликацији да укључи или искључи таблет."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Омогућава да апликација укључи и искључи телефон."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"покретање у режиму фабричког тестирања"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Покретање теста ниског нивоа који спроводи произвођач, који омогућава потпуни приступ хардверу таблета. Доступан је само када је таблет покренут у режиму тестирања које спроводи произвођач."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Покреће се као тест произвођача ниског нивоа, омогућавајући комплетан приступ хардверу таблета. Доступно је само када је таблет покренут у пробном режиму произвођача."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Покретање теста ниског нивоа који спроводи произвођач, које омогућава потпуни приступ хардверу телефона. Доступно је само када телефон покренут у режиму тестирања које спроводи произвођач."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"подешавање позадине"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Омогућава да апликација постави системску позадину."</string>
@@ -403,15 +403,15 @@
     <string name="permlab_masterClear" msgid="2315750423139697397">"поновно постављање фабричких подразумеваних подешавања"</string>
     <string name="permdesc_masterClear" msgid="5033465107545174514">"Омогућава да апликација поново постави комплетна фабричка подешавања система и тиме избрише све податке, конфигурацију и инсталиране апликације."</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"подешавање времена"</string>
-    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Омогућава да апликација промени време на сату таблета."</string>
+    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Омогућава апликацији да промени време приказано на сату таблета."</string>
     <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Омогућава да апликација промени време на сату телефона."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"подешавање временске зоне"</string>
-    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Омогућава да апликација промени временску зону таблета."</string>
+    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Омогућава апликацији да промени временску зону таблета."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Омогућава да апликација промени временску зону телефона."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"улога услуге управљања налогом"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Омогућава да апликација упућује позиве особама које издају потврду идентитета налога"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"откривање познатих налога"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Омогућава да апликација преузме листу налога за које постоје подаци на таблету."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Омогућава апликацији да преузме листу налога познатих таблету."</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Омогућава да апликација преузме листу налога за које постоје подаци на телефону."</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"улога потврде идентитета налога"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Омогућава да апликација користи могућности менаџера налога за потврду идентитета налога, укључујући отварање налога, као и преузимање и подешавање лозинки за њих."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"омогућавање пријема вишесмерног Wi-Fi саобраћаја"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Омогућава да апликација прима пакете који нису директно намењени вашем уређају. То може бити корисно при откривању услуга које се нуде у вашој близини. Користи више напајања од режима једносмерног саобраћаја."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"администрирање преко bluetooth-а"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Омогућава да апликација конфигурише локални Bluetooth таблет, као и да открије удаљене уређаје и упари се са њима."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Омогућава апликацији да конфигурише локални Bluetooth таблет, као и да открије даљинске уређаје и упари се са њима."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Омогућава да апликација конфигурише локални Bluetooth телефон, као и да открије удаљене уређаје и упари се са њима."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"креирање Bluetooth веза"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Омогућава да апликација види конфигурацију локалног Bluetooth таблета, као и да успоставља и прихвата везе са упареним уређајима."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Омогућава апликацији увид у конфигурацију локалног Bluetooth таблета, као и да успоставља и прихвата везе са упареним уређајима."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Омогућава да апликација види конфигурацију локалног Bluetooth телефона, као и да успоставља и прихвата везе са упареним уређајима."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"контрола комуникације у ужем пољу (Near Field Communication)"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Омогућава апликацији да комуницира са ознакама, картицама и читачима комуникације у ужем пољу (Near Field Communication – NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"онемогућавање закључавања тастатуре"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Омогућава да апликација онемогући закључавање тастатуре и свих безбедносних мера успостављених на основу лозинке. У оправдане примере додељивања такве дозволе спада онемогућавање закључавања тастатуре при пријему долазећег телефонског позива и поновно омогућавање тастатуре по његовом завршетку."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"читање подешавања синхронизације"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Омогућава да апликација чита све приватне речи, називе и фразе које је корисник сачувао у корисничком речнику."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"уписивање у речник који је корисник дефинисао"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Омогућава да апликација уписује нове речи у речник корисника."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"измена/брисање садржаја SD картице"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"измена/брисање садржаја USB меморије"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"измена/брисање садржаја SD картице"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Омогућава да апликација уписује податке на SD картицу."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Омогућава апликацији да уписује податке у USB меморију."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Омогућава да апликација уписује податке на SD картицу."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"измена/брисање интерне меморије медија"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Омогућава апликацији да мења садржај интерне медијске меморије."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"приступ систему датотека кеша"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Омогућава да апликација чита систем датотека кеша и уписује податке у њега."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Ограничење за лозинку"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Ограничава врсте лозинки које можете да користите."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Надгледање покушаја пријављивања"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Надгледање броја унетих нетачних лозинки приликом откључавања екрана и закључавање таблета или брисање свих података са њега уколико је унет превелики број нетачних лозинки"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Надгледање броја унетих нетачних лозинки приликом откључавања екрана и закључавање таблета или брисање свих података са њега уколико је унет превелики број нетачних лозинки"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Поновно постављање лозинке"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Принудна промена вредности лозинке, након чега ћете морати да затражите од администратора да вам је додели како бисте могли да се пријавите."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Принудно закључавање"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Контролисање закључавања телефона које захтева поновни унос лозинке."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"упућивање/пријем Интернет позива"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Омогућава апликацији да користи SIP услугу за упућивање/пријем Интернет позива."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Подешавање правила за лозинку"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Контрола дужине и знакова дозвољених у лозинкама за откључавање лозинки"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Надгледање покушаја откључавања екрана"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Надгледање броја нетачних лозинки унетих приликом откључавања екрана и закључавање таблета или брисање свих података на њему ако је превише пута унета нетачна лозинка"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Надгледање броја нетачних лозинки унетих приликом откључавања екрана и закључавање телефона или брисање свих података на њему ако је превише пута унета нетачна лозинка"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Промена лозинке за откључавање екрана"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Промена лозинке за откључавање екрана"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Закључавање екрана"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Контрола начина и времена закључавања екрана"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Брисање свих података"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Брисање података са таблета без упозорења враћањем фабричких података"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Брисање података са таблета без упозорења враћањем фабричких података"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Брисање података на таблету без упозорења враћањем фабричких података"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Брисање података на телефону без упозорења враћањем фабричких података"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Подесите глобални прокси сервер уређаја"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Подесите глобални прокси сервер уређаја који ће се користити док су омогућене смернице. Само први администратор уређаја поставља ефективни глобални прокси сервер."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Подеси време истека лозинке"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Контролишите време када лозинка за закључавање екрана треба да се промени"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Кућа"</item>
     <item msgid="869923650527136615">"Мобилни"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Пословни пејџер"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Помоћник"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Прилагођено"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Рођендан"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Годишњица"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Догађај"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Други"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Прилагођено"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Кућа"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Посао"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Посао"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Друго"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Прилагођено"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Прилагођено"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Помоћни"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Брат"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Дете"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Невенчани партнер"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Отац"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Пријатељ"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Менаџер"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Мајка"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Родитељ"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Партнер"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Упутио/ла"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Рођак"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Сестра"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Супруг/а"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Прилагођено"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Почетна"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Посао"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Други"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Унесите PIN кôд"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Унесите лозинку за откључавање"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Унесите PIN да бисте откључали тастатуру"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"PIN кôд је нетачан!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Да бисте откључали, притисните „Мени“, а затим 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Број за хитне случајеве"</string>
@@ -646,14 +615,13 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Назад на позив"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Тачно!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Жао нам је, покушајте поново"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Покушајте поново"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Пуњење (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Батерија је напуњена."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Повежите пуњач."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Нема SIM картице."</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У таблет није уметнута SIM картица."</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У таблету нема SIM картице."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"У телефон није уметнута SIM картица."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Уметните SIM картицу."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Само хитни позиви"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM картица је закључана."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Откључавање SIM картице…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"<xliff:g id="NUMBER_0">%d</xliff:g> пута сте нетачно унели шаблон за откључавање. "\n\n"Покушајте поново за <xliff:g id="NUMBER_1">%d</xliff:g> секунде(и)."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"<xliff:g id="NUMBER_0">%d</xliff:g> пута сте нетачно унели шаблон за откључавање. Након још "\n" неуспешна покушаја, од вас ће бити затражено да откључате таблет помоћу података за пријављивање на Google.<xliff:g id="NUMBER_2">%d</xliff:g><xliff:g id="NUMBER_1">%d</xliff:g>Покушајте поново за "\n" секунде(и)."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Унели сте нетачну лозинку <xliff:g id="NUMBER_0">%d</xliff:g> пута. "\n\n"Покушајте поново за <xliff:g id="NUMBER_1">%d</xliff:g> секунди."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Унели сте нетачни PIN <xliff:g id="NUMBER_0">%d</xliff:g> пута. "\n\n"Покушајте поново за <xliff:g id="NUMBER_1">%d</xliff:g> секунди."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"<xliff:g id="NUMBER_0">%d</xliff:g> пута сте унели нетачни шаблон за откључавање. Након још <xliff:g id="NUMBER_1">%d</xliff:g> неуспешних покушаја од вас ће бити затражено да откључате таблет помоћу Google података за пријављивање."\n\n" Покушајте поново за <xliff:g id="NUMBER_2">%d</xliff:g> секунди."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"<xliff:g id="NUMBER_0">%d</xliff:g> пута сте нетачно унели шаблон за откључавање. Након још <xliff:g id="NUMBER_1">%d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу података за пријављивање на Google."\n\n" Покушајте поново за <xliff:g id="NUMBER_2">%d</xliff:g> секунде(и)."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Покушајте поново за <xliff:g id="NUMBER">%d</xliff:g> секунде(и)."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Заборавили сте шаблон?"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Желите ли да напустите ову страницу?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Изаберите „Потврди“ ако желите да наставите или „Откажи“ да бисте остали на страници на којој сте тренутно."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Потврда"</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Савет: Додирните двапут да бисте увећали и умањили приказ."</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"Аут. поп."</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"Аутоматски попуни"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Подеси аут. поп."</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"читање историје и обележивача у прегледачу"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Омогућава да апликација чита све URL адресе које су посећене у прегледачу, као и све обележиваче у њему."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"уписивање историје и обележивача из прегледача"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Омогућава да апликација измени историју или обележиваче прегледача сачуване на таблету. Злонамерне апликације могу то да искористе да би избрисале или измениле податке у прегледачу."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Омогућава апликацији да измени историју или обележиваче у прегледачу сачуване на таблету. Злонамерне апликације на тај начин могу да избришу или измене податке у прегледачу."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Омогућава да апликација измени историју и обележиваче у прегледачу сачуване на телефону. Злонамерне апликације могу то да злоупотребе и да избришу или измене податке у прегледачу."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"подешавање аларма у будилнику"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Дозвољава да апликација подеси аларм у инсталираној апликацији будилника. Неке апликације будилника можда не примењују ову функцију."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Измена дозвола за географске локације прегледача"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Омогућава да апликација измени дозволе за утврђивање географске локације у прегледачу. Злонамерне апликације то могу да злоупотребе и искористе за слање информација о локацији насумичним веб сајтовима."</string>
     <string name="save_password_message" msgid="767344687139195790">"Желите ли да прегледач запамти ову лозинку?"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"Исеци"</string>
     <string name="copy" msgid="2681946229533511987">"Копирај"</string>
     <string name="paste" msgid="5629880836805036433">"Налепи"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Ништа није копирано"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Копирај URL адресу"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Изабери текст..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Избор текста"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод уноса"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Измени текст"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Радње у вези са текстом"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Мало простора"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Понестаје простора за складиштење на таблету."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Меморијски простор таблета је скоро попуњен."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Понестаје простора за складиштење на телефону."</string>
     <string name="ok" msgid="5970060430562524910">"Потврди"</string>
     <string name="cancel" msgid="6442560571259935130">"Откажи"</string>
     <string name="yes" msgid="5362982303337969312">"Потврди"</string>
     <string name="no" msgid="5141531044935541497">"Откажи"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Пажња"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Учитавање..."</string>
     <string name="capital_on" msgid="1544682755514494298">"УКЉУЧЕНО"</string>
     <string name="capital_off" msgid="6815870386972805832">"ИСКЉУЧЕНО"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Довршавање радње помоћу"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Принудно затвори"</string>
     <string name="report" msgid="4060218260984795706">"Пријави"</string>
     <string name="wait" msgid="7147118217226317732">"Сачекај"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Апликација је преусмерена"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> је сада покренута."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Првобитно је покренута апликација <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="smv_application" msgid="295583804361236288">"Апликација <xliff:g id="APPLICATION">%1$s</xliff:g> (процес <xliff:g id="PROCESS">%2$s</xliff:g>) је прекршила самонаметнуте StrictMode смернице."</string>
+    <string name="smv_process" msgid="5120397012047462446">"Процес <xliff:g id="PROCESS">%1$s</xliff:g> је прекршио самонаметнуте StrictMode смернице."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"Апликација <xliff:g id="APP">%1$s</xliff:g> је покренута"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Пребаците се на апликацију"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Желите ли да се пребаците са једне апликације на другу?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Већ је покренута друга апликација која мора бити заустављена да бисте могли да покренете нову."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Врати се у <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Не покрећи нову апликацију."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Покрени <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Заустави стару апликацију без чувања."</string>
     <string name="sendText" msgid="5132506121645618310">"Избор радње за слање текста"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Јачина звука звона"</string>
     <string name="volume_music" msgid="5421651157138628171">"Јачина звука медија"</string>
@@ -923,7 +866,7 @@
     <string name="sms_control_yes" msgid="2532062172402615953">"Потврди"</string>
     <string name="sms_control_no" msgid="1715320703137199869">"Откажи"</string>
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Подешавање времена"</string>
-    <string name="date_picker_dialog_title" msgid="5879450659453782278">"Подеси датум"</string>
+    <string name="date_picker_dialog_title" msgid="5879450659453782278">"Подешавање датума"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Подеси"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"Подразумевано"</string>
     <string name="no_permissions" msgid="7283357728219338112">"Није потребна ниједна дозвола"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Прикажи све"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB великог капацитета"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB је повезан"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Повезали сте телефон са рачунаром преко USB порта. Кликните на дугме у наставку ако желите да копирате датотеке са рачунара на SD картицу оперативног система Android и обратно."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Повезали сте телефон са рачунаром преко USB порта. Кликните на дугме у наставку ако желите да копирате датотеке са рачунара на SD картицу оперативног система Android и обратно."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Повезали сте рачунар преко USB-а. Додирните дугме испод ако желите да копирате датотеке са рачунара у Android USB меморију и обрнуто."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Ако сте свој рачунар повезали преко USB-а. Додирните дугме испод ако желите да копирате датотеке између датотеке између свог рачунара и Android SD картице."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Укључи USB меморију"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Дошло је до проблема у коришћењу SD картице за USB складиште."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Дошло је до проблема у коришћењу SD картице за USB складиште."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Дошло је до проблема приликом коришћења USB меморије за USB масовно меморисање."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Дошло је до проблема приликом коришћења SD картице за USB масовно меморисање."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB је повезан"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Изаберите да бисте копирали датотеке са рачунара или на њега."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Искључивање USB складиште"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Изаберите да бисте искључили USB складиште."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"USB складиште је у употреби"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Пре него што искључите USB складиште, уверите се да сте из рачунара уклонили („избацили“) SD картицу оперативног система Android."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Пре него што искључите USB меморију, уверите се да сте на рачунару искључили („избацили“) Android USB меморију."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Пре него што искључите USB складиште, уверите се да сте из рачунара уклонили („избацили“) SD картицу оперативног система Android."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Искључи USB складиште"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Дошло је до проблема приликом искључивања USB складишта. Уверите се да сте уклонили USB хост, а затим покушајте поново."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Ако укључите USB складиште, поједине апликације које користите престаће да раде и могу да постану недоступне док га поново не укључите."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Грешка са USB складиштем"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Потврди"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирање SD картице"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматирање USB меморије"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Форматирање SD картице"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Желите ли заиста да форматирате SD картицу? Сви подаци сачувани на њој биће избрисани."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Желите да форматирате USB меморију и избришете све датотеке у њој? Ову радњу није могуће опозвати!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Желите ли заиста да форматирате SD картицу? Сви подаци сачувани на њој биће избрисани."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Формат"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Отклањање грешака са USB-а је успостављено"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Припрема SD картице"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Припрема USB меморије"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Припрема SD картице"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Проверавање да ли постоје грешке."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Празна SD картица"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Празна USB меморија"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Празна SD картица"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"SD картица је празна или садржи систем датотека који није подржан."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"USB меморија је празна или садржи неподржани систем датотека."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"SD картица је празна или садржи систем датотека који није подржан."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Оштећена SD картица"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Оштећена USB меморија"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Оштећена SD картица"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"SD картица је оштећена. Можда ћете морати поново да је форматирате."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"USB меморија је оштећена. Можда ћете морати да је поново форматирате."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"SD картица је оштећена. Можда ћете морати поново да је форматирате."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"SD је неочекивано уклоњена"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"USB мем. неочекивано уклоњена"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"SD је неочекивано уклоњена"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Искључите SD картицу пре него што је уклоните како не би дошло до губитка података."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Искључите USB меморију пре него што је уклоните да не бисте изгубили податке."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Искључите SD картицу пре него што је уклоните како не би дошло до губитка података."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"SD картица се може безбедно уклонити"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Безбедно уклањање USB меморије"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"SD картица се може безбедно уклонити"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Можете безбедно да уклоните SD картицу."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Можете безбедно да уклоните USB меморију."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Можете безбедно да уклоните SD картицу."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"SD картица је уклоњена"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"USB меморија је уклоњена"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"SD картица је уклоњена"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"SD картица је уклоњена. Уметните нову картицу."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB меморија је уклоњена. Уметните нови медијум."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"SD картица је уклоњена. Уметните нову картицу."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Није пронађена ниједна подударна активност"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"ажурирање статистике о коришћењу компоненти"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Пошаљи"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Следеће"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Готово"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Претходно"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Изврши"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Бирај број"\n"користећи <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Креирајте контакт"\n"користећи <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Унапред дељени кључ заснован на протоколу L2TP/IPSec за VPN"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Сертификат заснован на протоколу L2TP/IPSec за VPN"</string>
     <string name="upload_file" msgid="2897957172366730416">"Одабери датотеку"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Није изабрана ниједна датотека"</string>
     <string name="reset" msgid="2448168080964209908">"Поново постави"</string>
     <string name="submit" msgid="1602335572089911941">"Пошаљи"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Режим рада у аутомобилу је омогућен"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Изаберите да бисте изашли из режима рада у аутомобилу."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Активно повезивање са Интернетом преко мобилног уређаја или врућа тачка"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Додирните да бисте конфигурисали"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Назад"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Next"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Прескочи"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Висок ниво коришћења података о мобилном уређају"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Додирните да бисте сазнали више о коришћењу података са мобилног уређаја"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Прекорачено је ограничење преноса података за мобилне уређаје"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Додирните да бисте сазнали више о коришћењу података са мобилног уређаја"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Нема подударања"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Пронађи на страници"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 подударање"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> од <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Done"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Искључивање USB меморије..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"У току је искључивање SD картице..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Брисање USB меморије је у току..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Брисање SD картице је у току..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Брисање USB меморије није успело."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Брисање SD картице није успело."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"SD картица није искључена пре него што је уклоњена."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Тренутно је у току провера USB меморије."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Тренутно је у току провера SD картице."</string>
+    <string name="media_removed" msgid="7001526905057952097">"SD картица је уклоњена."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Рачунар тренутно користи USB меморију."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"SD картица се тренутно користи на рачунару."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Екстерни медиј непознатог статуса."</string>
+    <string name="share" msgid="1778686618230011964">"Дели"</string>
+    <string name="find" msgid="4808270900322985960">"Пронађи"</string>
+    <string name="websearch" msgid="4337157977400211589">"Веб претрага"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index fb00acf..bda3863 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flygplansläge"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flygplansläge är AKTIVERAT"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flygplansläge är INAKTIVERAT"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tjänster som kostar pengar"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Tillåter att programmet styr lampan."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"åtkomst till USB-enheter"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Tillåter att programmet använder USB-enheter."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testa maskinvara"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Tillåter att ett program styr kringutrustning i syfte att testa maskinvara."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"ringa telefonnummer direkt"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Externa media i okänt tillstånd."</string>
     <string name="share" msgid="1778686618230011964">"Dela"</string>
     <string name="find" msgid="4808270900322985960">"Sök efter"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Webbsökning"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 4a7a632..41593f2 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"ข้อความเสียง"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"ปัญหาการเชื่อมต่อหรือรหัส MMI ไม่ถูกต้อง"</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"การดำเนินการถูกจำกัดไว้ที่การจำกัดหมายเลขโทรออกเท่านั้น"</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"เปิดใช้งานบริการแล้ว"</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"เปิดการใช้งานบริการสำหรับ:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"ปิดใช้งานบริการไว้"</string>
@@ -126,7 +125,7 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"ซิงค์"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"ซิงค์"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"มีการลบ <xliff:g id="CONTENT_TYPE">%s</xliff:g> มากเกินไป"</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"ที่เก็บข้อมูลแท็บเล็ตเต็ม! ลบบางไฟล์เพื่อเพิ่มที่ว่าง"</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"ที่เก็บข้อมูลของแท็บเล็ตเต็ม โปรดลบไฟล์บางไฟล์เพื่อเพิ่มพื้นที่ว่าง"</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"ที่เก็บข้อมูลโทรศัพท์เต็ม! ลบบางไฟล์เพื่อเพิ่มที่ว่าง"</string>
     <string name="me" msgid="6545696007631404292">"ฉัน"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"ตัวเลือกของแท็บเล็ต"</string>
@@ -137,10 +136,9 @@
     <string name="screen_lock" msgid="799094655496098153">"ล็อกหน้าจอ"</string>
     <string name="power_off" msgid="4266614107412865048">"ปิดเครื่อง"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"กำลังปิดระบบ..."</string>
-    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"แท็บเล็ตของคุณจะปิดเครื่อง"</string>
+    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"แท็บเล็ตของคุณจะปิดการทำงาน"</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"โทรศัพท์ของคุณจะปิดเครื่อง"</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"คุณต้องการปิดการทำงานหรือไม่"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"เมื่อเร็วๆ นี้"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"ไม่มีแอปพลิเคชันล่าสุด"</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"ตัวเลือกของแท็บเล็ต"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"โหมดใช้งานบนเครื่องบิน"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"เปิดโหมดใช้งานบนเครื่องบิน"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"โหมดใช้งานบนเครื่องบินปิดทำงานอยู่"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ระบบ Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"บริการที่ต้องเสียค่าใช้จ่าย"</string>
@@ -160,7 +160,7 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"ข้อความของคุณ"</string>
     <string name="permgroupdesc_messages" msgid="7045736972019211994">"อ่านและเขียน SMS อีเมล และข้อความอื่นๆ ของคุณ"</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"ข้อมูลส่วนบุคคลของคุณ"</string>
-    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"เข้าถึงที่อยู่ติดต่อและปฏิทินของที่จัดเก็บบนแท็บเล็ตโดยตรง"</string>
+    <string name="permgroupdesc_personalInfo" product="tablet" msgid="6975389054186265786">"การเข้าถึงสมุดโทรศัพท์และปฏิทินที่จัดเก็บอยู่บนแท็บเล็ตโดยตรง"</string>
     <string name="permgroupdesc_personalInfo" product="default" msgid="5488050357388806068">"เข้าถึงที่อยู่ติดต่อและปฏิทินของที่จัดเก็บบนโทรศัพท์โดยตรง"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"ตำแหน่งของคุณ"</string>
     <string name="permgroupdesc_location" msgid="2430258821648348660">"ตรวจดูตำแหน่งทางกายภาพของคุณ"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"เครื่องมือในการพัฒนา"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"คุณลักษณะที่จำเป็นสำหรับผู้พัฒนาแอปพลิเคชันเท่านั้น"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"พื้นที่เก็บข้อมูล"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"เข้าถึงการ์ด SD"</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"เข้าถึงที่เก็บข้อมูล USB"</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"เข้าถึงการ์ด SD"</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"ปิดการใช้งานหรือแก้ไขแถบสถานะ"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"อนุญาตให้แอปพลิเคชันปิดการใช้งานแถบสถานะหรือเพิ่มและนำไอคอนระบบออก"</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"แถบสถานะ"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"อนุญาตให้แอปพลิเคชันเป็นแถบสถานะ"</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"ขยาย/ยุบแถบสถานะ"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"อนุญาตให้แอปพลิเคชันขยายหรือยุบแถบสถานะ"</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"ดักสายโทรออก"</string>
@@ -196,10 +194,10 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"ส่งข้อความ SMS"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"อนุญาตให้แอปพลิเคชันส่งข้อความ SMS แอปพลิเคชันที่เป็นอันตรายอาจทำให้คุณเสียค่าใช้จ่ายโดยการส่งข้อความโดยไม่ขอการยืนยันจากคุณ"</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"อ่าน SMS หรือ MMS"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"อนุญาตให้แอปพลิเคชันอ่านข้อความ SMS ที่จัดเก็บในแท็บเล็ตหรือซิมการ์ดของคุณ แอปพลิเคชันที่เป็นอันตรายอาจอ่านข้อความลับของคุณได้"</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"อนุญาตให้แอปพลิเคชันอ่านข้อความ SMS ที่จัดเก็บอยู่บนแท็บเล็ตหรือซิมการ์ดของคุณ แอปพลิเคชันที่เป็นอันตรายอาจอ่านข้อความที่เป็นความลับของคุณได้"</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"อนุญาตให้แอปพลิเคชันอ่านข้อความ SMS ที่จัดเก็บในโทรศัพท์หรือซิมการ์ดของคุณ แอปพลิเคชันที่เป็นอันตรายอาจอ่านข้อความลับของคุณได้"</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"แก้ไข SMS หรือ MMS"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"อนุญาตให้แอปพลิเคชันเขียนลงบนข้อความ SMS ที่จัดเก็บในแท็บเล็ตหรือซิมการ์ดของคุณ แอปพลิเคชันที่เป็นอันตรายอาจลบข้อความของคุณได้"</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"อนุญาตให้แอปพลิเคชันเขียนไปยังข้อความ SMS ที่จัดเก็บอยู่บนแท็บเล็ตหรือซิมการ์ดของคุณ แอปพลิเคชันที่เป็นอันตรายอาจลบข้อความของคุณได้"</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"อนุญาตให้แอปพลิเคชันเขียนลงบนข้อความ SMS ที่จัดเก็บในโทรศัพท์หรือซิมการ์ดของคุณ แอปพลิเคชันที่เป็นอันตรายอาจลบข้อความของคุณได้"</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"ได้รับ WAP"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ WAP แอปพลิเคชันที่เป็นอันตรายอาจตรวจสอบหรือลบข้อความของคุณโดยไม่แสดงให้คุณเห็น"</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ป้องกันการเปลี่ยนแอปพลิเคชัน"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"ป้องกันไม่ให้ผู้ใช้เปลี่ยนไปที่แอปพลิเคชันอื่น"</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"ตรวจดูและควบคุมการเริ่มใช้งานแอปพลิเคชันทั้งหมด"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"อนุญาตให้แอปพลิเคชันตรวจดูและควบคุมวิธีเรียกใช้งานกิจกรรมต่างๆ ของระบบ แอปพลิเคชันที่เป็นอันตรายอาจทำให้ระบบอยู่ในความเสี่ยง การอนุญาตนี้จำเป็นสำหรับการพัฒนาเท่านั้น ไม่ใช่สำหรับการใช้งานทั่วไป"</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"อนุญาตให้แอปพลิเคชันตรวจสอบและควบคุมวิธีการที่ระบบเริ่มต้นกิจกรรม แอปพลิเคชันที่เป็นอันตรายอาจทำให้ระบบโดยรวมเสียหาย การอนุญาตนี้จำเป็นสำหรับการพัฒนาเท่านั้น แต่ไม่จำเป็นสำหรับการใช้งานปกติ"</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"ส่งการกระจายข้อมูลว่ามีการนำแพคเกจออก"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"อนุญาตให้แอปพลิเคชันกระจายข้อมูลแจ้งเตือนว่ามีการนำแพ็คเก็จของแอปพลิเคชันออกแล้ว แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้จบการทำงานแอปพลิเคชันอื่นที่ทำงานอยู่"</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"ส่งการกระจายข้อมูลว่าได้รับ SMS"</string>
@@ -250,7 +248,7 @@
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"จัดการโทเค็นของแอปพลิเคชัน"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"อนุญาตให้แอปพลิเคชันสร้างและจัดการโทเค็นของตนเอง โดยข้ามการจัดลำดับ Z ปกติไป ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"กดปุ่มต่างๆ และปุ่ม Ctrl"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"อนุญาตให้แอปพลิเคชันส่งกิจกรรมป้อนข้อมูลของตนเอง (การกดปุ่ม ฯลฯ) ไปยังแอปพลิเคชันอื่น แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ควบคุมแท็บเล็ต"</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"อนุญาตให้แอปพลิเคชันส่งกิจกรรมการป้อนข้อมูลของตนเอง (การกดแป้น ฯลฯ) ไปยังแอปพลิเคชันอื่น แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้เข้าควบคุมแท็บเล็ตได้"</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"อนุญาตให้แอปพลิเคชันส่งกิจกรรมป้อนข้อมูลของตนเอง (การกดปุ่ม ฯลฯ) ไปยังแอปพลิเคชันอื่น แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ควบคุมโทรศัพท์"</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"บันทึกสิ่งที่คุณพิมพ์และการทำงานของคุณ"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"อนุญาตให้แอปพลิเคชันดูปุ่มที่คุณกดแม้ในระหว่างที่ทำงานร่วมกับแอปพลิเคชันอื่น (เช่น ป้อนรหัสผ่าน) ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
@@ -281,14 +279,14 @@
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"อนุญาตให้แอปพลิเคชันเพิ่มพื้นที่ว่างให้โทรศัพท์โดยการลบไฟล์ในไดเรกทอรีที่เก็บแคชของแอปพลิเคชัน โดยทั่วไปการเข้าถึงกระบวนการของระบบจะถูกจำกัดอย่างเข้มงวด"</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"ย้ายแอปพลิเคชันรีซอร์ส"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"อนุญาตให้แอปพลิเคชันย้ายแอปพลิเคชันรีซอร์สจากสื่อภายในเป็นสื่อภายนอกและกลับกัน"</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"อ่านไฟล์บันทึกระบบ"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"อนุญาตให้แอปพลิเคชันอ่านไฟล์บันทึกหลายไฟล์ของระบบ เพื่อค้นหาข้อมูลทั่วไปเกี่ยวกับสิ่งที่คุณกำลังทำกับแท็บเล็ต ซึ่งอาจรวมถึงข้อมูลส่วนบุคคลหรือข้อมูลความลับใดๆ"</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"อนุญาตให้แอปพลิเคชันอ่านไฟล์บันทึกหลายไฟล์ของระบบ เพื่อค้นหาข้อมูลทั่วไปเกี่ยวกับสิ่งที่คุณกำลังทำกับแท็บเล็ต ซึ่งอาจรวมถึงข้อมูลส่วนบุคคลหรือข้อมูลความลับใดๆ"</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"อ่านข้อมูลบันทึกที่สำคัญ"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"อนุญาตให้แอปพลิเคชันอ่านจากไฟล์บันทึกต่างๆ ของระบบ เพื่อค้นหาข้อมูลทั่วไปเกี่ยวกับสิ่งที่คุณกำลังทำอยู่กับแท็บเล็ต ซึ่งอาจรวมไปถึงข้อมูลส่วนบุคคลหรือส่วนตัว"</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"อนุญาตให้แอปพลิเคชันอ่านจากไฟล์บันทึกต่างๆ ของระบบ เพื่อค้นหาข้อมูลทั่วไปเกี่ยวกับสิ่งที่คุณกำลังทำอยู่กับโทรศัพท์ ซึ่งอาจรวมไปถึงข้อมูลส่วนบุคคลหรือส่วนตัว"</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"อ่าน/เขียนไปยังรีซอร์สที่เป็นเจ้าของโดยกลุ่มวินิจฉัย"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"อนุญาตให้แอปพลิเคชันอ่านและเขียนไปยังรีซอร์สที่เป็นของกลุ่มวินิจฉัย เช่น ไฟล์ใน /dev การทำเช่นนี้อาจส่งผลต่อความเสถียรและความปลอดภัยของระบบ และควรใช้สำหรับการวินิจฉัยเกี่ยวกับฮาร์ดแวร์โดยเฉพาะที่ทำโดยผู้ผลิตหรือผู้ให้บริการเท่านั้น"</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"เปิดหรือปิดการใช้งานส่วนประกอบของแอปพลิเคชัน"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"อนุญาตให้แอปพลิเคชันเปลี่ยนว่าจะเปิดใช้งานส่วนประกอบของแอปพลิเคชันอื่นหรือไม่ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ปิดการใช้งานฟังก์ชันสำคัญของแท็บเล็ต การอนุญาตจึงต้องทำอย่างระมัดระวัง เพราะอาจทำให้ส่วนประกอบของแอปพลิเคชันอยู่ในสถานะใช้งานไม่ได้ ทำงานไม่คงที่ หรือไม่เสถียรได้"</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"อนุญาตให้แอปพลิเคชันเปลี่ยนว่าจะเปิดใช้งานส่วนประกอบของแอปพลิเคชันอื่นหรือไม่ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ปิดการใช้งานฟังก์ชันสำคัญของแท็บเล็ต การอนุญาตจึงต้องทำอย่างระมัดระวัง เพราะอาจทำให้ส่วนประกอบของแอปพลิเคชันอยู่ในสถานะใช้งานไม่ได้ ทำงานไม่คงที่ หรือไม่เสถียรได้"</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"อนุญาตให้แอปพลิเคชันเปลี่ยนว่าจะเปิดการใช้งานคอมโพเนนต์หรือแอปพลิเคชันอื่นหรือไม่ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้เพื่อปิดการใช้งานคุณสมบัติที่สำคัญของแท็บเล็ตได้ ต้องใช้ความระมัดระวังเกี่ยวกับการอนุญาตนี้เพราะอาจทำให้คอมโพเนนต์ของแอปพลิเคชันเข้าสู่สถานะที่ไม่สามารถใช้งานได้ ไม่คงที่ หรือไม่เสถียร"</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"อนุญาตให้แอปพลิเคชันเปลี่ยนว่าจะเปิดใช้งานส่วนประกอบหรือแอปพลิเคชันอื่นหรือไม่ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้เพื่อปิดการใช้งานคุณสมบัติที่สำคัญของโทรศัพท์ได้ การอนุญาตจึงต้องทำอย่างระมัดระวัง เพราะอาจทำให้ส่วนประกอบของแอปพลิเคชันอยู่ในสถานะใช้งานไม่ได้ ทำงานไม่คงที่ หรือไม่เสถียรได้"</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"ตั้งค่าแอปพลิเคชันที่เหมาะสม"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"อนุญาตให้แอปพลิเคชันแก้ไขแอปพลิเคชันที่คุณต้องการ วิธีนี้อาจทำให้แอปพลิเคชันที่เป็นอันตรายแอบเปลี่ยนแอปพลิเคชันที่มีการเรียกใช้งาน โดยการปลอมแปลงแอปพลิเคชันที่มีอยู่ของคุณเพื่อเก็บข้อมูลส่วนบุคคลจากคุณ"</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"แก้ไขการตั้งค่าระบบสากล"</string>
@@ -298,19 +296,19 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"แก้ไขแผนที่ของบริการ Google"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"อนุญาตให้แอปพลิเคชันแก้ไขแผนที่บริการของ Google ห้ามใช้โดยแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"เริ่มต้นอัตโนมัติเมื่อบูต"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"อนุญาตให้แอปพลิเคชันเริ่มการทำงานเองทันทีที่ระบบบูตเสร็จ วิธีนี้อาจทำให้การเริ่มการทำงานของแท็บเล็ตใช้เวลานานขึ้น และทำให้แอปพลิเคชันชะลอการทำงานโดยรวมของแท็บเล็ตด้วยการทำงานตลอดเวลา"</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"อนุญาตให้แอปพลิเคชันเริ่มการทำงานเองทันทีที่ระบบบูตเสร็จ วิธีนี้อาจทำให้ใช้เวลานานขึ้นในการเริ่มการทำงานของแท็บเล็ต และทำให้แอปพลิเคชันชะลอการทำงานโดยรวมของแท็บเล็ตด้วยการทำงานตลอดเวลา"</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"อนุญาตให้แอปพลิเคชันเริ่มการทำงานเองทันทีที่ระบบบูตเสร็จ วิธีนี้อาจทำให้การเริ่มการทำงานของโทรศัพท์ใช้เวลานานขึ้น และทำให้แอปพลิเคชันชะลอการทำงานโดยรวมของโทรศัพท์ด้วยการทำงานตลอดเวลา"</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"ส่งการกระจายข้อมูลที่ติดหนึบ"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"อนุญาตให้แอปพลิเคชันส่งการกระจายข้อมูลที่ติดหนึบ ซึ่งจะยังคงอยู่หลังจากการกระจายข้อมูลจบไปแล้ว แอปพลิเคชันที่เป็นอันตรายอาจทำให้แท็บเล็ตทำงานช้าลงหรือไม่เสถียรโดยการใช้หน่วยความจำมากเกินไป"</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"อนุญาตให้แอปพลิเคชันส่งการกระจายข้อมูลที่ติดหนึบ ซึ่งจะยังคงอยู่หลังจากการกระจายข้อมูลจบไปแล้ว แอปพลิเคชันที่เป็นอันตรายอาจทำให้โทรศัพท์ทำงานช้าลงหรือไม่เสถียรเนื่องจากการใช้หน่วยความจำมากเกินไป"</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"อนุญาตให้แอปพลิเคชันส่งการกระจายข้อมูลที่ติดหนึบ ซึ่งจะยังคงอยู่หลังจากการกระจายข้อมูลจบไปแล้ว แอปพลิเคชันที่เป็นอันตรายอาจทำให้โทรศัพท์ทำงานช้าลงหรือไม่เสถียรโดยการใช้หน่วยความจำมากเกินไป"</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"อ่านข้อมูลที่อยู่ติดต่อแล้ว"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลรายชื่อติดต่อ (ที่อยู่) ทั้งหมดที่จัดเก็บบนแท็บเล็ตของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ส่งข้อมูลของคุณไปหาผู้อื่นได้"</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลรายชื่อติดต่อ (ที่อยู่) ทั้งหมดที่จัดเก็บอยู่บนแท็บเล็ตของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ส่งข้อมูลของคุณให้แก่ผู้อื่นได้"</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลที่อยู่ติดต่อ (ที่อยู่) ทั้งหมดที่จัดเก็บบนโทรศัพท์ของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ส่งข้อมูลของคุณไปหาผู้อื่นได้"</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"เขียนข้อมูลที่อยู่ติดต่อ"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"อนุญาตให้แอปพลิเคชันแก้ไขข้อมูลรายชื่อติดต่อ (ที่อยู่) ที่จัดเก็บบนแท็บเล็ตของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ลบหรือแก้ไขข้อมูลรายชื่อติดต่อของคุณได้"</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"อนุญาตให้แอปพลิเคชันแก้ไขข้อมูลรายชื่อติดต่อ (ที่อยู่) ที่จัดเก็บอยู่บนแท็บเล็ตของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ลบหรือแก้ไขข้อมูลรายชื่อติดต่อของคุณได้"</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"อนุญาตให้แอปพลิเคชันแก้ไขข้อมูลที่อยู่ติดต่อ (ที่อยู่) ที่จัดเก็บบนโทรศัพท์ของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ลบหรือแก้ไขข้อมูลที่อยู่ติดต่อของคุณได้"</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"อ่านกิจกรรมบนปฏิทิน"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมบนปฏิทินทั้งหมดที่จัดเก็บบนแท็บเล็ตของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ส่งกิจกรรมบนปฏิทินไปหาผู้อื่นได้"</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมในปฏิทินทั้งหมดที่จัดเก็บอยู่บนแท็บเล็ตของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ส่งกิจกรรมในปฏิทินของคุณให้แก่ผู้อื่นได้"</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมบนปฏิทินทั้งหมดที่จัดเก็บบนโทรศัพท์ของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ส่งกิจกรรมบนปฏิทินไปหาผู้อื่นได้"</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"เพิ่มหรือแก้ไขกิจกรรมบนปฏิทินและส่งอีเมลไปที่แขก"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"อนุญาตให้แอปพลิเคชันเพิ่มหรือเปลี่ยนกิจกรรมบนปฏิทิน ซึ่งอาจมีการส่งอีเมลไปหาแขก แอปพลิเคชันที่เป็นอันตรายสามารถใช้วิธีนี้เพื่อลบหรือแก้ไขกิจกรรมบนปฏิทินหรือส่งอีเมลไปหาแขกได้"</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"การอนุญาตให้ติดตั้งโปรแกรมแจ้งตำแหน่ง"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"สร้างที่มาของตำแหน่งจำลองเพื่อทดสอบ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้เขียนทับตำแหน่งและ/หรือสถานะที่ที่ส่งคืนมาจากที่มาของตำแหน่งจริง เช่น GPS หรือผู้ให้บริการเครือข่าย หรือตรวจดูและรายงานตำแหน่งของคุณให้ที่มาภายนอกทราบ"</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"ตำแหน่ง (GPS) โดยละเอียด"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"เข้าถึงที่มาของตำแหน่งโดยละเอียด เช่น GPS บนแท็บเล็ตในกรณีที่ใช้งานได้ แอปพลิเคชันที่เป็นอันตรายสามารถใช้วิธีนี้ระบุตำแหน่งของคุณและอาจใช้พลังงานแบตเตอรี่มากกว่าปกติ"</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"เข้าถึงที่มาของตำแหน่งโดยละเอียด เช่น ระบบกำหนดตำแหน่งบนพื้นโลก (Global Positioning System) บนแท็บเล็ตในกรณีที่ใช้งานได้ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ในการระบุตำแหน่งของคุณและอาจต้องใช้พลังงานแบตเตอรี่มากกว่าปกติ"</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"เข้าถึงที่มาของตำแหน่งโดยละเอียด เช่น GPS บนโทรศัพท์ในกรณีที่ใช้งานได้ แอปพลิเคชันที่เป็นอันตรายสามารถใช้วิธีนี้กำหนดตำแหน่งของคุณและอาจใช้พลังงานแบตเตอรี่มากกว่าปกติ"</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"ตำแหน่งโดยประมาณ (ตามเครือข่าย)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"เข้าถึงที่มาของตำแหน่งคร่าวๆ เช่น ฐานข้อมูลเครือข่ายสถานีเพื่อกำหนดตำแหน่งโดยประมาณของแท็บเลตถ้าทำได้ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้กำหนดตำแหน่งโดยสังเขปของคุณได้"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"เข้าถึงที่มาของตำแหน่งคร่าวๆ เช่น ฐานข้อมูลเครือข่ายโทรศัพท์เคลื่อนที่เพื่อระบุตำแหน่งโดยประมาณของแท็บเล็ตถ้าทำได้ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ระบุตำแหน่งคร่าวๆ ของคุณได้"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"เข้าถึงที่มาของตำแหน่งคร่าวๆ เช่น ฐานข้อมูลเครือข่ายสถานีเพื่อกำหนดตำแหน่งโดยประมาณของโทรศัพท์ถ้าทำได้ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้กำหนดตำแหน่งโดยสังเขปของคุณได้"</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"เข้าถึง SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"อนุญาตให้แอปพลิเคชันใช้คุณลักษณะระดับต่ำของ SurfaceFlinger"</string>
@@ -334,37 +332,39 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"อนุญาตให้แอปพลิเคชันแก้ไขการตั้งค่าเสียงสากล เช่น ระดับเสียงและการกำหนดเส้นทาง"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"บันทึกเสียง"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"อนุญาตให้แอปพลิเคชันเข้าถึงเส้นทางการบันทึกเสียง"</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"ถ่ายภาพ"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"อนุญาตให้แอปพลิเคชันถ่ายภาพด้วยกล้องถ่ายรูป การทำงานนี้จะทำให้แอปพลิเคชันเก็บภาพที่กล้องเห็นเมื่อใดก็ได้"</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"ปิดใช้งานแท็บเล็ตถาวร"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"ถ่ายภาพและวิดีโอ"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"อนุญาตให้แอปพลิเคชันถ่ายภาพและวิดีโอด้วยกล้องถ่ายรูป ซึ่งจะทำให้แอปพลิเคชันสามารถรวบรวมภาพที่กล้องมองเห็นได้ตลอดเวลา"</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"ปิดการใช้งานแท็บเล็ตอย่างถาวร"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"ปิดการใช้งานโทรศัพท์ถาวร"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"อนุญาตให้แอปพลิเคชันปิดใช้งานแท็บเล็ตทั้งหมดอย่างถาวร การทำเช่นนี้ถือว่าอันตรายมาก"</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"อนุญาตให้แอปพลิเคชันปิดการใช้งานแท็บเล็ตทั้งเครื่องอย่างถาวร การดำเนินการนี้เป็นอันตรายอย่างยิ่ง"</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"อนุญาตให้แอปพลิเคชันปิดใช้งานโทรศัพท์ทั้งหมดอย่างถาวร การทำเช่นนี้ถือว่าอันตรายมาก"</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"บังคับแท็บเล็ตให้รีบูต"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"บังคับให้แท็บเล็ตรีบูต"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"บังคับให้โทรศัพท์รีบูต"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"อนุญาตให้แอปพลิเคชันบังคับแท็บเล็ตให้รีบูต"</string>
+    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"อนุญาตให้แอปพลิเคชันบังคับให้แท็บเล็ตรีบูต"</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"อนุญาตให้แอปพลิเคชันบังคับโทรศัพท์ให้รีบูต"</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"ต่อเชื่อมและยกเลิกการต่อเชื่อมระบบไฟล์"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"อนุญาตให้แอปพลิเคชันต่อเชื่อมและยกเลิกการต่อเชื่อมระบบไฟล์สำหรับที่เก็บข้อมูลแบบถอดได้"</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"ฟอร์แมตที่จัดเก็บข้อมูลภายนอก"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"อนุญาตให้แอปพลิเคชันฟอร์แมตที่เก็บข้อมูลแบบถอดได้"</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"รับข้อมูลบนที่จัดเก็บข้อมูลเพื่อความปลอดภัย"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"อนุญาตให้แอปพลิเคชันรับข้อมูลบนที่จัดเก็บข้อมูลเพื่อความปลอดภัย"</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"สร้างที่เก็บข้อมูลเพื่อความปลอดภัย"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"อนุญาตให้แอปพลิเคชันสร้างที่จัดเก็บข้อมูลเพื่อความปลอดภัย"</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"ทำลายที่เก็บข้อมูลเพื่อความปลอดภัย"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"อนุญาตให้แอปพลิเคชันทำลายที่จัดเก็บข้อมูลเพื่อความปลอดภัย"</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"ต่อเชื่อม/ยกเลิกการต่อเชื่อมที่จัดเก็บข้อมูลเพื่อความปลอดภัย"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"อนุญาตให้แอปพลิเคชันต่อเชื่อม/ยกเลิกการต่อเชื่อมที่เก็บข้อมูลเพื่อความปลอดภัย"</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"เปลี่ยนชื่อที่จัดเก็บข้อมูลเพื่อความปลอดภัย"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"อนุญาตให้แอปพลิเคชันเปลี่ยนชื่อที่จัดเก็บข้อมูลเพื่อความปลอดภัย"</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"รับข้อมูลบนที่เก็บข้อมูลภายใน"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"อนุญาตให้แอปพลิเคชันรับข้อมูลบนที่เก็บข้อมูลภายใน"</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"สร้างที่เก็บข้อมูลภายใน"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"อนุญาตให้แอปพลิเคชันสร้างที่เก็บข้อมูลภายใน"</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"ทำลายที่เก็บข้อมูลภายใน"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"อนุญาตให้แอปพลิเคชันทำลายที่เก็บข้อมูลภายใน"</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"ต่อเชื่อม/ยกเลิกการต่อเชื่อมที่เก็บข้อมูลภายใน"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"อนุญาตให้แอปพลิเคชันต่อเชื่อม/ยกเลิกการต่อเชื่อมที่เก็บข้อมูลภายใน"</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"เปลี่ยนชื่อที่เก็บข้อมูลภายใน"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"อนุญาตให้แอปพลิเคชันเปลี่ยนชื่อที่เก็บข้อมูลภายใน"</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"ควบคุมการสั่นเตือน"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"อนุญาตให้แอปพลิเคชันควบคุมการสั่นเตือน"</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"ควบคุมไฟฉาย"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"อนุญาตให้แอปพลิเคชันควบคุมไฟฉาย"</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"เข้าถึงอุปกรณ์ USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"อนุญาตให้แอปพลิเคชันเข้าถึงอุปกรณ์ USB"</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"ทดสอบฮาร์ดแวร์"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"อนุญาตให้แอปพลิเคชันควบคุมอุปกรณ์ต่อพ่วงหลายอย่างเพื่อการทดสอบฮาร์ดแวร์"</string>
@@ -389,9 +389,9 @@
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ป้องกันไม่ให้โทรศัพท์เข้าโหมดสลีป"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"อนุญาตให้แอปพลิเคชันป้องกันไม่ให้แท็บเล็ตเข้าสู่โหมดสลีป"</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"อนุญาตให้แอปพลิเคชันป้องกันไม่ให้โทรศัพท์เข้าสู่โหมดสลีป"</string>
-    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"เปิดหรือปิดแท็บเล็ต"</string>
+    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"เปิดหรือปิดเครื่องแท็บเล็ต"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"เปิดหรือปิดโทรศัพท์"</string>
-    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"อนุญาตให้แอปพลิเคชันปิดหรือเปิดแท็บเล็ต"</string>
+    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"อนุญาตให้แอปพลิเคชันเปิดหรือปิดแท็บเล็ต"</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"อนุญาตให้แอปพลิเคชันปิดหรือเปิดโทรศัพท์"</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"เรียกใช้ในโหมดการทดสอบจากโรงงาน"</string>
     <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"เรียกใช้การทดสอบจากผู้ผลิตในระดับต่ำ โดยอนุญาตให้เข้าถึงฮาร์ดแวร์แท็บเล็ตอย่างสมบูรณ์ ใช้ได้เฉพาะช่วงที่แท็บเล็ตทำงานในโหมดการทดสอบจากผู้ผลิตเท่านั้น"</string>
@@ -411,7 +411,7 @@
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"ทำหน้าที่เป็น AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"อนุญาตให้แอปพลิเคชันโทรไปยัง AccountAuthenticators"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"พบบัญชีที่ไม่รู้จัก"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"อนุญาตให้แอปพลิเคชันเรียกรายชื่อบัญชีที่แท็บเล็ตรู้จัก"</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"อนุญาตให้แอปพลิเคชันรับรายการบัญชีที่แท็บเล็ตรู้จัก"</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"อนุญาตให้แอปพลิเคชันเรียกรายชื่อบัญชีที่โทรศัพท์รู้จัก"</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"ทำหน้าที่เป็นตัวตรวจสอบสิทธิ์บัญชี"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"อนุญาตให้แอปพลิเคชันใช้ตัวตรวจสอบสิทธิ์บัญชีของ AccountManager รวมถึงการสร้างบัญชีและรับและตั้งค่ารหัสผ่าน"</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"อนุญาตให้รับมัลติแคสต์ผ่าน Wi-Fi"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"อนุญาตให้แอปพลิเคชันรับแพ็คเก็ตที่ไม่ได้ส่งถึงอุปกรณ์ของคุณโดยตรง วิธีนี้อาจเป็นประโยชน์เมื่อพบบริการที่นำเสนออยู่ใกล้ๆ แต่จะใช้พลังงานมากกว่าโหมดที่ไม่ใช่มัลติแคสต์"</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"การใช้บลูทูธ"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"อนุญาตให้แอปพลิเคชันกำหนดค่าแท็บเล็ตบลูทูธในพื้นที่ ตลอดจนค้นหาและจับคู่กับอุปกรณ์ที่อยู่ระยะไกล"</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"อนุญาตให้แอปพลิเคชันกำหนดค่าแท็บเล็ตบลูทูธในพื้นที่ รวมทั้งค้นหาและจับคู่กับอุปกรณ์รีโมต"</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"อนุญาตให้แอปพลิเคชันกำหนดค่าโทรศัพท์บลูทูธในพื้นที่ ตลอดจนค้นหาและจับคู่กับอุปกรณ์ที่อยู่ระยะไกล"</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"สร้างการเชื่อมต่อบลูทูธ"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"อนุญาตให้แอปพลิเคชันดูการกำหนดค่าของแท็บเล็ตบลูทูธในพื้นที่ ตลอดจนเชื่อมต่อและยอมรับการเชื่อมต่อด้วยอุปกรณ์ที่จับคู่ไว้"</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"อนุญาตให้แอปพลิเคชันดูการกำหนดค่าของแท็บเล็ตบลูทูธในพื้นที่ แล้วทำการเชื่อมต่อและยอมรับการเชื่อมต่อกับอุปกรณ์ที่จับคู่"</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"อนุญาตให้แอปพลิเคชันดูการกำหนดค่าของโทรศัพท์บลูทูธในพื้นที่ ตลอดจนเชื่อมต่อและยอมรับการเชื่อมต่อด้วยอุปกรณ์ที่จับคู่ไว้"</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"ควบคุม Near Field Communication"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"อนุญาตให้แอปพลิเคชันสื่อสารกับแท็ก Near Field Communication (NFC) การ์ด และโปรแกรมอ่าน"</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"ปิดการใช้งานการล็อกปุ่มกด"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"อนุญาตให้แอปพลิเคชันปิดการใช้งานการล็อกปุ่มและการรักษาความปลอดภัยรหัสผ่านที่เกี่ยวข้องใดๆ ตัวอย่างการใช้งานของกรณีนี้คือ โทรศัพท์ปิดการใช้งานการล็อกปุ่มกดเมื่อมีสายเรียกเข้า จากนั้นจึงเปิดการใช้งานการล็อกปุ่มกดใหม่เมื่อวางสายแล้ว"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"อ่านการตั้งค่าการซิงค์แล้ว"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"อนุญาตให้แอปพลิเคชันอ่านคำ ชื่อ และวลีส่วนบุคคลที่ผู้ใช้อาจจัดเก็บไว้ในพจนานุกรมผู้ใช้"</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"เขียนลงพจนานุกรมที่ผู้ใช้กำหนด"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"อนุญาตให้แอปพลิเคชันเขียนคำใหม่ลงในพจนานุกรมของผู้ใช้"</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"แก้ไข/ลบข้อมูลการ์ด SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"แก้ไข/ลบเนื้อหาของที่เก็บข้อมูล USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"แก้ไข/ลบข้อมูลการ์ด SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"อนุญาตให้แอปพลิเคชันเขียนลงบนการ์ด SD"</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"อนุญาตให้แอปพลิเคชันเขียนไปยังที่เก็บข้อมูล USB"</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"อนุญาตให้แอปพลิเคชันเขียนลงบนการ์ด SD"</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"แก้ไข/ลบเนื้อหาของที่เก็บข้อมูลสื่อภายใน"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"อนุญาตให้แอปพลิเคชันแก้ไขเนื้อหาของที่เก็บข้อมูลสื่อภายใน"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"เข้าถึงระบบไฟล์แคช"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"อนุญาตให้แอปพลิเคชันอ่านและเขียนระบบไฟล์แคช"</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"จำกัดรหัสผ่าน"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"จำกัดประเภทรหัสผ่านที่อนุญาตให้คุณใช้"</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"ดูจำนวนครั้งที่พยายามเข้าสู่ระบบ"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"ตรวจสอบจำนวนรหัสผ่านที่ป้อนผิดทั้งหมดเมื่อปลดล็อกหน้าจอ และล็อกแท็บเล็ตหรือลบข้อมูลแท็บเล็ตทั้งหมด หากมีการป้อนรหัสผิดมากครั้งเกินไป"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"ตรวจสอบจำนวนรหัสผ่านที่ป้อนผิดทั้งหมดเมื่อปลดล็อกหน้าจอ และล็อกแท็บเล็ตหรือลบข้อมูลแท็บเล็ตทั้งหมด หากมีการป้อนรหัสผิดมากครั้งเกินไป"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"รีเซ็ตรหัสผ่าน"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"เปลี่ยนรหัสผ่านของคุณลงเป็นค่าใหม่ ซึ่งต้องให้ผู้ดูแลระบบมอบรหัสผ่านให้ก่อนคุณจึงจะสามารถลงชื่อเข้าใช้ได้"</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"บังคับล็อก"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"การควบคุมเมื่ออุปกรณ์ล็อกซึ่งต้องให้คุณป้อนรหัสผ่านซ้ำอีกครั้ง"</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"โทรออก/รับสายอินเทอร์เน็ต"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"อนุญาตให้แอปพลิเคชันใช้บริการ SIP เพื่อโทรออก/รับสายอินเทอร์เน็ต"</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่ากฎรหัสผ่าน"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"ควบคุมความยาวและอักขระที่อนุญาตให้ใช้ในรหัสผ่านการปลดล็อกหน้าจอ"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"ตรวจสอบจำนวนรหัสผ่านที่ป้อนไม่ถูกต้องเมื่อปลดล็อกหน้าจอ และล็อกแท็บเล็ตหรือลบข้อมูลทั้งหมดของแท็บเล็ตในกรณีที่ป้อนรหัสผ่านไม่ถูกต้องหลายครั้งเกินไป"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"ตรวจสอบจำนวนรหัสผ่านที่ป้อนไม่ถูกต้องเมื่อปลดล็อกหน้าจอ และล็อกโทรศัพท์หรือลบข้อมูลทั้งหมดของโทรศัพท์ในกรณีที่ป้อนรหัสผ่านไม่ถูกต้องหลายครั้งเกินไป"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"เปลี่ยนรหัสผ่านการปลดล็อกหน้าจอ"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"เปลี่ยนรหัสผ่านการปลดล็อกหน้าจอ"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"ล็อกหน้าจอ"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"ควบคุมว่าหน้าจอจะล็อกอย่างไรและเมื่อใด"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"ลบข้อมูลทั้งหมด"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"ลบข้อมูลในแท็บเล็ตโดยไม่มีการเตือนโดยการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"ลบข้อมูลในแท็บเล็ตโดยไม่มีการเตือนโดยการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"ลบข้อมูลของแท็บเล็ตโดยไม่มีการเตือน ด้วยการดำเนินการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"ลบข้อมูลของโทรศัพท์โดยไม่มีการเตือน ด้วยการดำเนินการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"ตั้งค่าพร็อกซีส่วนกลางของอุปกรณ์"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"ตั้งค่าพร็อกซีส่วนกลางของอุปกรณ์ที่จะใช้ขณะเปิดการใช้งานนโยบาย เฉพาะผู้ดูแลอุปกรณ์คนแรกเท่านั้นที่ตั้งค่าพร็อกซีส่วนกลางที่มีผลบังคับ"</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"ตั้งค่าการหมดอายุของรหัสผ่าน"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"ควบคุมระยะเวลาก่อนที่จะต้องเปลี่ยนรหัสผ่านการล็อกหน้าจอ"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"บ้าน"</item>
     <item msgid="869923650527136615">"มือถือ"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"เพจเจอร์ที่ทำงาน"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"ผู้ช่วย"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"กำหนดเอง"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"วันเกิด"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"วันครบรอบ"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"กิจกรรม"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"อื่นๆ"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"กำหนดเอง"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"บ้าน"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"ที่ทำงาน"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"ที่ทำงาน"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"อื่นๆ"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"กำหนดเอง"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"กำหนดเอง"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"ผู้ช่วย"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"พี่ชาย-น้องชาย"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"บุตร"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"คู่ชีวิต"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"บิดา"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"เพื่อน"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"ผู้จัดการ"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"มารดา"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"บิดามารดา"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"หุ้นส่วน"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"แนะนำโดย"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"ญาติ"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"พี่สาว-น้องสาว"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"คู่สมรส"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"กำหนดเอง"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"หน้าแรก"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"ที่ทำงาน"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"อื่นๆ"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"ป้อนรหัส PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"ป้อนรหัสผ่านเพื่อปลดล็อก"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"ป้อน PIN เพื่อปลดล็อก"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"รหัส PIN ไม่ถูกต้อง!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"หากต้องการปลดล็อก กด เมนู ตามด้วย 0"</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"หมายเลขฉุกเฉิน"</string>
@@ -646,8 +615,7 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"กลับสู่การโทร"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"ถูกต้อง!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"ขออภัย โปรดลองอีกครั้ง"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"ขออภัย โปรดลองอีกครั้ง"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"กำลังชาร์จ (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"ชาร์จแล้ว"</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"ซิมการ์ดถูกล็อก"</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"กำลังปลดล็อกซิมการ์ด…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้ง"\n\n"โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_1">%d</xliff:g> วินาที"</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้ง หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกแท็บเล็ตโดยใช้การลงชื่อเข้าใช้ Google "\n\n" โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"คุณป้อนรหัสผ่านไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว "\n\n"โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_1">%d</xliff:g> วินาที"</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"คุณป้อน PIN ไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว "\n\n"โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_1">%d</xliff:g> วินาที"</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกแท็บเล็ตโดยใช้การลงชื่อเข้าใช้ Google ของคุณ"\n\n" โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งหากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้การลงชื่อเข้าใช้ Google"\n\n"โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"ลองใหม่อีกครั้งใน <xliff:g id="NUMBER">%d</xliff:g> วินาที"</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"ลืมรูปแบบหรือ"</string>
@@ -698,23 +664,17 @@
     <string name="double_tap_toast" msgid="1068216937244567247">"เคล็ดลับ: แตะสองครั้งเพื่อขยายและย่อ"</string>
     <string name="autofill_this_form" msgid="1272247532604569872">"ป้อนอัตโนมัติ"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"ตั้งค่าการป้อนอัตโนมัติ"</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"อ่านประวัติและบุ๊กมาร์กของเบราว์เซอร์"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"อนุญาตให้แอปพลิเคชันอ่าน URL ทั้งหมดที่เบราว์เซอร์เคยเข้าชมและบุ๊กมาร์กของเบราว์เซอร์ทั้งหมด"</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"เขียนประวัติและบุ๊กมาร์กของเบราว์เซอร์"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"อนุญาตให้แอปพลิเคชันแก้ไขประวัติหรือบุ๊กมาร์กของเบราว์เซอร์ที่จัดเก็บบนแท็บเล็ตของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ลบหรือแก้ไขข้อมูลเบราว์เซอร์ของคุณได้"</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"อนุญาตให้แอปพลิเคชันแก้ไขประวัติหรือบุ๊กมาร์กของเบราว์เซอร์ที่จัดเก็บอยู่บนแท็บเล็ตของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ในการลบหรือแก้ไขข้อมูลเบราว์เซอร์ของคุณได้"</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"อนุญาตให้แอปพลิเคชันแก้ไขประวัติหรือบุ๊กมาร์กของเบราว์เซอร์ที่จัดเก็บบนโทรศัพท์ของคุณ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้ลบหรือแก้ไขข้อมูลเบราว์เซอร์ของคุณได้"</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"ตั้งเวลาปลุกในนาฬิกาปลุก"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"อนุญาตให้แอปพลิเคชันนี้ตั้งเวลาปลุกในแอปพลิเคชันนาฬิกาปลุกที่ติดตั้งไว้ แอปพลิเคชันนาฬิกาปลุกบางประเภทอาจไม่ใช้คุณลักษณะนี้"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"แก้ไขการอนุญาตเกี่ยวกับการระบุตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"อนุญาตให้แอปพลิเคชันแก้ไขการอนุญาตเกี่ยวกับการระบุตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์ แอปพลิเคชันที่เป็นอันตรายอาจใช้วิธีนี้อนุญาตให้ส่งข้อมูลตำแหน่งไปที่เว็บไซต์อื่นได้โดยพลการ"</string>
     <string name="save_password_message" msgid="767344687139195790">"คุณต้องการให้เบราว์เซอร์จำรหัสผ่านนี้หรือไม่"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"ตัด"</string>
     <string name="copy" msgid="2681946229533511987">"คัดลอก"</string>
     <string name="paste" msgid="5629880836805036433">"วาง"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"ไม่มีสิ่งที่จะวาง"</string>
     <string name="copyUrl" msgid="2538211579596067402">"คัดลอก URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"เลือกข้อความ..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"การเลือกข้อความ"</string>
     <string name="inputMethod" msgid="1653630062304567879">"วิธีป้อนข้อมูล"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"แก้ไขข้อความ"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"การทำงานของข้อความ"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"เหลือที่ว่างน้อย"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"พื้นที่เก็บข้อมูลบนแท็บเล็ตเหลือน้อย"</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"ที่เก็บข้อมูลแท็บเล็ตมีพื้นที่เหลือน้อย"</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"พื้นที่เก็บข้อมูลบนโทรศัพท์เหลือน้อย"</string>
     <string name="ok" msgid="5970060430562524910">"ตกลง"</string>
     <string name="cancel" msgid="6442560571259935130">"ยกเลิก"</string>
     <string name="yes" msgid="5362982303337969312">"ตกลง"</string>
     <string name="no" msgid="5141531044935541497">"ยกเลิก"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"โปรดทราบ"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"กำลังโหลด..."</string>
     <string name="capital_on" msgid="1544682755514494298">"ในวันที่"</string>
     <string name="capital_off" msgid="6815870386972805832">"ปิด"</string>
     <string name="whichApplication" msgid="4533185947064773386">"ทำงานให้เสร็จโดยใช้"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"บังคับปิด"</string>
     <string name="report" msgid="4060218260984795706">"รายงาน"</string>
     <string name="wait" msgid="7147118217226317732">"รอ"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"เปลี่ยนเส้นทางแอปพลิเคชัน"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังทำงานอยู่ในขณะนี้"</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> เปิดใช้ไว้แล้ว"</string>
+    <string name="smv_application" msgid="295583804361236288">"แอปพลิเคชัน <xliff:g id="APPLICATION">%1$s</xliff:g> (กระบวนการ <xliff:g id="PROCESS">%2$s</xliff:g>) ละเมิดนโยบาย StrictMode ที่บังคับใช้ด้วยตัวเอง"</string>
+    <string name="smv_process" msgid="5120397012047462446">"กระบวนการ <xliff:g id="PROCESS">%1$s</xliff:g> ละเมิดนโยบาย StrictMode ที่บังคับใช้ด้วยตัวเอง"</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> กำลังทำงาน"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"เลือกเพื่อสลับแอปพลิเคชัน"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"สลับแอปพลิเคชันหรือไม่"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"มีแอปพลิเคชันอื่นที่กำลังทำงานอยู่แล้ว ซึ่งต้องหยุดทำงานก่อนที่คุณจะเริ่มแอปพลิเคชันใหม่ได้"</string>
+    <string name="old_app_action" msgid="493129172238566282">"กลับสู่ <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"อย่าเริ่มแอปพลิเคชันใหม่"</string>
+    <string name="new_app_action" msgid="5472756926945440706">"เริ่มต้น <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"หยุดการทำงานของแอปพลิเคชันเก่าโดยไม่บันทึก"</string>
     <string name="sendText" msgid="5132506121645618310">"เลือกการทำงานของข้อความ"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"ระดับความดังเสียงเรียกเข้า"</string>
     <string name="volume_music" msgid="5421651157138628171">"ระดับเสียงของสื่อ"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"แสดงทั้งหมด"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"พื้นที่เก็บข้อมูลขนาดใหญ่ USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"เชื่อมต่อ USB แล้ว"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"คุณได้เชื่อมต่อโทรศัพท์เข้ากับคอมพิวเตอร์ผ่าน USB เลือกปุ่มด้านล่างนี้หากคุณต้องการคัดลอกไฟล์ระหว่างคอมพิวเตอร์และการ์ด SD ของ Android"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"คุณได้เชื่อมต่อโทรศัพท์เข้ากับคอมพิวเตอร์ผ่าน USB เลือกปุ่มด้านล่างนี้หากคุณต้องการคัดลอกไฟล์ระหว่างคอมพิวเตอร์และการ์ด SD ของ Android"</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"คุณได้เชื่อมต่อกับคอมพิวเตอร์ผ่าน USB แล้ว แตะปุ่มด้านล่างถ้าคุณต้องการคัดลอกไฟล์ระหว่างคอมพิวเตอร์กับที่เก็บข้อมูล USB ของ Android"</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"คุณได้เชื่อมต่อกับคอมพิวเตอร์ผ่าน USB แล้ว แตะปุ่มด้านล่างถ้าต้องการคัดลอกไฟล์ระหว่างคอมพิวเตอร์กับการ์ด SD ของ Android"</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"เปิดที่เก็บข้อมูล USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"พบปัญหาในการใช้การ์ด SD สำหรับที่จัดเก็บข้อมูล USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"พบปัญหาในการใช้การ์ด SD สำหรับที่จัดเก็บข้อมูล USB"</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"เกิดปัญหาในการใช้ที่เก็บข้อมูล USB ของคุณเพื่อเก็บข้อมูลจำนวนมากแบบ USB"</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"เกิดปัญหาในการใช้การ์ด SD เพื่อเก็บข้อมูลจำนวนมากแบบ USB"</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"เชื่อมต่อ USB แล้ว"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"เลือกเพื่อคัดลอกไฟล์ไปยัง/จากคอมพิวเตอร์ของคุณ"</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"ปิดที่เก็บข้อมูล USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"เลือกเพื่อปิดที่เก็บข้อมูล USB"</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"ใช้การจัดเก็บใน USB"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"ก่อนปิดที่จัดเก็บข้อมูล USB ตรวจดูให้แน่ใจว่าคุณได้ยกเลิกการต่อเชื่อม (\"นำออก\") การ์ด SD ของ Android จากคอมพิวเตอร์แล้ว"</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"ก่อนปิดที่เก็บข้อมูล USB ตรวจสอบให้แน่ใจว่าคุณได้ยกเลิกการต่อเชื่อม (“นำออก”) ที่เก็บข้อมูล USB ของ Android จากคอมพิวเตอร์แล้ว"</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"ก่อนปิดที่จัดเก็บข้อมูล USB ตรวจดูให้แน่ใจว่าคุณได้ยกเลิกการต่อเชื่อม (\"นำออก\") การ์ด SD ของ Android จากคอมพิวเตอร์แล้ว"</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"ปิดที่เก็บข้อมูล USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"พบปัญหาในการปิดที่เก็บข้อมูล USB ตรวจสอบให้แน่ใจว่าคุณได้ยกเลิกการต่อเชื่อมโฮสต์ USB แล้ว จากนั้นลองใหม่อีกครั้ง"</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"หากคุณเปิดที่จัดเก็บข้อมูล USB แอปพลิเคชันบางอย่างที่คุณใช้อยู่จะหยุดและอาจใช้งานไม่ได้จนกว่าคุณจะปิดที่จัดเก็บข้อมูล USB"</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"การปฏิบัติงานของ USB ล้มเหลว"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"ตกลง"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"ฟอร์แมตการ์ด SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"ฟอร์แมตที่เก็บข้อมูล USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"ฟอร์แมตการ์ด SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"คุณแน่ใจหรือไม่ว่าต้องการฟอร์แมตการ์ด SD ข้อมูลทั้งหมดบนการ์ดจะหายไป"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"ฟอร์แมตที่เก็บข้อมูล USB โดยลบไฟล์ทั้งหมดที่จัดเก็บอยู่ในนั้นหรือไม่ การทำงานนี้ไม่สามารถย้อนกลับได้"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"คุณแน่ใจหรือไม่ว่าต้องการฟอร์แมตการ์ด SD ข้อมูลทั้งหมดบนการ์ดจะหายไป"</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"รูปแบบ"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"เชื่อมต่อการแก้ไขข้อบกพร่อง USB แล้ว"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"ตัวเลือก"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"กำลังเตรียมการ์ด SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"กำลังเตรียมที่เก็บข้อมูล USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"กำลังเตรียมการ์ด SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"กำลังตรวจสอบหาข้อผิดพลาด"</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"การ์ด SD ว่างเปล่า"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"ที่เก็บข้อมูล USB ว่างเปล่า"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"การ์ด SD ว่างเปล่า"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"การ์ด SD ว่างเปล่าหรือมีระบบไฟล์ที่ไม่ได้รับการสนับสนุน"</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"ที่เก็บข้อมูล USB ว่างเปล่าหรือมีระบบไฟล์ที่ไม่ได้รับการสนับสนุน"</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"การ์ด SD ว่างเปล่าหรือมีระบบไฟล์ที่ไม่ได้รับการสนับสนุน"</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"การ์ด SD เสียหาย"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"ที่เก็บข้อมูล USB เสียหาย"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"การ์ด SD เสียหาย"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"การ์ด SD เสียหาย คุณอาจต้องฟอร์แมตซ้ำ"</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"ที่เก็บข้อมูล USB เสียหาย คุณอาจต้องฟอร์แมตใหม่"</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"การ์ด SD เสียหาย คุณอาจต้องฟอร์แมตซ้ำ"</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"การ์ด SD ถูกนำออกโดยไม่คาดหมาย"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"ที่เก็บข้อมูล USB ถูกนำออกโดยไม่คาดคิด"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"การ์ด SD ถูกนำออกโดยไม่คาดหมาย"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"ยกเลิกการต่อเชื่อมการ์ด SD ก่อนนำออกเพื่อหลีกเลี่ยงข้อมูลสูญหาย"</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"ยกเลิกการต่อเชื่อมที่เก็บข้อมูล USB ก่อนนำออกเพื่อป้องกันข้อมูลสูญหาย"</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"ยกเลิกการต่อเชื่อมการ์ด SD ก่อนนำออกเพื่อหลีกเลี่ยงข้อมูลสูญหาย"</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"นำการ์ด SD ออกได้อย่างปลอดภัย"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"นำที่เก็บข้อมูล USB ออกอย่างปลอดภัย"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"นำการ์ด SD ออกได้อย่างปลอดภัย"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"คุณสามารถนำการ์ด SD ออกได้อย่างปลอดภัย"</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"คุณสามารถนำที่เก็บข้อมูล USB ออกได้อย่างปลอดภัย"</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"คุณสามารถนำการ์ด SD ออกได้อย่างปลอดภัย"</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"นำการ์ด SD ออกแล้ว"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"นำที่เก็บข้อมูล USB ออกแล้ว"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"นำการ์ด SD ออกแล้ว"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"การ์ด SD ถูกนำออก ใส่การ์ดใหม่"</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"ที่เก็บข้อมูล USB ถูกนำออกแล้ว ใส่สื่อใหม่"</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"การ์ด SD ถูกนำออก ใส่การ์ดใหม่"</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"ไม่พบกิจกรรมที่ตรงกัน"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"อัปเดตสถิติการใช้ส่วนประกอบ"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"ส่ง"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"ถัดไป"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"เสร็จสิ้น"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"ก่อนหน้า"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"ปฏิบัติ"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"หมุนหมายเลข "\n" โดยใช้ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"สร้างที่อยู่ติดต่อ "\n"โดยใช้ <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN ตามคีย์ที่ให้ใช้ร่วมกันล่วงหน้า"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/ VPN ตามใบรับรอง"</string>
     <string name="upload_file" msgid="2897957172366730416">"เลือกไฟล์"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"ไม่ได้เลือกไฟล์ไว้"</string>
     <string name="reset" msgid="2448168080964209908">"รีเซ็ต"</string>
     <string name="submit" msgid="1602335572089911941">"ส่ง"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"เปิดการใช้งานโหมดรถยนต์"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"เลือกเพื่อออกจากโหมดใช้ในรถยนต์"</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"การปล่อยสัญญาณหรือฮอตสปอตทำงานอยู่"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"แตะเพื่อกำหนดค่า"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"ย้อนกลับ"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"ถัดไป"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"ข้าม"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"การใช้งานข้อมูลมือถือในระดับสูง"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"แตะเพื่อเรียนรู้เพิ่มเติมเกี่ยวกับการใช้ข้อมูลมือถือ"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"เกินจำนวนสูงสุดของข้อมูลมือถือ"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"แตะเพื่อเรียนรู้เพิ่มเติมเกี่ยวกับการใช้ข้อมูลมือถือ"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"ไม่พบรายการที่ตรงกัน"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"ค้นหาบนหน้า"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 รายการที่ตรงกัน"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> จาก <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"เสร็จสิ้น"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"กำลังยกเลิกการต่อเชื่อมที่เก็บข้อมูล USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"กำลังยกเลิกการต่อเชื่อมการ์ด SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"กำลังลบที่เก็บข้อมูล USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"กำลังลบการ์ด SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"ลบที่เก็บข้อมูล USB ไม่สำเร็จ"</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"ลบการ์ด SD ไม่สำเร็จ"</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"การ์ด SD ถูกนำออกก่อนที่จะยกเลิกการต่อเชื่อม"</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"กำลังตรวจสอบที่เก็บข้อมูล USB อยู่ในขณะนี้"</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"กำลังตรวจสอบการ์ด SD อยู่ในขณะนี้"</string>
+    <string name="media_removed" msgid="7001526905057952097">"การ์ด SD ถูกนำออกแล้ว"</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"ขณะนี้ที่เก็บข้อมูล USB ถูกใช้งานอยู่โดยคอมพิวเตอร์"</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"ขณะนี้การ์ด SD มีการใช้งานอยู่โดยคอมพิวเตอร์"</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"สื่อภายนอกอยู่ในสถานะที่ไม่รู้จัก"</string>
+    <string name="share" msgid="1778686618230011964">"แบ่งปัน"</string>
+    <string name="find" msgid="4808270900322985960">"ค้นหา"</string>
+    <string name="websearch" msgid="4337157977400211589">"ค้นเว็บ"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 6dee767..f65d77e 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Voicemail"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Problema sa koneksyon o di-wastong MMI code."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Pinaghihigpitan ang pagpapatakbo sa mga fixed dialing number lang."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Pinagana ang serbisyo."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Pinagana ang serbisyo para sa:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Hindi pinagana ang serbisyo."</string>
@@ -126,10 +125,10 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"I-sync"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"I-sync"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Masyadong maraming pagtanggal ng <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Puno na ang imbakan ng tablet! Magtanggal ng ilang mga file upang magbakante ng espasyo."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Puno na ang imbakan ng tablet! Magtanggal ng ilang mga file upang magbakante ng puwang."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"Puno na ang imbakan ng telepono! Magtanggal ng ilang file upang magbakante ng espasyo."</string>
     <string name="me" msgid="6545696007631404292">"Ako"</string>
-    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Mga pagpipilian ng tablet"</string>
+    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Mga pagpipilian sa tablet"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"Mga pagpipilian sa telepono"</string>
     <string name="silent_mode" msgid="7167703389802618663">"Silent mode"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"I-on ang wireless"</string>
@@ -137,13 +136,12 @@
     <string name="screen_lock" msgid="799094655496098153">"Pag-lock sa screen"</string>
     <string name="power_off" msgid="4266614107412865048">"I-off"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Nagsa-shut down…"</string>
-    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Magsa-shut down ang iyong tablet."</string>
+    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Mag-shut down ang iyong tablet."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Magsa-shut down ang iyong telepono."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Gusto mo bang mag-shut down?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Kamakailan"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Walang mga kamakailang application."</string>
-    <string name="global_actions" product="tablet" msgid="408477140088053665">"Mga pagpipilian ng tablet"</string>
+    <string name="global_actions" product="tablet" msgid="408477140088053665">"Mga pagpipilian sa tablet"</string>
     <string name="global_actions" product="default" msgid="2406416831541615258">"Pagpipilian sa telepono"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Pag-lock sa screen"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"I-off"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Airplane mode"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Naka-ON ang airplane mode"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Naka-OFF ang airplane mode"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Mga serbisyong ginagastusan mo"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Mga tool na pang-develop"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Kailangan lang ang mga tampok para sa mga nag-develop ng application."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Imbakan"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"I-access ang SD card."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"I-access ang imbakan na USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"I-access ang SD card."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"huwag paganahin o baguhin ang status bar"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Pinapayagan ang application na huwag paganahin ang status bar o magdagdag at mag-alis ng mga icon ng system."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"status bar"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Pinapayagan ang application na maging status bar."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"palawakin/tiklupin ang status bar"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Pinapayagan ang application na palawakin o tiklupin ang status bar."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"sumagap ng mga papalabas na tawag"</string>
@@ -196,10 +194,10 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"magpadala ng mga SMS na mensahe"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Pinapayagan ang application na magpadala ng mga SMS na mensahe. Maaaring mapagastos ka ng mga nakakahamak na application sa pamamagitan ng pagpapadala ng mga mensahe nang wala ng iyong kumpirmasyon."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"magbasa ng SMS o MMS"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Pinapahintulutan ang application na basahin ang mga SMS na mensaheng nakaimbak sa iyong tablet o SIM card. Maaaring basahin ng mga nakakahamak na application ang iyong mga kumpedensyal na mensahe."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Pinapayagan ang application na basahin ang mga mensaheng SMS na nakaimbak sa iyong tablet o SIM card. Maaaring basahin ng mga nakapanghahamak na application ang iyong mga mensahe."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Pinapayagan ang application na basahin ang mga SMS na mensaheng nakaimbak sa iyong telepono o SIM card. Maaaring basahin ng mga nakakahamak na application ang iyong mga kumpidensyal na mensahe."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"i-edit ang SMS o MMS"</string>
-    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Pinapahintulutan ang application na magsulat sa mga SMS na mensahe na nakaimbak sa iyong tablet o SIM card. Maaaring tanggalin ng mga nakakahamak na application ang iyong mga mensahe."</string>
+    <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Pinapayagan ang application na magsulat sa mga mensaheng SMS na nakaimbak sa iyong tablet o SIM card. Maaaring tanggalin ng mga nakapanghahamak na application ang iyong mga mensahe."</string>
     <string name="permdesc_writeSms" product="default" msgid="6299398896177548095">"Pinapayagan ang application na magsulat sa mga SMS na mensahe na nakaimbak sa iyong telepono o SIM card. Maaaring tanggalin ng mga nakakahamak na application ang iyong mga mensahe."</string>
     <string name="permlab_receiveWapPush" msgid="8258226427716551388">"tumanggap ng WAP"</string>
     <string name="permdesc_receiveWapPush" msgid="5979623826128082171">"Pinapayagan ang application na tumanggap at magproseso ng mga WAP na mensahe. Maaaring subaybayan ng mga nakakahamak na application ang iyong mensahe o tanggalin ang mga ito nang hindi ipinapakita sa iyo."</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"pigilan ang mga paglipat ng app"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Pinipigilan ang user mula sa paglipat sa isa pang application."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"subaybayan at kontrolin ang lahat ng paglulunsad ng application"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Pinapahintulutan ang isang application na subaybayan at kontrolin kung paano naglulunsad ng mga aktibidad ang system. Maaaring ganap na malagay sa panganib ng mga nakakahamak na application ang system. Kailangan lang ang pahintulot na ito para sa pagpapaunlad, hindi kailanman para sa normal na paggamit."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Pinapayagan ang application na subaybayan at kontrolin kung paano naglulunsad ang system ng mga aktibidad. Maaaring kumpletong ikompromiso ng mga nakapanghahamak na application ang system. Kailangan lang ang pahintulot na ito para sa development, hindi para sa normal na paggamit."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"magpadala ng package inalis ang broadcast"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Pinapayagan ang isang application na mag-broadcast ng notification na naalis ang package ng application. Maaari itong gamitin ng mga nakakahamak na application upang isara ang anumang ibang tumatakbong application."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"magpadala ng broadcast na natatanggap sa SMS"</string>
@@ -244,13 +242,13 @@
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"ipakita ang mga hindi pinahintulutang window"</string>
     <string name="permdesc_internalSystemWindow" msgid="5895082268284998469">"Pinapayagan ang paglikha ng mga window na nilayon para sa paggamit ng user interface ng pangloob na system. Hindi para sa paggamit ng mga normal na application."</string>
     <string name="permlab_systemAlertWindow" msgid="3372321942941168324">"ipakita ang mga alerto sa antas ng system"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Pinapahintulutan ang isang application na ipakita ang system alert windows. Masasakop ng mga nakakahamak na application ang buong screen ng tablet."</string>
+    <string name="permdesc_systemAlertWindow" msgid="2884149573672821318">"Pinapayagan ang application na magpakita ng mga window ng alerto ng system. Maaaring kunin ng mga nakapanghahamak na application ang buong screen."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"baguhin ang bilis ng global animation"</string>
     <string name="permdesc_setAnimationScale" msgid="7181522138912391988">"Pinapayagan ang application na baguhin ang bilis ng global animation (mas mabibilis o mas mababagal na animation) anumang oras."</string>
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"pamahalaana ng mga token ng application"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Pinapayagan ang mga application na likhain at pamahalaan ang sariling mga token nito, at nilalampasan ang kanilang normal na Z-pagkasunud-sunod. Hindi kailanman dapat kailanganin para sa mga normal na application."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"pindutin ang mga key at kontrolin ang mga pindutan"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Pinapahintulutan ang isang application na ihatid ang sarili nitong mga input na kaganapan (mga pagpindot sa key, atbp.) sa ibang mga application. Magagamit ito ng mga nakakahamak na application upang sakupin ang tablet."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Pinapayagan ang application na ihatid ang sariling nitong mga kaganapan ng input (mga pagpindot sa key, atbp.) sa mga ibang application. Maaari itong gamitin ng mga nakapanghahamak na application upang sakupin ang tablet."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Pinapayagan ang isang application na ihatid ang sarili nitong mga input na kaganapan (mga pagpindot sa key, atbp.) sa ibang mga application. Magagamit ito ng mga nakakahamak na application upang sakupin ang telepono."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"itala kung ano ang iyong tina-type at mga pagkilos na iyong ginagawa"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Pinapayagan ang mga application na panoorin ang mga pinipindot mong key maging kapag nakikipag-ugnay sa isa pang application (gaya ng pagpasok ng password). Hindi dapat na kailanganin kailanman para sa mga normal na application."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"direktang i-install ang mga application"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Pinapayagan ang isang application na mag-install ng mga bago o na-update na Android package. Magagamit ito ng mga nakakahamak na application upang magdagdag ng mga bagong application nang may mga pabigla-biglang makapangyarihang pahintulot."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"tanggalin ang lahat ng data sa cache ng application"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Pinapahintulutan ang isang application na magbakante ng imbakan ng tablet sa pamamagitan ng pagtanggal ng mga file sa direktoryo ng cache ng application. Kadalasang napakahigpit ng access sa proseso ng system."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Pinapayagan ang application na bakantehin ang imbakan ng tablet sa pamamagitan ng pagtatanggal ng mga file sa direktoryo ng cache ng application. Karaniwang lubos na pinaghihigpitan ang access sa proseso ng system."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Pinapayagan ang isang application na magbakante ng imbakan ng telepono sa pamamagitan ng pagtanggal ng mga file sa direktoryo ng cache ng application. Kadalasang napakahigpit ng access sa proseso ng system."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Ilipat ang mga mapagkukunan ng application"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Pinapayagan ang isang application na ilipat ang mga mapagkukunan ng application mula sa panloob patungo sa panlabas na media at kabaligtaran."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"basahin ang mga file sa log ng system"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Pinapahintulutan ang isang application na magbasa mula sa iba\'t ibang file ng log ng system. Pinapahintulutan nito itong tumuklas ng pangkalahatang impormasyon tungkol sa kung ano ang ginagawa mo sa tablet, ngunit hindi dapat maglaman ang mga ito ng personal o pribadong impormasyon."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Pinapahintulutan ang isang application na magbasa mula sa iba\'t ibang file ng log ng system. Pinapahintulutan nito itong tumuklas ng pangkalahatang impormasyon tungkol sa kung ano ang ginagawa mo sa tablet, ngunit hindi dapat maglaman ang mga ito ng personal o pribadong impormasyon."</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"magbasa ng sensitibong data ng tala"</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Pinapayagan ang application na magbasa mula sa iba\'t ibang file ng tala ng system. Pinapayagan ito nito na tumuklas ng pangkalahatang impormasyon tungkol sa kung ano ang iyong ginagawa sa tablet, potensyal na kabilang ang personal o pribadong impormasyon."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Pinapayagan ang application na magbasa mula sa iba\'t ibang file ng tala ng system. Pinapayagan ito nito na tumuklas ng pangkalahatang impormasyon tungkol sa kung ano ang iyong ginagawa sa telepono, potensyal na kabilang ang personal o pribadong impormasyon."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"magbasa/magsulat sa mga mapagkukunang pag-aari ng diag"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Pinapayagan ang isang application na magbasa at magsulat ng anumang mapagkukunang pag-aari ng pangkat ng diag; halimbawa, mga file sa /dev. Posibleng maapektuhan nito ang katatagan at seguridad ng system. Dapat LANG itong gamitin sa mga tukoy sa hardware na diagnostic ng manufacturer o operator."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"paganahin o huwag paganahin ang mga nilalaman ng application"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Pinapahintulutan ang isang application na baguhin kung pinagana o hindi ang isang nilalaman ng isa pang application. Magagamit ito ng mga nakakahamak na application upang huwag paganahin ang mahahalagang kakayahan ng tablet. Ang pangangalaga ay dapat gamitin nang may pahintulot, dahil posibleng makuha ang mga nilalaman ng application sa hindi magagamit, pabagu-bago, o hindi matatag na katayuan."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Pinapahintulutan ang isang application na baguhin kung pinagana o hindi ang isang nilalaman ng isa pang application. Magagamit ito ng mga nakakahamak na application upang huwag paganahin ang mahahalagang kakayahan ng tablet. Ang pangangalaga ay dapat gamitin nang may pahintulot, dahil posibleng makuha ang mga nilalaman ng application sa hindi magagamit, pabagu-bago, o hindi matatag na katayuan."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Pinapayagan ang application na baguhin kung pinagana o hindi ang bahagi ng isa pang application. Maaari itong gamitin ng mga nakapanghahamak na application upang huwag paganahin ang mga mahalagang kakayahan ng tablet. Dapat na mag-ingat sa pahintulot na ito, dahil posibleng magawang hindi na magagamit, hindi patas, o hindi matatag na katayuan ang mga bahagi ng application."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Pinapayagan ang application na baguhin kung pinagana o hindi ang bahagi ng isa pang application. Maaari itong gamitin ng mga nakapanghahamak na application upang huwag paganahin ang mga mahalagang kakayahan ng telepono. Dapat na mag-ingat sa pahintulot na ito, dahil posibleng magawang hindi na magagamit, hindi patas, o hindi matatag na katayuan ang mga bahagi ng application."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"itakda ang mga ninanais na application"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Pinapayagan ang isang application na baguhin ang mga ninanais mong application. Mapapayagan nito ang mga nakakahamak na application na tahimik na baguhin ang mga application na pinapatakbo, na gumagaya sa iyong mga umiiral na application upang kumolekta ng pribadong data mula sa iyo."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"baguhin ang mga setting ng global system"</string>
@@ -298,19 +296,19 @@
     <string name="permlab_writeGservices" msgid="2149426664226152185">"baguhin ang mapa ng mga serbisyo ng Google"</string>
     <string name="permdesc_writeGservices" msgid="6602362746516676175">"Pinapayagan ang isang application na baguhin ang mapa ng mga serbisyo ng Google. Hindi para sa paggamit ng mga normal na application."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"awtomatikong magsimula sa boot"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Pinapahintulutan ang isang application na makapagsimula sa sandaling matapos mag-boot ang system. Magagawa nitong mapatagal ang pagsisimula ng tablet at pinapayagan ang application na pabagalin ang kabuuan ng tablet sa pamamagitan ng palagiang pagtakbo."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Pinapayagan ang application na simulan ang sarili nito pagkatapos mismo na mag-boot ng system. Maaari itong magsanhi na mas matagal magsimula ang tablet at payagan ang application na pabagalin ang pangkalahatang tablet sa pamamagitan ng palaging pagtakbo."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Pinapayagan ang isang application na makapagsimula sa sandaling matapos mag-boot ang system. Magagawa nitong mapatagal ang pagsisimula ng telepono at pinapayagan ang application na pabagalin ang kabuuan ng telepono sa pamamagitan ng palagiang pagtakbo."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"magpadala ng sticky na pag-broadcast"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Pinapahintulutan ang isang application na magpadala ng mga sticky na broadcast, na nananatili pagkatapos ng broadcast. Magagawa ng mga nakakahamak na application na pabagalin o hindi maayos ang tablet sa pamamagitan ng paggamit ng masyadong maraming memorya nito."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Pinapayagan ang application na magpadala ng mga sticky broadcast, na mananatili pagkatapos na magwakas ng broadcast. Maaaring pabagalin o gawing hindi maayos ng mga nakapanghahamak na application ang tablet sa pamamagitan ng pagsasanhi dito sa paggamit ng masyadong maraming memorya."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Pinapayagan ang isang application na magpadala ng mga sticky na broadcast, na nananatili pagkatapos ng broadcast. Magagawa ng mga nakakahamak na application na pabagalin o hindi maayos ang telepono sa pamamagitan ng paggamit ng masyadong maraming memorya nito."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"basahin ang data ng contact"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Pinapahintulutan ang isang application na basahin ang lahat ng mga data ng pakikipag-ugnay (address) na nakaimbak sa iyong tablet. Magagamit ito ng mga nakakahamak na application upang ipadala ang iyong data sa ibang tao."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Pinapayagan ang application na basahin ang lahat ng data ng contact (address) na nakaimbak sa iyong tablet. Maaari itong gamitin ng mga nakapanghahamak na application upang ipadala ang iyong data sa mga ibang tao."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Pinapayagan ang isang application na basahin ang lahat ng mga data ng pakikipag-ugnay (address) na nakaimbak sa iyong telepono. Magagamit ito ng mga nakakahamak na application upang ipadala ang iyong data sa ibang tao."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"sumulat ng data ng pakikipag-ugnay"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Pinapahintulutan ang isang application na baguhin ang data ng pakikipag-ugnay (address) na nakaimbak sa iyong tablet. Magagamit ito ng mga nakakahamak na application upang burahin o baguhin ang iyong data ng pakikipag-ugnay."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Pinapayagan ang application na baguhin ang data ng contact (address) na nakaimbak sa iyong tablet. Maaari itong gamitin ng mga nakapanghahamak na application upang burahin o baguhin ang data ng iyong contact."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Pinapayagan ang isang application na baguhin ang data ng pakikipag-ugny (address) na nakaimbak sa iyong telepono. Magagamit ito ng mga nakakahamak na application upang burahin o baguhin ang iyong data ng pakikipag-ugnay."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"basahin ang mga kaganapan sa kalendaryo"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Pinapahintulutan ang isang application na basahin ang lahat ng mga kaganapan sa kalendaryong nakaimbak sa iyong tablet. Magagamit ito ng mga nakakahamak na application upang ipadala ang iyong mga kaganapan sa kalendaryo sa ibang tao."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Pinapayagan ang application na basahin ang lahat ng mga kaganapan sa kalendaryo na nakaimbak sa iyong tablet. Maaari itong gamitin ng mga nakapanghahamak na application upang ipadala ang iyong mga kaganapan sa kalendaryo sa mga ibang tao."</string>
     <string name="permdesc_readCalendar" product="default" msgid="5533029139652095734">"Pinapayagan ang isang application na basahin ang lahat ng mga kaganapan sa kalendaryong nakaimbak sa iyong telepono. Magagamit ito ng mga nakakahamak na application upang ipadala ang iyong mga kaganapan sa kalendaryo sa ibang tao."</string>
     <string name="permlab_writeCalendar" msgid="3894879352594904361">"magdagdag o baguhin ang mga kaganapan sa kalendaryo at magpadala ng email sa mga bisita"</string>
     <string name="permdesc_writeCalendar" msgid="2988871373544154221">"Pinapayagan ang isang application na magdagdag o magbago ng mga kaganapan sa iyong kalendaryo, na maaaring magpadala ng email sa mga bisita. Magagamit ito ng mga nakakahamak na application upang burahin o baguhin ang iyong mga kaganapan sa kalendaryo o magpadala ng email sa mga bisita."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"pahintulot na mag-install ng provider ng lokasyon"</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Lumikha ng mga kunwaring pinagmumulan ng lokasyon para sa pagsubok. Magagamit ito ng mga nakakahamak na application upang i-override ang lokasyon at/o katayuang ibinalik ng mga tunay na pinagmumulan ng lokasyon gaya ng GPS o mga Network provider o subaybayan at iulat ang iyong lokasyon sa panlabas na pinagmumulan."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"mahusay na (GPS) lokasyon"</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"I-access ang mahuhusay na mga pinagmumulan ng lokasyon gaya ng Global Positioning System sa tablet, kung saan available. Magagamit ito ng mga nakakahamak na application upang tukuyin kung nasaan ka, at maaaring gumamit ng karagdagang lakas ng baterya."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"I-access ang mga pinong mapagkukunan ng lokasyon gaya ng Global Positioning System sa tablet, kung saan available. Maaaring gamitin ito ng mga nakapanghahamak na application upang matukoy kung nasaan ka, at maaaring makakonsumo ng karagdagang lakas ng baterya."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"I-access ang mahuhusay na pinagmumulan ng lokasyon gaya ng Global Positioning System sa telepono, kung saan available. Magagamit ito ng mga nakakahamak na application upang tukuyin kung nasaan ka, at maaaring gumamit ng karagdagang lakas ng baterya."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"hindi tumpak na (batay sa network) lokasyon"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"I-access ang mga hindi tumpak na pinagmumulan ng lokasyon gaya ng database ng cellular network upang tumukoy ng malapit na lokasyon ng tablet, kung saan available. Magagamit ito ng mga nakakahamak na application upang tukuyin ang pinakamalapit na kinaroroonan mo."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"I-access ang mga magaspang na mapagkukunan ng lokasyon tulad ng database ng cellular network upang matukoy ang tinatayang lokasyon ng tablet, kung saan available. Maaari itong gamitin ng mga nakapanghahamak na application upang tinantyang matukoy kung nasaan ka."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"I-access ang mga hindi tumpak na pinagmumulan ng lokasyon gaya ng database ng cellular network upang tumukoy ng malapit na lokasyon ng telepono, kung saan available. Magagamit ito ng mga nakakahamak na application upang tukuyin ang pinakamalapit na kinaroroonan mo."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"i-access ang SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Pinapayagan ang application na gumamit ng mababang antas na mga tampok ng SurfaceFlinger."</string>
@@ -334,37 +332,39 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Pinapayagan ang application na baguhin ang mga setting ng global audio gaya ng lakas ng tunog at pag-route."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"mag-record ng audio"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Pinapayagan ang application na i-access ang path ng audio record."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"kumuha ng mga larawan"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Pinapayagan ang application na kumuha ng mga larawan sa camera. Pinapayagan nito ang application anumang oras na kumolekta ng mga larawang nakikita ng camera."</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"kumuha ng mga larawan at video"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Pinapayagan ang application na kumuha ng mga larawan at video gamit ang camera. Pinapayagan nito ang application sa anumang oras na mangolekta ng mga larawan na nakikita ng camera."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"permanenteng huwag paganahin ang tablet"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"permanenteng huwag paganahin ang telepono"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Pinapahintulutan ang application na permanenteng huwag paganahin ang buong tablet. Napaka-mapanganib ito."</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Pinapayagan ang application na permanenteng huwag paganahin ang buong tablet. Lubos na mapanganib ito."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Pinapayagan ang application na permanenteng huwag paganahin ang buong telepono. Napaka-mapanganib nito."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"puwersahang pag-reboot ng tablet"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"puwersahin ang pag-reboot ng tablet"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"puwersahin ang pag-reboot ng telepono"</string>
-    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Pinapahintulutan ang application na puwersahing i-reboot ang tablet."</string>
+    <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Pinapayagan ang application na puwersahin ang tablet na mag-reboot."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Pinapayagan ang application na puwersahing i-reboot ang telepono."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"i-mount at huwag i-mount ang mga filesystem"</string>
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Pinapayagan ang application na i-mount at i-unmount ang mga filesystem para sa naaalis na imbakan."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"i-format ang panlabas na imbakan"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Pinapayagan ang application na i-format ang naaalis na imbakan."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"kumuha ng impormasyon sa secure na imbakan"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Pinapayagan ang application na kumuha ng impormasyon sa secure na imbakan."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"lumikha ng secure na imbakan"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Pinapayagan ang application na lumikha ng secure na imbakan."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"sirain ang secure na imbakan"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Pinapayagan ang application na sirain ang secure na imbakan."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"i-mount / i-unmount ang secure na imbakan"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Pinapayagan ang application na i-mount / i-unmount ang secure na imbakan."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"palitan ang pangalan ng secure na imbakan"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Pinapayagan ang application na palitan ang pangalan ng secure na imbakan."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"kumuha ng impormasyon sa panloob na imbakan"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Pinapayagan ang application na kumuha ng impormasyon sa panloob na imbakan."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"lumikha ng panloob na imbakan"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Pinapayagan ang application na likhain ang panloob na imbakan."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"sirain ang panloob na imbakan"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Pinapayagan ang application na sirain ang panloob na imbakan."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"i-mount / i-unmount ang panloob na imbakan"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Pinapayagan ang application na i-mount / i-unmount ang panloob na imbakan."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"palitan ang pangalan ng panloob na imbakan"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Pinapayagan ang application na palitan ang pangalan ng panloob na imbakan."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"kontrolin ang vibrator"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Pinapayagan ang application na kontrolin ang vibrator."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"kontrolin ang flashlight"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Pinapayagan ang application na kontrolin ang flashlight."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"i-access ang mga USB device"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Pinapayagan ang application na i-access ang mga USB device."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"subukan ang hardware"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Pinapayagan ang application na kontrolin ang iba\'t ibang peripheral para sa layunin ng pagsubok ng hardware."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"Pinapayagan ang application na tumawag sa mga numero ng telepono nang wala ng iyong panghihimasok. Maaarig magdulot ang mga nakakahamak na application ng mga hindi inaasahang tawag sa iyong singilin sa telepono. Tandaan na hindi nito pinapayagan ang application na tumawag sa mga pang-emergency na numero."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"direktang tawagan ang anumang numero ng telepono"</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Pinapayagan ang application na tumawag sa anumang numero ng telepono, kabilang ang mga pang-emergency na numero, nang wala ng iyong panghihimasok. Maaaring gumawa ang mga nakakahawak na application ng hindi kailangan at ilegal na tawag sa mga pang-emergency na serbisyo."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"direktang simulan ang pag-set up ng CDMA na tablet"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"direktang simulan ang setup ng CDMA tablet"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"direktang simulan ang pag-set up ng CDMA na telepono"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Pinapayagan ang application na simulan ang pagprobisyon ng CDMA. Maaaring simulan ng mga nakakahamak na application ang pagprobisyon ng CDMA"</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"kotrolin ang mga notification ng pag-update ng lokasyon"</string>
@@ -385,16 +385,16 @@
     <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Pinapayagan ang application na kontrolin ang mga tampok sa telepono ng device. Makakapagpalit ng mga network ang application na may ganitong pahintulot, i-on at i-off ang radyo at mga katulad nito nang hindi ka nino-notify."</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"basahin ang katayuan ng telepono at pagkakakilanlan"</string>
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"Pinapayagan ang application na i-access ang mga tampok sa telepono ng device. Matutukoy ng application na may ganitong pahintulot ang numero ng telepono at serial number ng teleponong ito, kung aktibo man ang tawag, ang numerong kung saan konektado ang tawag na iyon at mga katulad nito."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"pigilan ang tablet mula sa paghinto"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"pigilan ang tablet mula sa pag-sleep"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"pigilan ang telepono mula sa paghinto"</string>
-    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Pinapahintulutan ang isang application na pigilan ang tablet na huminto."</string>
+    <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Pinapayagan ang application na pigilan ang tablet mula sa pag-sleep."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Pinapayagan ang isang application na pigilan ang telepono na huminto."</string>
-    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"i-on o i-off ang tablet"</string>
+    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"i-on o i-off ang power tablet"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"i-on o i-off ang telepono"</string>
-    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Pinapahintulutan ang application na i-on o i-off ang tablet."</string>
+    <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Pinapayagan ang application na i-on o i-off ang tablet."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Pinapayagan ang application na i-on o i-off ang telepono."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"tumakbo sa factory test mode"</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Patakbuhin bilang mababang antas na pagsubok ng gumawa, na nagpapahintulot ng kumpletong access sa hardware ng tablet. Available lang kapag tumatakbo ang tablet sa test mode ng gumawa."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Patakbuhin bilang isang pagsubok ng mababang antas na gumagawa, na pumapayag sa kumpletong access sa hardware ng tablet. Available lang kapag tumatakbo ang isang tablet sa mode na pagsubok ng gumagawa."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Patakbuhin bilang mababang antas na pagsubok ng gumawa, na nagpapahintulot ng kumpletong access sa hardware ng telepono. Available lang kapag tumatakbo ang telepono sa test mode ng gumawa."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"itakda ang wallpaper"</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Pinapayagan ang application na itakda ang wallpaper ng system."</string>
@@ -403,15 +403,15 @@
     <string name="permlab_masterClear" msgid="2315750423139697397">"i-reset ang system sa mga factory default"</string>
     <string name="permdesc_masterClear" msgid="5033465107545174514">"Pinapayagan ang isang application na ganap na i-reset ang system sa mga setting ng factory nito, binubura ang lahat ng data, configuration, at mga naka-install na application."</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"itakda ang oras"</string>
-    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Pinapahintulutan ang isang application na baguhin ang oras sa orasan ng tablet."</string>
+    <string name="permdesc_setTime" product="tablet" msgid="209693136361006073">"Pinapayagan ang application na baguhin ang oras ng tablet."</string>
     <string name="permdesc_setTime" product="default" msgid="667294309287080045">"Pinapayagan ang isang application na baguhin ang oras sa orasan ng telepono."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"itakda ang time zone"</string>
-    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Pinapayagan ang isang application na baguhin ang time zone ng tablet."</string>
+    <string name="permdesc_setTimeZone" product="tablet" msgid="2522877107613885139">"Pinapayagan ang application na baguhin ang time zone ng tablet."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="1902540227418179364">"Pinapayagan ang isang application na baguhin ang time zone ng telepono."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"gumanap bilang AccountManagerService"</string>
     <string name="permdesc_accountManagerService" msgid="6056903274106394752">"Pinapayagan ang isang application na tumawag sa AccountAuthenticators"</string>
     <string name="permlab_getAccounts" msgid="4549918644233460103">"tuklasin ang mga kilalang account"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Pinapahintulutan ang isang application na makuha ang listahan ng mga account na kilala ng tablet."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="857622793935544694">"Pinapayagan ang application na makuha ang listahan ng mga account na kilala ng tablet."</string>
     <string name="permdesc_getAccounts" product="default" msgid="6839262446413155394">"Pinapayagan ang isang application na makuha ang listahan ng mga account na kilala ng telepono."</string>
     <string name="permlab_authenticateAccounts" msgid="3940505577982882450">"gumaganap bilang tagapagpatotoo ng account"</string>
     <string name="permdesc_authenticateAccounts" msgid="4006839406474208874">"Pinapayagan ang isang application na gamitin ang mga kakayanang makapagpatotoo ng account ng AccountManager, kabilang ang paglikha ng mga account at pagkuha at pagtakda ng kanilang mga password."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"payagan ang pagtanggap ng Wi-Fi Multicast"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Pinapayagan ang isang application na tumanggap ng mga packet na hindi direktang nakatugon sa iyong device. Magiging kapaki-pakinabang ito kapag tumutuklas ng mga serbisyong inaalok sa malapit. Gumagamit ito ng higit pang baterya kaysa sa non-multicast mode."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"pangangasiwa ng bluetooth"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Pinapahintulutan ang isang application na i-configure ang lokal na Bluetooth na tablet, at upang tumuklas at mapareha sa mga remote na device."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Pinapayagan ang application na i-configure ang lokal na Bluetooth tablet, at tumuklas at ipares sa mga malayuang device."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Pinapayagan ang isang application na i-configure ang lokal na Bluetooth na telepono, at upang tumuklas at mapareha sa mga remote na device."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"lumikha ng mga koneksyon ng Bluetooth"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Pinapahintulutan ang isang application na tingnan ang configuration ng lokal na Bluetooth na tablet, at upang gumawa at tumanggap ng mga koneksyon sa mga nakapares na device."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Pinapayagan ang application na tingnan ang configuration ng lokal na Bluetooth tablet, at gumawa at tumanggap ng mga koneksyon sa mga ipinares na device."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Pinapayagan ang isang application na tingnan ang configuration ng lokal na Bluetooth na telepono, at upang gumawa at tumanggap ng mga koneksyon sa mga nakapares na device."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"kontrolin ang Near Field Communication"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Pinapayagan ang application na makipagkomunika sa mga Near Field Communication (NFC) na tag, card, at reader."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"huwag paganahin ang keylock"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Pinapayagan ang isang application na huwag paganahin ang keylock at ang anumang nauugnay na seguridad sa password. Ang isang lehitimong halimbawa nito ay ang hindi pagpapagana ng telepono sa keylock kapag nakakatanggap ng papasok na tawag sa telepono, pagkatapos ay muling pagaganahin ang keylock kapag tapos na ang tawag."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"basahin ang mga setting ng sync"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Pinapayagan ang isang application na magbasa ng anumang mga pribadong salita, pangalan, at parirala na maaaring naimbak ng user sa diksyunaryo ng user."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"isulat sa diksyunaryong tinukoy ng user"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Pinapayagan ang isang application na magsulat ng mga bagong salita sa diksyunaryo ng user."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"baguhin/tanggalin ang mga nilalaman ng SD card"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"baguhin/tanggalin laman ng USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"baguhin/tanggalin ang mga nilalaman ng SD card"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Pinapayagan ang isang application na magsulat sa SD card."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Pinapayagan application na sumulat sa imbakan na USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Pinapayagan ang isang application na magsulat sa SD card."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"baguhin/tanggalin ang mga nilalaman ng panloob na imbakan ng media"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Pinapayagan ang application na baguhin ang mga nilalaman ng panloob na imbakan ng media."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"i-access ang cache filesystem"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Pinapayagan ang isang application na basahin at isulat ang cache filesystem."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Limitahan ang password"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Higpitan ang mga uri ng password na maaari mong gamitin."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Panoorin ang mga pagtatangka sa pag-login"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Subaybayan ang bilang ng mga maling password na naipasok kapag nag-unlock ng screen, at i-lock ang tablet o burahin ang lahat ng data ng tablet kung masyadong maraming maling password ang naipasok"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Subaybayan ang bilang ng mga maling password na naipasok kapag nag-unlock ng screen, at i-lock ang tablet o burahin ang lahat ng data ng tablet kung masyadong maraming maling password ang naipasok"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"I-reset ang password"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Puwersahin ang iyong password sa bagong halaga, na hinihiling na ibigay sa iyo ng administrator bago ka maka-log in."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Puwersahang i-lock"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontrolin kapag nag-lock ang device, hinihiling sa iyong muling ipasok ang password nito."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"gumawa/tumanggap ng mga tawag sa Internet"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Pinapayagan ang application upang gamitin ang serbisyong SIP upang gumawa/tumanggap ng mga tawag sa Internet."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Magtakda ng mga panuntunan sa password"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kontrolin ang haba at mga character na pinapayagan sa mga password sa pag-unlock ng screen"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Subaybayan ang bilang ng hindi tamang password na ipinasok kapag ina-unlock ang screen, at i-lock ang tablet o burahin ang lahat ng data ng telepono kung masyadong maraming hindi tamang password ang ipinasok"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Subaybayan ang bilang ng hindi tamang password na ipinasok kapag ina-unlock ang screen, at i-lock ang telepono o burahin ang lahat ng data ng telepono kung masyadong maraming hindi tamang password ang ipinasok"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Palitan ang password sa pag-unlock ng screen"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Palitan ang password sa pag-unlock ng screen"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"I-lock ang screen"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Kontrolin kung paano at kailan magla-lock ang screen"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Burahin ang lahat ng data"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Burahin ang data ng tablet nang walang babala, sa pamamagitan ng pagsasagawa ng pag-reset ng data ng factory"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Burahin ang data ng tablet nang walang babala, sa pamamagitan ng pagsasagawa ng pag-reset ng data ng factory"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Burahin ang data ng tablet nang walang babala, sa pamamagitan ng pagsasagawa ng pag-reset sa data ng factory"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Burahin ang data ng telepono nang walang babala, sa pamamagitan ng pagsasagawa ng pag-reset sa data ng factory"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Itakda ang pandaigdigang proxy ng device"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Itakda ang pandaigdigang proxy ng device na gagamitin habang pinagana ang patakaran. Tanging ang unang admin ng device ang magtatakda sa may bisang pandaigdigang proxy."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Itakda pag-expire ng password"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Kontrolin kung gaano katagal bago kailangang palitan ang password sa pag-lock ng screen"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Home"</item>
     <item msgid="869923650527136615">"Mobile"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Pager sa Trabaho"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Katuwang"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Custom"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Kaarawan"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Anibersaryo"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Kaganapan"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Iba pa"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Custom"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Home"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Trabaho"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Trabaho"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Iba pa"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Custom"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Custom"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Assistant"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Kapatid na Lalaki"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Anak"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Domestic Partner"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Ama"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Kaibigan"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Manager"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Ina"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Magulang"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Kasosyo"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Ni-refer ni"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Kamag-anak"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Kapatid na Babae"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Asawa"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Custom"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Home"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Trabaho"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Iba pa"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Ipasok ang PIN code"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Ipasok ang password upang i-unlock"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Ipasok ang PIN upang i-unlock"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Maling PIN code!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Upang i-unlock, pindutin ang Menu pagkatapos ay 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Pang-emergency na numero"</string>
@@ -646,8 +615,7 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Bumalik sa tawag"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Tama!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Paumanhin, subukang muli"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Paumanhin, subukang muli"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Nagcha-charge (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Naka-charge."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Naka-lock ang SIM card."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Ina-unlock ang SIM card…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Mali mong naguhit ang iyong pattern na pang-unlock nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. "\n\n"Pakisubukang muli sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> (na) segundo."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Nakuha mo nang mali ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%d</xliff:g> higit pang hindi matagumpay na pagtatangka, hihilingin sa iyong i-unlock ang iyong tablet gamit ang iyong pag-sign-in sa Google."\n\n" Mangyaring subukang muli sa <xliff:g id="NUMBER_2">%d</xliff:g> (na) segundo."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Naipasok mo nang hindi tama ang iyong password ng <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. "\n\n"Pakisubukang muli pagkalipas ng <xliff:g id="NUMBER_1">%d</xliff:g> (na) segundo."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Naipasok mo nang hindi tama ang iyong PIN ng <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. "\n\n"Pakisubukang muli pagkalipas ng <xliff:g id="NUMBER_1">%d</xliff:g> (na) segundo."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Naiguhit mo nang hindi tama ang iyong pattern sa pag-unlock ng <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%d</xliff:g> pang hindi matagumpay na pagsubok, hihilingin sa iyong i-unlock ang iyong tablet gamit ang iyong pag-sign-in sa Google."\n\n" Pakisubukang muli pagkalipas ng <xliff:g id="NUMBER_2">%d</xliff:g> (na) segundo."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Naguhit mo nang mali ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%d</xliff:g> higit pang hindi matagumpay na pagtatangka, hihingin sa iyong i-unlock ang iyong telepono gamit ang iyong pag-sign-in sa Google."\n\n" Pakisubukang muli sa loob ng <xliff:g id="NUMBER_2">%d</xliff:g> (na) segundo."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Subukang muli sa loob ng <xliff:g id="NUMBER">%d</xliff:g> (na) segundo."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Nakalimutan ang pattern?"</string>
@@ -698,23 +664,17 @@
     <string name="double_tap_toast" msgid="1068216937244567247">"Tip: mag-double-tap upang mag-zoom in at out."</string>
     <string name="autofill_this_form" msgid="1272247532604569872">"AutoFill"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Setup AutoFill"</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"basahin ang kasaysayan at mga bookmark ng Browser"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Pinapayagan ang application na basahin ang lahat ng URL na binisita ng Browser, at lahat ng bookmark ng Browser."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"isulat ang kasaysayan ng Browser at mga bookmark"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Pinapahintulutan ang isang application na baguhin ang kasaysayan o mga bookmark ng Browser na nakaimbak sa iyong tablet. Magagamit ito ng mga nakakahamak na application upang burahin o baguhin ang iyong data ng Browser."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Pinapayagan ang application na baguhin ang kasaysayan o mga bookmark ng Browser na nakaimbak sa iyong tablet. Maaari itong gamitin ng mga nakapanghahamak na application upang burahin o baguhin ang data ng iyong Browser."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Pinapayagan ang isang application na baguhin ang kasaysayan o mga bookmark ng Browser na nakaimbak sa iyong telepono. Magagamit ito ng mga nakakahamak na application upang burahin o baguhin ang iyong data ng Browser."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"itakda ang alarm sa alarm clock"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Pinapayagan ang application na magtakda ng alarm sa isang naka-install na application ng alarm clock. Maaaring hindi ipatupad ng ilang application ng alarm clock ang tampok na ito."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Baguhin ang mga pahintulot ng Browser geolocation"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Pinapayagan ang isang application na baguhin ang mga pahintulot sa geolocation ng Browser. Magagamit ito ng mga nakakahamak na application upang payagan ang pagpapadala ng impormasyon ng lokasyon sa mga hindi saklaw na web site."</string>
     <string name="save_password_message" msgid="767344687139195790">"Gusto mo bang tandaan ng browser ang password na ito?"</string>
@@ -830,25 +790,21 @@
     <string name="cut" msgid="3092569408438626261">"I-cut"</string>
     <string name="copy" msgid="2681946229533511987">"Kopyahin"</string>
     <string name="paste" msgid="5629880836805036433">"I-paste"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Walang ipe-paste"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Kopyahin ang URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Pumili ng teksto..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Pagpili ng teksto"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Pamamaraan ng pag-input"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"I-edit ang teksto"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Pagkilos ng teksto"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Mababa sa espasyo"</string>
-    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Lumiliit ang espasyo ng imbakan ng tablet."</string>
+    <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Bumababa na ang puwang ng imbakan ng Tablet."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Lumiliit ang espasyo ng imbakan ng telepono."</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
     <string name="cancel" msgid="6442560571259935130">"Kanselahin"</string>
     <string name="yes" msgid="5362982303337969312">"OK"</string>
     <string name="no" msgid="5141531044935541497">"Kanselahin"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Bigyang pansin"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Naglo-load..."</string>
     <string name="capital_on" msgid="1544682755514494298">"I-ON"</string>
     <string name="capital_off" msgid="6815870386972805832">"I-OFF"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Kumpletuhin ang pagkilos gamit ang"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Puwersahang pagsara"</string>
     <string name="report" msgid="4060218260984795706">"Ulat"</string>
     <string name="wait" msgid="7147118217226317732">"Maghintay"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Ni-redirect application"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"Tumatakbo na ngayon ang <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Orihinal na nalunsad ang <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="smv_application" msgid="295583804361236288">"Ang application na <xliff:g id="APPLICATION">%1$s</xliff:g> (prosesong <xliff:g id="PROCESS">%2$s</xliff:g>) ay lumabag sa sarili nitong ipinapatupad na patakarang StrictMode."</string>
+    <string name="smv_process" msgid="5120397012047462446">"Ang prosesong <xliff:g id="PROCESS">%1$s</xliff:g> ay lumabag sa sarili nitong ipinapatupad na patakarang StrictMode."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"Tumatakbo ang <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Piliin upang lumipat ng application"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Maglipat ng mga application?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"May tumatakbo nang isa pang application na dapat na ihinto bago ka maaaring magsimula ng isang bago."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Bumalik sa <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Huwag simulan ang bagong application."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Simulan ang <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Itigil ang lumang application nang hindi nagse-save."</string>
     <string name="sendText" msgid="5132506121645618310">"Pumili ng pagkilos para sa teksto"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Lakas ng tunog ng ringer"</string>
     <string name="volume_music" msgid="5421651157138628171">"Lakas ng tunog ng media"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Ipakita lahat"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB Mass Storage"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Nakakonekta ang USB"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Kinonekta mo ang iyong telepono sa iyong computer sa pamamagitan ng USB. Piliin ang pindutan sa ibaba kung gusto mong kumopya ng mga file sa pagitan ng iyong computer at SD card ng iyong Android."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Kinonekta mo ang iyong telepono sa iyong computer sa pamamagitan ng USB. Piliin ang pindutan sa ibaba kung gusto mong kumopya ng mga file sa pagitan ng iyong computer at SD card ng iyong Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Kumonekta ka sa iyong computer sa pamamagitan ng USB. Pindutin ang pindutan sa ibaba kung gusto mong kumopya ng mga file sa pagitan ng iyong computer at imbakan na USB ng iyong Android."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Kumonekta ka sa iyong computer sa pamamagitan ng USB. Pindutin ang pindutan sa ibaba kung gusto mong kumopya ng mga file sa pagitan ng iyong computer at SD card ng iyong Android."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"I-on ang USB storage"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"May problema sa paggamit ng iyong SD card para sa USB storage."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"May problema sa paggamit ng iyong SD card para sa USB storage."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"May problema sa paggamit ng iyong imbakan na USB para sa maramihang imbakan na USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Nagkaproblema sa paggamit ng iyong SD card para sa maramihang imbakan na USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Nakakonekta ang USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Piliin upang kopyahin ang mga file sa/mula sa iyong computer."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"I-off ang USB storage"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Piliin upang i-off ang USB storage."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Ginagamit ang USB storage"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Bago i-off ang USB storage, tiyaking na-unmount (“inalis”) mo ang SD card ng iyong Android mula sa iyong computer."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Bago i-off ang imbakan na USB, tiyaking na-unmount (“na-eject”) ang imbakan na USB ng Android mula sa iyong computer."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Bago i-off ang USB storage, tiyaking na-unmount (“inalis”) mo ang SD card ng iyong Android mula sa iyong computer."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"I-off ang USB storage"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Nagkaproblema sa pag-off ng USB storage. Tingnan upang matiyak na na-unmount mo ang host ng USB, pagkatapos ay subukan muli."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Kung io-on mo ang USB storage, titigil ang ilang application na ginagamit mo at maaaring maging hindi available hanggang sa i-off mo ang USB storage."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Nabigo ang pagpapatakbo ng USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"I-format ang SD card"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"I-format USB storage"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"I-format ang SD card"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Sigurado ka bang gusto mong i-format ang SD card? Mawawala ang lahat ng data sa iyong card."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"I-format ang imbakan na USB, na binubura ang lahat ng mga file na nakaimbak doon? Hindi maaaring maibalik ang pagkilos!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Sigurado ka bang gusto mong i-format ang SD card? Mawawala ang lahat ng data sa iyong card."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Konektado ang debugging ng USB"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"mga kandidato"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Hinahanda ang SD card"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Ihinahanda ang imbakan na USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Hinahanda ang SD card"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Sinusuri para sa mga error."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Blangkong SD card"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Blangkong imbakan na USB"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Blangkong SD card"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"blangko ang SD card o may hindi suportadong filesystem."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Blangko ang imbakan na USB o may hindi sinusuportahang filesystem."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"blangko ang SD card o may hindi suportadong filesystem."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Sirang SD card"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Nasirang imbakan na USB"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Sirang SD card"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Nasira ang SD card. Maaaring kailanganin mo itong i-reformat."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Nasira ang imbakan na USB. Maaaring kailangan mo itong i-reformat."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Nasira ang SD card. Maaaring kailanganin mo itong i-reformat."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Hindi inaasahang inalis ang SD card"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Di inasahan naalis USB storage"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Hindi inaasahang inalis ang SD card"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"I-unmount ang SD card bago alisin upang maiwasan ang pagkawala ng data."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"I-unmount ang imbakan na USB bago alisin upang maiwasan ang pagkawala ng data."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"I-unmount ang SD card bago alisin upang maiwasan ang pagkawala ng data."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"ligtas na alisin ang SD card"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Ligtas na alisin imbakan na USB"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"ligtas na alisin ang SD card"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Ligtas mo nang maaalis ang SD card."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Maaari mong ligtas na alisin ang imbakan na USB."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Ligtas mo nang maaalis ang SD card."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Naalis na SD card"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Inalis na imbakan na USB"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Naalis na SD card"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Inalis ang SD card. Magpasok ng bago."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Inalis ang imbakan na USB. Magpasok ng bagong media."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Inalis ang SD card. Magpasok ng bago."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Walang nakitang mga tumutugmang aktibidad"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"i-update ang mga istatistika ng paggamit ng nilalaman"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Ipadala"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Susunod"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Tapos na"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Nkraan"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Isakatuparan"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Mag-dial ng numero"\n"gamit ang <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Lumikha ng contact"\n"gamit ang <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Unang ibinahaging key na batay sa L2TP/IPSec VPN"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"Batay sa certificate na L2TP/IPSec VPN"</string>
     <string name="upload_file" msgid="2897957172366730416">"Pumili ng file"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Walang napiling file"</string>
     <string name="reset" msgid="2448168080964209908">"I-reset"</string>
     <string name="submit" msgid="1602335572089911941">"Isumite"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Pinagana ang car mode"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Piliin upang lumabas sa car mode."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Pagsasama o aktibong hotspot"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Galawin upang i-configure"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Bumalik"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Susunod"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Laktawan"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Mataas na paggamit ng data ng mobile"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Galawin upang matuto nang higit pa tungkol sa paggamit ng data ng mobile"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Lumagpas na sa limitasyon ng data ng mobile"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Galawin upang matuto nang higit pa tungkol sa paggamit ng data ng mobile"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Walang mga tugma"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Maghanap sa pahina"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 tugma"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> ng <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Tapos na"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Ina-unmount ang imbakan na USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Ina-unmount ang SD card..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Binubura ang imbakan na USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Binubura ang SD card..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Nabigong burahin ang imbakan na USB."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Nabigong burahin ang SD card."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Inalis ang SD card bago na-unmount."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Kasalukuyang sinusuri ang imbakan na USB."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Kasalukuyang sinusuri ang SD card."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Inalis ang SD card."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Kasalukuyang ginagamit ang imbakan na USB ng isang computer."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Kasalukuyang ginagamit ang SD card ng isang computer."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Panlabas na media sa hindi kilalang katayuan."</string>
+    <string name="share" msgid="1778686618230011964">"Ibahagi"</string>
+    <string name="find" msgid="4808270900322985960">"Hanapin"</string>
+    <string name="websearch" msgid="4337157977400211589">"Paghahanap sa Web"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 625f174..762ea47 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Uçak modu"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uçak modu AÇIK"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Uçak modu KAPALI"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Size maliyet getiren hizmetler"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Uygulamaların flaş ışığını denetlemesine izin verir."</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"USB cihazlarına erişme"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"Uygulamaların USB cihazlarına erişimine izin verir"</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"donanımı test et"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Uygulamanın donanım testi için çeşitli çevre birimlerini denetlemesine izin verir."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"telefon numaralarına doğrudan çağrı yap"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"Harici medyanın durumu bilinmiyor."</string>
     <string name="share" msgid="1778686618230011964">"Paylaş"</string>
     <string name="find" msgid="4808270900322985960">"Bul"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"Google Web Arama"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 4f21650..a2ad6dc 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Голос. пошта"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Пробл. підключення чи недійсний код MMI."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Операція лише для номерів фіксованого набору."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Послугу ввімкнено."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Службу ввімкнено для:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Службу вимкнено."</string>
@@ -126,10 +125,10 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"Синхр."</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Синхр."</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Забагато видалень <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Пам\'ять пристрою заповнено! Видаліть файли, щоб звільнити місце."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Пам\'ять пристр. заповнено! Видал. файли, щоб звільн. місце."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"Пам\'ять тел. заповн.! Видаліть файли, щоб звільн. місце."</string>
     <string name="me" msgid="6545696007631404292">"Я"</string>
-    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Параметри пристрою"</string>
+    <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Парам. пристрою"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"Параметри тел."</string>
     <string name="silent_mode" msgid="7167703389802618663">"Беззвуч. режим"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"Увімкнути радіо"</string>
@@ -139,8 +138,7 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"Заверш. роботи..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Ваш пристрій буде вимкнено."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Ваш телефон буде вимкнено."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Дійсно вимкнути?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Останні"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Немає останніх програм."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Парам. пристрою"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим польоту"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим польоту ВВІМК."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим польоту ВИМК."</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Служби, які потребують оплати"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Інструм. розробника"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Функції потрібні лише для розробників програми."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Зберігання"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Доступ до карти SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Отрим. доступу до носія USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Доступ до карти SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"вимикати чи змін. рядок стану"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Дозволяє програмі вимик. рядок стану чи додавати та видаляти системні піктогр."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"рядок стану"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Дозволяє програмі бути рядком стану."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"розгорнути/згорн. рядок стану"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Дозволяє програмі розгортати чи згортати рядок стану."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"перехопл. вихідні дзвінки"</string>
@@ -196,7 +194,7 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"надсил. SMS повідом."</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Дозволяє програмі надсил. SMS повідомл. Шкідливі програми можуть спричин. збитки, надсилаючи повідомлення без вашого підтвердження."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"читати SMS або MMS"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Дозволяє програмі читати SMS повідомлення, збережені в пристрої чи SIM-карті. Шкідливі програми можуть читати ваші конфіденційні повідомлення."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Дозволяє програмі читати SMS повідомлення, збережені в пристрої чи SIM-карті. Шкідливі програми можуть читати ваші конфіденц. повідомл."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Дозволяє програмі зчитувати SMS повідомлення, збереж. у вашому тел. чи SIM-карті. Шкідливі прогр. можуть зчит. ваші конфіденційні повід."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"редаг. SMS або MMS"</string>
     <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Дозволяє програмі змінювати SMS повідомлення, збережені в пристрої чи SIM-карті. Шкідливі програми можуть видаляти ваші повідомл."</string>
@@ -250,7 +248,7 @@
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"керувати маркерами програми"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Дозволяє програмам створ. і керувати власними маркерами, не застосовуючи звич. накладання по осі Z. Ніколи не потрібний для звичайних програм."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"натиск. клавіші чи кнопки керув."</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Дозволяє програмі надавати власні події введення (натискання клавіш тощо) іншим програмам. Шкідливі програми можуть використовувати це для контролю над пристроєм."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Дозволяє програмі надавати власні події введення (натискання клавіш тощо) іншим програмам. Шкідливі програми можуть використов. це для контролю над пристроєм."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Дозволяє програмі надавати власні події введення (натискання клавіш і т. д.) іншим програмам. Шкідливі програми можуть використ. це для контролю над телеф."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"записувати, що ви вводите та які дії викон."</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Дозволяє програмі переглядати клавіші, які ви натискаєте, навіть під час роботи з іншою програмою (наприклад, під час вводу пароля). Ніколи не потрібний для звичайних програм."</string>
@@ -281,14 +279,14 @@
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Дозволяє програмі звільняти пам\'ять телефону, видаливши файли в каталозі кешування програми. Доступ зазвичай строго обмежено системним процесом."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Переміщати ресурси програми"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Дозволяє програмі переміщувати ресурси програми з внутрішніх на зовнішні носії та навпаки."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"чит. файли сист. журналу"</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"зчит. закриті дані журн."</string>
     <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Дозволяє програмі здійснювати зчитування з різних файлів журналу системи. Це дозволяє дізнаватися загальну інформацію про ваші дії в пристрої, яка потенційно може містити особисті чи конфіденційні дані."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Дозволяє програмі здійснювати зчитування з різних файлів журналу системи. Це дозволяє дізнаватися загальну інформацію про ваші дії в пристрої, яка потенційно може містити особисті чи конфіденційні дані."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Дозволяє програмі здійснювати зчитування з різних файлів журналу системи. Це дозволяє дізнаватися загальну інформацію про ваші дії в телефоні, яка потенційно може містити особисті чи конфіденційні дані."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"чит./зап. на ресури., якими вол. діаг."</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Дозволяє програмі зчитувати та запис. на будь-який ресурс, яким володіє діагностична група; напр., файли в /dev. Це потенційно може вплинути на безпеку та стабільність системи. Це необхідно використ. ЛИШЕ для діагностики обладнання, яку виконує виробник чи оператор."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"вмикати чи вимикати компоненти програми"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Дозволяє програмі змінювати, чи ввімкнено компонент іншої програми. Шкідливі програми можуть використовувати це для вимкнення важливих можливостей пристрою. З цим типом дозволу треба поводитися обережно, оскільки компоненти програми можуть стати непридатними, невідповідними чи нестабільними."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Дозволяє програмі змінювати, чи ввімкнено компонент іншої програми. Шкідливі програми можуть використовувати це для вимкнення важливих можливостей пристрою. З цим типом дозволу треба поводитися обережно, оскільки компоненти програми можуть стати непридатними, невідповідними чи нестабільними."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Дозволяє програмі змінювати, чи ввімкнено компонент іншої програми. Шкідливі програми можуть використовувати це для вимкнення важливих можливостей телефону. З цим типом дозволу треба поводитися обережно, оскільки компоненти програми можуть стати непридатними, невідповідними чи нестабільними."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"установл. потрібні програми"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Дозволяє програмі змінювати ваші вибрані програми. Це може дозволити шкідливим програмам непомітно змінювати запущені програми, примушувати існуючі програми за допомогою спуфінгу збирати ваші особисті дані."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"змін. загальні налашт-ня сист."</string>
@@ -301,13 +299,13 @@
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7530977064379338199">"Дозволяє програмі запускатися відразу після завантаження системи. Це може затримати запуск пристрою та дозволяє програмі сповільнити загальну роботу пристрою своїм постійним функціонуванням."</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="698336728415008796">"Дозволяє програмі запускатися відразу після завантаження системи. Це може затримати запуск телефону та дозволяє програмі сповільнити загальну роботу телефону своїм постійним функціонуванням."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"надсилати закріпл. запис"</string>
-    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Дозволяє програмі надсилати закріплені записи, які залишаються після відтворення запису. Шкідливі програми можуть сповільнювати роботу пристрою, робити його нестабільним, спричиняти використання завеликої кількості пам\'яті."</string>
+    <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Дозволяє програмі надсил. закріпл. записи, які залиш. після відтвор. запису. Шкідливі прогр. можуть сповільн. роботу пристрою, робити його нестаб., спричин. викор. завеликої к-сті пам\'яті."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Дозволяє програмі надсил. закріпл. записи, які залиш. після відтвор. запису. Шкідливі програми можуть сповільн. роботу тел., робити його нестаб., спричин. викор. завеликої к-сті пам\'яті."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"читати контакт. дані"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Дозволяє програмі зчитувати всі контактні дані (адреси), збережені у вашому пристрої. Шкідливі програми можуть використовувати це для надсилання ваших даних іншим людям."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Дозволяє програмі зчитувати всі контактні дані (адреси), збережені у вашому пристрої. Шкідливі програми можуть використ. це для надсил. ваших даних іншим людям."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Дозволяє програмі зчитувати всі дані контактів (адреси), збережені у вашому тел. Шкідливі програми можуть використ. це для надсилання ваших даних іншим людям."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"запис. контактні дані"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Дозволяє програмі змінювати контактні дані (адреси), збережені в пристрої. Шкідливі програми можуть використовувати це для видалення чи зміни ваших контактних даних."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Дозволяє програмі змінювати контактні дані (адреси), збереж. в пристрої. Шкідливі програми можуть використ. це для видалення чи зміни ваших контактних даних."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Дозволяє програмі змінювати контактні дані (адресу), збереж. в телефоні. Шкідливі програми можуть використ. це для видалення чи зміни ваших контактних даних."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"читати події календаря"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Дозволяє програмі зчитувати всі події календаря, збережені в пристрої. Шкідливі програми можуть використовувати це для надсилання ваших подій календаря іншим людям."</string>
@@ -321,10 +319,10 @@
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"дозвіл на встановлення провайдера місцезнах."</string>
     <string name="permdesc_installLocationProvider" msgid="5449175116732002106">"Створ. фіктивні джерела місцезн. для тестув. Шкідливі прогр. можуть викор. це для заміни місцезн. і/чи статусу, отрим. від дійсних джерел місцезн., таких як GPS або моб. операторів, а також для відстеж. і передачі вашого місцезн. зовн. джерелу."</string>
     <string name="permlab_accessFineLocation" msgid="8116127007541369477">"точне (GPS) місцезнах."</string>
-    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Отримує доступ до джерел точного місцезнаходження, наприклад системи глобального позиціонування в пристрої, де це доступно. Шкідливі програми можуть використовувати це для визначення вашого місцезнаходження та споживати додаткову енергію батареї."</string>
+    <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Отрим. доступ до джерел точного місцезн., напр. системи глоб. позиціонування в пристрої, де це доступно. Шкідливі прогр. можуть викор. це для визначення вашого місцезн. і споживати додаткову енергію батареї."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Отрим. доступ до точних джерел місцезн., таких як сист. глоб. позиціонування в тел., де це доступно. Шкідливі прогр. можуть викор. це для визнач. вашого місцезн. і споживати додаткову енергію батареї."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"приблизне (мережеве) місцезнах."</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Отримує доступ до джерел приблизного місцезнаходження, наприклад баз даних мобільної мережі, для визначення приблизного місцезнаходження пристрою, де це доступно. Шкідливі програми можуть використовувати це, щоб приблизно визначати ваше місцезнаходження."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Отрим. доступ до джерел прибл. місцезнах., напр. баз даних моб. мережі, для визначення прибл. місцезнах. пристрою, де це доступно. Шкідливі програми можуть використов. це, щоб приблизно визначати ваше місцезнах."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Отрим. доступ до джерел прибл. місцезн., напр. баз даних моб. мережі, для визначення прибл. місцезн. телефону, де це доступно. Шкідливі програми можуть використов. це, щоб приблизно визначати ваше місцезн."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"дост. до SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Дозволяє програмі викор. низькорівневі функції SurfaceFlinger."</string>
@@ -334,13 +332,13 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Дозволяє програмі змінювати заг. налашт-ня аудіо, такі як гучність і маршрутиз."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"запис-ти аудіо"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Дозволяє програмі отрим. доступ до шляху аудіозапису."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"фотографувати"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Дозоляє програмі робити знімки за допомогою камери. Це дозволяє програмі будь-коли отримувати зображення з камери."</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"фотограф. та знімати відео"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Дозоляє програмі фотографувати та знімати відео за допомогою камери. Це дозволяє програмі будь-коли отримувати зображення з камери."</string>
     <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"остаточно вимкнути пристрій"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"остаточно вимкнути телефон"</string>
     <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Дозволяє програмі остаточно вимкнути весь пристрій. Це дуже небезпечно."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Дозволяє програмі остаточно вимкнути весь телефон. Це дуже небезпечно."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"примусово перезавантажити пристрій"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"примус.перезав.пристр."</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"примус. перезав. тел."</string>
     <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Дозволяє програмі примусово перезавантажувати пристрій."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Дозволяє програмі примусово перезавантажувати телефон."</string>
@@ -348,23 +346,25 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Дозволяє програмі підкл. і відкл. файлові сист. для зберіг. на знімних носіях."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"форматувати зовн. пам\'ять"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Дозволяє програмі форматувати знімну пам\'ять."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"переносити інф-ю в безпечне сховище"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Дозволяє програмі переносити інформацію в безпечне сховище."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"створ. безпечне сховище"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Дозволяє програмі створювати безпечне сховище."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"знищ. безпечне сховище"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Дозволяє програмі знищувати безпечне сховище."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"підкл./відкл. безпечне сховище"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Дозволяє програмі підключати/відключати безпечне сховище."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"переймен. безп. сховище"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Дозволяє програмі перейменовувати безпечне сховище."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"переносити інф-ю у внутрішню пам\'ять"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Дозволяє програмі переносити інформацію у внутрішню пам\'ять."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"створ. внутрішню пам\'ять"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Дозволяє програмі створювати внутрішню пам\'ять."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"знищувати внутрішню пам\'ять"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Дозволяє програмі знищувати внутрішню пам\'ять."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"підключ./відключ. внутрішню пам\'ять"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Дозволяє програмі підключати/відключати внутрішню пам\'ять."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"переймен. внутр. пам\'ять"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Дозволяє програмі перейменовувати внутрішню пам\'ять."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"контрол. вібросигн."</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Дозволяє програмі контролювати вібросигнал."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"контр. блим. світло"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Дозволяє програмі контролювати світловий сигнал."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"отр.дост.до прист.USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Дозволяє програмі отрим. доступ до пристр. USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"тест-ти обладн."</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Дозволяє програмі контрол. різні периферійні пристрої для тестування апаратного забезпечення."</string>
@@ -372,7 +372,7 @@
     <string name="permdesc_callPhone" msgid="3369867353692722456">"Дозволяє програмі набирати номери телефону без вашого залучення. Шкідливі програми можуть негативно впливати на стан вашого телефонного рахунку. Зауважте, що програмі не дозволено набирати номери аварійних служб."</string>
     <string name="permlab_callPrivileged" msgid="4198349211108497879">"прямо набирати будь-які ном. тел."</string>
     <string name="permdesc_callPrivileged" msgid="244405067160028452">"Дозволяє програмі набирати будь-який номер телефону, зокрема аварійні номери, без вашого залучення. Шкідливі програми можуть здійснювати непотрібні та незаконні дзвінки до аварійних служб."</string>
-    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"безпосередньо почати налаштування пристрою CDMA"</string>
+    <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"безпосер. поч. налашт. пристр. CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"безпосер. поч. налашт-ня CDMA тел."</string>
     <string name="permdesc_performCdmaProvisioning" msgid="6457447676108355905">"Дозволяє програмі запускати ініціалізацію CDMA. Шкідливі програми можуть без потреби запускати ініціалізацію CDMA"</string>
     <string name="permlab_locationUpdates" msgid="7785408253364335740">"контрол. сповіщ. про оновлення місцезн."</string>
@@ -385,16 +385,16 @@
     <string name="permdesc_modifyPhoneState" msgid="3302284561346956587">"Дозволяє програмі контролювати телефонні функції пристрою. Програма з цим дозволом може змінювати мережі, вмикати та вимикати радіо телефону тощо, не повідомляючи вас."</string>
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"читати стан телефону та ідентиф."</string>
     <string name="permdesc_readPhoneState" msgid="188877305147626781">"Дозволяє програмі отримувати доступ до телефонних функцій пристрою. Програма з цим дозволом може визначити номер телефону та серійний номер даного телефону, активність виклику, номер, на який робиться виклик та інше."</string>
-    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"не допускати перехід пристрою в режим сну"</string>
+    <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"не доп.перехід пристр.в реж.сну"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"недоп. перехід тел. в реж. сну"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="4032181488045338551">"Дозволяє програмі не допускати перехід пристрою в режим сну."</string>
     <string name="permdesc_wakeLock" product="default" msgid="7584036471227467099">"Дозволяє програмі не допускати перехід телефону в режим сну."</string>
-    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"увімкнути чи вимкнути пристрій"</string>
+    <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"увімк. чи вимк. пристрій"</string>
     <string name="permlab_devicePower" product="default" msgid="4928622470980943206">"вмик. чи вимик. телефон"</string>
     <string name="permdesc_devicePower" product="tablet" msgid="3853773100100451905">"Дозволяє програмі вимикати чи вимикати пристрій."</string>
     <string name="permdesc_devicePower" product="default" msgid="4577331933252444818">"Дозволяє програмі вимикати чи вимикати телефон."</string>
     <string name="permlab_factoryTest" msgid="3715225492696416187">"запуск у завод. реж. тест."</string>
-    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Запускає тест виробника на низькому рівні, дозволяючи повний доступ до апаратного забезпечення пристрою. Доступно лише коли пристрій запущено в режимі тестування виробником."</string>
+    <string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Запускає тест виробника на низьк. рівні, дозволяючи повний доступ до апарат. забезп. пристр. Доступно лише коли пристр. запущ. в режимі тестув. виробником."</string>
     <string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Запускає тест виробника на низькому рівні, дозволяючи повний доступ до апарат. забезп. тел. Доступно лише коли тел. запущено в режимі тестув. виробником."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"устан. фон. мал."</string>
     <string name="permdesc_setWallpaper" msgid="6417041752170585837">"Дозволяє програмі встановлювати фонов. мал. системи."</string>
@@ -438,15 +438,13 @@
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"дозвол. отримання багатоадр. Wi-Fi"</string>
     <string name="permdesc_changeWifiMulticastState" msgid="8199464507656067553">"Дозволяє програмі отрим. пакети, які не адрес. безпосер. вашому пристрою. Це може бути корисно під час виявл. пропонованих служб неподалік. Викор. більше потужності, ніж не багатоадресний реж."</string>
     <string name="permlab_bluetoothAdmin" msgid="1092209628459341292">"адміністрування bluetooth"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Дозволяє програмі налаштовувати локальний пристрій із Bluetooth, знаходити віддалені пристрої та створювати з ними пару."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Дозволяє програмі налашт. локальний пристрій із Bluetooth, знаходити віддалені пристрої та створ. з ними пару."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Дозволяє програмі налашт. локальний телефон із Bluetooth і знаходити та створ. пару з віддаленими пристроями."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"створюв. підключення Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Дозволяє програмі переглядати конфігурацію локального пристрою з Bluetooth, створювати та приймати з\'єднання зі спареними пристроями."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Дозволяє програмі переглядати конфігурацію локального Bluetooth телефону, створювати та приймати з\'єднання зі спареними пристроями."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"контрол. Near Field Communication"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Дозволяє прогр. обмін. даними з тегами, картками та читачами екрана Near Field Communication (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"вимик. блок. клав."</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Дозволяє програмі вимикати блокування клавіатури та будь-який пов\'язаний захист паролем. Допустимий приклад, коли телефон вимикає блокування клавіат. при отриманні вхідного дзвінка, після завершення якого блокування клавіатури відновлюється."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"чит. налашт-ня синхр."</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Дозволяє програмі зчитувати будь-які особисті вислови, назви та фрази, які користувач може зберігати в своєму словнику."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"запис. до заданого корист. словника"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Дозволяє програмі записувати до словника користувача нові слова."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"змінювати/видал. вміст карти SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"змін./видаляти вміст носія USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"змінювати/видал. вміст карти SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Дозволяє програмі записувати на карту SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Дозволяє програмі записувати на носій USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Дозволяє програмі записувати на карту SD."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"змін./видаляти вміст внутр. сховища медіа-файлів"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Дозволяє програмі змінювати вміст внутрішнього сховища медіа-файлів."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"отр. дост. до файл. сист. кешу"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Дозволяє програмі зчитувати та записувати файлову сист. кешу."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Обмежити пароль"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Обмежити типи паролів, дозволені для використання."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Перегляд спроб входу"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Відстежує кількість неправильних паролів, введених під час розблокування екрана, і блокує телефон або видаляє всі його дані, якщо введено забагато неправильних паролів"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Відстежує кількість неправильних паролів, введених під час розблокування екрана, і блокує телефон або видаляє всі його дані, якщо введено забагато неправильних паролів"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Змінити пароль"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Примусово присвоює паролю нове значення, що вимагає надання паролю адміністратором перед входом."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Примус. блок."</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Контрол., коли пристрій блок., вимагаючи повтор. ввести пароль."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"здійсн./отрим. Інтернет-дзвін."</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Дозволяє програмі використ. службу SIP, щоб здійсн./отрим. Інтернет-дзвінки."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Устан. правила пароля"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Контролює довжину паролів для розблокув. екрана та дозволені в них символи"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Відстежув. спроби розблок. екрана"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Відстежує кількість неправильних паролів, введених під час розблокування екрана, і блокує пристрій або видаляє всі його дані, якщо введено забагато неправильних паролів"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Відстежує кількість неправильних паролів, введених під час розблокування екрана, і блокує телефон або видаляє всі його дані, якщо введено забагато неправильних паролів"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Змінити пароль для розблокув. екрана"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Змінює пароль для розблок. екрана"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Блокувати екран"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Контролює, як і коли блокується екран"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Видалити всі дані"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Видаляє дані пристрою без попередження, відновлюючи заводські налаштування"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Видаляє дані пристрою без попередження, відновлюючи заводські налаштування"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Видаляє дані телефону без попередження, відновлюючи заводські налаштування"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Установ. глоб. проксі пристрою"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Устан. використ. глоб. проксі, коли ввімкнено політику. Лише адміністратор першого пристрою встановлює активний глоб. проксі."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Установити термін дії пароля"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Регулює, за скільки часу перед блокуванням екрана треба змінювати пароль"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Дом."</item>
     <item msgid="869923650527136615">"Мобільний"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Роб. пейджер"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Помічник"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Спеціальні"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"День нар."</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Річниця"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Подія"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Інші"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Спеціал."</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Дом."</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Роб."</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Роб."</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Інше"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Спеціал."</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Спеціальні"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Помічник"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Брат"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Дитина"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Співмешканець"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Батько"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Друг"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Керівник"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Мати"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Батько/мати"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Партнер"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Запросив(-ла)"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Родич"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Сестра"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Чоловік/дружина"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Спеціал."</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Головна"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Робоча"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Інша"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Введіть PIN-код"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Введіть пароль, щоб розбл."</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Введ. PIN для розблок."</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Неправильний PIN-код!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Щоб розбл., натисн. меню та 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Аварійний номер"</string>
@@ -646,14 +615,13 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Поверн. до дзвін."</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Правильно!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Спробуйте ще"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Спробуйте ще"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Зарядж-ся (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Заряджено."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Підкл. заряд. пристрій."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Нема SIM-карти."</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У пристрої немає SIM-карти."</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У пристр. нема SIM-карти."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"У тел. немає SIM-карти."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Вставте SIM-карту."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Лише аварійні виклики"</string>
@@ -663,11 +631,9 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM-карту заблок-но."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Розблокув. SIM-карти…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Неправильно намальовано ключ розблокування стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Спробуйте ще через <xliff:g id="NUMBER_1">%d</xliff:g> сек."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Неправильно намальовано ключ розблокування стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. Ваш пристрій потрібно буде розблоковувати за допомогою входу в Google після стількох додаткових неуспішних спроб: <xliff:g id="NUMBER_1">%d</xliff:g>."\n\n" Спробуйте ще через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Неправильно введено пароль стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Спробуйте ще через <xliff:g id="NUMBER_1">%d</xliff:g> сек."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Неправильно введено PIN-код стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n"Спробуйте ще через <xliff:g id="NUMBER_1">%d</xliff:g> сек."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Неправильно намал. ключ розблокування стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. Ваш пристрій потрібно буде розблок-ти за допомогою входу в Google після стількох додатк. неуспішних спроб: <xliff:g id="NUMBER_1">%d</xliff:g>."\n\n" Спробуйте ще через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Неправильно намал. ключ розблокування стільки разів: <xliff:g id="NUMBER_0">%d</xliff:g>. Ваш телефон потрібно буде розблок-ти за допомогою входу в Google після стількох додатк. неуспішних спроб: <xliff:g id="NUMBER_1">%d</xliff:g>."\n\n" Спробуйте ще через <xliff:g id="NUMBER_2">%d</xliff:g> сек."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Спробуйте ще через <xliff:g id="NUMBER">%d</xliff:g> сек."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Забули ключ?"</string>
@@ -696,25 +662,19 @@
     <string name="js_dialog_before_unload" msgid="1901675448179653089">"Перейти з цієї стор.?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Виберіть OK, щоб продовж., або \"Скасувати\", щоб залиш. на поточній стор."</string>
     <string name="save_password_label" msgid="6860261758665825069">"Підтверд."</string>
     <string name="double_tap_toast" msgid="1068216937244567247">"Порада: двічі нат. для збіл. або змен."</string>
-    <string name="autofill_this_form" msgid="1272247532604569872">"Автозап."</string>
+    <string name="autofill_this_form" msgid="1272247532604569872">"Автозаповн."</string>
     <string name="setup_autofill" msgid="8154593408885654044">"Налашт. автозап."</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"читати історію та закладки переглядача"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Дозволяє програмі зчитувати всі URL-адреси, на які заходив переглядач, і всі закладки переглядача."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"запис. історію та закладки переглядача"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Дозволяє програмі змінювати історію чи закладки веб-переглядача, збережені в пристрої. Шкідливі програми можуть використовувати це для видалення чи зміни даних веб-переглядача."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Дозволяє програмі змінювати історію чи закладки веб-переглядача, збережені в пристрої. Шкідливі прогр. можуть використ. це для видалення чи зміни даних веб-переглядача."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Дозволяє програмі змінювати історію чи закладки переглядача, збережені у вашому тел. Шкідливі програми можуть викор. це, щоб видаляти чи змінювати дані переглядача."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"налашт. сигнал у будильн."</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Дозволяє програмі налаштовувати сигнал у встановленій програмі будильника. У деяких програмах будильника ця функція може не застосовуватися."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Змін. дозволи геогр. місцезн. перегладача"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Дозволяє програмі змін. дозволи географ. місцезн. переглядача. Шкідливі програми можуть використ. це, щоб дозволяти надсилати інф-ю про місцезн. випадковим веб-сайтам."</string>
     <string name="save_password_message" msgid="767344687139195790">"Хочете, щоб переглядач запам\'ятав цей пароль?"</string>
@@ -830,15 +790,12 @@
     <string name="cut" msgid="3092569408438626261">"Виріз."</string>
     <string name="copy" msgid="2681946229533511987">"Копіюв."</string>
     <string name="paste" msgid="5629880836805036433">"Вставити"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Немає що вставити"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Копіюв. URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Вибрати текст..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Вибір тексту"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Метод введення"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Редаг. текст"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Дії з текстом"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Недост. місця"</string>
     <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Пам\'яті пристрою стає недостатньо."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Пам\'яті телефону стає недостатньо."</string>
@@ -847,8 +804,7 @@
     <string name="yes" msgid="5362982303337969312">"OK"</string>
     <string name="no" msgid="5141531044935541497">"Скасувати"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Увага"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Завант-ня..."</string>
     <string name="capital_on" msgid="1544682755514494298">"УВІМК."</string>
     <string name="capital_off" msgid="6815870386972805832">"ВИМК."</string>
     <string name="whichApplication" msgid="4533185947064773386">"Завершити дію за доп."</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Примус. закр."</string>
     <string name="report" msgid="4060218260984795706">"Повідом."</string>
     <string name="wait" msgid="7147118217226317732">"Чекати"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Програму переадресовано"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"Зараз працює <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"Спочатку було запущено <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
+    <string name="smv_application" msgid="295583804361236288">"Програма <xliff:g id="APPLICATION">%1$s</xliff:g> (процес <xliff:g id="PROCESS">%2$s</xliff:g>) порушила свою самозастосовну політику StrictMode."</string>
+    <string name="smv_process" msgid="5120397012047462446">"Процес <xliff:g id="PROCESS">%1$s</xliff:g> порушив свою самозастосовну політику StrictMode."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"Працює <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Виберіть, щоб перейти до програми"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Переключ. між прогр.?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Уже працює інша програма, яку потрібно зупинити перед тим, як запускати нову програму."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Поверн. до <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Не запускайте нову програму."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Запуст. <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Зупинити попередню програму без збереження."</string>
     <string name="sendText" msgid="5132506121645618310">"Виберіть дію для тексту"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Гучність дзвінка"</string>
     <string name="volume_music" msgid="5421651157138628171">"Гучність медіа"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Показ. всі"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB великої ємності"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"Підкл. через USB"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Ваш телефон було підключено до комп\'ютера за допомогою USB. Натисніть кнопку нижче, якщо хочете скопіювати файли з комп\'ютера на карту SD вашого Android."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Ваш телефон було підключено до комп\'ютера за допомогою USB. Натисніть кнопку нижче, якщо хочете скопіювати файли з комп\'ютера на карту SD вашого Android."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Ви підключилися до комп\'ютера за допомогою USB. Торкніться кнопки нижче, якщо хочете скопіювати файли з комп\'ютера на носій USB вашого пристрою Android або навпаки."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Ви підключилися до комп\'ютера за допомогою USB. Торкніться кнопки нижче, якщо хочете скопіювати файли з комп\'ютера на карту SD вашого пристрою Android або навпаки."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Увімкнути носій USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Виникла проблема з використанням карти SD для носія USB."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Виникла проблема з використанням карти SD для носія USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Виникла проблема з використанням носія USB замість носія USB великої ємності."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Виникла проблема з викор. карти SD замість носія USB вел. ємн."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"Підкл. через USB"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Виберіть, щоб скопіюв. файли на/з вашого комп."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Вимкнути носій USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Виберіть, щоб вимкнути носій USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Носій USB зайнято"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Перед вимкненням носія USB переконайтеся, що ви відключили (\"вийняли\") карту SD свого Android із комп\'ютера."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Перед вимкненням носія USB переконайтеся, що ви відключили від комп\'ютера (\"вийняли\") носій USB вашого пристрою Android."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Перед вимкненням носія USB переконайтеся, що ви відключили (\"вийняли\") карту SD свого Android із комп\'ютера."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Вимкнути носій USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Під час вимкнення носія USB виникла проблема. Перевірте, чи ви відключили USB-хост, після чого спробуйте знову."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Якщо ввімкнути носій USB, деякі програми, які викор., припинять свою роботу та можуть бути недоступними до вимкнення носія USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Помилка операції з USB"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Формат. карти SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Форматув. носій USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Формат. карти SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Ви дійсно хочете форматувати карту SD? Усі дані на вашій карті буде втрачено."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Форматувати носій USB, видаляючи всі збережені файли? Дію не можна скасувати!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Ви дійсно хочете форматувати карту SD? Усі дані на вашій карті буде втрачено."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Форматув."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Налагодження USB підключ."</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Пригот-ня карти SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Підготовка носія USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Пригот-ня карти SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Перевір. наявн. помил."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Порожня карта SD"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Порожній носій USB"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Порожня карта SD"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Карта SD порожня чи має непідтрим. файл. сист."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Носій USB порожній або має непідтримувану файлову систему."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Карта SD порожня чи має непідтрим. файл. сист."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Пошкодж. карта SD"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Пошкоджений носій USB"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Пошкодж. карта SD"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Карту SD пошкоджено. Її треба ще раз відформат."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Носій USB пошкоджено. Його треба ще раз відформатувати."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Карту SD пошкоджено. Її треба ще раз відформат."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Карту SD несподівано вилучено"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Носій USB несподівано вилучено"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Карту SD несподівано вилучено"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Відключ. карту SD перед її вилуч., щоб не втрат. дані."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Відключити носій USB перед його вилученням, щоб не втратити дані."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Відключ. карту SD перед її вилуч., щоб не втрат. дані."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Карту SD можна вилучити"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Носій USB можна вилучити"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"Карту SD можна вилучити"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Можна безпечно вилучити карту SD."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Можна безпечно вилучити носій USB."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Можна безпечно вилучити карту SD."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Вилучена карта SD"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Вилучений носій USB"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Вилучена карта SD"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Карту SD вилучено. Вставте нову."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Носій USB вилучено. Вставте новий носій."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Карту SD вилучено. Вставте нову."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Не знайдено відповідних дій"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"оновл. статистику викор. компонентів"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Надісл."</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Далі"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Готово"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Назад"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Запустити"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Набр. номер"\n", викор. <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Створ. контакт"\n", викор. <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"Спільн. ключ на осн. L2TP/IPSec VPN"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN на осн. сертифіката"</string>
     <string name="upload_file" msgid="2897957172366730416">"Виберіть файл"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Не вибрано файл"</string>
     <string name="reset" msgid="2448168080964209908">"Віднов."</string>
     <string name="submit" msgid="1602335572089911941">"Надіслати"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Режим авто ввімкн."</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Вибер. для вих. з реж.авто."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Прив\'язка чи точка дост. активна"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Натисн., щоб налашт."</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Назад"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Далі"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Пропустити"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Часте викор. моб. даних"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Натисн., щоб дізнатися про викор. моб. даних"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Перевищено ліміт моб. даних"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Натисн., щоб дізнатися про викор. моб. даних"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Немає збігів"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Знайти на сторінці"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 збіг"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> з <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Готово"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Відключення носія USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Відключення карти SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Очищення носія USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Очищення карти SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Помилка очищення носія USB."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Помилка очищення карти SD."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Карту SD вилучено раніше ніж її було відключено."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Носій USB наразі перевіряється."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Карта SD наразі перевіряється."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Карту SD вилучено."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Наразі комп\'ютер використовує носій USB."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Наразі комп\'ютер використовує карту SD."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Зовнішні носії в невідомому стані."</string>
+    <string name="share" msgid="1778686618230011964">"Надіслати"</string>
+    <string name="find" msgid="4808270900322985960">"Знайти"</string>
+    <string name="websearch" msgid="4337157977400211589">"Веб-пошук"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index fcdbf1c..4e5220a 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -34,8 +34,7 @@
     <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Thư thoại"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Sự cố kết nối hoặc mã MMI không hợp lệ."</string>
-    <!-- no translation found for mmiFdnError (5224398216385316471) -->
-    <skip />
+    <string name="mmiFdnError" msgid="5224398216385316471">"Chỉ hạn chế thao tác đối với số quay số định sẵn."</string>
     <string name="serviceEnabled" msgid="8147278346414714315">"Dịch vụ đã được bật."</string>
     <string name="serviceEnabledFor" msgid="6856228140453471041">"Dịch vụ đã được bật cho:"</string>
     <string name="serviceDisabled" msgid="1937553226592516411">"Dịch vụ đã bị vô hiệu hoá."</string>
@@ -126,7 +125,7 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"Đồng bộ hoá"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Đồng bộ hoá"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Quá nhiều lần xoá <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
-    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Bộ nhớ máy tính bảng đã đầy! Hãy xóa một số tệp để tạo thêm dung lượng."</string>
+    <string name="low_memory" product="tablet" msgid="2292820184396262278">"Bộ nhớ máy tính bảng đã đầy! Hãy xóa một số tệp để giải phóng dung lượng."</string>
     <string name="low_memory" product="default" msgid="6632412458436461203">"Bộ nhớ điện thoại đã đầy! Hãy xoá một số tệp để tạo thêm dung lượng."</string>
     <string name="me" msgid="6545696007631404292">"Tôi"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Tùy chọn máy tính bảng"</string>
@@ -139,8 +138,7 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"Đang tắt…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Máy tính bảng của bạn sẽ tắt."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Điện thoại của bạn sẽ tắt."</string>
-    <!-- no translation found for shutdown_confirm_question (6656441286856415014) -->
-    <skip />
+    <string name="shutdown_confirm_question" msgid="6656441286856415014">"Bạn có muốn tắt không?"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Gần đây"</string>
     <string name="no_recent_tasks" msgid="279702952298056674">"Không có ứng dụng nào gần đây."</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Tùy chọn máy tính bảng"</string>
@@ -153,6 +151,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Chế độ trên máy bay"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Chế độ trên máy bay BẬT"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Chế độ trên máy bay TẮT"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Dịch vụ tính tiền của bạn"</string>
@@ -177,14 +177,12 @@
     <string name="permgrouplab_developmentTools" msgid="3446164584710596513">"Công cụ phát triển"</string>
     <string name="permgroupdesc_developmentTools" msgid="9056431193893809814">"Các tính năng chỉ cần cho nhà phát triển ứng dụng."</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Dung lượng"</string>
-    <!-- outdated translation 9203302214915355774 -->     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Truy cập thẻ SD."</string>
+    <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Truy cập bộ nhớ USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Truy cập thẻ SD."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"vô hiệu hoá hoặc sửa đổi thanh trạng thái"</string>
     <string name="permdesc_statusBar" msgid="1365473595331989732">"Cho phép ứng dụng vô hiệu hoá thanh trạng thái hoặc thêm và xoá biểu tượng hệ thống."</string>
-    <!-- no translation found for permlab_statusBarService (7247281911387931485) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBarService (4097605867643520920) -->
-    <skip />
+    <string name="permlab_statusBarService" msgid="7247281911387931485">"thanh trạng thái"</string>
+    <string name="permdesc_statusBarService" msgid="4097605867643520920">"Cho phép ứng dụng là thanh trạng thái."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"mở rộng/thu gọn thanh trạng thái"</string>
     <string name="permdesc_expandStatusBar" msgid="7088604400110768665">"Cho phép ứng dụng mở rộng hoặc thu gọn thanh trạng thái."</string>
     <string name="permlab_processOutgoingCalls" msgid="1136262550878335980">"chặn các cuộc gọi đi"</string>
@@ -196,7 +194,7 @@
     <string name="permlab_sendSms" msgid="5600830612147671529">"gửi tin nhắn SMS"</string>
     <string name="permdesc_sendSms" msgid="1946540351763502120">"Cho phép ứng dụng gửi tin nhắn SMS. Các ứng dụng độc hại có thể khiến bạn tốn tiền bằng cách gửi tin nhắn mà không cần xác nhận của bạn."</string>
     <string name="permlab_readSms" msgid="4085333708122372256">"đọc SMS hoặc MMS"</string>
-    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Cho phép ứng dụng đọc tin nhắn SMS được lưu trữ trên máy tính bảng hoặc trên thẻ SIM của bạn. Các ứng dụng độc hại có thể đọc tin nhắn bí mật của bạn."</string>
+    <string name="permdesc_readSms" product="tablet" msgid="5836710350295631545">"Cho phép ứng dụng đọc tin nhắn SMS được lưu trữ trên máy tính bảng hoặc thẻ SIM của bạn. Các ứng dụng độc hại có thể đọc tin nhắn bí mật của bạn."</string>
     <string name="permdesc_readSms" product="default" msgid="3002170087197294591">"Cho phép ứng dụng đọc tin nhắn SMS được lưu trữ trên điện thoại hoặc thẻ SIM của bạn. Các ứng dụng độc hại có thể đọc tin nhắn bí mật của bạn."</string>
     <string name="permlab_writeSms" msgid="6881122575154940744">"chỉnh sửa SMS hoặc MMS"</string>
     <string name="permdesc_writeSms" product="tablet" msgid="5332124772918835437">"Cho phép ứng dụng ghi vào tin nhắn SMS được lưu trữ trên máy tính bảng hoặc thẻ SIM của bạn. Các ứng dụng độc hại có thể xóa tin nhắn của bạn."</string>
@@ -226,7 +224,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ngăn chuyển đổi ứng dụng"</string>
     <string name="permdesc_stopAppSwitches" msgid="3857886086919033794">"Ngăn người dùng chuyển sang ứng dụng khác."</string>
     <string name="permlab_runSetActivityWatcher" msgid="7811586187574696296">"giám sát và kiểm soát tất cả khởi chạy ứng dụng"</string>
-    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Cho phép ứng dụng giám sát và kiểm soát cách hệ thống khởi chạy các hoạt động. Các ứng dụng độc hại hoàn toàn có thể làm tổn hại hệ thống. Quyền này chỉ cần cho việc phát triển, không bao giờ dùng cho việc sử dụng thông thường."</string>
+    <string name="permdesc_runSetActivityWatcher" msgid="2149363027173451218">"Cho phép ứng dụng giám sát và kiểm soát cách hệ thống khởi chạy các hoạt động. Các ứng dụng độc hại có thể làm tổn hại hoàn toàn hệ thống. Quyền này chỉ cần cho việc phát triển, không bao giờ dùng cho việc sử dụng thông thường."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"gửi truyền phát đã xoá của gói"</string>
     <string name="permdesc_broadcastPackageRemoved" msgid="3453286591439891260">"Cho phép ứng dụng truyền phát thông báo rằng gói ứng dụng đã bị xoá. Các ứng dụng độc hại có thể sử dụng quyền này để loại bỏ mọi ứng dụng đang chạy khác."</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"gửi truyền phát SMS nhận được"</string>
@@ -250,7 +248,7 @@
     <string name="permlab_manageAppTokens" msgid="17124341698093865">"quản lý mã thông báo ứng dụng"</string>
     <string name="permdesc_manageAppTokens" msgid="977127907524195988">"Cho phép ứng dụng tạo và quản lý các mã thông báo riêng của mình, chuyển đổi thứ tự Z thông thường. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_injectEvents" msgid="1378746584023586600">"nhấn phím và kiểm soát các nút"</string>
-    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Cho phép ứng dụng phân phát các sự kiện nhập của riêng ứng dụng (số lần nhấn phím. v.v.) đến các ứng dụng khác. Các ứng dụng độc hại có thể sử dụng quyền này để kiểm soát máy tính bảng."</string>
+    <string name="permdesc_injectEvents" product="tablet" msgid="7200014808195664505">"Cho phép ứng dụng phân phát các sự kiện nhập của riêng ứng dụng (số lần nhấn phím. v.v..) đến các ứng dụng khác. Các ứng dụng độc hại có thể sử dụng quyền này để kiểm soát máy tính bảng."</string>
     <string name="permdesc_injectEvents" product="default" msgid="3946098050410874715">"Cho phép ứng dụng phân phát các sự kiện nhập của riêng ứng dụng (số lần nhấn phím. v.v..) đến các ứng dụng khác. Các ứng dụng độc hại có thể sử dụng quyền này để kiểm soát điện thoại."</string>
     <string name="permlab_readInputState" msgid="469428900041249234">"ghi lại nội dung bạn nhập và tác vụ bạn thực hiện"</string>
     <string name="permdesc_readInputState" msgid="5132879321450325445">"Cho phép ứng dụng xem các phím bạn nhấn ngay cả khi tương tác với ứng dụng khác (chẳng hạn như nhập mật khẩu). Không cần thiết cho các ứng dụng thông thường."</string>
@@ -277,18 +275,18 @@
     <string name="permlab_installPackages" msgid="335800214119051089">"cài đặt trực tiếp ứng dụng"</string>
     <string name="permdesc_installPackages" msgid="526669220850066132">"Cho phép ứng dụng cài đặt các gói Android mới hoặc đã được cập nhật. Các ứng dụng độc hại có thể sử dụng quyền này để thêm ứng dụng mới có quyền mạnh mẽ tuỳ ý."</string>
     <string name="permlab_clearAppCache" msgid="4747698311163766540">"xoá tất cả dữ liệu bộ nhớ cache của ứng dụng"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Cho phép ứng dụng tạo thêm dung lượng máy tính bảng bằng cách xóa các tệp trong thư mục bộ nhớ cache ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3097119797652477973">"Cho phép ứng dụng giải phóng bộ nhớ máy tính bảng bằng cách xóa các tệp trong thư mục bộ nhớ cache ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
     <string name="permdesc_clearAppCache" product="default" msgid="7740465694193671402">"Cho phép ứng dụng tạo thêm dung lượng điện thoại bằng cách xoá các tệp trong thư mục bộ nhớ cache ứng dụng. Quyền truy cập thường rất hạn chế đối với quy trình hệ thống."</string>
     <string name="permlab_movePackage" msgid="728454979946503926">"Chuyển tài nguyên của ứng dụng"</string>
     <string name="permdesc_movePackage" msgid="6323049291923925277">"Cho phép ứng dụng di chuyển các tài nguyên của ứng dụng từ phương tiện truyền thông bên trong ra phương tiện bên ngoài và ngược lại."</string>
-    <!-- outdated translation 4811921703882532070 -->     <string name="permlab_readLogs" msgid="6615778543198967614">"đọc tệp nhật ký hệ thống"</string>
+    <string name="permlab_readLogs" msgid="6615778543198967614">"đọc dữ liệu nhật ký nhạy cảm"</string>
     <string name="permdesc_readLogs" product="tablet" msgid="4077356893924755294">"Cho phép ứng dụng đọc từ nhiều tệp nhật ký khác nhau của hệ thống. Quyền này cho phép ứng dụng phát hiện thông tin chung về những gì bạn đang thực hiện với máy tính bảng, có thể bao gồm thông tin cá nhân hoặc riêng tư."</string>
-    <!-- outdated translation 4077356893924755294 -->     <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Cho phép ứng dụng đọc từ nhiều tệp nhật ký khác nhau của hệ thống. Quyền này cho phép ứng dụng phát hiện thông tin chung về những gì bạn đang thực hiện với máy tính bảng, có thể bao gồm thông tin cá nhân hoặc riêng tư."</string>
+    <string name="permdesc_readLogs" product="default" msgid="8896449437464867766">"Cho phép ứng dụng đọc từ nhiều tệp nhật ký khác nhau của hệ thống. Quyền này cho phép ứng dụng phát hiện thông tin chung về những gì bạn đang thực hiện với điện thoại, có thể bao gồm thông tin cá nhân hoặc riêng tư."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"đọc/ghi vào tài nguyên do chẩn đoán sở hữu"</string>
     <string name="permdesc_diagnostic" msgid="3121238373951637049">"Cho phép ứng dụng đọc và ghi vào bất kỳ tài nguyên nào do nhóm chẩn đoán sở hữu; ví dụ: các tệp trong /dev. Quyền này có thể ảnh hưởng đến sự ổn định và bảo mật của hệ thống. CHỈ nên sử dụng quyền này cho các chẩn đoán phần cứng cụ thể bởi nhà sản xuất hoặc nhà cung cấp dịch vụ."</string>
     <string name="permlab_changeComponentState" msgid="79425198834329406">"bật hoặc vô hiệu hoá các thành phần ứng dụng"</string>
-    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Cho phép ứng dụng thay đổi việc có nên bật thành phần của ứng dụng khác hay không. Các ứng dụng độc hại có thể sử dụng quyền này để vô hiệu hóa các tính năng quan trọng của máy tính bảng. Phải cẩn thận khi sử dụng quyền này vì nó có thể khiến các thành phần của ứng dụng rơi vào trạng thái không sử dụng được, không đồng nhất hoặc không ổn định."</string>
-    <!-- outdated translation 4647419365510068321 -->     <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Cho phép ứng dụng thay đổi việc có nên bật thành phần của ứng dụng khác hay không. Các ứng dụng độc hại có thể sử dụng quyền này để vô hiệu hóa các tính năng quan trọng của máy tính bảng. Phải cẩn thận khi sử dụng quyền này vì nó có thể khiến các thành phần của ứng dụng rơi vào trạng thái không sử dụng được, không đồng nhất hoặc không ổn định."</string>
+    <string name="permdesc_changeComponentState" product="tablet" msgid="4647419365510068321">"Cho phép ứng dụng thay đổi việc có nên bật thành phần của ứng dụng khác hay không. Các ứng dụng độc hại có thể sử dụng quyền này để vô hiệu hóa các tính năng quan trọng của máy tính bảng. Phải cẩn thận khi sử dụng quyền này vì nó có thể khiến các thành phần rơi vào trạng thái không sử dụng được, không đồng nhất hoặc không ổn định."</string>
+    <string name="permdesc_changeComponentState" product="default" msgid="3443473726140080761">"Cho phép ứng dụng thay đổi việc có nên bật thành phần của ứng dụng khác hay không. Các ứng dụng độc hại có thể sử dụng quyền này để vô hiệu hóa các tính năng quan trọng của điện thoại. Phải cẩn thận khi sử dụng các quyền vì nó có thể khiến các thành phần ứng dụng rơi vào trạng thái không sử dụng được, không đồng nhất hoặc không ổn định."</string>
     <string name="permlab_setPreferredApplications" msgid="3393305202145172005">"đặt ứng dụng ưa thích"</string>
     <string name="permdesc_setPreferredApplications" msgid="760008293501937546">"Cho phép ứng dụng sửa đổi các ứng dụng ưa thích của bạn. Quyền này có thể cho phép các ứng dụng độc hại ngầm thay đổi các ứng dụng đã được chạy, giả mạo các ứng dụng hiện có để thu thập dữ liệu cá nhân của bạn."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"sửa đổi cài đặt hệ thống chung"</string>
@@ -304,10 +302,10 @@
     <string name="permdesc_broadcastSticky" product="tablet" msgid="6322249605930062595">"Cho phép ứng dụng gửi truyền phát hấp dẫn người xem, tiếp tục sau khi truyền phát kết thúc. Các ứng dụng độc hại có thể làm cho máy tính bảng bị chậm hoặc không ổn định bằng cách khiến ứng dụng sử dụng quá nhiều bộ nhớ."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="1920045289234052219">"Cho phép ứng dụng gửi truyền phát hấp dẫn người xem, tiếp tục sau khi truyền phát kết thúc. Các ứng dụng độc hại có thể làm cho điện thoại bị chậm hoặc không ổn định bằng cách khiến ứng dụng sử dụng quá nhiều bộ nhớ."</string>
     <string name="permlab_readContacts" msgid="6219652189510218240">"đọc dữ liệu liên hệ"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Cho phép ứng dụng đọc tất cả dữ liệu liên hệ (địa chỉ) được lưu trữ trên máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để gửi dữ liệu của bạn cho những người khác."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="7596158687301157686">"Cho phép ứng dụng đọc tất cả dữ liệu (địa chỉ) liên hệ được lưu trữ trong máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để gửi dữ liệu của bạn cho những người khác."</string>
     <string name="permdesc_readContacts" product="default" msgid="3371591512896545975">"Cho phép ứng dụng đọc tất cả dữ liệu liên hệ (địa chỉ) được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để gửi dữ liệu của bạn cho những người khác."</string>
     <string name="permlab_writeContacts" msgid="644616215860933284">"ghi dữ liệu liên hệ"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Cho phép ứng dụng sửa đổi dữ liệu liên hệ (địa chỉ) được lưu trữ trên máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="7782689510038568495">"Cho phép ứng dụng sửa đổi dữ liệu (địa chỉ) liên hệ được lưu trữ trên máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
     <string name="permdesc_writeContacts" product="default" msgid="3924383579108183601">"Cho phép ứng dụng sửa đổi dữ liệu liên hệ (địa chỉ) được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xoá hoặc sửa đổi dữ liệu liên hệ của bạn."</string>
     <string name="permlab_readCalendar" msgid="6898987798303840534">"Đọc sự kiện lịch"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="5905870265734599678">"Cho phép ứng dụng đọc tất cả các sự kiện lịch được lưu trữ trên máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để gửi các sự kiện lịch của bạn cho những người khác."</string>
@@ -324,7 +322,7 @@
     <string name="permdesc_accessFineLocation" product="tablet" msgid="243973693233359681">"Truy cập các nguồn vị trí chính xác như Hệ thống định vị toàn cầu trên máy tính bảng, nếu có. Các ứng dụng độc hại có thể sử dụng quyền này để xác định vị trí của bạn và có thể tốn thêm nguồn pin."</string>
     <string name="permdesc_accessFineLocation" product="default" msgid="7411213317434337331">"Truy cập các nguồn vị trí chính xác như Hệ thống Định vị Toàn cầu trên điện thoại, nếu có. Các ứng dụng độc hại có thể sử dụng quyền này để xác định vị trí của bạn và có thể tốn thêm nguồn pin."</string>
     <string name="permlab_accessCoarseLocation" msgid="4642255009181975828">"vị trí (dựa trên mạng) tổng thể"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Truy cập các nguồn vị trí tổng thể chẳng hạn như cơ sở dữ liệu mạng di động nhằm xác định vị trí gần đúng của máy tính bảng, nếu có. Các ứng dụng độc hại có thể sử dụng quyền này để xác định vị trí gần đúng của bạn."</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3704633168985466045">"Truy cập các nguồn vị trí gần đúng chẳng hạn như cơ sở dữ liệu mạng di động nhằm xác định vị trí gần đúng của máy tính bảng, nếu có. Các ứng dụng độc hại có thể sử dụng quyền này để xác định vị trí gần đúng của bạn."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="8235655958070862293">"Truy cập các nguồn vị trí tổng thể chẳng hạn như cơ sở dữ liệu mạng di động nhằm xác định vị trí gần đúng của điện thoại, nếu có. Các ứng dụng độc hại có thể sử dụng quyền này để xác định vị trí gần đúng của bạn."</string>
     <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"truy cập SurfaceFlinger"</string>
     <string name="permdesc_accessSurfaceFlinger" msgid="6805241830020733025">"Cho phép ứng dụng sử dụng các tính năng cấp thấp của SurfaceFlinger."</string>
@@ -334,13 +332,13 @@
     <string name="permdesc_modifyAudioSettings" msgid="5793461287365991922">"Cho phép ứng dụng sửa đổi cài đặt âm thanh chung chẳng hạn như âm lượng và định tuyến."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ghi âm thanh"</string>
     <string name="permdesc_recordAudio" msgid="6493228261176552356">"Cho phép ứng dụng truy cập vào đường dẫn bản ghi âm thanh."</string>
-    <!-- outdated translation 8059288807274039014 -->     <string name="permlab_camera" msgid="3616391919559751192">"chụp ảnh"</string>
-    <!-- outdated translation 9013476258810982546 -->     <string name="permdesc_camera" msgid="6004878235852154239">"Cho phép ứng dụng chụp ảnh bằng máy ảnh. Quyền này cho phép ứng dụng thu thập ảnh mà máy ảnh chụp vào bất kỳ thời điểm nào."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"vô hiệu hóa máy tính bảng vĩnh viễn"</string>
+    <string name="permlab_camera" msgid="3616391919559751192">"chụp ảnh và quay video"</string>
+    <string name="permdesc_camera" msgid="6004878235852154239">"Cho phép ứng dụng chụp ảnh và quay video bằng máy ảnh. Quyền này cho phép ứng dụng thu thập ảnh mà máy ảnh chụp vào bất kỳ thời điểm nào."</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"vô hiệu hóa vĩnh viễn máy tính bảng"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"vĩnh viễn vô hiệu hoá điện thoại"</string>
-    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Cho phép ứng dụng vô hiệu hóa toàn bộ máy tính bảng vĩnh viễn. Việc này rất nguy hiểm."</string>
+    <string name="permdesc_brick" product="tablet" msgid="7379164636920817963">"Cho phép ứng dụng vô hiệu hóa vĩnh viễn toàn bộ máy tính bảng. Việc này rất nguy hiểm."</string>
     <string name="permdesc_brick" product="default" msgid="5569526552607599221">"Cho phép ứng dụng vô hiệu hoá vĩnh viễn toàn bộ điện thoại. Việc này rất nguy hiểm."</string>
-    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"bắt buộc khởi động lại máy tính bảng"</string>
+    <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"buộc máy tính bảng khởi động lại"</string>
     <string name="permlab_reboot" product="default" msgid="2898560872462638242">"buộc khởi động lại điện thoại"</string>
     <string name="permdesc_reboot" product="tablet" msgid="4555793623560701557">"Cho phép ứng dụng buộc máy tính bảng khởi động lại."</string>
     <string name="permdesc_reboot" product="default" msgid="7914933292815491782">"Cho phép ứng dụng buộc điện thoại khởi động lại."</string>
@@ -348,23 +346,25 @@
     <string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"Cho phép ứng dụng lắp và tháo các hệ thống tệp cho bộ nhớ di động."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"định dạng bộ nhớ bên ngoài"</string>
     <string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"Cho phép ứng dụng định dạng bộ nhớ di động."</string>
-    <!-- outdated translation 1070364079249834666 -->     <string name="permlab_asec_access" msgid="3411338632002193846">"nhận thông tin trên bộ lưu trữ an toàn"</string>
-    <!-- outdated translation 7691616292170590244 -->     <string name="permdesc_asec_access" msgid="8820326551687285439">"Cho phép ứng dụng nhận thông tin trên bộ lưu trữ an toàn."</string>
-    <!-- outdated translation 7312078032326928899 -->     <string name="permlab_asec_create" msgid="6414757234789336327">"tạo bộ lưu trữ an toàn"</string>
-    <!-- outdated translation 7041802322759014035 -->     <string name="permdesc_asec_create" msgid="2621346764995731250">"Cho phép ứng dụng tạo bộ lưu trữ an toàn."</string>
-    <!-- outdated translation 7787322878955261006 -->     <string name="permlab_asec_destroy" msgid="526928328301618022">"huỷ bỏ bộ lưu trữ an toàn"</string>
-    <!-- outdated translation 5740754114967893169 -->     <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Cho phép ứng dụng huỷ bỏ bộ lưu trữ an toàn."</string>
-    <!-- outdated translation 7517449694667828592 -->     <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"lắp / tháo bộ lưu trữ an toàn"</string>
-    <!-- outdated translation 5438078121718738625 -->     <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Cho phép ứng dụng lắp / tháo bộ lưu trữ an toàn."</string>
-    <!-- outdated translation 5685344390439934495 -->     <string name="permlab_asec_rename" msgid="7496633954080472417">"đổi tên bộ lưu trữ an toàn"</string>
-    <!-- outdated translation 1387881770708872470 -->     <string name="permdesc_asec_rename" msgid="2152829985238876790">"Cho phép ứng dụng đổi tên bộ lưu trữ an toàn."</string>
+    <string name="permlab_asec_access" msgid="3411338632002193846">"nhận thông tin trên bộ nhớ trong"</string>
+    <string name="permdesc_asec_access" msgid="8820326551687285439">"Cho phép ứng dụng nhận thông tin trên bộ nhớ trong."</string>
+    <string name="permlab_asec_create" msgid="6414757234789336327">"tạo bộ nhớ trong"</string>
+    <string name="permdesc_asec_create" msgid="2621346764995731250">"Cho phép ứng dụng tạo bộ nhớ trong."</string>
+    <string name="permlab_asec_destroy" msgid="526928328301618022">"hủy bỏ bộ nhớ trong"</string>
+    <string name="permdesc_asec_destroy" msgid="2746706889208066256">"Cho phép ứng dụng hủy bỏ bộ nhớ trong."</string>
+    <string name="permlab_asec_mount_unmount" msgid="2456287623689029744">"kết nối / ngắt kết nối bộ nhớ trong"</string>
+    <string name="permdesc_asec_mount_unmount" msgid="5934375590189368200">"Cho phép ứng dụng kết nối / ngắt kết nối bộ nhớ trong."</string>
+    <string name="permlab_asec_rename" msgid="7496633954080472417">"đổi tên bộ nhớ trong"</string>
+    <string name="permdesc_asec_rename" msgid="2152829985238876790">"Cho phép ứng dụng đổi tên bộ nhớ trong."</string>
     <string name="permlab_vibrate" msgid="7768356019980849603">"kiểm soát bộ rung"</string>
     <string name="permdesc_vibrate" msgid="2886677177257789187">"Cho phép ứng dụng kiểm soát bộ rung."</string>
     <string name="permlab_flashlight" msgid="2155920810121984215">"kiểm soát đèn nháy"</string>
     <string name="permdesc_flashlight" msgid="6433045942283802309">"Cho phép ứng dụng kiểm soát đèn nháy."</string>
-    <!-- no translation found for permlab_accessUsb (7362327818655760496) -->
+    <string name="permlab_accessUsb" msgid="7362327818655760496">"truy cập bộ nhớ USB"</string>
+    <string name="permdesc_accessUsb" msgid="2414271762914049292">"Cho phép ứng dụng truy cập thiết bị USB."</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
     <skip />
-    <!-- no translation found for permdesc_accessUsb (2414271762914049292) -->
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
     <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"kiểm tra phần cứng"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"Cho phép ứng dụng kiểm soát các thiết bị ngoại vi khác nhau nhằm mục đích kiểm tra phần cứng."</string>
@@ -441,12 +441,10 @@
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="3511795757324345837">"Cho phép ứng dụng định cấu hình máy tính bảng Bluetooth nội hạt cũng như phát hiện và ghép nối với các thiết bị từ xa."</string>
     <string name="permdesc_bluetoothAdmin" product="default" msgid="7256289774667054555">"Cho phép ứng dụng định cấu hình điện thoại Bluetooth nội hạt cũng như phát hiện và ghép nối với các thiết bị từ xa."</string>
     <string name="permlab_bluetooth" msgid="8361038707857018732">"tạo kết nối Bluetooth"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Cho phép ứng dụng xem cấu hình của máy tính bảng Bluetooth nội hạt cũng như tạo và chấp nhận các kết nối với các thiết bị được ghép nối."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="4191941825910543803">"Cho phép ứng dụng xem cấu hình của máy tính bảng Bluetooth nội hạt cũng như tạo và chấp nhận kết nối với các thiết bị được ghép nối."</string>
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Cho phép ứng dụng xem cấu hình của điện thoại Bluetooth nội hạt cũng như tạo và chấp nhận các kết nối với các thiết bị được ghép nối."</string>
-    <!-- no translation found for permlab_nfc (4423351274757876953) -->
-    <skip />
-    <!-- no translation found for permdesc_nfc (9171401851954407226) -->
-    <skip />
+    <string name="permlab_nfc" msgid="4423351274757876953">"kiểm soát Liên lạc trường gần"</string>
+    <string name="permdesc_nfc" msgid="9171401851954407226">"Cho phép ứng dụng liên lạc với thẻ Liên lạc trường gần (NFC), thẻ và trình đọc."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"vô hiệu hoá khoá phím"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Cho phép ứng dụng vô hiệu hoá khoá phím và bất kỳ bảo mật mật khẩu được liên kết nào. Ví dụ thích hợp của việc này là điện thoại vô hiệu hoá khoá phím khi nhận được cuộc gọi đến sau đó bật lại khoá phím khi cuộc gọi kết thúc."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"đọc cài đặt đồng bộ hoá"</string>
@@ -463,40 +461,32 @@
     <string name="permdesc_readDictionary" msgid="1082972603576360690">"Cho phép ứng dụng đọc bất kỳ từ, tên và cụm từ riêng nào mà người dùng có thể đã lưu trữ trong từ điển của người dùng."</string>
     <string name="permlab_writeDictionary" msgid="6703109511836343341">"ghi vào từ điển do người dùng xác định"</string>
     <string name="permdesc_writeDictionary" msgid="2241256206524082880">"Cho phép ứng dụng ghi từ mới vào từ điển của người dùng."</string>
-    <!-- outdated translation 8079403759001777291 -->     <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"sửa đổi/xoá nội dung thẻ SD"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"sửa đổi/xóa nội dung bộ nhớ USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"sửa đổi/xoá nội dung thẻ SD"</string>
-    <!-- outdated translation 6643963204976471878 -->     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Cho phép ứng dụng ghi vào thẻ SD."</string>
+    <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"C.phép ứ.dụng ghi vào b.nhớ USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Cho phép ứng dụng ghi vào thẻ SD."</string>
-    <!-- no translation found for permlab_mediaStorageWrite (6859839199706879015) -->
-    <skip />
-    <!-- no translation found for permdesc_mediaStorageWrite (8232008512478316233) -->
-    <skip />
+    <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"sửa đổi/xóa nội dung trên bộ nhớ phương tiện cục bộ"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Cho phép ứng dụng sửa đổi nội dung của bộ nhớ phương tiện nội bộ."</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"truy cập hệ thống tệp bộ nhớ cache"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Cho phép ứng dụng đọc và ghi hệ thống tệp bộ nhớ cache."</string>
-    <!-- no translation found for permlab_use_sip (5986952362795870502) -->
-    <skip />
-    <!-- no translation found for permdesc_use_sip (6320376185606661843) -->
-    <skip />
-    <!-- outdated translation 4307861496302850201 -->     <string name="policylab_limitPassword" msgid="4497420728857585791">"Giới hạn mật khẩu"</string>
-    <!-- outdated translation 1719877245692318299 -->     <string name="policydesc_limitPassword" msgid="9083400080861728056">"Hạn chế các loại mật khẩu bạn được phép sử dụng."</string>
-    <!-- outdated translation 7374780712664285321 -->     <string name="policylab_watchLogin" msgid="914130646942199503">"Xem các lần đăng nhập"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Giám sát số lượng mật khẩu đã nhập sai khi mở khóa màn hình và khóa máy tính bảng hoặc xóa tất cả dữ liệu của máy tính bảng nếu đã nhập quá nhiều mật khẩu sai"</string>
-    <!-- outdated translation 933601759466308092 -->     <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Giám sát số lượng mật khẩu đã nhập sai khi mở khóa màn hình và khóa máy tính bảng hoặc xóa tất cả dữ liệu của máy tính bảng nếu đã nhập quá nhiều mật khẩu sai"</string>
-    <!-- outdated translation 9084772090797485420 -->     <string name="policylab_resetPassword" msgid="2620077191242688955">"Đặt lại mật khẩu"</string>
-    <!-- outdated translation 3332167600331799991 -->     <string name="policydesc_resetPassword" msgid="5391240616981297361">"Buộc mật khẩu của bạn về giá trị mới, yêu cầu quản trị viên cung cấp mật khẩu mới cho bạn trước khi bạn có thể đăng nhập."</string>
-    <!-- outdated translation 5760466025247634488 -->     <string name="policylab_forceLock" msgid="2274085384704248431">"Buộc khoá"</string>
-    <!-- outdated translation 2819868664946089740 -->     <string name="policydesc_forceLock" msgid="5696964126226028442">"Kiểm soát khi thiết bị khoá, yêu cầu bạn nhập lại mật khẩu của thiết bị."</string>
+    <string name="permlab_use_sip" msgid="5986952362795870502">"thực hiện/nhận cuộc gọi qua Internet"</string>
+    <string name="permdesc_use_sip" msgid="6320376185606661843">"Cho phép ứng dụng sử dụng dịch vụ SIP để thực hiện/nhận cuộc gọi qua Internet."</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Đặt quy tắc mật khẩu"</string>
+    <string name="policydesc_limitPassword" msgid="9083400080861728056">"Kiểm soát độ dài và ký tự được phép trong mật khẩu mở khóa màn hình"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Giám sát những lần thử mở khóa màn hình"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="933601759466308092">"Giám sát số lượng mật khẩu không chính xác được nhập vào khi mở khóa màn hình và khóa máy tính bảng hoặc xóa tất cả dữ liệu của máy tính bảng nếu có quá nhiều mật khẩu không chính xác được nhập vào"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="7227578260165172673">"Giám sát số lượng mật khẩu không chính xác được nhập khi mở khóa màn hình và khóa điện thoại hoặc xóa tất cả dữ liệu trên điện thoại nếu có quá nhiều mật khẩu không chính xác được nhập vào"</string>
+    <string name="policylab_resetPassword" msgid="2620077191242688955">"Thay đổi mật khẩu mở khóa màn hình"</string>
+    <string name="policydesc_resetPassword" msgid="5391240616981297361">"Thay đổi mật khẩu mở khóa màn hình"</string>
+    <string name="policylab_forceLock" msgid="2274085384704248431">"Khóa màn hình"</string>
+    <string name="policydesc_forceLock" msgid="5696964126226028442">"Kiểm tra cách và thời điểm khóa màn hình"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Xoá tất cả dữ liệu"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Xóa dữ liệu của máy tính bảng mà không cảnh báo, bằng cách đặt lại về dữ liệu gốc"</string>
-    <!-- outdated translation 314455232799486222 -->     <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Xóa dữ liệu của máy tính bảng mà không cảnh báo, bằng cách đặt lại về dữ liệu gốc"</string>
-    <!-- no translation found for policylab_setGlobalProxy (2784828293747791446) -->
-    <skip />
-    <!-- no translation found for policydesc_setGlobalProxy (6387497466660154931) -->
-    <skip />
-    <!-- no translation found for policylab_expirePassword (2314569545488269564) -->
-    <skip />
-    <!-- no translation found for policydesc_expirePassword (7276906351852798814) -->
-    <skip />
+    <string name="policydesc_wipeData" product="tablet" msgid="314455232799486222">"Xóa dữ liệu trên máy tính bảng mà không cần cảnh báo, bằng cách thực hiện đặt lại về dữ liệu gốc"</string>
+    <string name="policydesc_wipeData" product="default" msgid="7669895333814222586">"Xóa dữ liệu trên điện thoại mà không cần cảnh báo, bằng cách thực hiện đặt lại về dữ liệu gốc"</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Đặt proxy chung của điện thoại"</string>
+    <string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Đặt proxy chung của điện thoại được sử dụng trong khi chính sách được bật. Chỉ quản trị viên đầu tiên của điện thoại mới có thể đặt proxy chung hiệu quả."</string>
+    <string name="policylab_expirePassword" msgid="2314569545488269564">"Đặt hết hạn mật khẩu"</string>
+    <string name="policydesc_expirePassword" msgid="7276906351852798814">"Kiểm soát thời lượng trước khi mật khẩu khóa màn hình cần được thay đổi"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Nhà riêng"</item>
     <item msgid="869923650527136615">"ĐT di động"</item>
@@ -561,11 +551,10 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"Số Máy nhắn tin tại Cơ quan"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"Số điện thoại Hỗ trợ"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <!-- no translation found for eventTypeCustom (7837586198458073404) -->
-    <skip />
+    <string name="eventTypeCustom" msgid="7837586198458073404">"Tùy chỉnh"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"Ngày sinh"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"Ngày kỷ niệm"</string>
-    <!-- outdated translation 5834288791948564594 -->     <string name="eventTypeOther" msgid="7388178939010143077">"Sự kiện"</string>
+    <string name="eventTypeOther" msgid="7388178939010143077">"Khác"</string>
     <string name="emailTypeCustom" msgid="8525960257804213846">"Tuỳ chỉnh"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"Nhà riêng"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"Cơ quan"</string>
@@ -592,48 +581,28 @@
     <string name="orgTypeWork" msgid="29268870505363872">"Cơ quan"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"Khác"</string>
     <string name="orgTypeCustom" msgid="225523415372088322">"Tuỳ chỉnh"</string>
-    <!-- no translation found for relationTypeCustom (3542403679827297300) -->
-    <skip />
-    <!-- no translation found for relationTypeAssistant (6274334825195379076) -->
-    <skip />
-    <!-- no translation found for relationTypeBrother (8757913506784067713) -->
-    <skip />
-    <!-- no translation found for relationTypeChild (1890746277276881626) -->
-    <skip />
-    <!-- no translation found for relationTypeDomesticPartner (6904807112121122133) -->
-    <skip />
-    <!-- no translation found for relationTypeFather (5228034687082050725) -->
-    <skip />
-    <!-- no translation found for relationTypeFriend (7313106762483391262) -->
-    <skip />
-    <!-- no translation found for relationTypeManager (6365677861610137895) -->
-    <skip />
-    <!-- no translation found for relationTypeMother (4578571352962758304) -->
-    <skip />
-    <!-- no translation found for relationTypeParent (4755635567562925226) -->
-    <skip />
-    <!-- no translation found for relationTypePartner (7266490285120262781) -->
-    <skip />
-    <!-- no translation found for relationTypeReferredBy (101573059844135524) -->
-    <skip />
-    <!-- no translation found for relationTypeRelative (1799819930085610271) -->
-    <skip />
-    <!-- no translation found for relationTypeSister (1735983554479076481) -->
-    <skip />
-    <!-- no translation found for relationTypeSpouse (394136939428698117) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeCustom (2473580593111590945) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeHome (6093598181069359295) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeWork (6920725730797099047) -->
-    <skip />
-    <!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
-    <skip />
+    <string name="relationTypeCustom" msgid="3542403679827297300">"Tùy chỉnh"</string>
+    <string name="relationTypeAssistant" msgid="6274334825195379076">"Trợ lý"</string>
+    <string name="relationTypeBrother" msgid="8757913506784067713">"Anh em trai"</string>
+    <string name="relationTypeChild" msgid="1890746277276881626">"Con cái"</string>
+    <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"Vợ chồng"</string>
+    <string name="relationTypeFather" msgid="5228034687082050725">"Cha"</string>
+    <string name="relationTypeFriend" msgid="7313106762483391262">"Bạn bè"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"Người quản lý"</string>
+    <string name="relationTypeMother" msgid="4578571352962758304">"Mẹ"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"Cha mẹ"</string>
+    <string name="relationTypePartner" msgid="7266490285120262781">"Đối tác"</string>
+    <string name="relationTypeReferredBy" msgid="101573059844135524">"Được giới thiệu bởi"</string>
+    <string name="relationTypeRelative" msgid="1799819930085610271">"Họ hàng"</string>
+    <string name="relationTypeSister" msgid="1735983554479076481">"Chị em gái"</string>
+    <string name="relationTypeSpouse" msgid="394136939428698117">"Vợ/chồng"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"Tùy chỉnh"</string>
+    <string name="sipAddressTypeHome" msgid="6093598181069359295">"Nhà riêng"</string>
+    <string name="sipAddressTypeWork" msgid="6920725730797099047">"Cơ quan"</string>
+    <string name="sipAddressTypeOther" msgid="4408436162950119849">"Khác"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"Nhập mã PIN"</string>
     <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"Nhập mật khẩu để mở khoá"</string>
-    <!-- no translation found for keyguard_password_enter_pin_password_code (638347075625491514) -->
-    <skip />
+    <string name="keyguard_password_enter_pin_password_code" msgid="638347075625491514">"Nhập PIN để mở khóa"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"Mã PIN không chính xác!"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Để mở khoá, hãy nhấn vào Trình đơn sau đó nhấn 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Số khẩn cấp"</string>
@@ -646,14 +615,13 @@
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Quay lại cuộc gọi"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Chính xác!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4817583279053112312">"Rất tiếc, hãy thử lại"</string>
-    <!-- no translation found for lockscreen_password_wrong (6237443657358168819) -->
-    <skip />
+    <string name="lockscreen_password_wrong" msgid="6237443657358168819">"Rất tiếc, hãy thử lại"</string>
     <string name="lockscreen_plugged_in" msgid="613343852842944435">"Đang sạc (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Đã sạc."</string>
     <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Kết nối bộ sạc của bạn."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Không có thẻ SIM nào."</string>
-    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Không có thẻ SIM trong máy tính bảng."</string>
+    <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Không có thẻ SIM nào trong máy tính bảng."</string>
     <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Không có thẻ SIM nào trong điện thoại."</string>
     <string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"Vui lòng lắp thẻ SIM."</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"Chỉ cuộc gọi khẩn cấp"</string>
@@ -663,10 +631,8 @@
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Thẻ SIM đã bị khoá."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Đang mở khoá thẻ SIM…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="3514742106066877476">"Bạn đã vẽ không chính xác hình mở khoá của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. "\n\n"Vui lòng thử lại sau <xliff:g id="NUMBER_1">%d</xliff:g> giây."</string>
-    <!-- no translation found for lockscreen_too_many_failed_password_attempts_dialog_message (4906034376425175381) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_pin_attempts_dialog_message (6827749231465145590) -->
-    <skip />
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="4906034376425175381">"Bạn đã nhập sai mật khẩu <xliff:g id="NUMBER_0">%d</xliff:g> lần. "\n\n"Vui lòng thử lại trong <xliff:g id="NUMBER_1">%d</xliff:g> giấy."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6827749231465145590">"Bạn đã nhập sai PIN <xliff:g id="NUMBER_0">%d</xliff:g> lần. "\n\n"Vui lòng thử lại trong <xliff:g id="NUMBER_1">%d</xliff:g> giây."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="8687762517114904651">"Bạn đã vẽ không chính xác hình mở khóa của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công khác, bạn sẽ được yêu cầu mở khóa máy tính bảng bằng thông tin đăng nhập Google của mình."\n\n" Vui lòng thử lại trong <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="3351013842320127827">"Bạn đã vẽ không chính xác hình mở khoá của mình <xliff:g id="NUMBER_0">%d</xliff:g> lần. Sau <xliff:g id="NUMBER_1">%d</xliff:g> lần thử không thành công khác, bạn sẽ được yêu cầu mở khoá điện thoại bằng thông tin đăng nhập Google của mình."\n\n" Vui lòng thử lại trong <xliff:g id="NUMBER_2">%d</xliff:g> giây."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Hãy thử lại sau <xliff:g id="NUMBER">%d</xliff:g> giây."</string>
@@ -698,23 +664,17 @@
     <string name="double_tap_toast" msgid="1068216937244567247">"Mẹo: nhấn đúp để phóng to và thu nhỏ."</string>
     <string name="autofill_this_form" msgid="1272247532604569872">"Tự động điền"</string>
     <string name="setup_autofill" msgid="8154593408885654044">"C.đặt TĐ điền"</string>
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_separator (7483307893170324129) -->
-    <skip />
-    <!-- no translation found for autofill_address_summary_format (4874459455786827344) -->
-    <skip />
+    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
+    <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
+    <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
     <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"đọc lịch sử và dấu trang của Trình duyệt"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"Cho phép ứng dụng đọc tất cả các URL mà Trình duyệt đã truy cập và tất cả các dấu trang của Trình duyệt."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"xem lịch sử và dấu trang của Trình duyệt"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="7193514090469945307">"Cho phép ứng dụng sửa đổi lịch sử hoặc dấu trang của Trình duyệt được lưu trữ trên máy tính bảng của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xóa hoặc sửa đổi dữ liệu Trình duyệt của bạn."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="945571990357114950">"Cho phép ứng dụng sửa đổi lịch sử hoặc dấu trang của Trình duyệt được lưu trữ trên điện thoại của bạn. Các ứng dụng độc hại có thể sử dụng quyền này để xoá hoặc sửa đổi dữ liệu Trình duyệt của bạn."</string>
-    <!-- no translation found for permlab_setAlarm (5924401328803615165) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlarm (5966966598149875082) -->
-    <skip />
+    <string name="permlab_setAlarm" msgid="5924401328803615165">"đặt báo thức trong đồng hồ báo thức"</string>
+    <string name="permdesc_setAlarm" msgid="5966966598149875082">"Cho phép ứng dụng đặt báo thức trong ứng dụng đồng hồ báo thức được cài đặt. Một số ứng dụng đồng hồ báo thức có thể không sử dụng tính năng này."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"Sửa đổi quyền về vị trí địa lý của Trình duyệt"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"Cho phép ứng dụng sửa đổi các quyền về vị trí địa lý của Trình duyệt. Các ứng dụng độc hại có thể sử dụng quyền này để cho phép gửi thông tin vị trí đến trang web bất kỳ."</string>
     <string name="save_password_message" msgid="767344687139195790">"Bạn có muốn trình duyệt nhớ mật khẩu này không?"</string>
@@ -830,15 +790,12 @@
     <string name="cut" msgid="3092569408438626261">"Cắt"</string>
     <string name="copy" msgid="2681946229533511987">"Sao chép"</string>
     <string name="paste" msgid="5629880836805036433">"Dán"</string>
-    <!-- no translation found for pasteDisabled (7259254654641456570) -->
-    <skip />
+    <string name="pasteDisabled" msgid="7259254654641456570">"Không có gì để dán"</string>
     <string name="copyUrl" msgid="2538211579596067402">"Sao chép URL"</string>
-    <!-- no translation found for selectTextMode (6738556348861347240) -->
-    <skip />
-    <!-- no translation found for textSelectionCABTitle (5236850394370820357) -->
-    <skip />
+    <string name="selectTextMode" msgid="6738556348861347240">"Chọn văn bản..."</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"Lựa chọn văn bản"</string>
     <string name="inputMethod" msgid="1653630062304567879">"Phương thức nhập"</string>
-    <!-- outdated translation 1672989176958581452 -->     <string name="editTextMenuTitle" msgid="4909135564941815494">"Chỉnh sửa văn bản"</string>
+    <string name="editTextMenuTitle" msgid="4909135564941815494">"Tác vụ văn bản"</string>
     <string name="low_internal_storage_view_title" msgid="1399732408701697546">"Còn ít dung lượng"</string>
     <string name="low_internal_storage_view_text" product="tablet" msgid="4231085657068852042">"Dung lượng lưu trữ của máy tính bảng thấp."</string>
     <string name="low_internal_storage_view_text" product="default" msgid="635106544616378836">"Dung lượng lưu trữ của điện thoại thấp."</string>
@@ -847,8 +804,7 @@
     <string name="yes" msgid="5362982303337969312">"OK"</string>
     <string name="no" msgid="5141531044935541497">"Huỷ"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"Chú ý"</string>
-    <!-- no translation found for loading (1760724998928255250) -->
-    <skip />
+    <string name="loading" msgid="1760724998928255250">"Đang tải..."</string>
     <string name="capital_on" msgid="1544682755514494298">"BẬT"</string>
     <string name="capital_off" msgid="6815870386972805832">"TẮT"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Hoàn tất tác vụ đang sử dụng"</string>
@@ -867,32 +823,19 @@
     <string name="force_close" msgid="3653416315450806396">"Buộc đóng"</string>
     <string name="report" msgid="4060218260984795706">"Báo cáo"</string>
     <string name="wait" msgid="7147118217226317732">"Đợi"</string>
-    <!-- no translation found for launch_warning_title (8323761616052121936) -->
-    <skip />
-    <!-- no translation found for launch_warning_replace (6202498949970281412) -->
-    <skip />
-    <!-- no translation found for launch_warning_original (188102023021668683) -->
-    <skip />
-    <!-- no translation found for smv_application (295583804361236288) -->
-    <skip />
-    <!-- no translation found for smv_process (5120397012047462446) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification (9087063985776626166) -->
-    <skip />
-    <!-- no translation found for heavy_weight_notification_detail (2423977499339403402) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_title (1135403633766694316) -->
-    <skip />
-    <!-- no translation found for heavy_weight_switcher_text (4592075610079319667) -->
-    <skip />
-    <!-- no translation found for old_app_action (493129172238566282) -->
-    <skip />
-    <!-- no translation found for old_app_description (942967900237208466) -->
-    <skip />
-    <!-- no translation found for new_app_action (5472756926945440706) -->
-    <skip />
-    <!-- no translation found for new_app_description (6830398339826789493) -->
-    <skip />
+    <string name="launch_warning_title" msgid="8323761616052121936">"Ứng dụng đã được chuyển hướng"</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> hiện đang chạy."</string>
+    <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> được khởi chạy trước tiên."</string>
+    <string name="smv_application" msgid="295583804361236288">"Ứng dụng <xliff:g id="APPLICATION">%1$s</xliff:g> (quá trình <xliff:g id="PROCESS">%2$s</xliff:g>) đã vi phạm chính sách StrictMode tự thi hành của mình."</string>
+    <string name="smv_process" msgid="5120397012047462446">"Quá trình <xliff:g id="PROCESS">%1$s</xliff:g> đã vi phạm chính sách StrictMode tự thi hành của mình."</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> đang hoạt động"</string>
+    <string name="heavy_weight_notification_detail" msgid="2423977499339403402">"Chọn để chuyển sang ứng dụng"</string>
+    <string name="heavy_weight_switcher_title" msgid="1135403633766694316">"Chuyển ứng dụng?"</string>
+    <string name="heavy_weight_switcher_text" msgid="4592075610079319667">"Bạn phải dừng một ứng dụng khác hiện đang chạy trước khi khởi động một ứng dụng mới."</string>
+    <string name="old_app_action" msgid="493129172238566282">"Quay lại <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="old_app_description" msgid="942967900237208466">"Không khởi động ứng dụng mới."</string>
+    <string name="new_app_action" msgid="5472756926945440706">"Bắt đầu <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
+    <string name="new_app_description" msgid="6830398339826789493">"Dừng ứng dụng cũ mà không lưu."</string>
     <string name="sendText" msgid="5132506121645618310">"Chọn một tác vụ cho văn bản"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"Âm lượng chuông"</string>
     <string name="volume_music" msgid="5421651157138628171">"Âm lượng phương tiện"</string>
@@ -931,17 +874,17 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Hiển thị tất cả"</b></string>
     <string name="usb_storage_activity_title" msgid="2399289999608900443">"Thiết bị lưu trữ USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB đã kết nối"</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Bạn đã kết nối điện thoại với máy tính của mình qua USB. Hãy chọn nút bên dưới nếu bạn muốn sao chép các tệp giữa máy tính và thẻ SD của Android của mình."</string>
-    <!-- outdated translation 4796759646167247178 -->     <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Bạn đã kết nối điện thoại với máy tính của mình qua USB. Hãy chọn nút bên dưới nếu bạn muốn sao chép các tệp giữa máy tính và thẻ SD của Android của mình."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="6631094834151575841">"Bạn đã kết nối với máy tính của mình qua USB. Hãy chạm nút bên dưới nếu bạn muốn sao chép các tệp giữa máy tính và bộ nhớ USB của Android của bạn."</string>
+    <string name="usb_storage_message" product="default" msgid="4510858346516069238">"Bạn đã kết nối với máy tính của mình qua USB. Hãy chạm nút bên dưới nếu bạn muốn sao chép các tệp giữa máy tính và thẻ SD của Android của bạn."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Bật bộ lưu trữ USB"</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Đã xảy ra sự cố khi sử dụng thẻ SD của bạn cho bộ lưu trữ USB."</string>
-    <!-- outdated translation 2534784751603345363 -->     <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Đã xảy ra sự cố khi sử dụng thẻ SD của bạn cho bộ lưu trữ USB."</string>
+    <string name="usb_storage_error_message" product="nosdcard" msgid="3276413764430468454">"Đã xảy ra sự cố khi sử dụng bộ nhớ USB của bạn cho bộ nhớ dung lượng lớn USB."</string>
+    <string name="usb_storage_error_message" product="default" msgid="120810397713773275">"Đã xảy ra sự cố khi sử dụng thẻ SD của bạn cho bộ nhớ dung lượng lớn USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB đã kết nối"</string>
     <string name="usb_storage_notification_message" msgid="7380082404288219341">"Chọn để sao chép tệp đến/từ máy tính của bạn."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Tắt bộ lưu trữ USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"Chọn tắt bộ lưu trữ USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Bộ lưu trữ USB đang được sử dụng"</string>
-    <!-- outdated translation 3613713396426604104 -->     <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Trước khi tắt bộ lưu trữ USB, đảm bảo rằng bạn đã tháo (“đẩy”) thẻ SD của Android khỏi máy tính của mình."</string>
+    <string name="usb_storage_stop_message" product="nosdcard" msgid="1368842269463745067">"Trước khi tắt bộ nhớ USB, đảm bảo rằng bạn đã ngắt kết nối (“đẩy”) bộ nhớ USB của Android khỏi máy tính của mình."</string>
     <string name="usb_storage_stop_message" product="default" msgid="3613713396426604104">"Trước khi tắt bộ lưu trữ USB, đảm bảo rằng bạn đã tháo (“đẩy”) thẻ SD của Android khỏi máy tính của mình."</string>
     <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"Tắt bộ lưu trữ USB"</string>
     <string name="usb_storage_stop_error_message" msgid="143881914840412108">"Đã xảy ra sự cố khi tắt bộ lưu trữ USB. Hãy kiểm tra để đảm bảo bạn đã tháo trình điều khiển chủ USB rồi thử lại."</string>
@@ -949,9 +892,9 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="3202838234780505886">"Nếu bạn bật bộ lưu trữ USB, một số ứng dụng bạn đang sử dụng sẽ dừng và có thể không khả dụng cho tới khi bạn tắt bộ lưu trữ USB."</string>
     <string name="dlg_error_title" msgid="8048999973837339174">"Thao tác USB không thành công"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <!-- outdated translation 8663247929551095854 -->     <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Định dạng thẻ SD"</string>
+    <string name="extmedia_format_title" product="nosdcard" msgid="7980995592595097841">"Định dạng b.nhớ USB"</string>
     <string name="extmedia_format_title" product="default" msgid="8663247929551095854">"Định dạng thẻ SD"</string>
-    <!-- outdated translation 3621369962433523619 -->     <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Bạn có chắc chắn muốn định dạng thẻ SD không? Tất cả dữ liệu trên thẻ của bạn sẽ bị mất."</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="8296908079722897772">"Định dạng bộ nhớ USB, xóa tất cả tệp được lưu trữ tại đây? Không thể hoàn tác tác vụ!"</string>
     <string name="extmedia_format_message" product="default" msgid="3621369962433523619">"Bạn có chắc chắn muốn định dạng thẻ SD không? Tất cả dữ liệu trên thẻ của bạn sẽ bị mất."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Định dạng"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Gỡ lỗi USB đã được kết nối"</string>
@@ -960,28 +903,28 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="candidates_style" msgid="4333913089637062257"><u>"ứng viên"</u></string>
-    <!-- outdated translation 5457603418970994050 -->     <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Đang chuẩn bị thẻ SD"</string>
+    <string name="ext_media_checking_notification_title" product="nosdcard" msgid="3449816005351468560">"Đang chuẩn bị bộ nhớ USB"</string>
     <string name="ext_media_checking_notification_title" product="default" msgid="5457603418970994050">"Đang chuẩn bị thẻ SD"</string>
     <string name="ext_media_checking_notification_message" msgid="8287319882926737053">"Đang kiểm tra lỗi."</string>
-    <!-- outdated translation 780477838241212997 -->     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Thẻ SD trống"</string>
+    <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Bộ nhớ USB trống"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Thẻ SD trống"</string>
-    <!-- outdated translation 3817704088027829380 -->     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Thẻ SD trống hoặc có hệ thống tệp không được hỗ trợ."</string>
+    <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="8623130522556087311">"Bộ nhớ USB trống hoặc không có hệ thống tệp được hỗ trợ."</string>
     <string name="ext_media_nofs_notification_message" product="default" msgid="3817704088027829380">"Thẻ SD trống hoặc có hệ thống tệp không được hỗ trợ."</string>
-    <!-- outdated translation 6410723906019100189 -->     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Thẻ SD đã bị hỏng"</string>
+    <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Bộ nhớ USB bị hỏng"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Thẻ SD đã bị hỏng"</string>
-    <!-- outdated translation 6902531775948238989 -->     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Thẻ SD bị hỏng. Bạn có thể phải định dạng lại thẻ SD đó."</string>
+    <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="529021299294450667">"Bộ nhớ USB bị hỏng. Bạn có thể phải định dạng lại bộ nhớ USB đó."</string>
     <string name="ext_media_unmountable_notification_message" product="default" msgid="6902531775948238989">"Thẻ SD bị hỏng. Bạn có thể phải định dạng lại thẻ SD đó."</string>
-    <!-- outdated translation 6872152882604407837 -->     <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Thẻ SD bị tháo đột ngột"</string>
+    <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"Bộ nhớ USB bị tháo đột ngột"</string>
     <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"Thẻ SD bị tháo đột ngột"</string>
-    <!-- outdated translation 7260183293747448241 -->     <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Tháo thẻ SD trước khi gỡ nhằm tránh mất dữ liệu."</string>
+    <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"Ngắt kết nối USB trước khi tháo nhằm tránh mất dữ liệu."</string>
     <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"Tháo thẻ SD trước khi gỡ nhằm tránh mất dữ liệu."</string>
-    <!-- outdated translation 6729801130790616200 -->     <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"An toàn để tháo thẻ SD"</string>
+    <string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"Bộ nhớ USB an toàn để tháo"</string>
     <string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"An toàn để tháo thẻ SD"</string>
-    <!-- outdated translation 568841278138377604 -->     <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Bạn có thể tháo an toàn thẻ SD."</string>
+    <string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"Bạn có thể tháo an toàn bộ nhớ USB."</string>
     <string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"Bạn có thể tháo an toàn thẻ SD."</string>
-    <!-- outdated translation 8902518030404381318 -->     <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Thẻ SD đã bị tháo"</string>
+    <string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"Bộ nhớ USB đã tháo"</string>
     <string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"Thẻ SD đã bị tháo"</string>
-    <!-- outdated translation 3870120652983659641 -->     <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Thẻ SD đã được tháo. Hãy lắp một thẻ mới."</string>
+    <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"Bộ nhớ USB bị tháo. Hãy lắp phương tiện mới."</string>
     <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Thẻ SD đã được tháo. Hãy lắp một thẻ mới."</string>
     <string name="activity_list_empty" msgid="4168820609403385789">"Không tìm thấy hoạt động nào phù hợp"</string>
     <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"cập nhật thống kê sử dụng thành phần"</string>
@@ -995,8 +938,7 @@
     <string name="ime_action_send" msgid="2316166556349314424">"Gửi"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Tiếp theo"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Xong"</string>
-    <!-- no translation found for ime_action_previous (1443550039250105948) -->
-    <skip />
+    <string name="ime_action_previous" msgid="1443550039250105948">"Trước"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"Thực hiện"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Quay số"\n"sử dụng <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Tạo liên hệ"\n"sử dụng <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1019,64 +961,43 @@
     <string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"L2TP/IPSec VPN dựa trên khoá chia sẻ trước"</string>
     <string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"L2TP/IPSec VPN dựa trên chứng chỉ"</string>
     <string name="upload_file" msgid="2897957172366730416">"Chọn tệp"</string>
-    <!-- no translation found for no_file_chosen (6363648562170759465) -->
-    <skip />
+    <string name="no_file_chosen" msgid="6363648562170759465">"Không có tệp nào được chọn"</string>
     <string name="reset" msgid="2448168080964209908">"Đặt lại"</string>
     <string name="submit" msgid="1602335572089911941">"Gửi"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Chế độ trên ô tô đã được bật"</string>
     <string name="car_mode_disable_notification_message" msgid="668663626721675614">"Chọn để thoát khỏi chế độ trên ô tô."</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"Chức năng điểm truy cập Internet hoặc điểm phát sóng đang hoạt động"</string>
     <string name="tethered_notification_message" msgid="3067108323903048927">"Chạm để định cấu hình"</string>
-    <!-- no translation found for back_button_label (2300470004503343439) -->
-    <skip />
-    <!-- no translation found for next_button_label (1080555104677992408) -->
-    <skip />
-    <!-- no translation found for skip_button_label (1275362299471631819) -->
-    <skip />
+    <string name="back_button_label" msgid="2300470004503343439">"Quay lại"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"Tiếp theo"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"Bỏ qua"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"Sử dụng dữ liệu di động có nguy cơ cao"</string>
     <string name="throttle_warning_notification_message" msgid="2609734763845705708">"Chạm để tìm hiểu thêm về việc sử dụng dữ liệu di động"</string>
     <string name="throttled_notification_title" msgid="6269541897729781332">"Đã vượt quá giới hạn dữ liệu di động"</string>
     <string name="throttled_notification_message" msgid="4712369856601275146">"Chạm để tìm hiểu thêm về việc sử dụng dữ liệu di động"</string>
-    <!-- no translation found for no_matches (8129421908915840737) -->
-    <skip />
-    <!-- no translation found for find_on_page (1946799233822820384) -->
-    <skip />
-    <!-- no translation found for matches_found:one (8167147081136579439) -->
-    <!-- no translation found for matches_found:other (4641872797067609177) -->
-    <!-- no translation found for action_mode_done (7217581640461922289) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (535863554318797377) -->
-    <skip />
-    <!-- no translation found for progress_unmounting (5556813978958789471) -->
-    <skip />
-    <!-- no translation found for progress_erasing (4183664626203056915) -->
-    <skip />
-    <!-- no translation found for progress_erasing (2115214724367534095) -->
-    <skip />
-    <!-- no translation found for format_error (4320339096529911637) -->
-    <skip />
-    <!-- no translation found for format_error (1343380371925238343) -->
-    <skip />
-    <!-- no translation found for media_bad_removal (7960864061016603281) -->
-    <skip />
-    <!-- no translation found for media_checking (418188720009569693) -->
-    <skip />
-    <!-- no translation found for media_checking (7334762503904827481) -->
-    <skip />
-    <!-- no translation found for media_removed (7001526905057952097) -->
-    <skip />
-    <!-- no translation found for media_shared (5830814349250834225) -->
-    <skip />
-    <!-- no translation found for media_shared (5706130568133540435) -->
-    <skip />
-    <!-- no translation found for media_unknown_state (729192782197290385) -->
-    <skip />
-    <!-- no translation found for share (1778686618230011964) -->
-    <skip />
-    <!-- no translation found for find (4808270900322985960) -->
-    <skip />
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="no_matches" msgid="8129421908915840737">"Không có kết quả nào phù hợp"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"Tìm kiếm trên trang"</string>
+  <plurals name="matches_found">
+    <item quantity="one" msgid="8167147081136579439">"1 kết quả phù hợp"</item>
+    <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> trong tổng số <xliff:g id="TOTAL">%d</xliff:g>"</item>
+  </plurals>
+    <string name="action_mode_done" msgid="7217581640461922289">"Xong"</string>
+    <string name="progress_unmounting" product="nosdcard" msgid="535863554318797377">"Đang ngắt kết nối bộ nhớ USB..."</string>
+    <string name="progress_unmounting" product="default" msgid="5556813978958789471">"Đang ngắt kết nối thẻ SD..."</string>
+    <string name="progress_erasing" product="nosdcard" msgid="4183664626203056915">"Đang xóa bộ nhớ USB..."</string>
+    <string name="progress_erasing" product="default" msgid="2115214724367534095">"Đang xóa thẻ SD..."</string>
+    <string name="format_error" product="nosdcard" msgid="4320339096529911637">"Không thể xóa bộ nhớ USB."</string>
+    <string name="format_error" product="default" msgid="1343380371925238343">"Không thể xóa thẻ SD."</string>
+    <string name="media_bad_removal" msgid="7960864061016603281">"Thẻ SD bị tháo trước khi được ngắt kết nối."</string>
+    <string name="media_checking" product="nosdcard" msgid="418188720009569693">"Bộ nhớ USB hiện đang được kiểm tra."</string>
+    <string name="media_checking" product="default" msgid="7334762503904827481">"Thẻ SD hiện đang được kiểm tra."</string>
+    <string name="media_removed" msgid="7001526905057952097">"Thẻ SD đã được tháo."</string>
+    <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"Bộ nhớ USB hiện đang được máy tính sử dụng."</string>
+    <string name="media_shared" product="default" msgid="5706130568133540435">"Thẻ SD hiện đang được máy tính sử dụng."</string>
+    <string name="media_unknown_state" msgid="729192782197290385">"Phương tiện bên ngoài ở trạng thái không xác định."</string>
+    <string name="share" msgid="1778686618230011964">"Chia sẻ"</string>
+    <string name="find" msgid="4808270900322985960">"Tìm"</string>
+    <string name="websearch" msgid="4337157977400211589">"Tìm kiếm trên web"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1087,4 +1008,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-xlarge-land/dimens.xml b/core/res/res/values-xlarge-land/dimens.xml
new file mode 100644
index 0000000..6a2b93f
--- /dev/null
+++ b/core/res/res/values-xlarge-land/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <!-- Minimum width of the search view text entry area. -->
+    <dimen name="search_view_text_min_width">256dip</dimen>
+</resources>
diff --git a/core/res/res/values-xlarge/dimens.xml b/core/res/res/values-xlarge/dimens.xml
index 8f590b7..5b0ea30 100644
--- a/core/res/res/values-xlarge/dimens.xml
+++ b/core/res/res/values-xlarge/dimens.xml
@@ -18,9 +18,10 @@
 */
 -->
 <resources>
-    <dimen name="status_bar_height">48dip</dimen>
     <!-- Height of the status bar -->
-    <dimen name="status_bar_icon_size">48dip</dimen>
+    <dimen name="status_bar_height">48dip</dimen>
+    <!-- Width and height of a single notification icon in the status bar -->
+    <dimen name="status_bar_icon_size">32dip</dimen>
     <!-- Size of the giant number (unread count) in the notifications -->
     <dimen name="status_bar_content_number_size">48sp</dimen>
     
@@ -40,4 +41,9 @@
     <!-- The standard size (both width and height) of an application icon that
          will be displayed in the app launcher and elsewhere. -->
     <dimen name="app_icon_size">64dip</dimen>
+    <!-- Minimum width of the search view text entry area. -->
+    <dimen name="search_view_text_min_width">192dip</dimen>
+
+    <item type="dimen" name="dialog_min_width_major">45%</item>
+    <item type="dimen" name="dialog_min_width_minor">72%</item>
 </resources>
diff --git a/core/res/res/values-xlarge/styles.xml b/core/res/res/values-xlarge/styles.xml
index 095a83d..ed05cb1 100644
--- a/core/res/res/values-xlarge/styles.xml
+++ b/core/res/res/values-xlarge/styles.xml
@@ -34,5 +34,13 @@
     <style name="TextAppearance.StatusBar.EventContent.Title">
         <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
+
+    <style name="PreferencePanel">
+        <item name="android:layout_marginLeft">@dimen/preference_screen_side_margin</item>
+        <item name="android:layout_marginRight">@dimen/preference_screen_side_margin</item>
+        <item name="android:layout_marginTop">48dip</item>
+        <item name="android:layout_marginBottom">48dip</item>
+        <item name="android:background">?attr/detailsElementBackground</item>
+    </style>
 </resources>
 
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index b416c06..1cfc5cf 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飞行模式"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"已开启飞行模式"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"已关闭飞行模式"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要您付费的服务"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"允许应用程序控制闪光灯。"</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"访问 USB 设备"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"允许应用程序访问 USB 设备。"</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"测试硬件"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"允许应用程序控制各外围设备以进行硬件测试。"</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"直接拨打电话号码"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"外部媒体处于未知状态。"</string>
     <string name="share" msgid="1778686618230011964">"分享"</string>
     <string name="find" msgid="4808270900322985960">"查找"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"网页搜索"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 1bb6028..d0f460f 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -152,6 +152,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飛航模式"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"飛航模式為 [開啟]"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"飛航模式為 [關閉]"</string>
+    <!-- no translation found for status_bar_notification_info_overflow (5833510281787786290) -->
+    <skip />
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要額外費用的服務。"</string>
@@ -361,6 +363,10 @@
     <string name="permdesc_flashlight" msgid="6433045942283802309">"允許應用程式控制閃光燈。"</string>
     <string name="permlab_accessUsb" msgid="7362327818655760496">"存取 USB 裝置"</string>
     <string name="permdesc_accessUsb" msgid="2414271762914049292">"允許應用程式存取 USB 裝置。"</string>
+    <!-- no translation found for permlab_accessMtp (4953468676795917042) -->
+    <skip />
+    <!-- no translation found for permdesc_accessMtp (6532961200486791570) -->
+    <skip />
     <string name="permlab_hardware_test" msgid="4148290860400659146">"測試硬體"</string>
     <string name="permdesc_hardware_test" msgid="3668894686500081699">"允許應用程式控制各種週邊設備,以供測試用。"</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"直接撥打電話號碼"</string>
@@ -997,8 +1003,7 @@
     <string name="media_unknown_state" msgid="729192782197290385">"外部媒體狀態不明。"</string>
     <string name="share" msgid="1778686618230011964">"分享"</string>
     <string name="find" msgid="4808270900322985960">"尋找"</string>
-    <!-- no translation found for websearch (4337157977400211589) -->
-    <skip />
+    <string name="websearch" msgid="4337157977400211589">"網頁搜尋"</string>
     <!-- no translation found for gpsNotifTicker (5622683912616496172) -->
     <skip />
     <!-- no translation found for gpsNotifTitle (5446858717157416839) -->
@@ -1009,4 +1014,14 @@
     <skip />
     <!-- no translation found for gpsVerifNo (1146564937346454865) -->
     <skip />
+    <!-- no translation found for sync_too_many_deletes (5296321850662746890) -->
+    <skip />
+    <!-- no translation found for sync_too_many_deletes_desc (7030265992955132593) -->
+    <skip />
+    <!-- no translation found for sync_really_delete (8933566316059338692) -->
+    <skip />
+    <!-- no translation found for sync_undo_deletes (8610996708225006328) -->
+    <skip />
+    <!-- no translation found for sync_do_nothing (8717589462945226869) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 701b8ca..19e2b8d 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -48,6 +48,7 @@
              theme does not set this value, meaning it is based on whether the
              window is floating. -->
         <attr name="backgroundDimEnabled" format="boolean" />
+
         <!-- =========== -->
         <!-- Text styles -->
         <!-- =========== -->
@@ -97,9 +98,9 @@
         <!-- Text color for urls in search suggestions, used by things like global search and the browser. @hide -->
         <attr name="textColorSearchUrl" format="reference|color" />
 
-        <!-- Color of highlighted text, when used in a light theme. @hide -->
+        <!-- Color of highlighted text, when used in a light theme. -->
         <attr name="textColorHighlightInverse" format="reference|color" />
-        <!-- Color of link text (URLs), when used in a light theme. @hide -->
+        <!-- Color of link text (URLs), when used in a light theme. -->
         <attr name="textColorLinkInverse" format="reference|color" />
 
         <!-- Color of list item text in alert dialogs. -->
@@ -140,8 +141,6 @@
         <attr name="editTextColor" format="reference|color" />
         <!-- EditText background drawable. -->
         <attr name="editTextBackground" format="reference" />
-        <!-- EditText background drawable for multiline EditText. -->
-        <attr name="editTextMultilineBackground" format="reference" />
 
         <!-- A styled string, specifying the style to be used for showing
              inline candidate text when composing with an input method.  The
@@ -261,7 +260,7 @@
         <!-- Flag indicating whether this is a translucent window. -->
         <attr name="windowIsTranslucent" format="boolean" />
         <!-- Flag indicating that this window's background should be the
-        	 user's current wallpaper. -->
+           user's current wallpaper. -->
         <attr name="windowShowWallpaper" format="boolean" />
         <!-- This Drawable is overlaid over the foreground of the Window's content area, usually
              to place a shadow below the title.  -->
@@ -372,6 +371,17 @@
         <attr name="alertDialogButtonGroupStyle" format="reference" />
         <attr name="alertDialogCenterButtons" format="boolean" />
 
+        <!-- ============== -->
+        <!-- Image elements -->
+        <!-- ============== -->
+        <eat-comment />
+
+        <!-- Background that can be used behind parts of a UI that provide
+             details on data the user is selecting.  For example, this is
+             the background element of PreferenceActivity's embedded
+             preference fragment. -->
+        <attr name="detailsElementBackground" format="reference" />
+
         <!-- ============ -->
         <!-- Panel styles -->
         <!-- ============ -->
@@ -481,8 +491,8 @@
         <attr name="spinnerItemStyle" format="reference" />
         <!-- Default MapView style. -->
         <attr name="mapViewStyle" format="reference" />
-        <!-- Default quickcontact badge style. -->
-        <attr name="quickContactBadgeStyle" format="reference" />
+        <!-- Drawable used as an overlay on top of quickcontact photos. -->
+        <attr name="quickContactBadgeOverlay" format="reference" />
         <!-- Default quickcontact badge style with small quickcontact window. -->
         <attr name="quickContactBadgeStyleWindowSmall" format="reference" />
         <!-- Default quickcontact badge style with medium quickcontact window. -->
@@ -503,21 +513,17 @@
         <!-- Default PopupMenu style. -->
         <attr name="popupMenuStyle" format="reference" />
 
-        <!-- @hide NumberPicker up button style -->
+        <!-- NumberPicker style. -->
+        <attr name="numberPickerStyle" format="reference" />
+        <!-- NumberPicker up button style. -->
         <attr name="numberPickerUpButtonStyle" format="reference" />
-        <!-- @hide NumberPicker down button style -->
+        <!-- NumberPicker down button style. -->
         <attr name="numberPickerDownButtonStyle" format="reference" />
-        <!-- @hide NumberPicker input text style -->
+        <!-- NumberPicker input text style. -->
         <attr name="numberPickerInputTextStyle" format="reference" />
 
-        <!-- @hide NumberPicker the fading edge length of the selector wheel -->
-        <attr name="numberPickerStyle" format="reference" />
-
-        <!-- @hide DayPicker$WeekView style-->
-        <attr name="dayPickerWeekViewStyle" format="reference" />
-
-        <!-- @hide DayPickerDayView style-->
-        <attr name="dayPickerWeekDayViewStyle" format="reference" />
+        <!-- The CalndarView style. -->
+        <attr name="calendarViewStyle" format="reference" />
 
         <!-- Fast scroller styles -->
         <eat-comment />
@@ -538,6 +544,9 @@
             <enum name="floating" value="0" />
             <enum name="atThumb" value="1" />
         </attr>
+        <!-- Text color for the fast scroll index overlay. Make sure it
+             plays nicely with fastScrollPreviewBackground[Left|Right]. -->
+        <attr name="fastScrollTextColor" format="color" />
 
         <!-- =================== -->
         <!-- Action bar styles   -->
@@ -603,8 +612,8 @@
         <attr name="ringtonePreferenceStyle" format="reference" />
         <!-- The preference layout that has the child/tabbed effect. -->
         <attr name="preferenceLayoutChild" format="reference" />
-        <!-- Preference panel background -->
-        <attr name="preferencePanelBackground" format="reference" />
+        <!-- Preference panel style -->
+        <attr name="preferencePanelStyle" format="reference" />
 
         <!-- ============================ -->
         <!-- Text selection handle styles -->
@@ -628,8 +637,16 @@
 
         <!-- Theme to use for dialogs spawned from this theme. -->
         <attr name="dialogTheme" format="reference" />
+        <!-- Window decor layout to use in dialog mode with icons -->
+        <attr name="dialogTitleIconsDecorLayout" format="reference" />
+        <!-- Window decor layout to use in dialog mode with custom titles -->
+        <attr name="dialogCustomTitleDecorLayout" format="reference" />
+        <!-- Window decor layout to use in dialog mode with title only -->
+        <attr name="dialogTitleDecorLayout" format="reference" />
         <!-- Theme to use for alert dialogs spawned from this theme. -->
         <attr name="alertDialogTheme" format="reference" />
+        <!-- Icon drawable to use for alerts -->
+        <attr name="alertDialogIcon" format="reference" />
 
         <!-- Drawable to use for generic vertical dividers. -->
         <attr name="dividerVertical" format="reference" />
@@ -667,6 +684,10 @@
         <attr name="searchViewSearchIcon" format="reference" />
         <!-- SearchView Voice button icon -->
         <attr name="searchViewVoiceIcon" format="reference" />
+        <!-- SearchView query refinement icon -->
+        <attr name="searchViewEditQuery" format="reference" />
+        <!-- SearchView query refinement icon background -->
+        <attr name="searchViewEditQueryBackground" format="reference" />
 
         <!-- Specifies a drawable to use for the 'home as up' indicator. -->
         <attr name="homeAsUpIndicator" format="reference" />
@@ -843,7 +864,8 @@
              {@link android.text.InputType#TYPE_TEXT_VARIATION_WEB_PASSWORD}. -->
         <flag name="textWebPassword" value="0x000000e1" />
         <!-- A numeric only field.  Corresponds to
-             {@link android.text.InputType#TYPE_CLASS_NUMBER}. -->
+             {@link android.text.InputType#TYPE_CLASS_NUMBER} |
+             {@link android.text.InputType#TYPE_NUMBER_VARIATION_NORMAL}. -->
         <flag name="number" value="0x00000002" />
         <!-- Can be combined with <var>number</var> and its other options to
              allow a signed number.  Corresponds to
@@ -855,6 +877,10 @@
              {@link android.text.InputType#TYPE_CLASS_NUMBER} |
              {@link android.text.InputType#TYPE_NUMBER_FLAG_DECIMAL}. -->
         <flag name="numberDecimal" value="0x00002002" />
+        <!-- A numeric password field.  Corresponds to
+             {@link android.text.InputType#TYPE_CLASS_NUMBER} |
+             {@link android.text.InputType#TYPE_NUMBER_VARIATION_PASSWORD}. -->
+        <flag name="numberPassword" value="0x00000012" />
         <!-- For entering a phone number.  Corresponds to
              {@link android.text.InputType#TYPE_CLASS_PHONE}. -->
         <flag name="phone" value="0x00000003" />
@@ -1316,6 +1342,16 @@
         <attr name="windowActionModeOverlay" />
         <attr name="windowActionBarOverlay" />
         <attr name="windowEnableSplitTouch" />
+        <!-- The minimum width the window is allowed to be, along the major
+             axis of the screen.  That is, when in landscape.  Can be either
+             an absolute dimension or a fraction of the screen size in that
+             dimension. -->
+        <attr name="windowMinWidthMajor" format="dimension|fraction" />
+        <!-- The minimum width the window is allowed to be, along the minor
+             axis of the screen.  That is, when in portrait.  Can be either
+             an absolute dimension or a fraction of the screen size in that
+             dimension. -->
+        <attr name="windowMinWidthMinor" format="dimension|fraction" />
     </declare-styleable>
 
     <!-- The set of attributes that describe a AlertDialog's theme. -->
@@ -1630,6 +1666,14 @@
              will result when the reference is accessed.-->
         <attr name="nextFocusDown" format="reference"/>
 
+        <!-- Defines the next view to give focus to when the next focus is
+             {@link android.view.View#FOCUS_FORWARD}
+
+             If the reference refers to a view that does not exist or is part
+             of a hierarchy that is invisible, a {@link java.lang.RuntimeException}
+             will result when the reference is accessed.-->
+        <attr name="nextFocusForward" format="reference"/>
+
         <!-- Defines whether this view reacts to click events. -->
         <attr name="clickable" format="boolean" />
 
@@ -1761,6 +1805,22 @@
             <!-- Place the scroll bar on the right. -->
             <enum name="right" value="2" />
         </attr>
+        
+        <!-- Specifies the type of layer backing this view. The default value is none.
+             Refer to {@link android.view.View#setLayerType(int, android.graphics.Paint)
+             for more information.-->
+        <attr name="layerType">
+            <!-- Don't use a layer. -->
+            <enum name="none" value="0" />
+            <!-- Use a software layer. Refer to
+                 {@link android.view.View#setLayerType(int, android.graphics.Paint) for
+                 more information. -->
+            <enum name="software" value="1" />
+            <!-- Use a hardware layer. Refer to
+                 {@link android.view.View#setLayerType(int, android.graphics.Paint) for
+                 more information. -->
+            <enum name="hardware" value="2" />
+        </attr>
     </declare-styleable>
 
     <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -2008,8 +2068,6 @@
              will use only the number of items in the adapter and the number of items visible
              on screen to determine the scrollbar's properties. -->
         <attr name="smoothScrollbar" format="boolean" />
-        <!-- A reference to an XML description of the adapter to attach to the list. -->
-        <attr name="adapter" format="reference" />
         <!-- Defines the choice behavior for the view. By default, lists do not have
              any choice behavior. By setting the choiceMode to singleChoice, the list
              allows up to one item to be in a chosen state. By setting the choiceMode to
@@ -2294,6 +2352,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. -->
@@ -2669,8 +2729,6 @@
         <attr name="textEditNoPasteWindowLayout" />
         <!-- Indicates that the content of a non-editable text can be selected. -->
         <attr name="textIsSelectable" />
-        <!--  A specific background drawable used by multi-line EditText only. -->
-        <attr name="multilineBackground" format="reference"/>
     </declare-styleable>
     <!-- An <code>input-extras</code> is a container for extra data to supply to
          an input method.  Contains
@@ -2800,12 +2858,22 @@
              spinnerMode="dropdown". This layout must contain a TextView with the id
              @android:id/text1 to be populated with the prompt text. -->
         <attr name="popupPromptView" format="reference" />
+        <!-- Gravity setting for positioning the currently selected item. -->
+        <attr name="gravity" />
     </declare-styleable>
     <declare-styleable name="DatePicker">
         <!-- The first year (inclusive), for example "1940". -->
         <attr name="startYear" format="integer" />
         <!-- The last year (inclusive), for example "2010". -->
         <attr name="endYear" format="integer" />
+        <!-- Whether the spinners are shown. -->
+        <attr name="spinnersShown" format="boolean" />
+        <!-- Whether the calendar view is shown. -->
+        <attr name="calendarViewShown" format="boolean" />
+        <!-- The minimal date shown by this calendar view in mm/dd/yyyy format. -->
+        <attr name="minDate" format="string" />
+        <!-- The minimal date shown by this calendar view in mm/dd/yyyy format. -->
+        <attr name="maxDate" format="string" />
     </declare-styleable>
 
     <declare-styleable name="TwoLineListItem">
@@ -2974,27 +3042,38 @@
         <attr name="minorWeightMax" format="float" />
     </declare-styleable>
 
-    <!-- @hide -->
-    <declare-styleable name="DayPickerWeekView">
-        <attr name="height" />
-        <attr name="weekStartDay" format="integer|reference" />
-        <attr name="weekDayCount" format="integer|reference" />
-        <attr name="showWeekNumber" format="boolean|reference" />
-        <attr name="weekSeperatorWidth" format="dimension" />
-        <attr name="textSize" />
-        <attr name="weekDayPadding" format="dimension" />
-        <attr name="selectedDayLineWidth" format="dimension" />
-        <attr name="selectionBackgroundColor" format="color|reference" />
+    <declare-styleable name="CalendarView">
+        <!-- The first day of week according to {@link java.util.Calendar}. -->
+        <attr name="firstDayOfWeek" format="integer" />
+        <!-- Whether do show week numbers. -->
+        <attr name="showWeekNumber" format="boolean" />
+        <!-- The minimal date shown by this calendar view in mm/dd/yyyy format. -->
+        <attr name="minDate" />
+        <!-- The minimal date shown by this calendar view in mm/dd/yyyy format. -->
+        <attr name="maxDate" />
+        <!-- The number of weeks to be shown. -->
+        <attr name="shownWeekCount" format="integer"/>
+        <!-- The background color for the selected week. -->
+        <attr name="selectedWeekBackgroundColor" format="color|reference" />
+        <!-- The color for the dates of the selected month. -->
         <attr name="focusedMonthDateColor" format="color|reference" />
-        <attr name="otherMonthDateColor" format="color|reference" />
+        <!-- The color for the dates of an unfocused month. -->
+        <attr name="unfocusedMonthDateColor" format="color|reference" />
+        <!-- The color for the week numbers. -->
         <attr name="weekNumberColor" format="color|reference" />
-        <attr name="gridLinesColor" format="color|reference" />
-        <attr name="selectedDayLine" format="reference" />
+        <!-- The color for the sepatator line between weeks. -->
+        <attr name="weekSeparatorLineColor" format="color|reference" />
+        <!-- Drawable for the vertical bar shown at the beggining and at the end of a selected date. -->
+        <attr name="selectedDateVerticalBar" format="reference" />
+        <!-- The text appearance for the week day abbreviation of the calendar header. -->
+        <attr name="weekDayTextAppearance" format="reference" />
+        <!-- The text appearance for the calendar dates. -->
+        <attr name="dateTextAppearance" format="reference" />
     </declare-styleable>
 
-    <!-- @hide -->
     <declare-styleable name="NumberPicker">
         <attr name="orientation" />
+        <!-- Color for the solid color background if such for optimized rendering. -->
         <attr name="solidColor" format="color|reference" />
     </declare-styleable>
 
@@ -3661,6 +3740,10 @@
         <!-- State identifier indicating the popup will be above the anchor. -->
         <attr name="state_above_anchor" format="boolean" />
     </declare-styleable>
+    <declare-styleable name="TextViewMultiLineBackgroundState">
+        <!-- State identifier indicating a TextView has a multi-line layout. -->
+        <attr name="state_multiline" format="boolean" />
+    </declare-styleable>
 
     <!-- ***************************************************************** -->
     <!-- Support for Searchable activities. -->
@@ -4306,7 +4389,7 @@
              If not supplied, then no activity will be launched. -->
         <attr name="configure" format="string" />
         <!-- A preview of what the AppWidget will look like after it's configured.
-       	     If not supplied, the AppWidget's icon will be used. -->
+              If not supplied, the AppWidget's icon will be used. -->
         <attr name="previewImage" format="reference" />
         <!-- The view id of the AppWidget subview which should be auto-advanced.
              by the widget's host. -->
@@ -4417,6 +4500,10 @@
         <attr name="smallIcon" format="reference"/>
         <!-- A preferences.xml file for authenticator-specific settings. -->
         <attr name="accountPreferences" format="reference"/>
+        <!-- Account handles its own token storage and permissions.
+             Default to false
+          -->
+        <attr name="customTokens" format="boolean"/>
     </declare-styleable>
 
     <!-- =============================== -->
@@ -4511,69 +4598,6 @@
         <attr name="settingsActivity" />
     </declare-styleable>
 
-    <!-- =============================== -->
-    <!-- Adapters attributes             -->
-    <!-- =============================== -->
-    <eat-comment />
-
-    <!-- Adapter used to bind cursors. -->
-    <declare-styleable name="CursorAdapter">
-        <!-- URI to get the cursor from. Optional. -->
-        <attr name="uri" format="string" />
-        <!-- Selection statement for the query. Optional. -->
-        <attr name="selection" format="string" />
-        <!-- Sort order statement for the query. Optional. -->
-        <attr name="sortOrder" format="string" />
-        <!-- Layout resource used to display each row from the cursor. Mandatory. -->
-        <attr name="layout" />
-    </declare-styleable>
-
-    <!-- Attributes used in bind items for XML cursor adapters. -->
-    <declare-styleable name="CursorAdapter_BindItem">
-        <!-- The name of the column to bind from. Mandatory. -->
-        <attr name="from" format="string" />
-        <!-- The resource id of the view to bind to. Mandatory. -->
-        <attr name="to" format="reference" />
-        <!-- The type of binding. If this value is not specified, the type will be
-             inferred from the type of the "to" target view. Mandatory.
-
-             The type can be one of:
-             <ul>
-             <li>string, The content of the column is interpreted as a string.</li>
-             <li>image, The content of the column is interpreted as a blob describing an image.</li>
-             <li>image-uri, The content of the column is interpreted as a URI to an image.</li>
-             <li>drawable, The content of the column is interpreted as a resource id to a drawable.</li>
-             <li>A fully qualified class name, corresponding to an implementation of
-                 android.widget.Adapters.CursorBinder.</li>
-             </ul>
-         -->
-        <attr name="as" format="string" />
-    </declare-styleable>
-
-    <!-- Attributes used in select items for XML cursor adapters. -->
-    <declare-styleable name="CursorAdapter_SelectItem">
-        <!-- The name of the column to select. Mandatory. -->
-        <attr name="column" format="string" />
-    </declare-styleable>
-
-    <!-- Attributes used to map values to new values in XML cursor adapters' bind items. -->
-    <declare-styleable name="CursorAdapter_MapItem">
-        <!-- The original value from the column. Mandatory. -->
-        <attr name="fromValue" format="string" />
-        <!-- The new value from the column. Mandatory. -->
-        <attr name="toValue" format="string" />
-    </declare-styleable>
-
-    <!-- Attributes used to map values to new values in XML cursor adapters' bind items. -->
-    <declare-styleable name="CursorAdapter_TransformItem">
-        <!-- The transformation expression. Mandatory if "withClass" is not specified. -->
-        <attr name="withExpression" format="string" />
-        <!-- The transformation class, an implementation of
-             android.widget.Adapters.CursorTransformation. Mandatory if "withExpression"
-             is not specified. -->
-        <attr name="withClass" format="string" />
-    </declare-styleable>
-
     <!-- Attributes used to style the Action Bar. -->
     <declare-styleable name="ActionBar">
         <!-- The type of navigation to use. -->
@@ -4645,6 +4669,8 @@
         <attr name="iconifiedByDefault" format="boolean"/>
         <!-- An optional maximum width of the SearchView. -->
         <attr name="maxWidth" />
+        <!-- An optional query hint string to be displayed in the empty query field. -->
+        <attr name="queryHint" format="string" />
     </declare-styleable>
 
     <declare-styleable name="ActionBar_LayoutParams">
@@ -4669,4 +4695,13 @@
         <!-- Minimum space between the switch and caption text -->
         <attr name="switchPadding" format="dimension" />
     </declare-styleable>
+
+    <declare-styleable name="PointerIcon">
+        <!-- Drawable to use as the icon bitmap. -->
+        <attr name="bitmap" format="reference" />
+        <!-- X coordinate of the icon hot spot. -->
+        <attr name="hotSpotX" format="float" />
+        <!-- Y coordinate of the icon hot spot. -->
+        <attr name="hotSpotY" format="float" />
+    </declare-styleable>
 </resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index fe6176d..5ff6212 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -234,8 +234,20 @@
          the safe mode.  -->
     <attr name="vmSafeMode" format="boolean" />
 
-    <!-- Flag indicating whether the application's rendering should be hardware
-         accelerated if possible.  -->
+    <!-- <p>Flag indicating whether the application's rendering should be hardware
+         accelerated if possible. This flag is turned off by default, both for
+         applications and activities.</p>
+         <p>This flag can be set on the application and any activity declared
+         in the manifest. When enabled for the application, each activity is
+         automatically assumed to be hardware accelerated. This flag can be
+         overriden in the activity tags, either turning it off (if on for the
+         application) or on (if off for the application.)</p>
+         <p>When this flag is turned on for an activity (either directly or via
+         the application tag), every window created from the activity, including
+         the activity's own window, will be hardware accelerated, if possible.</p>
+         <p>Please refer to the documentation of
+         {@link android.view.WindowManager.LayoutParams#FLAG_HARDWARE_ACCELERATED}
+         for more information on how to control this flag programmatically.</p> -->
     <attr name="hardwareAccelerated" format="boolean" />
 
     <!-- Flag indicating whether the given application component is available
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index b1c54ff..1a6f404 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -91,7 +91,7 @@
     <color name="search_url_text_selected">@android:color/black</color>
     <color name="search_url_text_pressed">@android:color/black</color>
     <color name="search_widget_corpus_item_background">@android:color/lighter_gray</color>
-    
+
     <!-- SlidingTab -->
     <color name="sliding_tab_text_color_active">@android:color/black</color>
     <color name="sliding_tab_text_color_shadow">@android:color/black</color>
@@ -103,6 +103,12 @@
     <color name="keyguard_text_color_soundon">#e69310</color>
     <color name="keyguard_text_color_decline">#fe0a5a</color>
 
+    <!-- keyguard clock -->
+    <color name="lockscreen_clock_background">#b3ffffff</color>
+    <color name="lockscreen_clock_foreground">#7affffff</color>
+    <color name="lockscreen_clock_am_pm">#ff9a9a9a</color>
+    <color name="lockscreen_owner_info">#ff9a9a9a</color>
+
     <!-- For holo theme -->
 	  <drawable name="screen_background_holo_light">#fff3f3f3</drawable>
 	  <drawable name="screen_background_holo_dark">#ff000000</drawable>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5d03638..8bb05fb 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -214,6 +214,14 @@
          rotations as the default behavior. -->
     <bool name="config_allowAllRotations">true</bool>
 
+    <!-- If true, the direction rotation is applied to get to an application's requested
+         orientation is reversed.  Normally, the model is that landscape is
+         clockwise from portrait; thus on a portrait device an app requesting
+         landscape will cause a clockwise rotation, and on a landscape device an
+         app requesting portrait will cause a counter-clockwise rotation.  Setting
+         true here reverses that logic. -->
+    <bool name="config_reverseDefaultRotation">false</bool>
+
     <!-- The number of degrees to rotate the display when the keyboard is open. -->
     <integer name="config_lidOpenRotation">90</integer>
 
@@ -489,6 +497,9 @@
     <!-- Enables SIP on WIFI only -->
     <bool name="config_sip_wifi_only">true</bool>
 
+    <!-- Enables built-in SIP phone capability -->
+    <bool name="config_built_in_sip_phone">false</bool>
+
     <!-- Boolean indicating if restoring network selection should be skipped -->
     <!-- The restoring is handled by modem if it is true-->
     <bool translatable="false" name="skip_restoring_network_selection">false</bool>
@@ -497,6 +508,17 @@
          to handle queries on each database. -->
     <integer name="db_connection_pool_size">1</integer>
 
+    <!-- Max space (in MB) allocated to DownloadManager to store the downloaded
+         files if they are to be stored in DownloadManager's data dir,
+         which typically is /data/data/com.android.providers.downloads/files -->
+    <integer name="config_downloadDataDirSize">100</integer>
+
+    <!-- When the free space available in DownloadManager's data dir falls
+         below the percentage value specified by this param, DownloadManager
+         starts removing files to try to make percentage of available
+         free space above this threshold value. -->
+    <integer name="config_downloadDataDirLowSpaceThreshold">10</integer>
+
     <!-- The URL that should be sent in an x-wap-profile header with an HTTP request,
          as defined in the Open Mobile Alliance User Agent Profile specification
          OMA-TS-UAProf-V2_0-20060206-A Section 8.1.1.1. If the URL contains a '%s'
@@ -504,4 +526,11 @@
          Build.MODEL. The format string shall not be escaped. -->
     <string name="config_useragentprofile_url"></string>
 
+    <!-- When a database query is executed, the results retuned are paginated
+         in pages of size (in KB) indicated by this value -->
+    <integer name="config_cursorWindowSize">2048</integer>
+
+    <!-- Sets whether menu shortcuts should be displayed on panel menus when
+         a keyboard is present. -->
+    <bool name="config_showMenuShortcutsWhenKeyboardPresent">false</bool>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 2f0dfc1..e5b6563 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -54,6 +54,18 @@
     <dimen name="password_keyboard_spacebar_vertical_correction">4dip</dimen>
     <!-- Preference activity side margins -->
     <dimen name="preference_screen_side_margin">0dp</dimen>
+    <!-- Preference activity side margins negative-->
+    <dimen name="preference_screen_side_margin_negative">0dp</dimen>
     <!-- Preference widget area width (to the left of the text) -->
     <dimen name="preference_widget_width">56dp</dimen>
+
+    <!-- The platform's desired minimum size for a dialog's width when it
+         is along the major axis (that is the screen is landscape).  This may
+         be either a fraction or a dimension. -->
+    <item type="dimen" name="dialog_min_width_major">65%</item>
+
+    <!-- The platform's desired minimum size for a dialog's width when it
+         is along the minor axis (that is the screen is portrait).  This may
+         be either a fraction or a dimension. -->
+    <item type="dimen" name="dialog_min_width_minor">95%</item>
 </resources>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 7a0fede..837e04f 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -73,4 +73,6 @@
   <item type="id" name="fillInIntent" />
   <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/public.xml b/core/res/res/values/public.xml
index 3a5b238..e73486d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1231,7 +1231,7 @@
   <public type="attr" name="expandableListViewWhiteStyle" id="0x010102b6" />
 
 <!-- ===============================================================
-     Resources proposed for Froyo.
+     Resources added in version 8 of the platform (Froyo / 2.2)
      =============================================================== -->
   <eat-comment />
   <public type="attr" name="installLocation" id="0x010102b7" />
@@ -1247,7 +1247,7 @@
   <public type="anim" name="cycle_interpolator" id="0x010a000c" />
 
 <!-- ===============================================================
-     Resources introduced in Gingerbread.
+     Resources added in version 9 of the platform (Gingerbread / 2.3)
      =============================================================== -->
   <eat-comment />
   <public type="attr" name="logo" id="0x010102be" />
@@ -1282,18 +1282,6 @@
      Resources proposed for Honeycomb.
      =============================================================== -->
   <eat-comment />
-  <public type="attr" name="adapter" />
-  <public type="attr" name="selection" />
-  <public type="attr" name="sortOrder" />
-  <public type="attr" name="uri" />
-  <public type="attr" name="from" />
-  <public type="attr" name="to" />
-  <public type="attr" name="as" />
-  <public type="attr" name="fromValue" />
-  <public type="attr" name="toValue" />
-  <public type="attr" name="column" />
-  <public type="attr" name="withExpression" />
-  <public type="attr" name="withClass" />
   <public type="attr" name="allContactsName" />
   <public type="attr" name="windowActionBar" />
   <public type="attr" name="actionBarStyle" />
@@ -1407,18 +1395,72 @@
   <public type="attr" name="fastScrollPreviewBackgroundRight" />
   <public type="attr" name="fastScrollTrackDrawable" />
   <public type="attr" name="fastScrollOverlayPosition" />
+  <public type="attr" name="customTokens" />
+  <public type="attr" name="nextFocusForward" />
+  <public type="attr" name="firstDayOfWeek" />
+  <public type="attr" name="showWeekNumber" />
+  <public type="attr" name="minDate" />
+  <public type="attr" name="maxDate" />
+  <public type="attr" name="shownWeekCount" />
+  <public type="attr" name="selectedWeekBackgroundColor" />
+  <public type="attr" name="focusedMonthDateColor" />
+  <public type="attr" name="unfocusedMonthDateColor" />
+  <public type="attr" name="weekNumberColor" />
+  <public type="attr" name="weekSeparatorLineColor" />
+  <public type="attr" name="selectedDateVerticalBar" />
+  <public type="attr" name="weekDayTextAppearance" />
+  <public type="attr" name="dateTextAppearance" />
+  <public type="attr" name="solidColor" />
+  <public type="attr" name="spinnersShown" />
+  <public type="attr" name="calendarViewShown" />
+  <public type="attr" name="state_multiline" />
+  <public type="attr" name="detailsElementBackground" />
+  <public type="attr" name="textColorHighlightInverse" />
+  <public type="attr" name="textColorLinkInverse" />
+  <public type="attr" name="editTextColor" />
+  <public type="attr" name="editTextBackground" />
+  <public type="attr" name="horizontalScrollViewStyle" />
+  <public type="attr" name="layerType" />
+  <public type="attr" name="alertDialogIcon" />
+  <public type="attr" name="windowMinWidthMajor" />
+  <public type="attr" name="windowMinWidthMinor" />
+  <public type="attr" name="queryHint" />
+  <public type="attr" name="fastScrollTextColor" />
 
-  <public type="anim" name="animator_fade_in" />
-  <public type="anim" name="animator_fade_out" />
+  <!-- A simple fade-in animation. -->
+  <public type="animator" name="fade_in" id="0x010b0000" />
+  <!-- A simple fade-out animation. -->
+  <public type="animator" name="fade_out" />
 
-  <!-- Acceleration curve matching a cubic ease in function. -->
-  <public type="anim" name="accelerate_cubic_interpolator" />
+  <!-- Acceleration curve matching a quadtratic ease out function. -->
+  <public type="interpolator" name="accelerate_quad" id="0x010c0000" />
+  <!-- Acceleration curve matching a quadtratic ease in function. -->
+  <public type="interpolator" name="decelerate_quad" />
   <!-- Acceleration curve matching a cubic ease out function. -->
-  <public type="anim" name="decelerate_cubic_interpolator" />
-  <!-- Acceleration curve matching a quint ease in function. -->
-  <public type="anim" name="accelerate_quint_interpolator" />
+  <public type="interpolator" name="accelerate_cubic" />
+  <!-- Acceleration curve matching a cubic ease in function. -->
+  <public type="interpolator" name="decelerate_cubic" />
   <!-- Acceleration curve matching a quint ease out function. -->
-  <public type="anim" name="decelerate_quint_interpolator" />
+  <public type="interpolator" name="accelerate_quint" />
+  <!-- Acceleration curve matching a quint ease in function. -->
+  <public type="interpolator" name="decelerate_quint" />
+  <!-- Acceleration curve matching an ease in + ease out function -->
+  <public type="interpolator" name="accelerate_decelerate" />
+  <!-- An interpolator where the change starts backward then flings forward. -->
+  <public type="interpolator" name="anticipate" />
+  <!-- An interpolator where the change flings forward and overshoots the last
+       value then comes back. -->
+  <public type="interpolator" name="overshoot" />
+  <!-- An interpolator where the change starts backward then flings forward and
+       overshoots the target value and finally goes back to the final value. -->
+  <public type="interpolator" name="anticipate_overshoot" />
+  <!-- An interpolator where the change bounces at the end. -->
+  <public type="interpolator" name="bounce" />
+  <!-- An interpolator where the rate of change is constant. -->
+  <public type="interpolator" name="linear" />
+  <!-- Repeats the animation for one cycle. The rate of change follows a
+       sinusoidal pattern. -->
+  <public type="interpolator" name="cycle" />
 
   <public type="id" name="home" />
   <!-- Context menu ID for the "Select text..." menu item to switch to text
@@ -1426,6 +1468,9 @@
   <public type="id" name="selectTextMode" />
   <public type="id" name="up" />
 
+  <public type="dimen" name="dialog_min_width_major" />
+  <public type="dimen" name="dialog_min_width_minor" />
+
   <!-- Standard content view for a {@link android.app.ListFragment}.
        If you are implementing a subclass of ListFragment with your
        own customized content, you can include this layout in that
@@ -1447,7 +1492,6 @@
   <public type="layout" name="simple_list_item_activated_2" />
 
   <public type="style" name="Theme.WithActionBar" />
-  <public type="style" name="Theme.Dialog.NoFrame" />
   <public type="style" name="Theme.NoTitleBar.OverlayActionModes" />
 
   <public type="style" name="Theme.Holo" />
@@ -1456,17 +1500,22 @@
   <public type="style" name="Theme.Holo.NoActionBar.Fullscreen" />
   <public type="style" name="Theme.Holo.Light" />
   <public type="style" name="Theme.Holo.Dialog" />
+  <public type="style" name="Theme.Holo.Dialog.MinWidth" />
   <public type="style" name="Theme.Holo.Dialog.NoActionBar" />
+  <public type="style" name="Theme.Holo.Dialog.NoActionBar.MinWidth" />
   <public type="style" name="Theme.Holo.Light.Dialog" />
+  <public type="style" name="Theme.Holo.Light.Dialog.MinWidth" />
   <public type="style" name="Theme.Holo.Light.Dialog.NoActionBar" />
-  <public type="style" name="Theme.Holo.Dialog.Alert" />
-  <public type="style" name="Theme.Holo.Light.Dialog.Alert" />
+  <public type="style" name="Theme.Holo.Light.Dialog.NoActionBar.MinWidth" />
   <public type="style" name="Theme.Holo.DialogWhenLarge" />
   <public type="style" name="Theme.Holo.DialogWhenLarge.NoActionBar" />
   <public type="style" name="Theme.Holo.Light.DialogWhenLarge" />
   <public type="style" name="Theme.Holo.Light.DialogWhenLarge.NoActionBar" />
+  <public type="style" name="Theme.Holo.Panel" />
+  <public type="style" name="Theme.Holo.Light.Panel" />
   <public type="style" name="Theme.Holo.Wallpaper" />
   <public type="style" name="Theme.Holo.Wallpaper.NoTitleBar" />
+  <public type="style" name="Theme.Holo.InputMethod" />
 
   <public type="style" name="TextAppearance.Widget.PopupMenu.Large" />
   <public type="style" name="TextAppearance.Widget.PopupMenu.Small" />
@@ -1576,5 +1625,21 @@
   <public type="style" name="Holo.Light.ButtonBar.AlertDialog" />
   <public type="style" name="Holo.SegmentedButton" />
   <public type="style" name="Holo.Light.SegmentedButton" />
+  <public type="style" name="Widget.ImageButton.NumberPickerUpButton" />
+  <public type="style" name="Widget.EditText.NumberPickerInputText" />
+  <public type="style" name="Widget.ImageButton.NumberPickerDownButton" />
+  <public type="style" name="Widget.Holo.ImageButton.NumberPickerUpButton" />
+  <public type="style" name="Widget.Holo.EditText.NumberPickerInputText" />
+  <public type="style" name="Widget.Holo.ImageButton.NumberPickerDownButton" />
+  <public type="style" name="Widget.Holo.Light.ImageButton.NumberPickerUpButton" />
+  <public type="style" name="Widget.Holo.Light.EditText.NumberPickerInputText" />
+  <public type="style" name="Widget.Holo.Light.ImageButton.NumberPickerDownButton" />
+  <public type="style" name="Widget.CalendarView" />
+  <public type="style" name="Widget.Holo.CalendarView" />
+  <public type="style" name="Widget.Holo.Light.CalendarView" />
+
   <public type="string" name="selectTextMode" />
+
+  <!-- Default icon for applications that don't specify an icon. -->
+  <public type="mipmap" name="sym_def_app_icon" id="0x010d0000" />
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e48321c..2658b53 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -298,12 +298,12 @@
     <string name="shutdown_confirm_question">Would you like to shut down?</string>
 
     <!-- Recent Tasks dialog: title
-     TODO: this should move to SystemUI.apk, but the code for the old 
+     TODO: this should move to SystemUI.apk, but the code for the old
             recent dialog is still in the framework
      -->
     <string name="recent_tasks_title">Recent</string>
     <!-- Recent Tasks dialog: message when there are no recent applications
-     TODO: this should move to SystemUI.apk, but the code for the old 
+     TODO: this should move to SystemUI.apk, but the code for the old
             recent dialog is still in the framework
      -->
     <string name="no_recent_tasks">No recent applications.</string>
@@ -337,6 +337,11 @@
     <!-- status message in phone options dialog for when airplane mode is off -->
     <string name="global_actions_airplane_mode_off_status">Airplane mode is OFF</string>
 
+    <!-- Text to use when the number in a notification info is too large (> 100).  Most likely does not need
+    to be translated.  We do this so, for example, if the user has tens of thousands of unread
+    emails, the whole notification isn't taken over by the number. [CHAR LIMIT=5] -->
+    <string name="status_bar_notification_info_overflow">100+</string>
+
     <!-- Displayed to the user to tell them that they have started up the phone in "safe mode" -->
     <string name="safeMode">Safe mode</string>
 
@@ -1025,6 +1030,11 @@
     <string name="permdesc_accessUsb">Allows the application to access USB devices.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_accessMtp">implement MTP protocol</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_accessMtp">Allows access to the kernel MTP driver to implement the MTP USB protocol.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_hardware_test">test hardware</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_hardware_test">Allows the application to control
@@ -1363,17 +1373,17 @@
     <!-- Title of policy access to limiting the user's password choices -->
     <string name="policylab_limitPassword">Set password rules</string>
     <!-- Description of policy access to limiting the user's password choices -->
-    <string name="policydesc_limitPassword">Control the length and the characters 
+    <string name="policydesc_limitPassword">Control the length and the characters
     allowed in screen-unlock passwords</string>
     <!-- Title of policy access to watch user login attempts -->
     <string name="policylab_watchLogin">Monitor screen-unlock attempts</string>
     <!-- Description of policy access to watch user login attempts -->
-    <string name="policydesc_watchLogin" product="tablet">Monitor the number of incorrect passwords 
-    entered when unlocking the screen, and lock the tablet or erase all the tablet\'s 
+    <string name="policydesc_watchLogin" product="tablet">Monitor the number of incorrect passwords
+    entered when unlocking the screen, and lock the tablet or erase all the tablet\'s
     data if too many incorrect passwords are entered</string>
     <!-- Description of policy access to watch user login attempts -->
-    <string name="policydesc_watchLogin" product="default">Monitor the number of incorrect passwords 
-    entered when unlocking the screen, and lock the phone or erase all the phone\'s 
+    <string name="policydesc_watchLogin" product="default">Monitor the number of incorrect passwords
+    entered when unlocking the screen, and lock the phone or erase all the phone\'s
     data if too many incorrect passwords are entered</string>
     <!-- Title of policy access to reset user's password -->
     <string name="policylab_resetPassword">Change the screen-unlock password</string>
@@ -1386,10 +1396,10 @@
     <!-- Title of policy access to wipe the user's data -->
     <string name="policylab_wipeData">Erase all data</string>
     <!-- Description of policy access to wipe the user's data -->
-    <string name="policydesc_wipeData" product="tablet">Erase the tablet\'s data without warning, 
+    <string name="policydesc_wipeData" product="tablet">Erase the tablet\'s data without warning,
     by performing a factory data reset</string>
     <!-- Description of policy access to wipe the user's data -->
-    <string name="policydesc_wipeData" product="default">Erase the phone\'s data without warning, 
+    <string name="policydesc_wipeData" product="default">Erase the phone\'s data without warning,
     by performing a factory data reset</string>
     <string name="policylab_setGlobalProxy">Set the device global proxy</string>
     <!-- Description of policy access to wipe the user's data -->
@@ -1401,6 +1411,11 @@
     <!-- Description of policy access to enforce password expiration [CHAR LIMIT=110]-->
     <string name="policydesc_expirePassword">Control how long before lockscreen password needs to be
     changed</string>
+    <!-- Title of policy access to require encrypted storage [CHAR LIMIT=30]-->
+    <string name="policylab_encryptedStorage">Set storage encryption</string>
+    <!-- Description of policy access to require encrypted storage [CHAR LIMIT=110]-->
+    <string name="policydesc_encryptedStorage">Require that stored application data be encrypted
+        </string>
 
     <!-- The order of these is important, don't reorder without changing Contacts.java --> <skip />
     <!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. -->
@@ -1602,7 +1617,7 @@
     <string name="relationTypeSister">Sister</string>
     <!-- Spouse relationship type [CHAR LIMIT=20] -->
     <string name="relationTypeSpouse">Spouse</string>
-    
+
     <!-- Custom SIP address type -->
     <string name="sipAddressTypeCustom">Custom</string>
     <!-- Home SIP address type -->
@@ -2147,7 +2162,8 @@
     <!-- Preference framework strings. -->
     <string name="no">Cancel</string>
     <!-- This is the generic "attention" string to be used in attention dialogs.  Typically
-         combined with setIcon(android.R.drawable.ic_dialog_alert) -->
+         combined with setIconAttribute(android.R.attr.alertDialogIcon)
+         (or setIcon(android.R.drawable.ic_dialog_alert) on legacy versions of the platform) -->
     <string name="dialog_alert_title">Attention</string>
 
     <!-- Text shown by list fragment when waiting for data to display. -->
@@ -2387,6 +2403,8 @@
 
     <!-- Title of the pop-up dialog in which the user switches input method components. -->
     <string name="select_input_method">Select input method</string>
+    <!-- Title of a button to open the settings for input methods [CHAR LIMIT=30] -->
+    <string name="configure_input_methods">Configure input methods</string>
 
     <string name="fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
     <string name="fast_scroll_numeric_alphabet">\u00200123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
@@ -2640,4 +2658,15 @@
     <!-- Network positioning verification No. Button to push to deny sharing of location
          information. -->
     <string name="gpsVerifNo">No</string>
+
+    <!-- Error message when the sync tried to delete too many things -->
+    <string name="sync_too_many_deletes">Delete limit exceeded</string>
+    <!-- Dialog message for when there are too many deletes that would take place and we want user confirmation -->
+    <string name="sync_too_many_deletes_desc">There are <xliff:g id="number_of_deleted_items">%1$d</xliff:g> deleted items for <xliff:g id="type_of_sync">%2$s</xliff:g>, account <xliff:g id="account_name">%3$s</xliff:g>. What would you like to do?</string>
+    <!-- Dialog action for when there are too many deletes that would take place and we want user confirmation, and the user wants to delete the items -->
+    <string name="sync_really_delete">Delete the items.</string>
+    <!-- Dialog action for when there are too many deletes that would take place and we want user confirmation, and the user wants to undo the deletions -->
+    <string name="sync_undo_deletes">Undo the deletes.</string>
+    <!-- Dialog action for when there are too many deletes that would take place and we want user confirmation, and the user wants to do nothing for now -->
+    <string name="sync_do_nothing">Do nothing for now.</string>
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 3e75261..1183915 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -81,14 +81,14 @@
         <item name="wallpaperIntraOpenExitAnimation">@anim/wallpaper_intra_open_exit</item>
         <item name="wallpaperIntraCloseEnterAnimation">@anim/wallpaper_intra_close_enter</item>
         <item name="wallpaperIntraCloseExitAnimation">@anim/wallpaper_intra_close_exit</item>
-        <item name="fragmentOpenEnterAnimation">@anim/fragment_open_enter</item>
-        <item name="fragmentOpenExitAnimation">@anim/fragment_open_exit</item>
-        <item name="fragmentCloseEnterAnimation">@anim/fragment_close_enter</item>
-        <item name="fragmentCloseExitAnimation">@anim/fragment_close_exit</item>
-        <item name="fragmentNextEnterAnimation">@anim/fragment_next_enter</item>
-        <item name="fragmentNextExitAnimation">@anim/fragment_next_exit</item>
-        <item name="fragmentPrevEnterAnimation">@anim/fragment_prev_enter</item>
-        <item name="fragmentPrevExitAnimation">@anim/fragment_prev_exit</item>
+        <item name="fragmentOpenEnterAnimation">@animator/fragment_open_enter</item>
+        <item name="fragmentOpenExitAnimation">@animator/fragment_open_exit</item>
+        <item name="fragmentCloseEnterAnimation">@animator/fragment_close_enter</item>
+        <item name="fragmentCloseExitAnimation">@animator/fragment_close_exit</item>
+        <item name="fragmentNextEnterAnimation">@animator/fragment_next_enter</item>
+        <item name="fragmentNextExitAnimation">@animator/fragment_next_exit</item>
+        <item name="fragmentPrevEnterAnimation">@animator/fragment_prev_enter</item>
+        <item name="fragmentPrevExitAnimation">@animator/fragment_prev_exit</item>
     </style>
 
     <!-- Standard animations for a non-full-screen window or activity. -->
@@ -238,8 +238,7 @@
         <item name="android:textColor">#ff272727</item>
     </style>
 
-    <!-- @hide -->
-    <style name="TextAppearance.Small.DayPickerWeekDayView">
+    <style name="TextAppearance.Small.CalendarViewWeekDayView">
         <item name="android:textStyle">bold</item>
     </style>
 
@@ -445,7 +444,6 @@
         <item name="android:focusableInTouchMode">true</item>
         <item name="android:clickable">true</item>
         <item name="android:background">?android:attr/editTextBackground</item>
-        <item name="android:multilineBackground">?android:attr/editTextMultilineBackground</item>
         <item name="android:textAppearance">?android:attr/textAppearanceMediumInverse</item>
         <item name="android:textColor">?android:attr/editTextColor</item>
         <item name="android:gravity">center_vertical</item>
@@ -473,25 +471,22 @@
         <item name="android:background">@android:drawable/btn_default</item>
     </style>
 
-    <!-- @hide -->
-    <style name="Widget.DayPickerWeekView">
-        <item name="android:height">26dip</item>
-        <item name="android:weekStartDay">1</item>
-        <item name="android:weekDayCount">7</item>
+    <style name="Widget.CalendarView">
         <item name="android:showWeekNumber">true</item>
-        <item name="android:weekSeperatorWidth">1dip</item>
-        <item name="android:textSize">14dip</item>
-        <item name="android:weekDayPadding">0dip</item>
-        <item name="android:selectedDayLineWidth">6dip</item>
-        <item name="android:selectionBackgroundColor">#330099FF</item>
+        <item name="android:firstDayOfWeek">1</item>
+        <item name="android:minDate">01/01/1900</item>
+        <item name="android:maxDate">12/31/2100</item>
+        <item name="android:shownWeekCount">6</item>
+        <item name="android:selectedWeekBackgroundColor">#330099FF</item>
         <item name="android:focusedMonthDateColor">#FFFFFFFF</item>
-        <item name="android:otherMonthDateColor">#66FFFFFF</item>
+        <item name="android:unfocusedMonthDateColor">#66FFFFFF</item>
         <item name="android:weekNumberColor">#33FFFFFF</item>
-        <item name="android:gridLinesColor">#19FFFFFF</item>
-        <item name="selectedDayLine">@android:drawable/day_picker_week_view_dayline_holo_dark</item>
+        <item name="android:weekSeparatorLineColor">#19FFFFFF</item>
+        <item name="android:selectedDateVerticalBar">@android:drawable/day_picker_week_view_dayline_holo</item>
+        <item name="android:weekDayTextAppearance">@android:style/TextAppearance.Small.CalendarViewWeekDayView</item>
+        <item name="android:dateTextAppearance">?android:attr/textAppearanceSmall</item>
     </style>
 
-    <!-- @hide -->
     <style name="Widget.NumberPicker">
         <item name="android:orientation">vertical</item>
         <item name="android:fadingEdge">vertical</item>
@@ -499,22 +494,19 @@
         <item name="android:solidColor">@android:color/transparent</item>
     </style>
 
-    <!-- @hide -->
     <style name="Widget.ImageButton.NumberPickerUpButton">
-        <item name="android:background">@android:drawable/timepicker_up_btn</item>
+        <item name="android:background">@android:drawable/numberpicker_up_btn</item>
     </style>
 
-    <!-- @hide -->
     <style name="Widget.ImageButton.NumberPickerDownButton">
-        <item name="android:background">@android:drawable/timepicker_down_btn</item>
+        <item name="android:background">@android:drawable/numberpicker_down_btn</item>
     </style>
 
-    <!-- @hide -->
     <style name="Widget.EditText.NumberPickerInputText">
         <item name="android:textAppearance">@style/TextAppearance.Large.Inverse.NumberPickerInputText</item>
         <item name="android:gravity">center</item>
         <item name="android:singleLine">true</item>
-        <item name="android:background">@drawable/timepicker_input</item>
+        <item name="android:background">@drawable/numberpicker_input</item>
     </style>
 
     <style name="Widget.AutoCompleteTextView" parent="Widget.EditText">
@@ -538,6 +530,7 @@
         <item name="android:dropDownHorizontalOffset">0dip</item>
         <item name="android:dropDownWidth">wrap_content</item>
         <item name="android:popupPromptView">@android:layout/simple_dropdown_hint</item>
+        <item name="android:gravity">center</item>
     </style>
 
     <style name="Widget.Spinner.DropDown">
@@ -665,21 +658,21 @@
         <item name="android:shadowRadius">2.75</item>
     </style>
 
-    <style name="Widget.QuickContactBadge">
-        <item name="android:layout_width">47.33333dip</item>
-        <item name="android:layout_height">56dip</item>
-        <item name="android:background">@android:drawable/quickcontact_badge</item>
+    <style name="Widget.GenericQuickContactBadge">
+        <item name="android:background">@null</item>
         <item name="android:clickable">true</item>
         <item name="android:scaleType">fitCenter</item>
         <item name="android:src">@android:drawable/ic_contact_picture</item>
     </style>
+
+    <style name="Widget.QuickContactBadge" parent="Widget.GenericQuickContactBadge">
+        <item name="android:layout_width">64dip</item>
+        <item name="android:layout_height">64dip</item>
+    </style>
     
-    <style name="Widget.QuickContactBadgeSmall">
-        <item name="android:layout_width">39dip</item>
-        <item name="android:layout_height">42dip</item>
-        <item name="android:background">@android:drawable/quickcontact_badge_small</item>
-        <item name="android:clickable">true</item>
-        <item name="android:scaleType">fitCenter</item>
+    <style name="Widget.QuickContactBadgeSmall" parent="Widget.GenericQuickContactBadge">
+        <item name="android:layout_width">40dip</item>
+        <item name="android:layout_height">40dip</item>
     </style>
 
     <style name="Widget.QuickContactBadge.WindowSmall">
@@ -861,7 +854,6 @@
         <item name="android:textStyle">bold</item>
     </style>
 
-    <!-- @hide -->
     <style name="TextAppearance.Large.Inverse.NumberPickerInputText">
         <item name="android:textColor">@android:color/primary_text_light</item>
         <item name="android:textSize">30sp</item>
@@ -896,7 +888,6 @@
     <style name="Preference.DialogPreference">
         <item name="android:positiveButtonText">@android:string/ok</item>
         <item name="android:negativeButtonText">@android:string/cancel</item>
-        <item name="android:widgetLayout">@android:layout/preference_dialog</item>
     </style>
     
     <style name="Preference.DialogPreference.YesNoPreference">
@@ -912,7 +903,20 @@
         <item name="android:ringtoneType">ringtone</item>
         <item name="android:showSilent">true</item>
         <item name="android:showDefault">true</item>
-        <item name="android:widgetLayout">@android:layout/preference_dialog</item>
+    </style>
+
+    <!-- No margins or background by default. Could be different for x-large screens -->
+    <style name="PreferencePanel">
+    </style>
+
+    <!-- The attributes are overridden here because the x-large or large resources may have
+         changed the margins and background in the parent PreferencePanel style. -->
+    <style name="PreferencePanel.Dialog">
+        <item name="android:layout_marginLeft">0dip</item>
+        <item name="android:layout_marginRight">0dip</item>
+        <item name="android:layout_marginTop">0dip</item>
+        <item name="android:layout_marginBottom">0dip</item>
+        <item name="android:background">@null</item>
     </style>
 
     <!-- Other Misc Styles -->
@@ -1024,9 +1028,10 @@
     </style>
 
     <style name="Widget.ActionButton">
-        <item name="android:background">@null</item>
+        <item name="android:background">?android:attr/selectableItemBackground</item>
         <item name="android:paddingLeft">16dip</item>
         <item name="android:paddingRight">16dip</item>
+        <item name="android:minWidth">64dip</item>
     </style>
 
     <style name="Widget.ActionButton.Overflow">
@@ -1189,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">
@@ -1228,8 +1233,7 @@
         <item name="android:textSize">18sp</item>
     </style>
 
-    <!-- @hide -->
-    <style name="TextAppearance.Holo.DayPickerWeekDayView" parent="TextAppearance.Small.DayPickerWeekDayView">
+    <style name="TextAppearance.Holo.CalendarViewWeekDayView" parent="TextAppearance.Small.CalendarViewWeekDayView">
         <item name="android:textColor">#505050</item>
     </style>
 
@@ -1329,8 +1333,7 @@
         <item name="android:textSize">18sp</item>
     </style>
 
-    <!-- @hide -->
-    <style name="TextAppearance.Holo.Light.DayPickerWeekDayView" parent="TextAppearance.Small.DayPickerWeekDayView">
+    <style name="TextAppearance.Holo.Light.CalendarViewWeekDayView" parent="TextAppearance.Small.CalendarViewWeekDayView">
     </style>
 
     <!-- Widget Styles -->
@@ -1443,35 +1446,34 @@
         <item name="android:listSelector">?android:attr/selectableItemBackground</item>
     </style>
 
-    <!-- @hide -->
-    <style name="Widget.Holo.DayPickerWeekView" parent="Widget.DayPickerWeekView">
-        <item name="android:selectionBackgroundColor">#330099FF</item>
+    <style name="Widget.Holo.CalendarView" parent="Widget.CalendarView">
+        <item name="android:selectedWeekBackgroundColor">#330099FF</item>
         <item name="android:focusedMonthDateColor">#FFFFFFFF</item>
-        <item name="android:otherMonthDateColor">#66FFFFFF</item>
+        <item name="android:unfocusedMonthDateColor">#66FFFFFF</item>
         <item name="android:weekNumberColor">#33FFFFFF</item>
-        <item name="android:gridLinesColor">#19FFFFFF</item>
-        <item name="selectedDayLine">@android:drawable/day_picker_week_view_dayline_holo_dark</item>
+        <item name="android:weekSeparatorLineColor">#19FFFFFF</item>
+        <item name="android:selectedDateVerticalBar">@android:drawable/day_picker_week_view_dayline_holo</item>
+        <item name="android:weekDayTextAppearance">@android:style/TextAppearance.Holo.CalendarViewWeekDayView</item>
     </style>
 
     <style name="Widget.Holo.ImageButton" parent="Widget.ImageButton">
         <item name="android:background">@android:drawable/btn_default_holo_dark</item>
     </style>
 
-    <!-- @hide -->
     <style name="Widget.Holo.ImageButton.NumberPickerUpButton">
         <item name="android:background">@null</item>
-        <item name="android:paddingBottom">26sp</item>
-        <item name="android:src">@android:drawable/timepicker_up_btn_holo_dark</item>
+        <item name="android:src">@android:drawable/numberpicker_up_btn_holo_dark</item>
+        <item name="android:paddingTop">26dip</item>
+        <item name="android:paddingBottom">26dip</item>
     </style>
 
-    <!-- @hide -->
     <style name="Widget.Holo.ImageButton.NumberPickerDownButton">
         <item name="android:background">@null</item>
-        <item name="android:paddingTop">26sp</item>
-        <item name="android:src">@android:drawable/timepicker_down_btn_holo_dark</item>
+        <item name="android:src">@android:drawable/numberpicker_down_btn_holo_dark</item>
+        <item name="android:paddingTop">26dip</item>
+        <item name="android:paddingBottom">26dip</item>
     </style>
 
-    <!-- @hide -->
     <style name="Widget.Holo.EditText.NumberPickerInputText">
         <item name="android:paddingTop">13sp</item>
         <item name="android:paddingBottom">13sp</item>
@@ -1507,8 +1509,9 @@
 
     <style name="Widget.Holo.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal">
         <item name="android:progressDrawable">@android:drawable/progress_horizontal_holo_dark</item>
-        <item name="android:minHeight">24dip</item>
-        <item name="android:maxHeight">24dip</item>
+        <item name="android:indeterminateDrawable">@android:drawable/progress_indeterminate_horizontal_holo</item>
+        <item name="android:minHeight">16dip</item>
+        <item name="android:maxHeight">16dip</item>
     </style>
 
     <style name="Widget.Holo.ProgressBar.Small" parent="Widget.ProgressBar.Small">
@@ -1535,9 +1538,9 @@
         <item name="android:indeterminateOnly">false</item>
         <item name="android:progressDrawable">@android:drawable/scrubber_progress_horizontal_holo_dark</item>
         <item name="android:indeterminateDrawable">@android:drawable/scrubber_progress_horizontal_holo_dark</item>
-        <item name="android:minHeight">6dip</item>
-        <item name="android:maxHeight">6dip</item>
-        <item name="android:thumb">@android:drawable/scrubber_control_holo</item>
+        <item name="android:minHeight">13dip</item>
+        <item name="android:maxHeight">13dip</item>
+        <item name="android:thumb">@android:drawable/scrubber_control_selector_holo</item>
         <item name="android:thumbOffset">16dip</item>
         <item name="android:focusable">true</item>
     </style>
@@ -1568,13 +1571,13 @@
         <item name="android:dropDownHorizontalOffset">0dip</item>
         <item name="android:dropDownWidth">wrap_content</item>
         <item name="android:popupPromptView">@android:layout/simple_dropdown_hint</item>
+        <item name="android:gravity">left|center_vertical</item>
     </style>
 
     <style name="Widget.Holo.Spinner.DropDown">
     </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">
@@ -1647,8 +1650,10 @@
     </style>
 
     <style name="Widget.Holo.ActionButton" parent="Widget.ActionButton">
-        <item name="android:paddingLeft">4dip</item>
-        <item name="android:paddingRight">4dip</item>
+        <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>
         <item name="android:scaleType">center</item>
     </style>
@@ -1673,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">
@@ -1722,7 +1724,7 @@
 
     <style name="Widget.Holo.Light.Button" parent="Widget.Button">
         <item name="android:background">@android:drawable/btn_default_holo_light</item>
-        <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
+        <item name="android:textAppearance">?android:attr/textAppearanceMediumInverse</item>
         <item name="android:textColor">@android:color/primary_text_holo_light</item>
         <item name="android:minHeight">48dip</item>
         <item name="android:paddingLeft">32dip</item>
@@ -1817,27 +1819,23 @@
         <item name="android:background">@android:drawable/btn_default_holo_light</item>
     </style>
 
-    <!-- @hide -->
-    <style name="Widget.Holo.Light.DayPickerWeekView" parent="Widget.DayPickerWeekView">
-        <item name="android:selectionBackgroundColor">#7F080030</item>
+    <style name="Widget.Holo.Light.CalendarView" parent="Widget.CalendarView">
+        <item name="android:selectedWeekBackgroundColor">#330066ff</item>
         <item name="android:focusedMonthDateColor">#FF000000</item>
-        <item name="android:otherMonthDateColor">#7F08002B</item>
+        <item name="android:unfocusedMonthDateColor">#7F08002B</item>
         <item name="android:weekNumberColor">#7F080021</item>
-        <item name="android:gridLinesColor">#7F08002A</item>
-        <item name="selectedDayLine">@android:drawable/day_picker_week_view_dayline_holo_light</item>
+        <item name="android:weekSeparatorLineColor">#7F08002A</item>
+        <item name="android:weekDayTextAppearance">@android:style/TextAppearance.Holo.Light.CalendarViewWeekDayView</item>
     </style>
 
-    <!-- @hide -->
     <style name="Widget.Holo.Light.ImageButton.NumberPickerUpButton" parent="Widget.Holo.ImageButton.NumberPickerUpButton">
-        <item name="android:src">@android:drawable/timepicker_up_btn_holo_light</item>
+        <item name="android:src">@android:drawable/numberpicker_up_btn_holo_light</item>
     </style>
 
-    <!-- @hide -->
     <style name="Widget.Holo.Light.ImageButton.NumberPickerDownButton" parent="Widget.Holo.ImageButton.NumberPickerDownButton">
-        <item name="android:src">@android:drawable/timepicker_down_btn_holo_light</item>
+        <item name="android:src">@android:drawable/numberpicker_down_btn_holo_light</item>
     </style>
 
-    <!-- @hide -->
     <style name="Widget.Holo.Light.EditText.NumberPickerInputText" parent="Widget.Holo.EditText.NumberPickerInputText">
     </style>
 
@@ -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">
@@ -1981,7 +1978,6 @@
 
     <style name="Widget.Holo.Light.ActionButton.Overflow">
         <item name="android:src">@android:drawable/ic_menu_moreoverflow_holo_light</item>
-        <item name="android:background">?android:attr/selectableItemBackground</item>
         <item name="android:paddingLeft">16dip</item>
         <item name="android:paddingRight">16dip</item>
     </style>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index f0f101e..f65b1f2 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -72,7 +72,6 @@
         
         <item name="editTextColor">?android:attr/textColorPrimaryInverse</item>
         <item name="editTextBackground">@android:drawable/edit_text</item>
-        <item name="editTextMultilineBackground">@android:drawable/edit_text</item>
         
         <item name="candidatesTextStyleSpans">@android:string/candidates_style</item>
         
@@ -143,8 +142,12 @@
         <!-- Dialog attributes -->
         <item name="alertDialogStyle">@android:style/AlertDialog</item>
         <item name="dialogTheme">@android:style/Theme.Dialog</item>
+        <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons</item>
+        <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title</item>
+        <item name="dialogTitleDecorLayout">@layout/dialog_title</item>
         <item name="alertDialogTheme">@android:style/Theme.Dialog.Alert</item>
         <item name="alertDialogCenterButtons">true</item>
+        <item name="alertDialogIcon">@android:drawable/ic_dialog_alert</item>
         
         <!-- Panel attributes -->
         <item name="panelBackground">@android:drawable/menu_background</item>
@@ -214,6 +217,7 @@
         <item name="spinnerItemStyle">@android:style/Widget.TextView.SpinnerItem</item>
         <item name="dropDownHintAppearance">@android:style/TextAppearance.Widget.DropDownHint</item>
         <item name="keyboardViewStyle">@android:style/Widget.KeyboardView</item>
+        <item name="quickContactBadgeOverlay">@android:drawable/quickcontact_badge_overlay_dark</item>
         <item name="quickContactBadgeStyleWindowSmall">@android:style/Widget.QuickContactBadge.WindowSmall</item>
         <item name="quickContactBadgeStyleWindowMedium">@android:style/Widget.QuickContactBadge.WindowMedium</item>
         <item name="quickContactBadgeStyleWindowLarge">@android:style/Widget.QuickContactBadge.WindowLarge</item>
@@ -234,7 +238,8 @@
         <item name="editTextPreferenceStyle">@android:style/Preference.DialogPreference.EditTextPreference</item>
         <item name="ringtonePreferenceStyle">@android:style/Preference.RingtonePreference</item>
         <item name="preferenceLayoutChild">@android:layout/preference_child</item>
-        <item name="preferencePanelBackground">@android:drawable/panel_bg_holo_dark</item>
+        <item name="preferencePanelStyle">@style/PreferencePanel</item>
+        <item name="detailsElementBackground">@android:drawable/panel_bg_holo_dark</item>
 
         <!-- Search widget styles -->
         <item name="searchWidgetCorpusItemBackground">@android:color/search_widget_corpus_item_background</item>
@@ -269,7 +274,8 @@
         <item name="searchViewSearchIcon">@android:drawable/ic_search</item>
         <item name="searchViewGoIcon">@android:drawable/ic_go</item>
         <item name="searchViewVoiceIcon">@android:drawable/ic_voice_search</item>
-
+        <item name="searchViewEditQuery">@android:drawable/ic_commit</item>
+        <item name="searchViewEditQueryBackground">?attr/selectableItemBackground</item>
 
         <!-- PreferenceFrameLayout attributes -->
         <item name="preferenceFrameLayoutStyle">@android:style/Widget.PreferenceFrameLayout</item>
@@ -280,17 +286,15 @@
         <item name="numberPickerInputTextStyle">@style/Widget.EditText.NumberPickerInputText</item>
         <item name="numberPickerStyle">@style/Widget.NumberPicker</item>
 
-        <!-- DayPicker$WeekView style-->
-        <item name="dayPickerWeekViewStyle">@style/Widget.DayPickerWeekView</item>
-
-        <!-- DayPickerWeekDayView style-->
-        <item name="dayPickerWeekDayViewStyle">@style/TextAppearance.Small.DayPickerWeekDayView</item>
+        <!-- CalendarView style-->
+        <item name="calendarViewStyle">@style/Widget.CalendarView</item>
 
         <item name="fastScrollThumbDrawable">@android:drawable/scrollbar_handle_accelerated_anim2</item>
         <item name="fastScrollTrackDrawable">@null</item>
         <item name="fastScrollPreviewBackgroundRight">@android:drawable/menu_submenu_background</item>
         <item name="fastScrollPreviewBackgroundLeft">@android:drawable/menu_submenu_background</item>
         <item name="fastScrollOverlayPosition">floating</item>
+        <item name="fastScrollTextColor">@android:color/primary_text_dark</item>
 
     </style>
 
@@ -339,6 +343,7 @@
         <item name="listChoiceBackgroundIndicator">@android:drawable/list_selected_background_light</item>
 
         <item name="activatedBackgroundIndicator">@android:drawable/activated_background_light</item>
+        <item name="quickContactBadgeOverlay">@android:drawable/quickcontact_badge_overlay_light</item>
 
         <item name="popupWindowStyle">@android:style/Widget.PopupWindow</item>
         
@@ -362,8 +367,15 @@
         <item name="actionModePasteDrawable">@android:drawable/ic_menu_paste_light</item>
         <!-- SearchView attributes -->
         <item name="searchDropdownBackground">@android:drawable/search_dropdown_light</item>
+        <item name="searchViewCloseIcon">@android:drawable/ic_clear_holo_light</item>
+        <item name="searchViewSearchIcon">@android:drawable/ic_search_api_holo_light</item>
+        <item name="searchViewGoIcon">@android:drawable/ic_go_search_api_holo_light</item>
+        <item name="searchViewVoiceIcon">@android:drawable/ic_voice_search_api_holo_light</item>
+        <item name="searchViewEditQuery">@android:drawable/ic_commit_search_api_holo_light</item>
+
+        <item name="detailsElementBackground">@android:drawable/panel_bg_holo_light</item>
     </style>
-    
+
     <!-- Variant of the light theme with no title bar -->
     <style name="Theme.Light.NoTitleBar">
         <item name="android:windowNoTitle">true</item>
@@ -544,6 +556,7 @@
         <item name="windowBackground">@android:color/transparent</item>
         <item name="windowTitleStyle">@android:style/DialogWindowTitle</item>
         <item name="windowContentOverlay">@null</item>
+        <item name="itemTextAppearance">@android:style/TextAppearance.Large.Inverse</item>
     </style>
     
     <!-- Default dark theme for panel windows.  This removes all extraneous
@@ -555,6 +568,7 @@
         <item name="android:colorBackgroundCacheHint">@null</item>
         <item name="android:windowFrame">@null</item>
         <item name="android:windowContentOverlay">@null</item>
+        <item name="android:windowAnimationStyle">@null</item>
         <item name="android:windowIsFloating">true</item>
         <item name="android:backgroundDimEnabled">false</item>
         <item name="android:windowIsTranslucent">true</item>
@@ -570,6 +584,23 @@
         <item name="android:colorBackgroundCacheHint">@null</item>
         <item name="android:windowFrame">@null</item>
         <item name="android:windowContentOverlay">@null</item>
+        <item name="android:windowAnimationStyle">@null</item>
+        <item name="android:windowIsFloating">true</item>
+        <item name="android:backgroundDimEnabled">false</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowNoTitle">true</item>
+    </style>
+
+    <!-- Default holo dark theme for panel windows.  This removes all extraneous
+         window decorations, so you basically have an empty rectangle in which
+         to place your content.  It makes the window floating, with a transparent
+         background, and turns off dimming behind the window. -->
+    <style name="Theme.Holo.Panel">
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:colorBackgroundCacheHint">@null</item>
+        <item name="android:windowFrame">@null</item>
+        <item name="android:windowContentOverlay">@null</item>
+        <item name="android:windowAnimationStyle">@null</item>
         <item name="android:windowIsFloating">true</item>
         <item name="android:backgroundDimEnabled">false</item>
         <item name="android:windowIsTranslucent">true</item>
@@ -585,6 +616,7 @@
         <item name="android:colorBackgroundCacheHint">@null</item>
         <item name="android:windowFrame">@null</item>
         <item name="android:windowContentOverlay">@null</item>
+        <item name="android:windowAnimationStyle">@null</item>
         <item name="android:windowIsFloating">true</item>
         <item name="android:backgroundDimEnabled">false</item>
         <item name="android:windowIsTranslucent">true</item>
@@ -593,10 +625,8 @@
 
     <!-- Default theme for input methods, which is used by the
          {@link android.inputmethodservice.InputMethodService} class.
-         this inherits from Theme.NoTitleBar, but makes the background
-         transparent, the window floating and translucent, and ensures that
-         it does not dim the UI behind it.  This also configures the window
-         with the standard IME animations and visuals. -->
+         this inherits from Theme.Panel, but sets up IME appropriate animations
+         and a few custom attributes. -->
     <style name="Theme.InputMethod" parent="Theme.Panel">
         <item name="android:windowAnimationStyle">@android:style/Animation.InputMethod</item>
         <item name="android:imeFullscreenBackground">@android:drawable/input_method_fullscreen_background</item>
@@ -604,6 +634,17 @@
         <item name="android:imeExtractExitAnimation">@android:anim/input_method_extract_exit</item>
     </style>
 
+    <!-- Default theme for modern holo style input methods, which is used by the
+         {@link android.inputmethodservice.InputMethodService} class.
+         this inherits from Theme.Panel, but sets up IME appropriate animations
+         and a few custom attributes. -->
+    <style name="Theme.Holo.InputMethod" parent="Theme.Holo.Panel">
+        <item name="android:windowAnimationStyle">@android:style/Animation.InputMethod</item>
+        <item name="android:imeFullscreenBackground">@android:drawable/input_method_fullscreen_background</item>
+        <item name="android:imeExtractEnterAnimation">@android:anim/input_method_extract_enter</item>
+        <item name="android:imeExtractExitAnimation">@android:anim/input_method_extract_exit</item>
+    </style>
+    
     <!-- Theme for the search input bar. -->
     <style name="Theme.SearchBar" parent="Theme.Holo.Light.Panel">
         <item name="windowContentOverlay">@null</item>        
@@ -732,7 +773,6 @@
         
         <item name="editTextColor">?android:attr/textColorPrimary</item>
         <item name="editTextBackground">@android:drawable/edit_text_holo_dark</item>
-        <item name="editTextMultilineBackground">@android:drawable/edit_text_multiline_holo_dark</item>
         
         <item name="candidatesTextStyleSpans">@android:string/candidates_style</item>
         
@@ -803,8 +843,12 @@
         <!-- Dialog attributes -->
         <item name="alertDialogStyle">@android:style/AlertDialog.Holo</item>
         <item name="dialogTheme">@android:style/Theme.Holo.Dialog</item>
+        <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item>
+        <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item>
+        <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item>
         <item name="alertDialogTheme">@android:style/Theme.Holo.Dialog.Alert</item>
         <item name="alertDialogCenterButtons">false</item>
+        <item name="alertDialogIcon">@android:drawable/ic_dialog_alert_holo_dark</item>
         
         <!-- Panel attributes -->
         <item name="panelBackground">@android:drawable/menu_background</item>
@@ -892,7 +936,7 @@
         <item name="editTextPreferenceStyle">@android:style/Preference.DialogPreference.EditTextPreference</item>
         <item name="ringtonePreferenceStyle">@android:style/Preference.RingtonePreference</item>
         <item name="preferenceLayoutChild">@android:layout/preference_child</item>
-        <item name="preferencePanelBackground">@android:drawable/panel_bg_holo_dark</item>
+        <item name="detailsElementBackground">@android:drawable/panel_bg_holo_dark</item>
 
         <!-- Search widget styles -->
         <item name="searchWidgetCorpusItemBackground">@android:color/search_widget_corpus_item_background</item>
@@ -929,11 +973,8 @@
         <item name="numberPickerDownButtonStyle">@style/Widget.Holo.ImageButton.NumberPickerDownButton</item>
         <item name="numberPickerInputTextStyle">@style/Widget.Holo.EditText.NumberPickerInputText</item>
 
-        <!-- DayPicker$WeekView style-->
-        <item name="dayPickerWeekViewStyle">@style/Widget.Holo.DayPickerWeekView</item>
-
-        <!-- DayPickerWeekDayView style-->
-        <item name="dayPickerWeekDayViewStyle">@style/TextAppearance.Holo.DayPickerWeekDayView</item>
+        <!-- CalendarView style-->
+        <item name="calendarViewStyle">@style/Widget.Holo.CalendarView</item>
 
         <item name="fastScrollThumbDrawable">@android:drawable/fastscroll_thumb_holo</item>
         <item name="fastScrollPreviewBackgroundLeft">@android:drawable/fastscroll_label_left_holo_dark</item>
@@ -994,7 +1035,6 @@
 
         <item name="editTextColor">?android:attr/textColorPrimary</item>
         <item name="editTextBackground">@android:drawable/edit_text_holo_light</item>
-        <item name="editTextMultilineBackground">@android:drawable/edit_text_multiline_holo_light</item>
 
         <item name="candidatesTextStyleSpans">@android:string/candidates_style</item>
         
@@ -1064,7 +1104,12 @@
         <!-- Dialog attributes -->
         <item name="alertDialogStyle">@android:style/AlertDialog.Holo.Light</item>
         <item name="dialogTheme">@android:style/Theme.Holo.Light.Dialog</item>
+        <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item>
+        <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item>
+        <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item>
+        <item name="alertDialogCenterButtons">false</item>
         <item name="alertDialogTheme">@android:style/Theme.Holo.Light.Dialog.Alert</item>
+        <item name="alertDialogIcon">@android:drawable/ic_dialog_alert_holo_light</item>
         
         <!-- Panel attributes -->
         <item name="panelBackground">@android:drawable/menu_background</item>
@@ -1152,7 +1197,7 @@
         <item name="editTextPreferenceStyle">@android:style/Preference.DialogPreference.EditTextPreference</item>
         <item name="ringtonePreferenceStyle">@android:style/Preference.RingtonePreference</item>
         <item name="preferenceLayoutChild">@android:layout/preference_child</item>
-        <item name="preferencePanelBackground">@android:drawable/panel_bg_holo_light</item>
+        <item name="detailsElementBackground">@android:drawable/panel_bg_holo_light</item>
 
         <!-- Search widget styles -->
         <item name="searchWidgetCorpusItemBackground">@android:color/search_widget_corpus_item_background</item>
@@ -1186,11 +1231,8 @@
         <item name="numberPickerDownButtonStyle">@style/Widget.Holo.Light.ImageButton.NumberPickerDownButton</item>
         <item name="numberPickerInputTextStyle">@style/Widget.Holo.Light.EditText.NumberPickerInputText</item>
 
-        <!-- DayPicker$WeekView style-->
-        <item name="dayPickerWeekViewStyle">@style/Widget.Holo.Light.DayPickerWeekView</item>
-
-        <!-- DayPickerWeekDayView style-->
-        <item name="dayPickerWeekDayViewStyle">@style/TextAppearance.Holo.Light.DayPickerWeekDayView</item>
+        <!-- CalendarView style-->
+        <item name="calendarViewStyle">@style/Widget.Holo.Light.CalendarView</item>
 
         <item name="fastScrollThumbDrawable">@android:drawable/fastscroll_thumb_holo</item>
         <item name="fastScrollPreviewBackgroundLeft">@android:drawable/fastscroll_label_left_holo_light</item>
@@ -1258,12 +1300,26 @@
         <item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Inverse</item>
     </style>
 
+    <!-- Variation of Theme.Holo.Dialog that has a nice minumum width for
+         a regular dialog. -->
+    <style name="Theme.Holo.Dialog.MinWidth">
+        <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
+        <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_major</item>
+    </style>
+
     <!-- Variation of Theme.Holo.Dialog that does not include a title bar. -->
     <style name="Theme.Holo.Dialog.NoActionBar">
         <item name="android:windowActionBar">false</item>
         <item name="android:windowNoTitle">true</item>
     </style>
 
+    <!-- Variation of Theme.Holo.Dialog.NoActionVar that has a nice minumum width for
+         a regular dialog. -->
+    <style name="Theme.Holo.Dialog.NoActionBar.MinWidth">
+        <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
+        <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_major</item>
+    </style>
+
     <!-- Variation of Theme.Holo.Dialog that does not include a frame (or background).
          The view hierarchy of the dialog is responsible for drawing all of
          its pixels. -->
@@ -1286,6 +1342,8 @@
         <item name="windowBackground">@android:color/transparent</item>
         <item name="windowTitleStyle">@android:style/DialogWindowTitle.Holo</item>
         <item name="windowContentOverlay">@null</item>
+        <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
+        <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_major</item>
     </style>
 
     <!-- Theme for a window that will be displayed either full-screen on
@@ -1299,7 +1357,7 @@
          (large, xlarge). -->
     <style name="Theme.Holo.DialogWhenLarge.NoActionBar" parent="@android:style/Theme.Holo.NoActionBar">
     </style>
-    
+
     <!-- Light holo dialog themes -->
 
     <!-- Holo light theme for dialog windows and activities, which is used by the
@@ -1328,12 +1386,26 @@
         <item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Light.Inverse</item>
     </style>
 
+    <!-- Variation of Theme.Holo.Light.Dialog that has a nice minumum width for
+         a regular dialog. -->
+    <style name="Theme.Holo.Light.Dialog.MinWidth">
+        <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
+        <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_major</item>
+    </style>
+
     <!-- Variation of Theme.Holo.Light.Dialog that does not include a title bar. -->
     <style name="Theme.Holo.Light.Dialog.NoActionBar">
         <item name="android:windowActionBar">false</item>
         <item name="android:windowNoTitle">true</item>
     </style>
 
+    <!-- Variation of Theme.Holo.Light.Dialog.NoActionBar that has a nice minumum width for
+         a regular dialog. -->
+    <style name="Theme.Holo.Light.Dialog.NoActionBar.MinWidth">
+        <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
+        <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_major</item>
+    </style>
+
     <!-- Theme for a window that will be displayed either full-screen on
          smaller screens (small, normal) or as a dialog on larger screens
          (large, xlarge). -->
@@ -1356,6 +1428,8 @@
         <item name="windowBackground">@android:color/transparent</item>
         <item name="windowTitleStyle">@android:style/DialogWindowTitle.Holo.Light</item>
         <item name="windowContentOverlay">@null</item>
+        <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
+        <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_major</item>
     </style>
 
     <!-- Default holographic (dark) for windows that want to have the user's selected
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index af74c6f..3d5588c 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -22,6 +22,10 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Bundle;
+import android.os.IPowerManager;
+import android.os.PowerManager;
+import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -460,6 +464,26 @@
         return mWifiManager.setWifiEnabled(true);
     }
 
+    // Turn screen off
+    public void turnScreenOff() {
+        log("Turn screen off");
+        PowerManager pm =
+            (PowerManager) getSystemService(Context.POWER_SERVICE);
+        pm.goToSleep(SystemClock.uptimeMillis() + 100);
+    }
+
+    // Turn screen on
+    public void turnScreenOn() {
+        log("Turn screen on");
+        IPowerManager mPowerManagerService = IPowerManager.Stub.asInterface(
+                ServiceManager.getService("power"));;
+        try {
+            mPowerManagerService.userActivityWithForce(SystemClock.uptimeMillis(), false, true);
+        } catch (Exception e) {
+            log(e.toString());
+        }
+    }
+
     /**
      * Associate the device to given SSID
      * If the device is already associated with a WiFi, disconnect and forget it,
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index 4e5fc0e..1655e27 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -63,11 +63,16 @@
         wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "CMWakeLock");
         wl.acquire();
         // Each test case will start with cellular connection
+        if (Settings.System.getInt(getInstrumentation().getContext().getContentResolver(),
+                Settings.System.AIRPLANE_MODE_ON) == 1) {
+            Log.v(LOG_TAG, "airplane is not disabled, disable it.");
+            cmActivity.setAirplaneMode(getInstrumentation().getContext(), false);
+        }
         if (!cmActivity.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
                 ConnectivityManagerTestActivity.LONG_TIMEOUT)) {
             // Note: When the test fails in setUp(), tearDown is not called. In that case,
             // the activity is destroyed which blocks the next test at "getActivity()".
-            // tearDown() is called hear to avoid that situation.
+            // tearDown() is called here to avoid that situation.
             tearDown();
             fail("Device is not connected to Mobile, setUp failed");
         }
@@ -82,6 +87,7 @@
         // if airplane mode is set, disable it.
         if (Settings.System.getInt(getInstrumentation().getContext().getContentResolver(),
                 Settings.System.AIRPLANE_MODE_ON) == 1) {
+            Log.v(LOG_TAG, "disable airplane mode if it is enabled");
             cmActivity.setAirplaneMode(getInstrumentation().getContext(), false);
         }
         super.tearDown();
@@ -93,13 +99,11 @@
         assertEquals("network type is not MOBILE", ConnectivityManager.TYPE_MOBILE,
                 extraNetInfo.getType());
         assertTrue("not connected to cellular network", extraNetInfo.isConnected());
-        assertTrue("no data connection", cmActivity.mState.equals(State.CONNECTED));
     }
 
     // Test case 1: Test enabling Wifi without associating with any AP
     @LargeTest
     public void test3GToWifiNotification() {
-        // To avoid UNKNOWN state when device boots up
         cmActivity.enableWifi();
         try {
             Thread.sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
@@ -108,7 +112,10 @@
         }
 
         cmActivity.disableWifi();
-        // As Wifi stays in DISCONNECTED, the connectivity manager will not broadcast
+
+        cmActivity.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
+                State.DISCONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT);
+        // As Wifi stays in DISCONNETED, the connectivity manager will not broadcast
         // any network connectivity event for Wifi
         NetworkInfo networkInfo = cmActivity.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
         cmActivity.setStateTransitionCriteria(ConnectivityManager.TYPE_MOBILE, networkInfo.getState(),
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
index 2ac7265..ea79f8c 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
@@ -26,7 +26,10 @@
 import android.net.wifi.WifiConfiguration.AuthAlgorithm;
 import android.net.wifi.WifiManager;
 import android.os.Environment;
+import android.os.IPowerManager;
 import android.os.PowerManager;
+import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
@@ -46,7 +49,6 @@
     private final static String OUTPUT_FILE = "WifiStressTestOutput.txt";
     private ConnectivityManagerTestActivity mAct;
     private int iterations;
-    private PowerManager.WakeLock mWakelock = null;
     private BufferedWriter mOutputWriter = null;
     private int mLastIteration = 0;
 
@@ -61,17 +63,11 @@
         ConnectivityManagerStressTestRunner mRunner =
             (ConnectivityManagerStressTestRunner)getInstrumentation();
         iterations = mRunner.mSoftapIterations;
-        PowerManager pm =
-            (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
-        mWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "wifiApStress");
-        mWakelock.acquire();
+        mAct.turnScreenOn();
     }
 
     @Override
     public void tearDown() throws Exception {
-        if (mWakelock != null) {
-            mWakelock.release();
-        }
         // write the total number of iterations into output file
         mOutputWriter = new BufferedWriter(new FileWriter(new File(
                 Environment.getExternalStorageDirectory(), OUTPUT_FILE)));
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index 7914417..ae009ca 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -30,7 +30,9 @@
 import android.net.wifi.WifiManager;
 import android.os.Environment;
 import android.os.PowerManager;
+import android.os.IPowerManager;
 import android.os.SystemClock;
+import android.os.ServiceManager;
 import android.provider.Settings;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -57,7 +59,7 @@
     /**
      * Wi-Fi idle time for default sleep policy
      */
-    private final static long WIFI_IDLE_MS = 5 * 1000;
+    private final static long WIFI_IDLE_MS = 60 * 1000;
 
     /**
      * The delay for Wi-Fi to get into idle, after screen off + WIFI_IDEL_MS + WIFI_IDLE_DELAY
@@ -73,7 +75,6 @@
     private String mSsid;
     private String mPassword;
     private ConnectivityManagerStressTestRunner mRunner;
-    private PowerManager.WakeLock wl = null;
     private BufferedWriter mOutputWriter = null;
 
     public WifiStressTest() {
@@ -90,10 +91,11 @@
         mPassword = mRunner.mReconnectPassword;
         mScanIterations = mRunner.mScanIterations;
         mWifiSleepTime = mRunner.mSleepTime;
-        wl = null;
         mOutputWriter = new BufferedWriter(new FileWriter(new File(
                 Environment.getExternalStorageDirectory(), OUTPUT_FILE), true));
+        mAct.turnScreenOn();
         if (!mAct.mWifiManager.isWifiEnabled()) {
+            log("Enable wi-fi before stress tests.");
             if (!mAct.enableWifi()) {
                 tearDown();
                 fail("enable wifi failed.");
@@ -106,9 +108,6 @@
     @Override
     public void tearDown() throws Exception {
         log("tearDown()");
-        if ((wl != null) && wl.isHeld()) {
-            wl.release();
-        }
         if (mOutputWriter != null) {
             mOutputWriter.close();
         }
@@ -129,26 +128,6 @@
         }
     }
 
-    private void turnScreenOff() {
-        log("Turn screen off");
-        if (wl != null) {
-            log("release wake lock");
-            wl.release();
-        }
-        PowerManager pm =
-            (PowerManager) mRunner.getContext().getSystemService(Context.POWER_SERVICE);
-        pm.goToSleep(SystemClock.uptimeMillis() + 50);
-    }
-
-    private void turnScreenOn() {
-        log("Turn screen on");
-        PowerManager pm =
-            (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
-        wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
-                "wifiStressTest");
-        wl.acquire();
-    }
-
     public void log(String message) {
         Log.v(TAG, message);
     }
@@ -247,7 +226,6 @@
                 Settings.Secure.WIFI_IDLE_MS, WIFI_IDLE_MS);
 
         // Connect to a Wi-Fi network
-        turnScreenOn();
         WifiConfiguration config = new WifiConfiguration();
         config.SSID = mSsid;
         config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
@@ -267,26 +245,34 @@
                 ConnectivityManagerTestActivity.LONG_TIMEOUT));
         int i;
         for (i = 0; i < mReconnectIterations; i++) {
-            // 1. Put device into sleep
-            // 2. Wait for the device to sleep for sometime, very 3G is connected
-            // 3. Wake up the device
+            // 1. Put device into sleep mode
+            // 2. Wait for the device to sleep for sometime, verify wi-fi is off and mobile is on.
+            // 3. Maintain the sleep mode for some time,
+            // 4. Verify the Wi-Fi is still off, and data is on
+            // 5. Wake up the device, verify Wi-Fi is enabled and connected.
             writeOutput(String.format("iteration %d out of %d",
                     i, mReconnectIterations));
             log("iteration: " + i);
-            turnScreenOff();
+            mAct.turnScreenOff();
             PowerManager pm =
                 (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
             assertFalse(pm.isScreenOn());
-            sleep(WIFI_IDLE_MS + WIFI_IDLE_DELAY, "Interruped while wait for wifi to be idle");
+            sleep(WIFI_IDLE_MS, "Interruped while wait for wifi to be idle");
             assertTrue("Wait for Wi-Fi to idle timeout",
                     mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.DISCONNECTED,
-                    ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+                    6 * ConnectivityManagerTestActivity.SHORT_TIMEOUT));
+            // use long timeout as the pppd startup may take several retries.
             assertTrue("Wait for cellular connection timeout",
                     mAct.waitForNetworkState(ConnectivityManager.TYPE_MOBILE, State.CONNECTED,
                     ConnectivityManagerTestActivity.LONG_TIMEOUT));
             sleep(mWifiSleepTime + WIFI_IDLE_DELAY, "Interrupted while device is in sleep mode");
+            // Verify the wi-fi is still off and data connection is on
+            assertEquals("Wi-Fi is reconnected", State.DISCONNECTED,
+                    mAct.mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState());
+            assertEquals("Cellular connection is down", State.CONNECTED,
+                    mAct.mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState());
             // Turn screen on again
-            turnScreenOn();
+            mAct.turnScreenOn();
             assertTrue("Wait for Wi-Fi enable timeout after wake up",
                     mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
                     ConnectivityManagerTestActivity.SHORT_TIMEOUT));
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java
index 6717bda..e22b018 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java
@@ -18,14 +18,17 @@
 
 import android.content.BroadcastReceiver;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.Context;
 import android.app.Instrumentation;
 import android.os.Handler;
 import android.os.Message;
+import android.net.NetworkInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiConfiguration.Status;
+import android.net.wifi.SupplicantState;
 
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.AndroidTestCase;
@@ -45,10 +48,62 @@
 
     //10s delay for turning on wifi
     private static final int DELAY = 10000;
+    private WifiStateListener mWifiStateListener;
+    int mWifiState;
+    int mDisableBroadcastCounter = 0;
+    int mEnableBroadcastCounter = 0;
+    NetworkInfo mNetworkInfo;
+    boolean mSupplicantConnection;
+    SupplicantState mSupplicantState;
+
+    private class WifiStateListener extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+                mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                        WifiManager.WIFI_STATE_UNKNOWN);
+                switch (mWifiState) {
+                    case WifiManager.WIFI_STATE_DISABLING:
+                        if (mDisableBroadcastCounter == 0) mDisableBroadcastCounter++;
+                        break;
+                    case WifiManager.WIFI_STATE_DISABLED:
+                        if (mDisableBroadcastCounter == 1) mDisableBroadcastCounter++;
+                        break;
+                    case WifiManager.WIFI_STATE_ENABLING:
+                        if (mEnableBroadcastCounter == 0) mEnableBroadcastCounter++;
+                        break;
+                    case WifiManager.WIFI_STATE_ENABLED:
+                        if (mEnableBroadcastCounter == 1) mEnableBroadcastCounter++;
+                        break;
+                }
+            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+                mNetworkInfo = (NetworkInfo)
+                        intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+            } else if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
+                mSupplicantState = (SupplicantState)
+                        intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
+            } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
+                mSupplicantConnection =
+                        intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false);
+            }
+        }
+    }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        // register a connectivity receiver for CONNECTIVITY_ACTION;
+
+        mWifiStateListener = new WifiStateListener();
+        IntentFilter mIntentFilter = new IntentFilter();
+        mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
+        mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        getContext().registerReceiver(mWifiStateListener, mIntentFilter);
+
         mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
         mWifiManager.setWifiEnabled(true);
         assertNotNull(mWifiManager);
@@ -77,7 +132,7 @@
         List<WifiConfiguration> configList = mWifiManager.getConfiguredNetworks();
         boolean found = false;
         for (WifiConfiguration c : configList) {
-            if (c.networkId == netId) {
+            if (c.networkId == netId && c.SSID.equals(config.SSID)) {
                 found = true;
             }
         }
@@ -183,4 +238,37 @@
         assertTrue(ret);
         mWifiManager.saveConfiguration();
     }
+
+    // Test case 5: test wifi state change broadcasts
+    @LargeTest
+    public void testWifiBroadcasts() {
+
+        /* Initialize */
+        mWifiManager.setWifiEnabled(false);
+        sleepAfterWifiEnable();
+        mDisableBroadcastCounter = 0;
+        mEnableBroadcastCounter = 0;
+        mSupplicantConnection = false;
+        mNetworkInfo = null;
+        mSupplicantState = null;
+
+        /* Enable wifi */
+        mWifiManager.setWifiEnabled(true);
+        sleepAfterWifiEnable();
+        assertTrue(mEnableBroadcastCounter == 2);
+        assertTrue(mSupplicantConnection == true);
+        assertTrue(mNetworkInfo.isConnected());
+        assertTrue(mSupplicantState == SupplicantState.COMPLETED);
+
+
+        /* Disable wifi */
+        mWifiManager.setWifiEnabled(false);
+        sleepAfterWifiEnable();
+        assertTrue(mDisableBroadcastCounter == 2);
+        assertTrue(mSupplicantConnection == false);
+        assertTrue(!mNetworkInfo.isConnected());
+        assertTrue(mSupplicantState != SupplicantState.COMPLETED);
+
+    }
+
 }
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index b1e38ee..72120a8 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -4,9 +4,9 @@
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
-  
+
           http://www.apache.org/licenses/LICENSE-2.0
-  
+
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -36,6 +36,9 @@
             android:description="@string/permdesc_testDenied" />
 
     <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
+    <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" />
+    <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED" />
+    <uses-permission android:name="android.permission.DOWNLOAD_CACHE_NON_PURGEABLE" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@@ -114,7 +117,7 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.focus.FocusAfterRemoval" android:label="FocusAfterRemoval">
@@ -142,28 +145,28 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.focus.ListOfEditTexts" android:label="ListOfEditTexts">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.focus.ListOfInternalSelectionViews" android:label="ListOfInternalSelectionViews">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>                        
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.focus.ListWithFooterViewAndNewLabels" android:label="FocusListWithFooter">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.focus.ListWithMailMessages" android:label="ListWithMailMessages">
@@ -177,7 +180,7 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.focus.VerticalFocusSearch" android:label="VerticalFocusSearch">
@@ -254,7 +257,7 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.layout.linear.LLOfButtons1" android:label="LLOfButtons1">
@@ -282,7 +285,7 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.layout.linear.Weight" android:label="Weight">
@@ -480,7 +483,7 @@
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.view.PreDrawListener" android:label="PreDrawListener">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -515,7 +518,7 @@
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.widget.listview.ListScrollListener" android:label="ListScrollListener">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -529,21 +532,21 @@
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.widget.listview.ListTakeFocusFromSide" android:label="ListTakeFocusFromSide">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.widget.listview.ListBottomGravity" android:label="ListBottomGravity">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.widget.listview.ListBottomGravityMany" android:label="ListBottomGravityMany">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -565,19 +568,19 @@
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.widget.listview.ListTopGravityMany" android:label="ListTopGravityMany">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.widget.listview.ListEndingWithMultipleSeparators" android:label="ListEndingWithMultipleSeparators">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>                        
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.listview.ListGetSelectedView" android:label="ListGetSelectedView">
@@ -612,21 +615,21 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.listview.ListOfItemsTallerThanScreen" android:label="ListOfItemsTallerThanScreen">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.listview.ListOfThinItems" android:label="ListOfThinItems">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>                        
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.listview.ListOfShortTallShort" android:label="ListOfShortTallShort">
@@ -640,14 +643,14 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.listview.ListWithOffScreenNextSelectable" android:label="ListWithOffScreenNextSelectable">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>                                    
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.listview.ListWithFirstScreenUnSelectable" android:label="ListWithFirstScreenUnSelectable">
@@ -662,7 +665,7 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.listview.ListWithHeaders" android:label="ListWithHeaders">
@@ -683,14 +686,14 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.listview.ListWithScreenOfNoSelectables" android:label="ListWithScreenOfNoSelectables">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.listview.ListItemFocusablesFarApart" android:label="ListItemFocusablesFarApart">
@@ -718,21 +721,21 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.listview.ListItemsExpandOnSelection" android:label="ListItemsExpandOnSelection">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.listview.ListWithOnItemSelectedAction" android:label="ListWithOnItemSelectedAction">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
 
         <activity android:name="android.widget.listview.ListItemISVAndButton" android:label="ListItemISVAndButton">
@@ -767,30 +770,30 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
-       
+
 	    <activity android:name="android.widget.listview.ListManagedCursor" android:label="ListManagedCursor">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-       
+
 	    <activity android:name="android.widget.listview.ListWithEmptyView" android:label="ListWithEmptyView">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.widget.gridview.GridInHorizontal" android:label="GridInHorizontal">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.widget.gridview.GridPadding" android:label="GridPadding">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -881,21 +884,21 @@
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.widget.gridview.GridVerticalSpacingStackFromBottom" android:label="GridVerticalSpacingStackFromBottom">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.widget.gridview.GridSingleColumn" android:label="GridSingleColumn">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.view.menu.ListContextMenu" android:label="ListContextMenu">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -1009,7 +1012,7 @@
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
             </intent-filter>
         </activity>
-        
+
         <activity android:name="android.widget.AutoCompleteTextViewSimple"
                   android:label="AutoCompleteTextViewSimple">
             <intent-filter>
@@ -1034,9 +1037,9 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>            
+            </intent-filter>
         </activity>
-        
+
 
 
         <!-- Activity-level metadata -->
@@ -1049,13 +1052,6 @@
         <meta-data android:name="com.android.frameworks.coretests.reference"
                    android:resource="@xml/metadata_app" />
 
-        <activity android:name="AndroidPerformanceTests" android:label="Android Performance Tests">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.UNIT_TEST" />
-            </intent-filter>
-        </activity>
-
         <!-- Application components used for activity tests -->
 
         <activity android:name="android.app.activity.TestedActivity"
diff --git a/core/tests/coretests/apks/install_uses_feature/Android.mk b/core/tests/coretests/apks/install_uses_feature/Android.mk
new file mode 100644
index 0000000..c0a5067
--- /dev/null
+++ b/core/tests/coretests/apks/install_uses_feature/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := FrameworkCoreTests_install_uses_feature
+
+include $(BUILD_PACKAGE)
+
diff --git a/core/tests/coretests/apks/install_uses_feature/AndroidManifest.xml b/core/tests/coretests/apks/install_uses_feature/AndroidManifest.xml
new file mode 100644
index 0000000..ecbd7c4
--- /dev/null
+++ b/core/tests/coretests/apks/install_uses_feature/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.frameworks.coretests.install_uses_feature">
+
+    <uses-feature android:name="com.android.frameworks.coretests.nonexistent" />
+        
+    <application android:hasCode="false">
+    </application>
+</manifest>
diff --git a/core/tests/coretests/apks/install_uses_feature/res/values/strings.xml b/core/tests/coretests/apks/install_uses_feature/res/values/strings.xml
new file mode 100644
index 0000000..3b8b3b1
--- /dev/null
+++ b/core/tests/coretests/apks/install_uses_feature/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="dummy">dummy</string>
+</resources>
diff --git a/core/tests/coretests/res/raw/install_uses_feature b/core/tests/coretests/res/raw/install_uses_feature
new file mode 100644
index 0000000..769a246
--- /dev/null
+++ b/core/tests/coretests/res/raw/install_uses_feature
Binary files differ
diff --git a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
index 8df37ad..6a471ad 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
@@ -16,8 +16,12 @@
 
 package android.app;
 
+import coretestutils.http.MockResponse;
+import coretestutils.http.MockWebServer;
+
 import android.app.DownloadManager.Query;
 import android.app.DownloadManager.Request;
+import android.app.DownloadManagerBaseTest.DataType;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -27,11 +31,10 @@
 import android.net.NetworkInfo;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
-import android.os.Bundle;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
-import android.os.SystemClock;
 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
@@ -43,31 +46,24 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.net.URL;
-import java.util.concurrent.TimeoutException;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Random;
 import java.util.Set;
-import java.util.Vector;
-
-import junit.framework.AssertionFailedError;
-
-import coretestutils.http.MockResponse;
-import coretestutils.http.MockWebServer;
+import java.util.concurrent.TimeoutException;
 
 /**
  * Base class for Instrumented tests for the Download Manager.
  */
 public class DownloadManagerBaseTest extends InstrumentationTestCase {
-
+    private static final String TAG = "DownloadManagerBaseTest";
     protected DownloadManager mDownloadManager = null;
     protected MockWebServer mServer = null;
     protected String mFileType = "text/plain";
     protected Context mContext = null;
     protected MultipleDownloadsCompletedReceiver mReceiver = null;
-    protected static final int DEFAULT_FILE_SIZE = 130 * 1024;  // 130kb
+    protected static final int DEFAULT_FILE_SIZE = 10 * 1024;  // 10kb
     protected static final int FILE_BLOCK_READ_SIZE = 1024 * 1024;
 
     protected static final String LOG_TAG = "android.net.DownloadManagerBaseTest";
@@ -85,6 +81,9 @@
     protected static final int MAX_WAIT_FOR_DOWNLOAD_TIME = 5 * 60 * 1000; // 5 minutes
     protected static final int MAX_WAIT_FOR_LARGE_DOWNLOAD_TIME = 15 * 60 * 1000; // 15 minutes
 
+    protected static final int DOWNLOAD_TO_SYSTEM_CACHE = 1;
+    protected static final int DOWNLOAD_TO_DOWNLOAD_CACHE_DIR = 2;
+
     // Just a few popular file types used to return from a download
     protected enum DownloadFileType {
         PLAINTEXT,
@@ -617,19 +616,22 @@
         int nextChunkSize = CHUNK_SIZE;
         byte[] randomData = null;
         Random rng = new LoggingRng();
+        byte[] chunkSizeData = generateData(nextChunkSize, type, rng);
 
         try {
             while (remaining > 0) {
                 if (remaining < CHUNK_SIZE) {
                     nextChunkSize = (int)remaining;
                     remaining = 0;
+                    randomData = generateData(nextChunkSize, type, rng);
                 }
                 else {
                     remaining -= CHUNK_SIZE;
+                    randomData = chunkSizeData;
                 }
-
-                randomData = generateData(nextChunkSize, type, rng);
                 output.write(randomData);
+                Log.i(TAG, "while creating " + fileSize + " file, " +
+                        "remaining bytes to be written: " + remaining);
             }
         } catch (IOException e) {
             Log.e(LOG_TAG, "Error writing to file " + file.getAbsolutePath());
@@ -888,30 +890,46 @@
      */
     protected void removeAllCurrentDownloads() {
         Log.i(LOG_TAG, "Removing all current registered downloads...");
+        ArrayList<Long> ids = new ArrayList<Long>();
         Cursor cursor = mDownloadManager.query(new Query());
         try {
             if (cursor.moveToFirst()) {
                 do {
                     int index = cursor.getColumnIndex(DownloadManager.COLUMN_ID);
                     long downloadId = cursor.getLong(index);
-
-                    mDownloadManager.remove(downloadId);
+                    ids.add(downloadId);
                 } while (cursor.moveToNext());
             }
         } finally {
             cursor.close();
         }
+        // delete all ids
+        for (long id : ids) {
+            mDownloadManager.remove(id);
+        }
+        // make sure the database is empty
+        cursor = mDownloadManager.query(new Query());
+        try {
+            assertEquals(0, cursor.getCount());
+        } finally {
+            cursor.close();
+        }
     }
 
     /**
      * Helper to perform a standard enqueue of data to the mock server.
+     * download is performed to the downloads cache dir (NOT systemcache dir)
      *
      * @param body The body to return in the response from the server
      */
     protected long doStandardEnqueue(byte[] body) throws Exception {
+        return enqueueDownloadRequest(body, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR);
+    }
+
+    protected long enqueueDownloadRequest(byte[] body, int location) throws Exception {
         // Prepare the mock server with a standard response
         enqueueResponse(HTTP_OK, body);
-        return doCommonStandardEnqueue();
+        return doEnqueue(location);
     }
 
     /**
@@ -920,9 +938,13 @@
      * @param body The body to return in the response from the server, contained in the file
      */
     protected long doStandardEnqueue(File body) throws Exception {
+        return enqueueDownloadRequest(body, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR);
+    }
+
+    protected long enqueueDownloadRequest(File body, int location) throws Exception {
         // Prepare the mock server with a standard response
         enqueueResponse(HTTP_OK, body);
-        return doCommonStandardEnqueue();
+        return doEnqueue(location);
     }
 
     /**
@@ -930,13 +952,17 @@
      * doing a standard enqueue request to the server.
      */
     protected long doCommonStandardEnqueue() throws Exception {
-        Uri uri = getServerUri(DEFAULT_FILENAME);
-        Request request = new Request(uri);
-        request.setTitle(DEFAULT_FILENAME);
+        return doEnqueue(DOWNLOAD_TO_DOWNLOAD_CACHE_DIR);
+    }
 
-        long dlRequest = mDownloadManager.enqueue(request);
-        Log.i(LOG_TAG, "request ID: " + dlRequest);
-        return dlRequest;
+    private long doEnqueue(int location) throws Exception {
+        Uri uri = getServerUri(DEFAULT_FILENAME);
+        Request request = new Request(uri).setTitle(DEFAULT_FILENAME);
+        if (location == DOWNLOAD_TO_SYSTEM_CACHE) {
+            request.setDestinationToSystemCache();
+        }
+
+        return mDownloadManager.enqueue(request);
     }
 
     /**
@@ -997,4 +1023,16 @@
         return cursor;
     }
 
+    /**
+     * Helper that does the actual basic download verification.
+     */
+    protected long doBasicDownload(byte[] blobData, int location) throws Exception {
+        long dlRequest = enqueueDownloadRequest(blobData, location);
+
+        // wait for the download to complete
+        waitForDownloadOrTimeout(dlRequest);
+
+        assertEquals(1, mReceiver.numDownloadsCompleted());
+        return dlRequest;
+    }
 }
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java b/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java
new file mode 100644
index 0000000..afe7f55
--- /dev/null
+++ b/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import coretestutils.http.MockResponse;
+
+import android.app.DownloadManager.Query;
+import android.app.DownloadManager.Request;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import java.io.File;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Integration tests of the DownloadManager API.
+ */
+public class DownloadManagerFunctionalTest extends DownloadManagerBaseTest {
+    private static final String TAG = "DownloadManagerFunctionalTest";
+    private final static String CACHE_DIR =
+            Environment.getDownloadCacheDirectory().getAbsolutePath();
+    private final static String PROHIBITED_DIRECTORY =
+            Environment.getRootDirectory().getAbsolutePath();
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        setWiFiStateOn(true);
+        mServer.play();
+        removeAllCurrentDownloads();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        setWiFiStateOn(true);
+        removeAllCurrentDownloads();
+
+        if (mReceiver != null) {
+            mContext.unregisterReceiver(mReceiver);
+            mReceiver = null;
+        }
+    }
+
+    /**
+     * Verifies a particular error code was received from a download
+     *
+     * @param uri The uri to enqueue to the DownloadManager
+     * @param error The error code expected
+     * @throws Exception if the test fails
+     */
+    public void doErrorTest(Uri uri, int error) throws Exception {
+        Request request = new Request(uri);
+        request.setTitle(DEFAULT_FILENAME);
+
+        long dlRequest = mDownloadManager.enqueue(request);
+        waitForDownloadOrTimeout(dlRequest);
+
+        Cursor cursor = getCursor(dlRequest);
+        try {
+            verifyInt(cursor, DownloadManager.COLUMN_REASON, error);
+        } finally {
+            cursor.close();
+        }
+    }
+
+    /**
+     * Test a basic download of a binary file 500k in size.
+     */
+    @LargeTest
+    public void testBinaryDownloadToSystemCache() throws Exception {
+        int fileSize = 1024;
+        byte[] blobData = generateData(fileSize, DataType.BINARY);
+
+        long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_SYSTEM_CACHE);
+        verifyDownload(dlRequest, blobData);
+        mDownloadManager.remove(dlRequest);
+    }
+
+    /**
+     * Tests the basic downloading of a text file 300000 bytes in size.
+     */
+    @LargeTest
+    public void testTextDownloadToSystemCache() throws Exception {
+        int fileSize = 1024;
+        byte[] blobData = generateData(fileSize, DataType.TEXT);
+
+        long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_SYSTEM_CACHE);
+        verifyDownload(dlRequest, blobData);
+        mDownloadManager.remove(dlRequest);
+    }
+    
+    /**
+     * Helper to verify a standard single-file download from the mock server, and clean up after
+     * verification
+     *
+     * Note that this also calls the Download manager's remove, which cleans up the file from cache.
+     *
+     * @param requestId The id of the download to remove
+     * @param fileData The data to verify the file contains
+     */
+    private void verifyDownload(long requestId, byte[] fileData)
+            throws Exception {
+        int fileSize = fileData.length;
+        ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(requestId);
+        Cursor cursor = mDownloadManager.query(new Query().setFilterById(requestId));
+        try {
+            assertEquals(1, cursor.getCount());
+            assertTrue(cursor.moveToFirst());
+
+            mServer.checkForExceptions();
+
+            verifyFileSize(pfd, fileSize);
+            verifyFileContents(pfd, fileData);
+            int colIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);
+            String fileName = cursor.getString(colIndex);
+            assertTrue(fileName.startsWith(CACHE_DIR));
+        } finally {
+            pfd.close();
+            cursor.close();
+        }
+    }
+
+    /**
+     * Tests trying to download to SD card when the file with same name already exists.
+     */
+    @LargeTest
+    public void testDownloadToExternal_fileExists() throws Exception {
+        File existentFile = createFileOnSD(null, 1, DataType.TEXT, null);
+        byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT);
+
+        // Prepare the mock server with a standard response
+        enqueueResponse(HTTP_OK, blobData);
+
+        try {
+            Uri uri = getServerUri(DEFAULT_FILENAME);
+            Request request = new Request(uri);
+
+            Uri localUri = Uri.fromFile(existentFile);
+            request.setDestinationUri(localUri);
+
+            long dlRequest = mDownloadManager.enqueue(request);
+
+            // wait for the download to complete
+            waitForDownloadOrTimeout(dlRequest);
+            Cursor cursor = getCursor(dlRequest);
+
+            try {
+                verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_SUCCESSFUL);
+            } finally {
+                cursor.close();
+            }
+        } finally {
+            existentFile.delete();
+        }
+    }
+
+    /**
+     * Tests trying to download a file to SD card.
+     */
+    @LargeTest
+    public void testDownloadToExternal() throws Exception {
+        String localDownloadDirectory = Environment.getExternalStorageDirectory().getPath();
+        File downloadedFile = new File(localDownloadDirectory, DEFAULT_FILENAME);
+        // make sure the file doesn't already exist in the directory
+        downloadedFile.delete();
+
+        try {
+            byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT);
+
+            // Prepare the mock server with a standard response
+            enqueueResponse(HTTP_OK, blobData);
+
+            Uri uri = getServerUri(DEFAULT_FILENAME);
+            Request request = new Request(uri);
+
+            Uri localUri = Uri.fromFile(downloadedFile);
+            request.setDestinationUri(localUri);
+
+            long dlRequest = mDownloadManager.enqueue(request);
+
+            // wait for the download to complete
+            waitForDownloadOrTimeout(dlRequest);
+
+            verifyAndCleanupSingleFileDownload(dlRequest, blobData);
+
+            assertEquals(1, mReceiver.numDownloadsCompleted());
+        } finally {
+            downloadedFile.delete();
+        }
+    }
+
+    /**
+     * Tests trying to download a file to the system partition.
+     */
+    @LargeTest
+    public void testDownloadToProhibitedDirectory() throws Exception {
+        File downloadedFile = new File(PROHIBITED_DIRECTORY, DEFAULT_FILENAME);
+        try {
+            byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT);
+
+            // Prepare the mock server with a standard response
+            enqueueResponse(HTTP_OK, blobData);
+
+            Uri uri = getServerUri(DEFAULT_FILENAME);
+            Request request = new Request(uri);
+
+            Uri localUri = Uri.fromFile(downloadedFile);
+            request.setDestinationUri(localUri);
+
+            try {
+                mDownloadManager.enqueue(request);
+                fail("Failed to throw SecurityException when trying to write to /system.");
+            } catch (SecurityException s) {
+                assertFalse(downloadedFile.exists());
+            }
+        } finally {
+            // Just in case file somehow got created, make sure to delete it
+            downloadedFile.delete();
+        }
+    }
+
+    /**
+     * Tests that we get the correct download ID from the download notification.
+     */
+    @LargeTest
+    public void testGetDownloadIdOnNotification() throws Exception {
+        byte[] blobData = generateData(3000, DataType.TEXT);  // file size = 3000 bytes
+
+        MockResponse response = enqueueResponse(HTTP_OK, blobData);
+        long dlRequest = doCommonStandardEnqueue();
+        waitForDownloadOrTimeout(dlRequest);
+
+        Set<Long> ids = mReceiver.getDownloadIds();
+        assertEquals(1, ids.size());
+        Iterator<Long> it = ids.iterator();
+        assertEquals("Download ID received from notification does not match initial id!",
+                dlRequest, it.next().longValue());
+    }
+
+    /**
+     * Tests the download failure error after too many redirects (>5).
+     */
+    @LargeTest
+    public void testErrorTooManyRedirects() throws Exception {
+        Uri uri = getServerUri(DEFAULT_FILENAME);
+
+        // force 6 redirects
+        for (int i = 0; i < 6; ++i) {
+            MockResponse response = enqueueResponse(HTTP_REDIRECT);
+            response.addHeader("Location", uri.toString());
+        }
+        doErrorTest(uri, DownloadManager.ERROR_TOO_MANY_REDIRECTS);
+    }
+
+    /**
+     * Tests the download failure error from an unhandled HTTP status code
+     */
+    @LargeTest
+    public void testErrorUnhandledHttpCode() throws Exception {
+        Uri uri = getServerUri(DEFAULT_FILENAME);
+        MockResponse response = enqueueResponse(HTTP_PARTIAL_CONTENT);
+
+        doErrorTest(uri, DownloadManager.ERROR_UNHANDLED_HTTP_CODE);
+    }
+
+    /**
+     * Tests the download failure error from an unhandled HTTP status code
+     */
+    @LargeTest
+    public void testErrorHttpDataError_invalidRedirect() throws Exception {
+        Uri uri = getServerUri(DEFAULT_FILENAME);
+        MockResponse response = enqueueResponse(HTTP_REDIRECT);
+        response.addHeader("Location", "://blah.blah.blah.com");
+
+        doErrorTest(uri, DownloadManager.ERROR_HTTP_DATA_ERROR);
+    }
+
+    /**
+     * Tests that we can remove a download from the download manager.
+     */
+    @LargeTest
+    public void testRemoveDownload() throws Exception {
+        int fileSize = 1024;
+        byte[] blobData = generateData(fileSize, DataType.BINARY);
+
+        long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR);
+        Cursor cursor = mDownloadManager.query(new Query().setFilterById(dlRequest));
+        try {
+            assertEquals("The count of downloads with this ID is not 1!", 1, cursor.getCount());
+            mDownloadManager.remove(dlRequest);
+            cursor.requery();
+            assertEquals("The count of downloads with this ID is not 0!", 0, cursor.getCount());
+        } finally {
+            cursor.close();
+        }
+    }
+
+    /**
+     * Tests that we can set the title of a download.
+     */
+    @LargeTest
+    public void testSetTitle() throws Exception {
+        int fileSize = 1024;
+        byte[] blobData = generateData(fileSize, DataType.BINARY);
+        MockResponse response = enqueueResponse(HTTP_OK, blobData);
+
+        // An arbitrary unicode string title
+        final String title = "\u00a5123;\"\u0152\u017d \u054b \u0a07 \ucce0 \u6820\u03a8\u5c34" +
+                "\uf4ad\u0da9\uc0c5\uc1a8 \uf4c5 \uf4aa\u0023\'";
+
+        Uri uri = getServerUri(DEFAULT_FILENAME);
+        Request request = new Request(uri);
+        request.setTitle(title);
+
+        long dlRequest = mDownloadManager.enqueue(request);
+        waitForDownloadOrTimeout(dlRequest);
+
+        Cursor cursor = getCursor(dlRequest);
+        try {
+            verifyString(cursor, DownloadManager.COLUMN_TITLE, title);
+        } finally {
+            cursor.close();
+        }
+    }
+
+    /**
+     * Tests that a download set for Wifi does not progress while Wifi is disabled, but resumes
+     * once Wifi is re-enabled.
+     */
+    @LargeTest
+    public void testDownloadNoWifi() throws Exception {
+        long timeout = 60 * 1000; // wait only 60 seconds before giving up
+        int fileSize = 1024;  // 140k
+        byte[] blobData = generateData(fileSize, DataType.TEXT);
+
+        setWiFiStateOn(false);
+        enqueueResponse(HTTP_OK, blobData);
+
+        try {
+            Uri uri = getServerUri(DEFAULT_FILENAME);
+            Request request = new Request(uri);
+            request.setAllowedNetworkTypes(Request.NETWORK_WIFI);
+
+            long dlRequest = mDownloadManager.enqueue(request);
+
+            // wait for the download to complete
+            boolean success = waitForDownloadOrTimeoutNoThrow(dlRequest,
+                    WAIT_FOR_DOWNLOAD_POLL_TIME, timeout);
+            assertFalse("Download proceeded without Wifi connection!", success);
+
+            setWiFiStateOn(true);
+            waitForDownloadOrTimeout(dlRequest);
+
+            assertEquals(1, mReceiver.numDownloadsCompleted());
+        } finally {
+            setWiFiStateOn(true);
+        }
+    }
+
+    /**
+     * Tests when the server drops the connection after all headers (but before any data send).
+     */
+    @LargeTest
+    public void testDropConnection_headers() throws Exception {
+        byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT);
+
+        MockResponse response = enqueueResponse(HTTP_OK, blobData);
+        response.setCloseConnectionAfterHeader("content-length");
+        long dlRequest = doCommonStandardEnqueue();
+
+        // Download will never complete when header is dropped
+        boolean success = waitForDownloadOrTimeoutNoThrow(dlRequest, DEFAULT_WAIT_POLL_TIME,
+                DEFAULT_MAX_WAIT_TIME);
+
+        assertFalse(success);
+    }
+
+    /**
+     * Tests that we get an error code when the server drops the connection during a download.
+     */
+    @LargeTest
+    public void testServerDropConnection_body() throws Exception {
+        byte[] blobData = generateData(25000, DataType.TEXT);  // file size = 25000 bytes
+
+        MockResponse response = enqueueResponse(HTTP_OK, blobData);
+        response.setCloseConnectionAfterXBytes(15382);
+        long dlRequest = doCommonStandardEnqueue();
+        waitForDownloadOrTimeout(dlRequest);
+
+        Cursor cursor = getCursor(dlRequest);
+        try {
+            verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_FAILED);
+            verifyInt(cursor, DownloadManager.COLUMN_REASON,
+                    DownloadManager.ERROR_CANNOT_RESUME);
+        } finally {
+            cursor.close();
+        }
+        // Even tho the server drops the connection, we should still get a completed notification
+        assertEquals(1, mReceiver.numDownloadsCompleted());
+    }
+}
diff --git a/core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java b/core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java
deleted file mode 100644
index 4f79108..0000000
--- a/core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.app.DownloadManager.Query;
-import android.app.DownloadManager.Request;
-import android.app.DownloadManagerBaseTest.DataType;
-import android.app.DownloadManagerBaseTest.MultipleDownloadsCompletedReceiver;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.database.Cursor;
-import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.os.Environment;
-import android.os.ParcelFileDescriptor;
-import android.os.StatFs;
-import android.os.SystemClock;
-import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Iterator;
-import java.util.Random;
-import java.util.Set;
-
-import junit.framework.AssertionFailedError;
-
-import coretestutils.http.MockResponse;
-import coretestutils.http.MockWebServer;
-
-/**
- * Integration tests of the DownloadManager API.
- */
-public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest {
-
-    private final static String LOG_TAG = "android.net.DownloadManagerIntegrationTest";
-    private final static String PROHIBITED_DIRECTORY =
-            Environment.getRootDirectory().getAbsolutePath();
-    private final static String CACHE_DIR =
-            Environment.getDownloadCacheDirectory().getAbsolutePath();
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        setWiFiStateOn(true);
-        mServer.play();
-        removeAllCurrentDownloads();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void tearDown() throws Exception {
-        super.tearDown();
-        setWiFiStateOn(true);
-        removeAllCurrentDownloads();
-
-        if (mReceiver != null) {
-            mContext.unregisterReceiver(mReceiver);
-            mReceiver = null;
-        }
-    }
-
-    /**
-     * Helper that does the actual basic download verification.
-     */
-    protected long doBasicDownload(byte[] blobData) throws Exception {
-        long dlRequest = doStandardEnqueue(blobData);
-
-        // wait for the download to complete
-        waitForDownloadOrTimeout(dlRequest);
-
-        assertEquals(1, mReceiver.numDownloadsCompleted());
-        return dlRequest;
-    }
-
-    /**
-     * Verifies a particular error code was received from a download
-     *
-     * @param uri The uri to enqueue to the DownloadManager
-     * @param error The error code expected
-     * @throws an Exception if the test fails
-     */
-    @LargeTest
-    public void doErrorTest(Uri uri, int error) throws Exception {
-        Request request = new Request(uri);
-        request.setTitle(DEFAULT_FILENAME);
-
-        long dlRequest = mDownloadManager.enqueue(request);
-        waitForDownloadOrTimeout(dlRequest);
-
-        Cursor cursor = getCursor(dlRequest);
-        try {
-            verifyInt(cursor, DownloadManager.COLUMN_REASON, error);
-        } finally {
-            cursor.close();
-        }
-    }
-
-    /**
-     * Test a basic download of a binary file 500k in size.
-     */
-    @LargeTest
-    public void testBasicBinaryDownload() throws Exception {
-        int fileSize = 500 * 1024;  // 500k
-        byte[] blobData = generateData(fileSize, DataType.BINARY);
-
-        long dlRequest = doBasicDownload(blobData);
-        verifyAndCleanupSingleFileDownload(dlRequest, blobData);
-    }
-
-    /**
-     * Tests the basic downloading of a text file 300000 bytes in size.
-     */
-    @LargeTest
-    public void testBasicTextDownload() throws Exception {
-        int fileSize = 300000;
-        byte[] blobData = generateData(fileSize, DataType.TEXT);
-
-        long dlRequest = doBasicDownload(blobData);
-        verifyAndCleanupSingleFileDownload(dlRequest, blobData);
-    }
-
-    /**
-     * Tests when the server drops the connection after all headers (but before any data send).
-     */
-    @LargeTest
-    public void testDropConnection_headers() throws Exception {
-        byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT);
-
-        MockResponse response = enqueueResponse(HTTP_OK, blobData);
-        response.setCloseConnectionAfterHeader("content-length");
-        long dlRequest = doCommonStandardEnqueue();
-
-        // Download will never complete when header is dropped
-        boolean success = waitForDownloadOrTimeoutNoThrow(dlRequest, DEFAULT_WAIT_POLL_TIME,
-                DEFAULT_MAX_WAIT_TIME);
-
-        assertFalse(success);
-    }
-
-    /**
-     * Tests that we get an error code when the server drops the connection during a download.
-     */
-    @LargeTest
-    public void testServerDropConnection_body() throws Exception {
-        byte[] blobData = generateData(25000, DataType.TEXT);  // file size = 25000 bytes
-
-        MockResponse response = enqueueResponse(HTTP_OK, blobData);
-        response.setCloseConnectionAfterXBytes(15382);
-        long dlRequest = doCommonStandardEnqueue();
-        waitForDownloadOrTimeout(dlRequest);
-
-        Cursor cursor = getCursor(dlRequest);
-        try {
-            verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_FAILED);
-            verifyInt(cursor, DownloadManager.COLUMN_REASON,
-                    DownloadManager.ERROR_CANNOT_RESUME);
-        } finally {
-            cursor.close();
-        }
-        // Even tho the server drops the connection, we should still get a completed notification
-        assertEquals(1, mReceiver.numDownloadsCompleted());
-    }
-
-    /**
-     * Attempts to download several files simultaneously
-     */
-    @LargeTest
-    public void testMultipleDownloads() throws Exception {
-        // need to be sure all current downloads have stopped first
-        removeAllCurrentDownloads();
-        int NUM_FILES = 10;
-        int MAX_FILE_SIZE = 500 * 1024; // 500 kb
-
-        Random r = new LoggingRng();
-        for (int i=0; i<NUM_FILES; ++i) {
-            int size = r.nextInt(MAX_FILE_SIZE);
-            byte[] blobData = generateData(size, DataType.TEXT);
-
-            Uri uri = getServerUri(DEFAULT_FILENAME + i);
-            Request request = new Request(uri);
-            request.setTitle(String.format("%s--%d", DEFAULT_FILENAME + i, i));
-
-            // Prepare the mock server with a standard response
-            enqueueResponse(HTTP_OK, blobData);
-
-            long requestID = mDownloadManager.enqueue(request);
-            Log.i(LOG_TAG, "request: " + i + " -- requestID: " + requestID);
-        }
-
-        waitForDownloadsOrTimeout(WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME);
-        Cursor cursor = mDownloadManager.query(new Query());
-        try {
-            assertEquals(NUM_FILES, cursor.getCount());
-
-            if (cursor.moveToFirst()) {
-                do {
-                    int status = cursor.getInt(cursor.getColumnIndex(
-                            DownloadManager.COLUMN_STATUS));
-                    String filename = cursor.getString(cursor.getColumnIndex(
-                            DownloadManager.COLUMN_URI));
-                    String errorString = String.format(
-                            "File %s failed to download successfully. Status code: %d",
-                            filename, status);
-                    assertEquals(errorString, DownloadManager.STATUS_SUCCESSFUL, status);
-                } while (cursor.moveToNext());
-            }
-
-            assertEquals(NUM_FILES, mReceiver.numDownloadsCompleted());
-        } finally {
-            Log.i(LOG_TAG, "All download IDs: " + mReceiver.getDownloadIds().toString());
-            Log.i(LOG_TAG, "Total downloads completed: " + mReceiver.getDownloadIds().size());
-            cursor.close();
-        }
-    }
-
-    /**
-     * Tests trying to download to SD card when the file with same name already exists.
-     */
-    @LargeTest
-    public void testDownloadToExternal_fileExists() throws Exception {
-        File existentFile = createFileOnSD(null, 1, DataType.TEXT, null);
-        byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT);
-
-        // Prepare the mock server with a standard response
-        enqueueResponse(HTTP_OK, blobData);
-
-        try {
-            Uri uri = getServerUri(DEFAULT_FILENAME);
-            Request request = new Request(uri);
-
-            Uri localUri = Uri.fromFile(existentFile);
-            Log.i(LOG_TAG, "setting localUri to: " + localUri.getPath());
-            request.setDestinationUri(localUri);
-
-            long dlRequest = mDownloadManager.enqueue(request);
-
-            // wait for the download to complete
-            waitForDownloadOrTimeout(dlRequest);
-            Cursor cursor = getCursor(dlRequest);
-
-            try {
-                verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_FAILED);
-                verifyInt(cursor, DownloadManager.COLUMN_REASON,
-                        DownloadManager.ERROR_FILE_ALREADY_EXISTS);
-            } finally {
-                cursor.close();
-            }
-        } finally {
-            existentFile.delete();
-        }
-    }
-
-    /**
-     * Tests trying to download a file to SD card.
-     */
-    @LargeTest
-    public void testDownloadToExternal() throws Exception {
-        String localDownloadDirectory = Environment.getExternalStorageDirectory().getPath();
-        File downloadedFile = new File(localDownloadDirectory, DEFAULT_FILENAME);
-        // make sure the file doesn't already exist in the directory
-        downloadedFile.delete();
-
-        try {
-            byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT);
-
-            // Prepare the mock server with a standard response
-            enqueueResponse(HTTP_OK, blobData);
-
-            Uri uri = getServerUri(DEFAULT_FILENAME);
-            Request request = new Request(uri);
-
-            Uri localUri = Uri.fromFile(downloadedFile);
-            Log.i(LOG_TAG, "setting localUri to: " + localUri.getPath());
-            request.setDestinationUri(localUri);
-
-            long dlRequest = mDownloadManager.enqueue(request);
-
-            // wait for the download to complete
-            waitForDownloadOrTimeout(dlRequest);
-
-            verifyAndCleanupSingleFileDownload(dlRequest, blobData);
-
-            assertEquals(1, mReceiver.numDownloadsCompleted());
-        } finally {
-            downloadedFile.delete();
-        }
-    }
-
-    /**
-     * Tests trying to download a file to the system partition.
-     */
-    @LargeTest
-    public void testDownloadToProhibitedDirectory() throws Exception {
-        File downloadedFile = new File(PROHIBITED_DIRECTORY, DEFAULT_FILENAME);
-        try {
-            byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT);
-
-            // Prepare the mock server with a standard response
-            enqueueResponse(HTTP_OK, blobData);
-
-            Uri uri = getServerUri(DEFAULT_FILENAME);
-            Request request = new Request(uri);
-
-            Uri localUri = Uri.fromFile(downloadedFile);
-            Log.i(LOG_TAG, "setting localUri to: " + localUri.getPath());
-            request.setDestinationUri(localUri);
-
-            try {
-                mDownloadManager.enqueue(request);
-                fail("Failed to throw SecurityException when trying to write to /system.");
-            } catch (SecurityException s) {
-                assertFalse(downloadedFile.exists());
-            }
-        } finally {
-            // Just in case file somehow got created, make sure to delete it
-            downloadedFile.delete();
-        }
-    }
-
-    /**
-     * Tests that a download set for Wifi does not progress while Wifi is disabled, but resumes
-     * once Wifi is re-enabled.
-     */
-    @LargeTest
-    public void testDownloadNoWifi() throws Exception {
-        long timeout = 60 * 1000; // wait only 60 seconds before giving up
-        int fileSize = 140 * 1024;  // 140k
-        byte[] blobData = generateData(fileSize, DataType.TEXT);
-
-        setWiFiStateOn(false);
-        enqueueResponse(HTTP_OK, blobData);
-
-        try {
-            Uri uri = getServerUri(DEFAULT_FILENAME);
-            Request request = new Request(uri);
-            request.setAllowedNetworkTypes(Request.NETWORK_WIFI);
-
-            long dlRequest = mDownloadManager.enqueue(request);
-
-            // wait for the download to complete
-            boolean success = waitForDownloadOrTimeoutNoThrow(dlRequest,
-                    WAIT_FOR_DOWNLOAD_POLL_TIME, timeout);
-            assertFalse("Download proceeded without Wifi connection!", success);
-
-            setWiFiStateOn(true);
-            waitForDownloadOrTimeout(dlRequest);
-
-            assertEquals(1, mReceiver.numDownloadsCompleted());
-        } finally {
-            setWiFiStateOn(true);
-        }
-    }
-
-    /**
-     * Tests downloading a file to cache when there isn't enough space in the cache to hold the
-     * entire file.
-     */
-    @LargeTest
-    public void testDownloadToCache_whenFull() throws Exception {
-        int DOWNLOAD_FILE_SIZE = 500000;
-
-        StatFs fs = new StatFs(CACHE_DIR);
-        Log.i(LOG_TAG, "getAvailableBlocks: " + fs.getAvailableBlocks());
-        Log.i(LOG_TAG, "getBlockSize: " + fs.getBlockSize());
-
-        int blockSize = fs.getBlockSize();
-        int availableBlocks = fs.getAvailableBlocks();
-        int availableBytes = blockSize * availableBlocks;
-        File outFile = null;
-
-        try {
-            // fill cache to ensure we don't have enough space - take half the size of the
-            // download size, and leave that much freespace left on the cache partition
-            if (DOWNLOAD_FILE_SIZE <= availableBytes) {
-                int writeSizeBytes = availableBytes - (DOWNLOAD_FILE_SIZE / 2);
-
-                int writeSizeBlocks = writeSizeBytes / blockSize;
-                int remainderSizeBlocks = availableBlocks - writeSizeBlocks;
-
-                FileOutputStream fo = null;
-                try {
-                    outFile = File.createTempFile("DM_TEST", null, new File(CACHE_DIR));
-                    Log.v(LOG_TAG, "writing " + writeSizeBlocks + " blocks to file "
-                            + outFile.getAbsolutePath());
-
-                    fo = new FileOutputStream(outFile);
-
-                    byte[] buffer = new byte[blockSize];
-                    while (fs.getAvailableBlocks() >= remainderSizeBlocks) {
-                        fo.write(buffer);
-                        fs.restat(CACHE_DIR);
-                    }
-                } catch (IOException e) {
-                    Log.e(LOG_TAG, "error filling file: ", e);
-                    throw e;
-                } finally {
-                    if (fo != null) {
-                        fo.close();
-                    }
-                }
-            }
-
-            Log.i(LOG_TAG, "Done creating filler file.");
-            assertTrue(DOWNLOAD_FILE_SIZE > (fs.getAvailableBlocks() * blockSize));
-            byte[] blobData = generateData(DOWNLOAD_FILE_SIZE, DataType.TEXT);
-            long dlRequest = doBasicDownload(blobData);
-            verifyAndCleanupSingleFileDownload(dlRequest, blobData);
-
-        } finally {
-            if (outFile != null) {
-                outFile.delete();
-            }
-        }
-    }
-
-    /**
-     * Tests that files are not deleted when DOWNLOAD_CACHE_NON_PURGEABLE is set, even if we've
-     * run out of space.
-     */
-    @LargeTest
-    public void testDownloadCacheNonPurgeable() throws Exception {
-        int fileSize = 10000000;
-        byte[] blobData = generateData(fileSize, DataType.BINARY);
-        long dlRequest = -1;
-
-        // Fill up the cache partition until there's not enough room for another download.
-        // Note that we need to initiate a download first, then check for the available space. This
-        // is b/c there could be some files that are still left in the cache that can (and will be)
-        // cleared out, but not until DM gets a request for a download and reclaims that
-        // space first.
-        boolean spaceAvailable = true;
-        while (spaceAvailable) {
-            dlRequest = doStandardEnqueue(blobData);
-            waitForDownloadOrTimeout(dlRequest);
-
-            // Check if we've filled up the cache yet
-            StatFs fs = new StatFs(CACHE_DIR);
-            Log.i(LOG_TAG, "getAvailableBlocks: " + fs.getAvailableBlocks());
-            Log.i(LOG_TAG, "getBlockSize: " + fs.getBlockSize());
-            int availableBytes = fs.getBlockSize() * fs.getAvailableBlocks();
-            spaceAvailable = (availableBytes > fileSize) ? true : false;
-        }
-
-        // Now add one more download (should not fit in the space left over)
-        dlRequest = doStandardEnqueue(blobData);
-        waitForDownloadOrTimeout(dlRequest);
-
-        // For the last download we should have failed b/c there is not enough space left in cache
-        Cursor cursor = getCursor(dlRequest);
-        try {
-            verifyInt(cursor, DownloadManager.COLUMN_REASON,
-                    DownloadManager.ERROR_INSUFFICIENT_SPACE);
-        } finally {
-            cursor.close();
-        }
-    }
-
-    /**
-     * Tests that we get the correct download ID from the download notification.
-     */
-    @LargeTest
-    public void testGetDownloadIdOnNotification() throws Exception {
-        byte[] blobData = generateData(3000, DataType.TEXT);  // file size = 3000 bytes
-
-        MockResponse response = enqueueResponse(HTTP_OK, blobData);
-        long dlRequest = doCommonStandardEnqueue();
-        waitForDownloadOrTimeout(dlRequest);
-
-        Set<Long> ids = mReceiver.getDownloadIds();
-        assertEquals(1, ids.size());
-        Iterator<Long> it = ids.iterator();
-        assertEquals("Download ID received from notification does not match initial id!",
-                dlRequest, it.next().longValue());
-    }
-
-    /**
-     * Tests the download failure error after too many redirects (>5).
-     */
-    @LargeTest
-    public void testErrorTooManyRedirects() throws Exception {
-        Uri uri = getServerUri(DEFAULT_FILENAME);
-
-        // force 6 redirects
-        for (int i = 0; i < 6; ++i) {
-            MockResponse response = enqueueResponse(HTTP_REDIRECT);
-            response.addHeader("Location", uri.toString());
-        }
-        doErrorTest(uri, DownloadManager.ERROR_TOO_MANY_REDIRECTS);
-    }
-
-    /**
-     * Tests the download failure error from an unhandled HTTP status code
-     */
-    @LargeTest
-    public void testErrorUnhandledHttpCode() throws Exception {
-        Uri uri = getServerUri(DEFAULT_FILENAME);
-        MockResponse response = enqueueResponse(HTTP_PARTIAL_CONTENT);
-
-        doErrorTest(uri, DownloadManager.ERROR_UNHANDLED_HTTP_CODE);
-    }
-
-    /**
-     * Tests the download failure error from an unhandled HTTP status code
-     */
-    @LargeTest
-    public void testErrorHttpDataError_invalidRedirect() throws Exception {
-        Uri uri = getServerUri(DEFAULT_FILENAME);
-        MockResponse response = enqueueResponse(HTTP_REDIRECT);
-        response.addHeader("Location", "://blah.blah.blah.com");
-
-        doErrorTest(uri, DownloadManager.ERROR_HTTP_DATA_ERROR);
-    }
-
-    /**
-     * Tests that we can remove a download from the download manager.
-     */
-    @LargeTest
-    public void testRemoveDownload() throws Exception {
-        int fileSize = 100 * 1024;  // 100k
-        byte[] blobData = generateData(fileSize, DataType.BINARY);
-
-        long dlRequest = doBasicDownload(blobData);
-        Cursor cursor = mDownloadManager.query(new Query().setFilterById(dlRequest));
-        try {
-            assertEquals("The count of downloads with this ID is not 1!", 1, cursor.getCount());
-            mDownloadManager.remove(dlRequest);
-            cursor.requery();
-            assertEquals("The count of downloads with this ID is not 0!", 0, cursor.getCount());
-        } finally {
-            cursor.close();
-        }
-    }
-
-    /**
-     * Tests that we can set the title of a download.
-     */
-    @LargeTest
-    public void testSetTitle() throws Exception {
-        int fileSize = 50 * 1024;  // 50k
-        byte[] blobData = generateData(fileSize, DataType.BINARY);
-        MockResponse response = enqueueResponse(HTTP_OK, blobData);
-
-        // An arbitrary unicode string title
-        final String title = "\u00a5123;\"\u0152\u017d \u054b \u0a07 \ucce0 \u6820\u03a8\u5c34" +
-                "\uf4ad\u0da9\uc0c5\uc1a8 \uf4c5 \uf4aa\u0023\'";
-
-        Uri uri = getServerUri(DEFAULT_FILENAME);
-        Request request = new Request(uri);
-        request.setTitle(title);
-
-        long dlRequest = mDownloadManager.enqueue(request);
-        waitForDownloadOrTimeout(dlRequest);
-
-        Cursor cursor = getCursor(dlRequest);
-        try {
-            verifyString(cursor, DownloadManager.COLUMN_TITLE, title);
-        } finally {
-            cursor.close();
-        }
-    }
-}
diff --git a/core/tests/coretests/src/android/app/DownloadManagerStressTest.java b/core/tests/coretests/src/android/app/DownloadManagerStressTest.java
index e0b28d0..bdeb554 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerStressTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerStressTest.java
@@ -16,19 +16,28 @@
 
 package android.app;
 
-import java.io.File;
-import java.util.Random;
-
 import android.app.DownloadManager.Query;
 import android.app.DownloadManager.Request;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.Environment;
 import android.os.ParcelFileDescriptor;
+import android.os.StatFs;
+import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
 
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Random;
 
+/**
+ * Integration tests of the DownloadManager API.
+ */
 public class DownloadManagerStressTest extends DownloadManagerBaseTest {
-    private static String LOG_TAG = "android.net.DownloadManagerStressTest";
+    private static final String TAG = "DownloadManagerStressTest";
+    private final static String CACHE_DIR =
+            Environment.getDownloadCacheDirectory().getAbsolutePath();
 
     /**
      * {@inheritDoc}
@@ -36,79 +45,83 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        mServer.play(0);
         setWiFiStateOn(true);
+        mServer.play();
         removeAllCurrentDownloads();
     }
 
     /**
-     * Attempts to downloading thousands of files simultaneously
+     * {@inheritDoc}
      */
-    public void testDownloadThousands() throws Exception {
-        int NUM_FILES = 1500;
-        int MAX_FILE_SIZE = 3000;
-        long[] reqs = new long[NUM_FILES];
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        setWiFiStateOn(true);
+        removeAllCurrentDownloads();
 
-        // need to be sure all current downloads have stopped first
-        MultipleDownloadsCompletedReceiver receiver = registerNewMultipleDownloadsReceiver();
-        Cursor cursor = null;
-        try {
-            Random r = new LoggingRng();
-            for (int i = 0; i < NUM_FILES; ++i) {
-                int size = r.nextInt(MAX_FILE_SIZE);
-                byte[] blobData = generateData(size, DataType.TEXT);
-
-                Uri uri = getServerUri(DEFAULT_FILENAME);
-                Request request = new Request(uri);
-                request.setTitle(String.format("%s--%d", DEFAULT_FILENAME, i));
-
-                // Prepare the mock server with a standard response
-                enqueueResponse(HTTP_OK, blobData);
-
-                Log.i(LOG_TAG, "issuing request: " + i);
-                long reqId = mDownloadManager.enqueue(request);
-                reqs[i] = reqId;
-            }
-
-            // wait for the download to complete or timeout
-            waitForDownloadsOrTimeout(WAIT_FOR_DOWNLOAD_POLL_TIME,
-                    MAX_WAIT_FOR_LARGE_DOWNLOAD_TIME);
-            cursor = mDownloadManager.query(new Query());
-            assertEquals(NUM_FILES, cursor.getCount());
-            Log.i(LOG_TAG, "Verified number of downloads in download manager is what we expect.");
-            while (cursor.moveToNext()) {
-                int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
-                String filename = cursor.getString(cursor.getColumnIndex(
-                        DownloadManager.COLUMN_URI));
-                String errorString = String.format("File %s failed to download successfully. " +
-                        "Status code: %d", filename, status);
-                assertEquals(errorString, DownloadManager.STATUS_SUCCESSFUL, status);
-            }
-            Log.i(LOG_TAG, "Verified each download was successful.");
-            assertEquals(NUM_FILES, receiver.numDownloadsCompleted());
-            Log.i(LOG_TAG, "Verified number of completed downloads in our receiver.");
-
-            // Verify that for each request, we can open the downloaded file
-            for (int i = 0; i < NUM_FILES; ++i) {
-                ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(reqs[i]);
-                pfd.close();
-            }
-            Log.i(LOG_TAG, "Verified we can open each file.");
-        } finally {
-            if (cursor != null) {
-                cursor.close();
-            }
-            mContext.unregisterReceiver(receiver);
-            removeAllCurrentDownloads();
+        if (mReceiver != null) {
+            mContext.unregisterReceiver(mReceiver);
+            mReceiver = null;
         }
     }
 
     /**
+     * Attempts to download several files simultaneously
+     */
+    @LargeTest
+    public void testMultipleDownloads() throws Exception {
+        // need to be sure all current downloads have stopped first
+        removeAllCurrentDownloads();
+        int NUM_FILES = 10;
+        int MAX_FILE_SIZE = 10 * 1024; // 10 kb
+
+        Random r = new LoggingRng();
+        for (int i=0; i<NUM_FILES; ++i) {
+            int size = r.nextInt(MAX_FILE_SIZE);
+            byte[] blobData = generateData(size, DataType.TEXT);
+
+            Uri uri = getServerUri(DEFAULT_FILENAME + i);
+            Request request = new Request(uri);
+            request.setTitle(String.format("%s--%d", DEFAULT_FILENAME + i, i));
+
+            // Prepare the mock server with a standard response
+            enqueueResponse(HTTP_OK, blobData);
+
+            long requestID = mDownloadManager.enqueue(request);
+        }
+
+        waitForDownloadsOrTimeout(WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME);
+        Cursor cursor = mDownloadManager.query(new Query());
+        try {
+            assertEquals(NUM_FILES, cursor.getCount());
+
+            if (cursor.moveToFirst()) {
+                do {
+                    int status = cursor.getInt(cursor.getColumnIndex(
+                            DownloadManager.COLUMN_STATUS));
+                    String filename = cursor.getString(cursor.getColumnIndex(
+                            DownloadManager.COLUMN_URI));
+                    String errorString = String.format(
+                            "File %s failed to download successfully. Status code: %d",
+                            filename, status);
+                    assertEquals(errorString, DownloadManager.STATUS_SUCCESSFUL, status);
+                } while (cursor.moveToNext());
+            }
+
+            assertEquals(NUM_FILES, mReceiver.numDownloadsCompleted());
+        } finally {
+            cursor.close();
+        }
+    }
+    /**
      * Tests trying to download a large file (50M bytes).
      */
+    @LargeTest
     public void testDownloadLargeFile() throws Exception {
         long fileSize = 50000000L;  // note: kept relatively small to not exceed /cache dir size
+        Log.i(TAG, "creating a file of size: " + fileSize);
         File largeFile = createFileOnSD(null, fileSize, DataType.TEXT, null);
+        Log.i(TAG, "DONE creating a file of size: " + fileSize);
         MultipleDownloadsCompletedReceiver receiver = registerNewMultipleDownloadsReceiver();
 
         try {
@@ -130,30 +143,63 @@
         }
     }
 
+
     /**
-     * Tests trying to download a large file (~600M bytes) when there's not enough space in cache
+     * Tests downloading a file to system cache when there isn't enough space in the system cache 
+     * to hold the entire file. DownloadManager deletes enough files to make space for the
+     * new download.
      */
-    public void testInsufficientSpace() throws Exception {
-        // @TODO: Rework this to fill up cache partition with a dynamically calculated size
-        long fileSize = 600000000L;
-        File largeFile = createFileOnSD(null, fileSize, DataType.TEXT, null);
+    @LargeTest
+    public void testDownloadToCacheWithAlmostFullCache() throws Exception {
+        int DOWNLOAD_FILE_SIZE = 1024 * 1024; // 1MB
 
-        Cursor cursor = null;
+        StatFs fs = new StatFs(CACHE_DIR);
+        int blockSize = fs.getBlockSize();
+        int availableBlocks = fs.getAvailableBlocks();
+        int availableBytes = blockSize * availableBlocks;
+        Log.i(TAG, "INITIAL stage, available space in /cache: " + availableBytes);
+        File outFile = File.createTempFile("DM_TEST", null, new File(CACHE_DIR));
+        byte[] buffer = new byte[blockSize];
+
         try {
-            long dlRequest = doStandardEnqueue(largeFile);
+            // fill cache to ensure we don't have enough space - take half the size of the
+            // download size, and leave that much freespace left on the cache partition
+            if (DOWNLOAD_FILE_SIZE <= availableBytes) {
+                int writeSizeBytes = availableBytes - (DOWNLOAD_FILE_SIZE / 2);
 
-             // wait for the download to complete
-            waitForDownloadOrTimeout(dlRequest);
+                int writeSizeBlocks = writeSizeBytes / blockSize;
+                int remainderSizeBlocks = availableBlocks - writeSizeBlocks;
 
-            cursor = getCursor(dlRequest);
-            verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_FAILED);
-            verifyInt(cursor, DownloadManager.COLUMN_REASON,
-                    DownloadManager.ERROR_INSUFFICIENT_SPACE);
-        } finally {
-            if (cursor != null) {
-                cursor.close();
+                FileOutputStream fo = null;
+                try {
+                    fo = new FileOutputStream(outFile);
+                    while (fs.getAvailableBlocks() >= remainderSizeBlocks) {
+                        fo.write(buffer);
+                        fs.restat(CACHE_DIR);
+                    }
+                } catch (IOException e) {
+                    Log.e(LOG_TAG, "error filling file: ", e);
+                    throw e;
+                } finally {
+                    if (fo != null) {
+                        fo.close();
+                    }
+                }
             }
-            largeFile.delete();
+
+            // /cache should now be almost full. 
+            long spaceAvailable = fs.getAvailableBlocks() * blockSize;
+            Log.i(TAG, "BEFORE download, available space in /cache: " + spaceAvailable);
+            assertTrue(DOWNLOAD_FILE_SIZE > spaceAvailable);
+
+            // try to download 1MB file into /cache - and it should succeed
+            byte[] blobData = generateData(DOWNLOAD_FILE_SIZE, DataType.TEXT);
+            long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_SYSTEM_CACHE);
+            verifyAndCleanupSingleFileDownload(dlRequest, blobData);
+        } finally {
+            if (outFile != null) {
+                outFile.delete();
+            }
         }
     }
 }
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
index 43cf06a..96b028a 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
@@ -19,6 +19,16 @@
 import android.content.Context;
 import android.test.InstrumentationTestCase;
 
+/**
+ * Stress test suite for Bluetooth related functions.
+ *
+ * Includes tests for enabling/disabling bluetooth, enabling/disabling discoverable mode,
+ * starting/stopping scans, connecting/disconnecting to HFP, A2DP, HID, PAN profiles, and verifying
+ * that remote connections/disconnections occur for the PAN profile.
+ * <p>
+ * This test suite uses {@link android.bluetooth.BluetoothTestRunner} to for parameters such as the
+ * number of iterations and the addresses of remote Bluetooth devices.
+ */
 public class BluetoothStressTest extends InstrumentationTestCase {
     private static final String TAG = "BluetoothStressTest";
     private static final String OUTPUT_FILE = "BluetoothStressTestOutput.txt";
@@ -40,6 +50,9 @@
         mTestUtils.close();
     }
 
+    /**
+     * Stress test for enabling and disabling Bluetooth.
+     */
     public void testEnable() {
         int iterations = BluetoothTestRunner.sEnableIterations;
         if (iterations == 0) {
@@ -55,6 +68,9 @@
         }
     }
 
+    /**
+     * Stress test for putting the device in and taking the device out of discoverable mode.
+     */
     public void testDiscoverable() {
         int iterations = BluetoothTestRunner.sDiscoverableIterations;
         if (iterations == 0) {
@@ -73,6 +89,9 @@
         mTestUtils.disable(adapter);
     }
 
+    /**
+     * Stress test for starting and stopping Bluetooth scans.
+     */
     public void testScan() {
         int iterations = BluetoothTestRunner.sScanIterations;
         if (iterations == 0) {
@@ -91,6 +110,30 @@
         mTestUtils.disable(adapter);
     }
 
+    /**
+     * Stress test for enabling and disabling the PAN NAP profile.
+     */
+    public void testEnablePan() {
+        int iterations = BluetoothTestRunner.sEnablePanIterations;
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        mTestUtils.enable(adapter);
+
+        for (int i = 0; i < iterations; i++) {
+            mTestUtils.writeOutput("testEnablePan iteration " + (i + 1) + " of "
+                    + iterations);
+            mTestUtils.enablePan(adapter);
+            mTestUtils.disablePan(adapter);
+        }
+
+        mTestUtils.disable(adapter);
+    }
+
+    /**
+     * Stress test for pairing and unpairing with a remote device.
+     * <p>
+     * In this test, the local device initiates pairing with a remote device, and then unpairs with
+     * the device after the pairing has successfully completed.
+     */
     public void testPair() {
         int iterations = BluetoothTestRunner.sPairIterations;
         if (iterations == 0) {
@@ -110,6 +153,12 @@
         mTestUtils.disable(adapter);
     }
 
+    /**
+     * Stress test for accepting a pairing request and unpairing with a remote device.
+     * <p>
+     * In this test, the local device waits for a pairing request from a remote device.  It accepts
+     * the request and then unpairs after the paring has successfully completed.
+     */
     public void testAcceptPair() {
         int iterations = BluetoothTestRunner.sPairIterations;
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -125,6 +174,12 @@
         mTestUtils.disable(adapter);
     }
 
+    /**
+     * Stress test for connecting and disconnecting with an A2DP source.
+     * <p>
+     * In this test, the local device plays the role of an A2DP sink, and initiates connections and
+     * disconnections with an A2DP source.
+     */
     public void testConnectA2dp() {
         int iterations = BluetoothTestRunner.sConnectA2dpIterations;
         if (iterations == 0) {
@@ -143,10 +198,16 @@
             mTestUtils.disconnectProfile(adapter, device, BluetoothProfile.A2DP);
         }
 
-        // TODO: Unpair from device if device can accept pairing after unpairing
+        mTestUtils.unpair(adapter, device);
         mTestUtils.disable(adapter);
     }
 
+    /**
+     * Stress test for connecting and disconnecting the HFP with a hands free device.
+     * <p>
+     * In this test, the local device plays the role of an HFP audio gateway, and initiates
+     * connections and disconnections with a hands free device.
+     */
     public void testConnectHeadset() {
         int iterations = BluetoothTestRunner.sConnectHeadsetIterations;
         if (iterations == 0) {
@@ -165,7 +226,94 @@
             mTestUtils.disconnectProfile(adapter, device, BluetoothProfile.HEADSET);
         }
 
-        // TODO: Unpair from device if device can accept pairing after unpairing
+        mTestUtils.unpair(adapter, device);
+        mTestUtils.disable(adapter);
+    }
+
+    /**
+     * Stress test for connecting and disconnecting with a HID device.
+     * <p>
+     * In this test, the local device plays the role of a HID host, and initiates connections and
+     * disconnections with a HID device.
+     */
+    public void testConnectInput() {
+        int iterations = BluetoothTestRunner.sConnectInputIterations;
+        if (iterations == 0) {
+            return;
+        }
+
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sInputAddress);
+        mTestUtils.enable(adapter);
+        mTestUtils.pair(adapter, device, BluetoothTestRunner.sPairPasskey,
+                BluetoothTestRunner.sPairPin);
+
+        for (int i = 0; i < iterations; i++) {
+            mTestUtils.writeOutput("connectInput iteration " + (i + 1) + " of " + iterations);
+            mTestUtils.connectInput(adapter, device);
+            mTestUtils.disconnectInput(adapter, device);
+        }
+
+        mTestUtils.unpair(adapter, device);
+        mTestUtils.disable(adapter);
+    }
+
+    /**
+     * Stress test for connecting and disconnecting with a PAN NAP.
+     * <p>
+     * In this test, the local device plays the role of a PANU, and initiates connections and
+     * disconnections with a NAP.
+     */
+    public void testConnectPan() {
+        int iterations = BluetoothTestRunner.sConnectPanIterations;
+        if (iterations == 0) {
+            return;
+        }
+
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sPanAddress);
+        mTestUtils.enable(adapter);
+        mTestUtils.pair(adapter, device, BluetoothTestRunner.sPairPasskey,
+                BluetoothTestRunner.sPairPin);
+
+        for (int i = 0; i < iterations; i++) {
+            mTestUtils.writeOutput("connectPan iteration " + (i + 1) + " of " + iterations);
+            mTestUtils.connectPan(adapter, device);
+            mTestUtils.disconnectPan(adapter, device);
+        }
+
+        mTestUtils.unpair(adapter, device);
+        mTestUtils.disable(adapter);
+    }
+
+    /**
+     * Stress test for verifying a PANU connecting and disconnecting with the device.
+     * <p>
+     * In this test, the local device plays the role of a NAP which a remote PANU connects and
+     * disconnects from.
+     */
+    public void testIncomingPanConnection() {
+        int iterations = BluetoothTestRunner.sConnectPanIterations;
+        if (iterations == 0) {
+            return;
+        }
+
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        BluetoothDevice device = adapter.getRemoteDevice(BluetoothTestRunner.sPanAddress);
+        mTestUtils.enable(adapter);
+        mTestUtils.enablePan(adapter);
+        mTestUtils.acceptPair(adapter, device, BluetoothTestRunner.sPairPasskey,
+                BluetoothTestRunner.sPairPin);
+
+        for (int i = 0; i < iterations; i++) {
+            mTestUtils.writeOutput("incomingPanConnection iteration " + (i + 1) + " of "
+                    + iterations);
+            mTestUtils.incomingPanConnection(adapter, device);
+            mTestUtils.incomingPanDisconnection(adapter, device);
+        }
+
+        mTestUtils.unpair(adapter, device);
+        mTestUtils.disablePan(adapter);
         mTestUtils.disable(adapter);
     }
 }
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java
index 3e589fc..cede05a 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestRunner.java
@@ -23,19 +23,51 @@
 import android.test.InstrumentationTestSuite;
 import android.util.Log;
 
+/**
+ * Instrumentation test runner for Bluetooth tests.
+ * <p>
+ * To run:
+ * <pre>
+ * {@code
+ * adb shell am instrument \
+ *     [-e enable_iterations <iterations>] \
+ *     [-e discoverable_iterations <iterations>] \
+ *     [-e scan_iterations <iterations>] \
+ *     [-e enable_pan_iterations <iterations>] \
+ *     [-e pair_iterations <iterations>] \
+ *     [-e connect_a2dp_iterations <iterations>] \
+ *     [-e connect_headset_iterations <iterations>] \
+ *     [-e connect_input_iterations <iterations>] \
+ *     [-e connect_pan_iterations <iterations>] \
+ *     [-e pair_address <address>] \
+ *     [-e headset_address <address>] \
+ *     [-e a2dp_address <address>] \
+ *     [-e input_address <address>] \
+ *     [-e pan_address <address>] \
+ *     [-e pair_pin <pin>] \
+ *     [-e pair_passkey <passkey>] \
+ *     -w com.android.frameworks.coretests/android.bluetooth.BluetoothTestRunner
+ * }
+ * </pre>
+ */
 public class BluetoothTestRunner extends InstrumentationTestRunner {
     private static final String TAG = "BluetoothTestRunner";
 
     public static int sEnableIterations = 100;
     public static int sDiscoverableIterations = 1000;
     public static int sScanIterations = 1000;
+    public static int sEnablePanIterations = 1000;
     public static int sPairIterations = 100;
     public static int sConnectHeadsetIterations = 100;
     public static int sConnectA2dpIterations = 100;
+    public static int sConnectInputIterations = 100;
+    public static int sConnectPanIterations = 100;
 
     public static String sPairAddress = "";
     public static String sHeadsetAddress = "";
     public static String sA2dpAddress = "";
+    public static String sInputAddress = "";
+    public static String sPanAddress = "";
 
     public static byte[] sPairPin = {'1', '2', '3', '4'};
     public static int sPairPasskey = 123456;
@@ -81,6 +113,15 @@
             }
         }
 
+        val = arguments.getString("enable_pan_iterations");
+        if (val != null) {
+            try {
+                sEnablePanIterations = Integer.parseInt(val);
+            } catch (NumberFormatException e) {
+                // Invalid argument, fall back to default value
+            }
+        }
+
         val = arguments.getString("pair_iterations");
         if (val != null) {
             try {
@@ -108,6 +149,24 @@
             }
         }
 
+        val = arguments.getString("connect_input_iterations");
+        if (val != null) {
+            try {
+                sConnectInputIterations = Integer.parseInt(val);
+            } catch (NumberFormatException e) {
+                // Invalid argument, fall back to default value
+            }
+        }
+
+        val = arguments.getString("connect_pan_iterations");
+        if (val != null) {
+            try {
+                sConnectPanIterations = Integer.parseInt(val);
+            } catch (NumberFormatException e) {
+                // Invalid argument, fall back to default value
+            }
+        }
+
         val = arguments.getString("pair_address");
         if (val != null) {
             sPairAddress = val;
@@ -123,6 +182,16 @@
             sA2dpAddress = val;
         }
 
+        val = arguments.getString("input_address");
+        if (val != null) {
+            sInputAddress = val;
+        }
+
+        val = arguments.getString("pan_address");
+        if (val != null) {
+            sPanAddress = val;
+        }
+
         val = arguments.getString("pair_pin");
         if (val != null) {
             sPairPin = BluetoothDevice.convertPinToBytes(val);
@@ -143,9 +212,13 @@
         Log.i(TAG, String.format("pair_iterations=%d", sPairIterations));
         Log.i(TAG, String.format("connect_a2dp_iterations=%d", sConnectA2dpIterations));
         Log.i(TAG, String.format("connect_headset_iterations=%d", sConnectHeadsetIterations));
+        Log.i(TAG, String.format("connect_input_iterations=%d", sConnectInputIterations));
+        Log.i(TAG, String.format("connect_pan_iterations=%d", sConnectPanIterations));
         Log.i(TAG, String.format("pair_address=%s", sPairAddress));
         Log.i(TAG, String.format("a2dp_address=%s", sA2dpAddress));
         Log.i(TAG, String.format("headset_address=%s", sHeadsetAddress));
+        Log.i(TAG, String.format("input_address=%s", sInputAddress));
+        Log.i(TAG, String.format("pan_address=%s", sPanAddress));
         Log.i(TAG, String.format("pair_pin=%s", new String(sPairPin)));
         Log.i(TAG, String.format("pair_passkey=%d", sPairPasskey));
 
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
index 6da38a7..effed76 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
@@ -35,49 +35,29 @@
 public class BluetoothTestUtils extends Assert {
 
     /**
-     * Timeout for {@link BluetoothAdapter#disable()} in ms.
+     * Timeout for enable/disable in ms.
      */
-    private static final int DISABLE_TIMEOUT = 20000;
+    private static final int ENABLE_DISABLE_TIMEOUT = 20000;
 
     /**
-     * Timeout for {@link BluetoothAdapter#enable()} in ms.
+     * Timeout for discoverable/undiscoverable in ms.
      */
-    private static final int ENABLE_TIMEOUT = 20000;
+    private static final int DISCOVERABLE_UNDISCOVERABLE_TIMEOUT = 5000;
 
     /**
-     * Timeout for {@link BluetoothAdapter#setScanMode(int)} in ms.
+     * Timeout for starting/stopping a scan in ms.
      */
-    private static final int SET_SCAN_MODE_TIMEOUT = 5000;
+    private static final int START_STOP_SCAN_TIMEOUT = 5000;
 
     /**
-     * Timeout for {@link BluetoothAdapter#startDiscovery()} in ms.
+     * Timeout for pair/unpair in ms.
      */
-    private static final int START_DISCOVERY_TIMEOUT = 5000;
+    private static final int PAIR_UNPAIR_TIMEOUT = 20000;
 
     /**
-     * Timeout for {@link BluetoothAdapter#cancelDiscovery()} in ms.
+     * Timeout for connecting/disconnecting a profile in ms.
      */
-    private static final int CANCEL_DISCOVERY_TIMEOUT = 5000;
-
-    /**
-     * Timeout for {@link BluetoothDevice#createBond()} in ms.
-     */
-    private static final int PAIR_TIMEOUT = 20000;
-
-    /**
-     * Timeout for {@link BluetoothDevice#removeBond()} in ms.
-     */
-    private static final int UNPAIR_TIMEOUT = 20000;
-
-    /**
-     * Timeout for {@link BluetoothProfile#connect(BluetoothDevice)} in ms.
-     */
-    private static final int CONNECT_PROFILE_TIMEOUT = 20000;
-
-    /**
-     * Timeout for {@link BluetoothProfile#disconnect(BluetoothDevice)} in ms.
-     */
-    private static final int DISCONNECT_PROFILE_TIMEOUT = 20000;
+    private static final int CONNECT_DISCONNECT_PROFILE_TIMEOUT = 20000;
 
     /**
      * Timeout to connect a profile proxy in ms.
@@ -265,7 +245,6 @@
 
         @Override
         public void onReceive(Context context, Intent intent) {
-
             if (mConnectionAction != null && mConnectionAction.equals(intent.getAction())) {
                 if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
                     return;
@@ -291,6 +270,91 @@
         }
     }
 
+    private class ConnectInputReceiver extends FlagReceiver {
+        private static final int STATE_DISCONNECTED_FLAG = 1;
+        private static final int STATE_CONNECTING_FLAG = 1 << 1;
+        private static final int STATE_CONNECTED_FLAG = 1 << 2;
+        private static final int STATE_DISCONNECTING_FLAG = 1 << 3;
+
+        private BluetoothDevice mDevice;
+
+        public ConnectInputReceiver(BluetoothDevice device, int expectedFlags) {
+            super(expectedFlags);
+
+            mDevice = device;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
+                return;
+            }
+
+            if (BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED.equals(intent.getAction())) {
+                int state = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, -1);
+                assertNotSame(-1, state);
+                switch (state) {
+                    case BluetoothInputDevice.STATE_DISCONNECTED:
+                        setFiredFlag(STATE_DISCONNECTED_FLAG);
+                        break;
+                    case BluetoothInputDevice.STATE_CONNECTING:
+                        setFiredFlag(STATE_CONNECTING_FLAG);
+                        break;
+                    case BluetoothInputDevice.STATE_CONNECTED:
+                        setFiredFlag(STATE_CONNECTED_FLAG);
+                        break;
+                    case BluetoothInputDevice.STATE_DISCONNECTING:
+                        setFiredFlag(STATE_DISCONNECTING_FLAG);
+                        break;
+                }
+            }
+        }
+    }
+
+    private class ConnectPanReceiver extends FlagReceiver {
+        private static final int STATE_DISCONNECTED_FLAG = 1;
+        private static final int STATE_CONNECTING_FLAG = 1 << 1;
+        private static final int STATE_CONNECTED_FLAG = 1 << 2;
+        private static final int STATE_DISCONNECTING_FLAG = 1 << 3;
+
+        private BluetoothDevice mDevice;
+        private int mRole;
+
+        public ConnectPanReceiver(BluetoothDevice device, int role, int expectedFlags) {
+            super (expectedFlags);
+
+            mDevice = device;
+            mRole = role;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))
+                    || mRole != intent.getIntExtra(BluetoothPan.EXTRA_LOCAL_ROLE, -1)) {
+                return;
+            }
+
+            if (BluetoothPan.ACTION_PAN_STATE_CHANGED.equals(intent.getAction())) {
+                int state = intent.getIntExtra(BluetoothPan.EXTRA_PAN_STATE, -1);
+                assertNotSame(-1, state);
+                switch (state) {
+                    case BluetoothPan.STATE_DISCONNECTED:
+                        setFiredFlag(STATE_DISCONNECTED_FLAG);
+                        break;
+                    case BluetoothPan.STATE_CONNECTING:
+                        setFiredFlag(STATE_CONNECTING_FLAG);
+                        break;
+                    case BluetoothPan.STATE_CONNECTED:
+                        setFiredFlag(STATE_CONNECTED_FLAG);
+                        break;
+                    case BluetoothPan.STATE_DISCONNECTING:
+                        setFiredFlag(STATE_DISCONNECTING_FLAG);
+                        break;
+                }
+            }
+        }
+    }
+
     private BluetoothProfile.ServiceListener mServiceListener =
             new BluetoothProfile.ServiceListener() {
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -330,10 +394,24 @@
     private BluetoothA2dp mA2dp;
     private BluetoothHeadset mHeadset;
 
+    /**
+     * Creates a utility instance for testing Bluetooth.
+     *
+     * @param context The context of the application using the utility.
+     * @param tag The log tag of the application using the utility.
+     */
     public BluetoothTestUtils(Context context, String tag) {
         this(context, tag, null);
     }
 
+    /**
+     * Creates a utility instance for testing Bluetooth.
+     *
+     * @param context The context of the application using the utility.
+     * @param tag The log tag of the application using the utility.
+     * @param outputFile The path to an output file if the utility is to write results to a
+     *        separate file.
+     */
     public BluetoothTestUtils(Context context, String tag, String outputFile) {
         mContext = context;
         mTag = tag;
@@ -352,6 +430,9 @@
         }
     }
 
+    /**
+     * Closes the utility instance and unregisters any BroadcastReceivers.
+     */
     public void close() {
         while (!mReceivers.isEmpty()) {
             mContext.unregisterReceiver(mReceivers.remove(0));
@@ -366,6 +447,12 @@
         }
     }
 
+    /**
+     * Enables Bluetooth and checks to make sure that Bluetooth was turned on and that the correct
+     * actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     */
     public void enable(BluetoothAdapter adapter) {
         int mask = (BluetoothReceiver.STATE_TURNING_ON_FLAG | BluetoothReceiver.STATE_ON_FLAG
                 | BluetoothReceiver.SCAN_MODE_CONNECTABLE_FLAG);
@@ -397,22 +484,19 @@
         }
 
         long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < ENABLE_TIMEOUT) {
+        while (System.currentTimeMillis() - s < ENABLE_DISABLE_TIMEOUT) {
             state = adapter.getState();
-            if (state == BluetoothAdapter.STATE_ON) {
+            if (state == BluetoothAdapter.STATE_ON
+                    && (receiver.getFiredFlags() & mask) == mask) {
                 assertTrue(adapter.isEnabled());
-                if ((receiver.getFiredFlags() & mask) == mask) {
-                    long finish = receiver.getCompletedTime();
-                    if (start != -1 && finish != -1) {
-                        writeOutput(String.format("enable() completed in %d ms", (finish - start)));
-                    } else {
-                        writeOutput("enable() completed");
-                    }
-                    removeReceiver(receiver);
-                    return;
+                long finish = receiver.getCompletedTime();
+                if (start != -1 && finish != -1) {
+                    writeOutput(String.format("enable() completed in %d ms", (finish - start)));
+                } else {
+                    writeOutput("enable() completed");
                 }
-            } else {
-                assertEquals(BluetoothAdapter.STATE_TURNING_ON, state);
+                removeReceiver(receiver);
+                return;
             }
             sleep(POLL_TIME);
         }
@@ -423,6 +507,12 @@
                 state, BluetoothAdapter.STATE_ON, firedFlags, mask));
     }
 
+    /**
+     * Disables Bluetooth and checks to make sure that Bluetooth was turned off and that the correct
+     * actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     */
     public void disable(BluetoothAdapter adapter) {
         int mask = (BluetoothReceiver.STATE_TURNING_OFF_FLAG | BluetoothReceiver.STATE_OFF_FLAG
                 | BluetoothReceiver.SCAN_MODE_NONE_FLAG);
@@ -454,23 +544,19 @@
         }
 
         long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < DISABLE_TIMEOUT) {
+        while (System.currentTimeMillis() - s < ENABLE_DISABLE_TIMEOUT) {
             state = adapter.getState();
-            if (state == BluetoothAdapter.STATE_OFF) {
+            if (state == BluetoothAdapter.STATE_OFF
+                    && (receiver.getFiredFlags() & mask) == mask) {
                 assertFalse(adapter.isEnabled());
-                if ((receiver.getFiredFlags() & mask) == mask) {
-                    long finish = receiver.getCompletedTime();
-                    if (start != -1 && finish != -1) {
-                        writeOutput(String.format("disable() completed in %d ms",
-                                (finish - start)));
-                    } else {
-                        writeOutput("disable() completed");
-                    }
-                    removeReceiver(receiver);
-                    return;
+                long finish = receiver.getCompletedTime();
+                if (start != -1 && finish != -1) {
+                    writeOutput(String.format("disable() completed in %d ms", (finish - start)));
+                } else {
+                    writeOutput("disable() completed");
                 }
-            } else {
-                assertEquals(BluetoothAdapter.STATE_TURNING_OFF, state);
+                removeReceiver(receiver);
+                return;
             }
             sleep(POLL_TIME);
         }
@@ -481,6 +567,12 @@
                 state, BluetoothAdapter.STATE_OFF, firedFlags, mask));
     }
 
+    /**
+     * Puts the local device into discoverable mode and checks to make sure that the local device
+     * is in discoverable mode and that the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     */
     public void discoverable(BluetoothAdapter adapter) {
         int mask = BluetoothReceiver.SCAN_MODE_CONNECTABLE_DISCOVERABLE_FLAG;
 
@@ -499,17 +591,14 @@
         long start = System.currentTimeMillis();
         assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE));
 
-        while (System.currentTimeMillis() - start < SET_SCAN_MODE_TIMEOUT) {
+        while (System.currentTimeMillis() - start < DISCOVERABLE_UNDISCOVERABLE_TIMEOUT) {
             scanMode = adapter.getScanMode();
-            if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
-                if ((receiver.getFiredFlags() & mask) == mask) {
-                    writeOutput(String.format("discoverable() completed in %d ms",
-                            (receiver.getCompletedTime() - start)));
-                    removeReceiver(receiver);
-                    return;
-                }
-            } else {
-                assertEquals(BluetoothAdapter.SCAN_MODE_CONNECTABLE, scanMode);
+            if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE
+                    && (receiver.getFiredFlags() & mask) == mask) {
+                writeOutput(String.format("discoverable() completed in %d ms",
+                        (receiver.getCompletedTime() - start)));
+                removeReceiver(receiver);
+                return;
             }
             sleep(POLL_TIME);
         }
@@ -521,6 +610,12 @@
                 firedFlags, mask));
     }
 
+    /**
+     * Puts the local device into connectable only mode and checks to make sure that the local
+     * device is in in connectable mode and that the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     */
     public void undiscoverable(BluetoothAdapter adapter) {
         int mask = BluetoothReceiver.SCAN_MODE_CONNECTABLE_FLAG;
 
@@ -539,17 +634,14 @@
         long start = System.currentTimeMillis();
         assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE));
 
-        while (System.currentTimeMillis() - start < SET_SCAN_MODE_TIMEOUT) {
+        while (System.currentTimeMillis() - start < DISCOVERABLE_UNDISCOVERABLE_TIMEOUT) {
             scanMode = adapter.getScanMode();
-            if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE) {
-                if ((receiver.getFiredFlags() & mask) == mask) {
-                    writeOutput(String.format("undiscoverable() completed in %d ms",
-                            (receiver.getCompletedTime() - start)));
-                    removeReceiver(receiver);
-                    return;
-                }
-            } else {
-                assertEquals(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, scanMode);
+            if (scanMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE
+                    && (receiver.getFiredFlags() & mask) == mask) {
+                writeOutput(String.format("undiscoverable() completed in %d ms",
+                        (receiver.getCompletedTime() - start)));
+                removeReceiver(receiver);
+                return;
             }
             sleep(POLL_TIME);
         }
@@ -561,6 +653,12 @@
                 mask));
     }
 
+    /**
+     * Starts a scan for remote devices and checks to make sure that the local device is scanning
+     * and that the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     */
     public void startScan(BluetoothAdapter adapter) {
         int mask = BluetoothReceiver.DISCOVERY_STARTED_FLAG;
 
@@ -577,7 +675,7 @@
         long start = System.currentTimeMillis();
         assertTrue(adapter.startDiscovery());
 
-        while (System.currentTimeMillis() - start < START_DISCOVERY_TIMEOUT) {
+        while (System.currentTimeMillis() - start < START_STOP_SCAN_TIMEOUT) {
             if (adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
                 writeOutput(String.format("startScan() completed in %d ms",
                         (receiver.getCompletedTime() - start)));
@@ -593,6 +691,12 @@
                 adapter.isDiscovering(), firedFlags, mask));
     }
 
+    /**
+     * Stops a scan for remote devices and checks to make sure that the local device is not scanning
+     * and that the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     */
     public void stopScan(BluetoothAdapter adapter) {
         int mask = BluetoothReceiver.DISCOVERY_FINISHED_FLAG;
 
@@ -610,7 +714,7 @@
         // TODO: put assertTrue() around cancelDiscovery() once it starts returning true.
         adapter.cancelDiscovery();
 
-        while (System.currentTimeMillis() - start < CANCEL_DISCOVERY_TIMEOUT) {
+        while (System.currentTimeMillis() - start < START_STOP_SCAN_TIMEOUT) {
             if (!adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
                 writeOutput(String.format("stopScan() completed in %d ms",
                         (receiver.getCompletedTime() - start)));
@@ -627,20 +731,84 @@
 
     }
 
+    /**
+     * Enables PAN tethering on the local device and checks to make sure that tethering is enabled.
+     *
+     * @param adapter The BT adapter.
+     */
+    public void enablePan(BluetoothAdapter adapter) {
+        BluetoothPan pan = new BluetoothPan(mContext);
+        assertNotNull(pan);
+
+        long start = System.currentTimeMillis();
+        pan.setBluetoothTethering(true);
+        long stop = System.currentTimeMillis();
+        assertTrue(pan.isTetheringOn());
+
+        writeOutput(String.format("enablePan() completed in %d ms", (stop - start)));
+    }
+
+    /**
+     * Disables PAN tethering on the local device and checks to make sure that tethering is
+     * disabled.
+     *
+     * @param adapter The BT adapter.
+     */
+    public void disablePan(BluetoothAdapter adapter) {
+        BluetoothPan pan = new BluetoothPan(mContext);
+        assertNotNull(pan);
+
+        long start = System.currentTimeMillis();
+        pan.setBluetoothTethering(false);
+        long stop = System.currentTimeMillis();
+        assertFalse(pan.isTetheringOn());
+
+        writeOutput(String.format("disablePan() completed in %d ms", (stop - start)));
+    }
+
+    /**
+     * Initiates a pairing with a remote device and checks to make sure that the devices are paired
+     * and that the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
+     * @param pin The pairing pin if pairing requires a pin. Any value if not.
+     */
     public void pair(BluetoothAdapter adapter, BluetoothDevice device, int passkey, byte[] pin) {
         pairOrAcceptPair(adapter, device, passkey, pin, true);
     }
 
+    /**
+     * Accepts a pairing with a remote device and checks to make sure that the devices are paired
+     * and that the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
+     * @param pin The pairing pin if pairing requires a pin. Any value if not.
+     */
     public void acceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
             byte[] pin) {
         pairOrAcceptPair(adapter, device, passkey, pin, false);
     }
 
+    /**
+     * Helper method used by {@link #pair(BluetoothAdapter, BluetoothDevice, int, byte[])} and
+     * {@link #acceptPair(BluetoothAdapter, BluetoothDevice, int, byte[])} to either pair or accept
+     * a pairing request.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     * @param passkey The pairing passkey if pairing requires a passkey. Any value if not.
+     * @param pin The pairing pin if pairing requires a pin. Any value if not.
+     * @param shouldPair Whether to pair or accept the pair.
+     */
     private void pairOrAcceptPair(BluetoothAdapter adapter, BluetoothDevice device, int passkey,
-            byte[] pin, boolean pair) {
+            byte[] pin, boolean shouldPair) {
         int mask = PairReceiver.STATE_BONDING_FLAG | PairReceiver.STATE_BONDED_FLAG;
         long start = -1;
-        String methodName = pair ? "pair()" : "acceptPair()";
+        String methodName = shouldPair ? "pair()" : "acceptPair()";
 
         if (!adapter.isEnabled()) {
             fail(methodName + " bluetooth not enabled");
@@ -653,7 +821,7 @@
             case BluetoothDevice.BOND_NONE:
                 assertFalse(adapter.getBondedDevices().contains(device));
                 start = System.currentTimeMillis();
-                if (pair) {
+                if (shouldPair) {
                     assertTrue(device.createBond());
                 }
                 break;
@@ -670,21 +838,19 @@
         }
 
         long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < PAIR_TIMEOUT) {
+        while (System.currentTimeMillis() - s < PAIR_UNPAIR_TIMEOUT) {
             state = device.getBondState();
-            if (state == BluetoothDevice.BOND_BONDED) {
+            if (state == BluetoothDevice.BOND_BONDED && (receiver.getFiredFlags() & mask) == mask) {
                 assertTrue(adapter.getBondedDevices().contains(device));
-                if ((receiver.getFiredFlags() & mask) == mask) {
-                    long finish = receiver.getCompletedTime();
-                    if (start != -1 && finish != -1) {
-                        writeOutput(String.format("%s completed in %d ms: device=%s", methodName,
-                                (finish - start), device));
-                    } else {
-                        writeOutput(String.format("%s completed: device=%s", methodName, device));
-                    }
-                    removeReceiver(receiver);
-                    return;
+                long finish = receiver.getCompletedTime();
+                if (start != -1 && finish != -1) {
+                    writeOutput(String.format("%s completed in %d ms: device=%s", methodName,
+                            (finish - start), device));
+                } else {
+                    writeOutput(String.format("%s completed: device=%s", methodName, device));
                 }
+                removeReceiver(receiver);
+                return;
             }
             sleep(POLL_TIME);
         }
@@ -696,6 +862,13 @@
                 BluetoothDevice.BOND_BONDED, firedFlags, mask));
     }
 
+    /**
+     * Deletes a pairing with a remote device and checks to make sure that the devices are unpaired
+     * and that the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     */
     public void unpair(BluetoothAdapter adapter, BluetoothDevice device) {
         int mask = PairReceiver.STATE_NONE_FLAG;
         long start = -1;
@@ -727,20 +900,19 @@
         }
 
         long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < UNPAIR_TIMEOUT) {
-            if (device.getBondState() == BluetoothDevice.BOND_NONE) {
+        while (System.currentTimeMillis() - s < PAIR_UNPAIR_TIMEOUT) {
+            if (device.getBondState() == BluetoothDevice.BOND_NONE
+                    && (receiver.getFiredFlags() & mask) == mask) {
                 assertFalse(adapter.getBondedDevices().contains(device));
-                if ((receiver.getFiredFlags() & mask) == mask) {
-                    long finish = receiver.getCompletedTime();
-                    if (start != -1 && finish != -1) {
-                        writeOutput(String.format("unpair() completed in %d ms: device=%s",
-                                (finish - start), device));
-                    } else {
-                        writeOutput(String.format("unpair() completed: device=%s", device));
-                    }
-                    removeReceiver(receiver);
-                    return;
+                long finish = receiver.getCompletedTime();
+                if (start != -1 && finish != -1) {
+                    writeOutput(String.format("unpair() completed in %d ms: device=%s",
+                            (finish - start), device));
+                } else {
+                    writeOutput(String.format("unpair() completed: device=%s", device));
                 }
+                removeReceiver(receiver);
+                return;
             }
         }
 
@@ -751,6 +923,15 @@
                 firedFlags, mask));
     }
 
+    /**
+     * Connects a profile from the local device to a remote device and checks to make sure that the
+     * profile is connected and that the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     * @param profile The profile to connect. One of {@link BluetoothProfile#A2DP} or
+     *        {@link BluetoothProfile#HEADSET}.
+     */
     public void connectProfile(BluetoothAdapter adapter, BluetoothDevice device, int profile) {
         int mask = (ConnectProfileReceiver.STATE_CONNECTING_FLAG
                 | ConnectProfileReceiver.STATE_CONNECTED_FLAG);
@@ -794,21 +975,20 @@
         }
 
         long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < CONNECT_PROFILE_TIMEOUT) {
+        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
             state = proxy.getConnectionState(device);
-            if (state == BluetoothProfile.STATE_CONNECTED) {
-                if ((receiver.getFiredFlags() & mask) == mask) {
-                    long finish = receiver.getCompletedTime();
-                    if (start != -1 && finish != -1) {
-                        writeOutput(String.format("connectProfile() completed in %d ms: "
-                                + "device=%s, profile=%d", (finish - start), device, profile));
-                    } else {
-                        writeOutput(String.format("connectProfile() completed: device=%s, "
-                                + "profile=%d", device, profile));
-                    }
-                    removeReceiver(receiver);
-                    return;
+            if (state == BluetoothProfile.STATE_CONNECTED
+                    && (receiver.getFiredFlags() & mask) == mask) {
+                long finish = receiver.getCompletedTime();
+                if (start != -1 && finish != -1) {
+                    writeOutput(String.format("connectProfile() completed in %d ms: "
+                            + "device=%s, profile=%d", (finish - start), device, profile));
+                } else {
+                    writeOutput(String.format("connectProfile() completed: device=%s, "
+                            + "profile=%d", device, profile));
                 }
+                removeReceiver(receiver);
+                return;
             }
             sleep(POLL_TIME);
         }
@@ -820,6 +1000,15 @@
                 BluetoothProfile.STATE_CONNECTED, firedFlags, mask));
     }
 
+    /**
+     * Disconnects a profile between the local device and a remote device and checks to make sure
+     * that the profile is disconnected and that the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     * @param profile The profile to disconnect. One of {@link BluetoothProfile#A2DP} or
+     *        {@link BluetoothProfile#HEADSET}.
+     */
     public void disconnectProfile(BluetoothAdapter adapter, BluetoothDevice device, int profile) {
         int mask = (ConnectProfileReceiver.STATE_DISCONNECTING_FLAG
                 | ConnectProfileReceiver.STATE_DISCONNECTED_FLAG);
@@ -863,21 +1052,20 @@
         }
 
         long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < DISCONNECT_PROFILE_TIMEOUT) {
+        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
             state = proxy.getConnectionState(device);
-            if (state == BluetoothProfile.STATE_DISCONNECTED) {
-                if ((receiver.getFiredFlags() & mask) == mask) {
-                    long finish = receiver.getCompletedTime();
-                    if (start != -1 && finish != -1) {
-                        writeOutput(String.format("disconnectProfile() completed in %d ms: "
-                                + "device=%s, profile=%d", (finish - start), device, profile));
-                    } else {
-                        writeOutput(String.format("disconnectProfile() completed: device=%s, "
-                                + "profile=%d", device, profile));
-                    }
-                    removeReceiver(receiver);
-                    return;
+            if (state == BluetoothProfile.STATE_DISCONNECTED
+                    && (receiver.getFiredFlags() & mask) == mask) {
+                long finish = receiver.getCompletedTime();
+                if (start != -1 && finish != -1) {
+                    writeOutput(String.format("disconnectProfile() completed in %d ms: "
+                            + "device=%s, profile=%d", (finish - start), device, profile));
+                } else {
+                    writeOutput(String.format("disconnectProfile() completed: device=%s, "
+                            + "profile=%d", device, profile));
                 }
+                removeReceiver(receiver);
+                return;
             }
             sleep(POLL_TIME);
         }
@@ -889,6 +1077,360 @@
                 BluetoothProfile.STATE_DISCONNECTED, firedFlags, mask));
     }
 
+    /**
+     * Connects the local device with a remote HID device and checks to make sure that the profile
+     * is connected and that the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     */
+    public void connectInput(BluetoothAdapter adapter, BluetoothDevice device) {
+        int mask = (ConnectInputReceiver.STATE_CONNECTING_FLAG
+                | ConnectInputReceiver.STATE_CONNECTED_FLAG);
+        long start = -1;
+
+        if (!adapter.isEnabled()) {
+            fail(String.format("connectInput() bluetooth not enabled: device=%s", device));
+        }
+
+        if (!adapter.getBondedDevices().contains(device)) {
+            fail(String.format("connectInput() device not paired: device=%s", device));
+        }
+
+        BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext);
+        assertNotNull(inputDevice);
+        ConnectInputReceiver receiver = getConnectInputReceiver(device, mask);
+
+        int state = inputDevice.getInputDeviceState(device);
+        switch (state) {
+            case BluetoothInputDevice.STATE_CONNECTED:
+                removeReceiver(receiver);
+                return;
+            case BluetoothInputDevice.STATE_CONNECTING:
+                mask = 0; // Don't check for received intents since we might have missed them.
+                break;
+            case BluetoothInputDevice.STATE_DISCONNECTED:
+            case BluetoothInputDevice.STATE_DISCONNECTING:
+                start = System.currentTimeMillis();
+                assertTrue(inputDevice.connectInputDevice(device));
+                break;
+            default:
+                removeReceiver(receiver);
+                fail(String.format("connectInput() invalid state: device=%s, state=%d", device,
+                        state));
+        }
+
+        long s = System.currentTimeMillis();
+        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
+            state = inputDevice.getInputDeviceState(device);
+            if (state == BluetoothInputDevice.STATE_CONNECTED
+                    && (receiver.getFiredFlags() & mask) == mask) {
+                long finish = receiver.getCompletedTime();
+                if (start != -1 && finish != -1) {
+                    writeOutput(String.format("connectInput() completed in %d ms: device=%s",
+                            (finish - start), device));
+                } else {
+                    writeOutput(String.format("connectInput() completed: device=%s", device));
+                }
+                removeReceiver(receiver);
+                return;
+            }
+            sleep(POLL_TIME);
+        }
+
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
+        fail(String.format("connectInput() timeout: device=%s, state=%d (expected %d), "
+                + "flags=0x%x (expected 0x%s)", device, state, BluetoothInputDevice.STATE_CONNECTED,
+                firedFlags, mask));
+    }
+
+    /**
+     * Disconnects the local device with a remote HID device and checks to make sure that the
+     * profile is connected and that the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     */
+    public void disconnectInput(BluetoothAdapter adapter, BluetoothDevice device) {
+        int mask = (ConnectInputReceiver.STATE_DISCONNECTING_FLAG
+                | ConnectInputReceiver.STATE_DISCONNECTED_FLAG);
+        long start = -1;
+
+        if (!adapter.isEnabled()) {
+            fail(String.format("disconnectInput() bluetooth not enabled: device=%s", device));
+        }
+
+        if (!adapter.getBondedDevices().contains(device)) {
+            fail(String.format("disconnectInput() device not paired: device=%s", device));
+        }
+
+        BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext);
+        assertNotNull(inputDevice);
+        ConnectInputReceiver receiver = getConnectInputReceiver(device, mask);
+
+        int state = inputDevice.getInputDeviceState(device);
+        switch (state) {
+            case BluetoothInputDevice.STATE_CONNECTED:
+            case BluetoothInputDevice.STATE_CONNECTING:
+                start = System.currentTimeMillis();
+                assertTrue(inputDevice.disconnectInputDevice(device));
+                break;
+            case BluetoothInputDevice.STATE_DISCONNECTED:
+                removeReceiver(receiver);
+                return;
+            case BluetoothInputDevice.STATE_DISCONNECTING:
+                mask = 0; // Don't check for received intents since we might have missed them.
+                break;
+            default:
+                removeReceiver(receiver);
+                fail(String.format("disconnectInput() invalid state: device=%s, state=%d", device,
+                        state));
+        }
+
+        long s = System.currentTimeMillis();
+        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
+            state = inputDevice.getInputDeviceState(device);
+            if (state == BluetoothInputDevice.STATE_DISCONNECTED
+                    && (receiver.getFiredFlags() & mask) == mask) {
+                long finish = receiver.getCompletedTime();
+                if (start != -1 && finish != -1) {
+                    writeOutput(String.format("disconnectInput() completed in %d ms: device=%s",
+                            (finish - start), device));
+                } else {
+                    writeOutput(String.format("disconnectInput() completed: device=%s", device));
+                }
+                removeReceiver(receiver);
+                return;
+            }
+            sleep(POLL_TIME);
+        }
+
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
+        fail(String.format("disconnectInput() timeout: device=%s, state=%d (expected %d), "
+                + "flags=0x%x (expected 0x%s)", device, state,
+                BluetoothInputDevice.STATE_DISCONNECTED, firedFlags, mask));
+    }
+
+    /**
+     * Connects the PANU to a remote NAP and checks to make sure that the PANU is connected and that
+     * the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     */
+    public void connectPan(BluetoothAdapter adapter, BluetoothDevice device) {
+        connectPanOrIncomingPanConnection(adapter, device, true);
+    }
+
+    /**
+     * Checks that a remote PANU connects to the local NAP correctly and that the correct actions
+     * were broadcast.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     */
+    public void incomingPanConnection(BluetoothAdapter adapter, BluetoothDevice device) {
+        connectPanOrIncomingPanConnection(adapter, device, false);
+    }
+
+    /**
+     * Helper method used by {@link #connectPan(BluetoothAdapter, BluetoothDevice)} and
+     * {@link #incomingPanConnection(BluetoothAdapter, BluetoothDevice)} to either connect to a
+     * remote NAP or verify that a remote device connected to the local NAP.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     * @param connect If the method should initiate the connection (is PANU)
+     */
+    private void connectPanOrIncomingPanConnection(BluetoothAdapter adapter, BluetoothDevice device,
+            boolean connect) {
+        long start = -1;
+        int mask, role;
+        String methodName;
+
+        if (connect) {
+            methodName = "connectPan()";
+            mask = (ConnectPanReceiver.STATE_CONNECTED_FLAG |
+                    ConnectPanReceiver.STATE_CONNECTING_FLAG);
+            role = BluetoothPan.LOCAL_PANU_ROLE;
+        } else {
+            methodName = "incomingPanConnection()";
+            mask = ConnectPanReceiver.STATE_CONNECTED_FLAG;
+            role = BluetoothPan.LOCAL_NAP_ROLE;
+        }
+
+        if (!adapter.isEnabled()) {
+            fail(String.format("%s bluetooth not enabled: device=%s", methodName, device));
+        }
+
+        if (!adapter.getBondedDevices().contains(device)) {
+            fail(String.format("%s device not paired: device=%s", methodName, device));
+        }
+
+        BluetoothPan pan = new BluetoothPan(mContext);
+        assertNotNull(pan);
+        ConnectPanReceiver receiver = getConnectPanReceiver(device, role, mask);
+
+        int state = pan.getPanDeviceState(device);
+        switch (state) {
+            case BluetoothPan.STATE_CONNECTED:
+                removeReceiver(receiver);
+                return;
+            case BluetoothPan.STATE_CONNECTING:
+                mask = 0; // Don't check for received intents since we might have missed them.
+                break;
+            case BluetoothPan.STATE_DISCONNECTED:
+            case BluetoothPan.STATE_DISCONNECTING:
+                start = System.currentTimeMillis();
+                if (role == BluetoothPan.LOCAL_PANU_ROLE) {
+                    Log.i("BT", "connect to pan");
+                    assertTrue(pan.connect(device));
+                }
+                break;
+            default:
+                removeReceiver(receiver);
+                fail(String.format("%s invalid state: device=%s, state=%d", methodName, device,
+                        state));
+        }
+
+        long s = System.currentTimeMillis();
+        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
+            state = pan.getPanDeviceState(device);
+            if (state == BluetoothPan.STATE_CONNECTED
+                    && (receiver.getFiredFlags() & mask) == mask) {
+                long finish = receiver.getCompletedTime();
+                if (start != -1 && finish != -1) {
+                    writeOutput(String.format("%s completed in %d ms: device=%s", methodName,
+                            (finish - start), device));
+                } else {
+                    writeOutput(String.format("%s completed: device=%s", methodName, device));
+                }
+                removeReceiver(receiver);
+                return;
+            }
+            sleep(POLL_TIME);
+        }
+
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
+        fail(String.format("%s timeout: device=%s, state=%d (expected %d), "
+                + "flags=0x%x (expected 0x%s)", methodName, device, state,
+                BluetoothPan.STATE_CONNECTED, firedFlags, mask));
+    }
+
+    /**
+     * Disconnects the PANU from a remote NAP and checks to make sure that the PANU is disconnected
+     * and that the correct actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     */
+    public void disconnectPan(BluetoothAdapter adapter, BluetoothDevice device) {
+        disconnectFromRemoteOrVerifyConnectNap(adapter, device, true);
+    }
+
+    /**
+     * Checks that a remote PANU disconnects from the local NAP correctly and that the correct
+     * actions were broadcast.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     */
+    public void incomingPanDisconnection(BluetoothAdapter adapter, BluetoothDevice device) {
+        disconnectFromRemoteOrVerifyConnectNap(adapter, device, false);
+    }
+
+    /**
+     * Helper method used by {@link #disconnectPan(BluetoothAdapter, BluetoothDevice)} and
+     * {@link #incomingPanDisconnection(BluetoothAdapter, BluetoothDevice)} to either disconnect
+     * from a remote NAP or verify that a remote device disconnected from the local NAP.
+     *
+     * @param adapter The BT adapter.
+     * @param device The remote device.
+     * @param disconnect Whether the method should connect or verify.
+     */
+    private void disconnectFromRemoteOrVerifyConnectNap(BluetoothAdapter adapter,
+            BluetoothDevice device, boolean disconnect) {
+        long start = -1;
+        int mask, role;
+        String methodName;
+
+        if (disconnect) {
+            methodName = "disconnectPan()";
+            mask = (ConnectPanReceiver.STATE_DISCONNECTED_FLAG |
+                    ConnectPanReceiver.STATE_DISCONNECTING_FLAG);
+            role = BluetoothPan.LOCAL_PANU_ROLE;
+        } else {
+            methodName = "incomingPanDisconnection()";
+            mask = ConnectPanReceiver.STATE_DISCONNECTED_FLAG;
+            role = BluetoothPan.LOCAL_NAP_ROLE;
+        }
+
+        if (!adapter.isEnabled()) {
+            fail(String.format("%s bluetooth not enabled: device=%s", methodName, device));
+        }
+
+        if (!adapter.getBondedDevices().contains(device)) {
+            fail(String.format("%s device not paired: device=%s", methodName, device));
+        }
+
+        BluetoothPan pan = new BluetoothPan(mContext);
+        assertNotNull(pan);
+        ConnectPanReceiver receiver = getConnectPanReceiver(device, role, mask);
+
+        int state = pan.getPanDeviceState(device);
+        switch (state) {
+            case BluetoothInputDevice.STATE_CONNECTED:
+            case BluetoothInputDevice.STATE_CONNECTING:
+                start = System.currentTimeMillis();
+                if (role == BluetoothPan.LOCAL_PANU_ROLE) {
+                    assertTrue(pan.disconnect(device));
+                }
+                break;
+            case BluetoothInputDevice.STATE_DISCONNECTED:
+                removeReceiver(receiver);
+                return;
+            case BluetoothInputDevice.STATE_DISCONNECTING:
+                mask = 0; // Don't check for received intents since we might have missed them.
+                break;
+            default:
+                removeReceiver(receiver);
+                fail(String.format("%s invalid state: device=%s, state=%d", methodName, device,
+                        state));
+        }
+
+        long s = System.currentTimeMillis();
+        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
+            state = pan.getPanDeviceState(device);
+            if (state == BluetoothInputDevice.STATE_DISCONNECTED
+                    && (receiver.getFiredFlags() & mask) == mask) {
+                long finish = receiver.getCompletedTime();
+                if (start != -1 && finish != -1) {
+                    writeOutput(String.format("%s completed in %d ms: device=%s", methodName,
+                            (finish - start), device));
+                } else {
+                    writeOutput(String.format("%s completed: device=%s", methodName, device));
+                }
+                removeReceiver(receiver);
+                return;
+            }
+            sleep(POLL_TIME);
+        }
+
+        int firedFlags = receiver.getFiredFlags();
+        removeReceiver(receiver);
+        fail(String.format("%s timeout: device=%s, state=%d (expected %d), "
+                + "flags=0x%x (expected 0x%s)", methodName, device, state,
+                BluetoothInputDevice.STATE_DISCONNECTED, firedFlags, mask));
+    }
+
+    /**
+     * Writes a string to the logcat and a file if a file has been specified in the constructor.
+     *
+     * @param s The string to be written.
+     */
     public void writeOutput(String s) {
         Log.i(mTag, s);
         if (mOutputWriter == null) {
@@ -902,38 +1444,60 @@
         }
     }
 
-    private BluetoothReceiver getBluetoothReceiver(int expectedFlags) {
-        BluetoothReceiver receiver = new BluetoothReceiver(expectedFlags);
+    private void addReceiver(BroadcastReceiver receiver, String[] actions) {
         IntentFilter filter = new IntentFilter();
-        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
-        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
-        filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
-        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+        for (String action: actions) {
+            filter.addAction(action);
+        }
         mContext.registerReceiver(receiver, filter);
         mReceivers.add(receiver);
+    }
+
+    private BluetoothReceiver getBluetoothReceiver(int expectedFlags) {
+        String[] actions = {
+                BluetoothAdapter.ACTION_DISCOVERY_FINISHED,
+                BluetoothAdapter.ACTION_DISCOVERY_STARTED,
+                BluetoothAdapter.ACTION_SCAN_MODE_CHANGED,
+                BluetoothAdapter.ACTION_STATE_CHANGED};
+        BluetoothReceiver receiver = new BluetoothReceiver(expectedFlags);
+        addReceiver(receiver, actions);
         return receiver;
     }
 
     private PairReceiver getPairReceiver(BluetoothDevice device, int passkey, byte[] pin,
             int expectedFlags) {
+        String[] actions = {
+                BluetoothDevice.ACTION_PAIRING_REQUEST,
+                BluetoothDevice.ACTION_BOND_STATE_CHANGED};
         PairReceiver receiver = new PairReceiver(device, passkey, pin, expectedFlags);
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
-        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
-        mContext.registerReceiver(receiver, filter);
-        mReceivers.add(receiver);
+        addReceiver(receiver, actions);
         return receiver;
     }
 
     private ConnectProfileReceiver getConnectProfileReceiver(BluetoothDevice device, int profile,
             int expectedFlags) {
+        String[] actions = {
+                BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED,
+                BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED};
         ConnectProfileReceiver receiver = new ConnectProfileReceiver(device, profile,
                 expectedFlags);
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
-        mContext.registerReceiver(receiver, filter);
-        mReceivers.add(receiver);
+        addReceiver(receiver, actions);
+        return receiver;
+    }
+
+    private ConnectInputReceiver getConnectInputReceiver(BluetoothDevice device,
+            int expectedFlags) {
+        String[] actions = {BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED};
+        ConnectInputReceiver receiver = new ConnectInputReceiver(device, expectedFlags);
+        addReceiver(receiver, actions);
+        return receiver;
+    }
+
+    private ConnectPanReceiver getConnectPanReceiver(BluetoothDevice device, int role,
+            int expectedFlags) {
+        String[] actions = {BluetoothPan.ACTION_PAN_STATE_CHANGED};
+        ConnectPanReceiver receiver = new ConnectPanReceiver(device, role, expectedFlags);
+        addReceiver(receiver, actions);
         return receiver;
     }
 
diff --git a/core/tests/coretests/src/android/content/ContentResolverTest.java b/core/tests/coretests/src/android/content/ContentResolverTest.java
new file mode 100644
index 0000000..2b6dee8b
--- /dev/null
+++ b/core/tests/coretests/src/android/content/ContentResolverTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content;
+
+import android.content.ContentResolver;
+import android.provider.ContactsContract;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+
+public class ContentResolverTest extends AndroidTestCase {
+    private ContentResolver mContentResolver;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContentResolver = mContext.getContentResolver();
+    }
+
+    @LargeTest
+    public void testCursorFinalizer() throws Exception {
+        // TODO: Want a test case that more predictably reproduce this issue. Selected
+        // 600 as this causes the problem 100% of the runs on current hw, it might not
+        // do so on some other configuration though.
+        for (int i = 0; i < 600; i++) {
+            mContentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/content/pm/AppCacheTest.java b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
index dd25220..2982816 100755
--- a/core/tests/coretests/src/android/content/pm/AppCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
@@ -35,14 +35,17 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 public class AppCacheTest extends AndroidTestCase {
     private static final boolean localLOGV = false;
     public static final String TAG="AppCacheTest";
     public final long MAX_WAIT_TIME=60*1000;
     public final long WAIT_TIME_INCR=10*1000;
-    private static final int THRESHOLD=5;
-    private static final int ACTUAL_THRESHOLD=10;
+    private static final long THRESHOLD=5;
+    private static final long ACTUAL_THRESHOLD=10;
     
     @Override
     protected void setUp() throws Exception {
@@ -94,24 +97,27 @@
         String testName="testDeleteAllCacheFiles";
         cleanUpCacheDirectory();
     }
-    
+
     void failStr(String errMsg) {
         Log.w(TAG, "errMsg="+errMsg);
         fail(errMsg);
     }
+
     void failStr(Exception e) {
         Log.w(TAG, "e.getMessage="+e.getMessage());
         Log.w(TAG, "e="+e);
     }
+
     long getFreeStorageBlks(StatFs st) {
         st.restat("/data");
         return st.getFreeBlocks();
     }
-    
+
     long getFreeStorageSize(StatFs st) {
         st.restat("/data");
-        return (st.getFreeBlocks()*st.getBlockSize());
+        return (long) st.getFreeBlocks() * (long) st.getBlockSize();
     }
+
     @LargeTest
     public void testFreeApplicationCacheAllFiles() throws Exception {
         boolean TRACKING = true;
@@ -124,7 +130,9 @@
         long blks2 = getFreeStorageBlks(st);
         if(localLOGV || TRACKING) Log.i(TAG, "blk1="+blks1+", blks2="+blks2);
         //this should free up the test files that were created earlier
-        invokePMFreeApplicationCache(availableMem);
+        if (!invokePMFreeApplicationCache(availableMem)) {
+            fail("Could not successfully invoke PackageManager free app cache API");
+        }
         long blks3 = getFreeStorageBlks(st);
         if(localLOGV || TRACKING) Log.i(TAG, "blks3="+blks3);
         verifyTestFiles1(cacheDir, "testtmpdir", 5);
@@ -139,7 +147,9 @@
         long blks2 = getFreeStorageBlks(st);
         Log.i(TAG, "blk1="+blks1+", blks2="+blks2);
         long diff = (blks1-blks2-2);
-        assertTrue(invokePMFreeApplicationCache(diff*st.getBlockSize()));    
+        if (!invokePMFreeApplicationCache(diff * st.getBlockSize())) {
+            fail("Could not successfully invoke PackageManager free app cache API");
+        }
         long blks3 = getFreeStorageBlks(st);
         //blks3 should be greater than blks2 and less than blks1
         if(!((blks3 <= blks1) && (blks3 >= blks2))) {
@@ -256,23 +266,23 @@
         }
         return sbuffer.getBytes();
     }
-    
-    long getFileNumBlocks(long fileSize, int blkSize) {
+
+    long getFileNumBlocks(long fileSize, long blkSize) {
         long ret = fileSize/blkSize;
         if(ret*blkSize < fileSize) {
             ret++;
         }
         return ret;
     }
-    
+
     //@LargeTest
     public void testAppCacheClear() {
         String dataDir="/data/data";
         StatFs st = new StatFs(dataDir);
-        int blkSize = st.getBlockSize();
-        int totBlks = st.getBlockCount();
+        long blkSize = st.getBlockSize();
+        long totBlks = st.getBlockCount();
         long availableBlks = st.getFreeBlocks();
-        long thresholdBlks = (totBlks*THRESHOLD)/100;
+        long thresholdBlks = (totBlks * THRESHOLD) / 100L;
         String testDirName = "testdir";
         //create directory in cache
         File testDir = new File(mContext.getCacheDir(),  testDirName);
@@ -345,7 +355,7 @@
         if((fileSize > (shouldFree-blkSize) && (fileSize < (shouldFree+blkSize)))) {
             Log.i(TAG, "passed");
         }
-        assertTrue(removedFlag);
+        assertTrue("Files should have been removed", removedFlag);
     }
     
     //createTestFiles(new File(super.getContext().getCacheDir(), "testtmp", "dir", 3)
@@ -375,16 +385,21 @@
             }
         }
     }
-    
+
     void verifyTestFiles1(File cacheDir, String testFilePrefix, int numTestFiles) {
+        List<String> files = new ArrayList<String>();
         for(int i = 0; i < numTestFiles; i++) {
             File file1 = new File(cacheDir, testFilePrefix+i+".txt");
             if(file1.exists()) {
-                fail("file:"+file1+" should not exist");
+                files.add(file1.getName());
             }
         }
+        if (files.size() > 0) {
+            fail("Files should have been deleted: "
+                    + Arrays.toString(files.toArray(new String[files.size()])));
+        }
     }
-    
+
     void createTestFiles2(File cacheDir, String rootTestDirName, String subDirPrefix, int numDirs, String testFilePrefix) {
         Context con = super.getContext();
         File testTmpDir = new File(cacheDir, rootTestDirName);
@@ -639,7 +654,9 @@
         PendingIntent pi = PendingIntent.getBroadcast(mContext,
                 0,  new Intent(FreeStorageReceiver.ACTION_FREE), 0);
         // Invoke PackageManager api
-        invokePMFreeStorage(availableMem, receiver, pi);
+        if (!invokePMFreeStorage(availableMem, receiver, pi)) {
+            fail("Could not invoke PackageManager free storage API");
+        }
         long blks3 = getFreeStorageBlks(st);
         if(localLOGV || TRACKING) Log.i(TAG, "Available blocks after freeing cache"+blks3);
         assertEquals(receiver.getResultCode(), 1);
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index d5f385b..2126529 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
@@ -47,6 +48,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Arrays;
 
 public class PackageManagerTests extends AndroidTestCase {
     private static final boolean localLOGV = true;
@@ -215,7 +217,7 @@
         }
     }
 
-    public void invokeInstallPackageFail(Uri packageURI, int flags, int result) {
+    public void invokeInstallPackageFail(Uri packageURI, int flags, int expectedResult) {
         PackageInstallObserver observer = new PackageInstallObserver();
         try {
             // Wait on observer
@@ -233,7 +235,7 @@
                 if(!observer.isDone()) {
                     fail("Timed out waiting for packageInstalled callback");
                 }
-                assertEquals(observer.returnCode, result);
+                assertEquals(expectedResult, observer.returnCode);
             }
         } finally {
         }
@@ -622,6 +624,11 @@
 
     @LargeTest
     public void testInstallSdcard() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         mountMedia();
         sampleInstallFromRawResource(PackageManager.INSTALL_EXTERNAL, true);
     }
@@ -723,6 +730,11 @@
 
     @LargeTest
     public void testReplaceFailSdcard() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         sampleReplaceFromRawResource(PackageManager.INSTALL_EXTERNAL);
     }
 
@@ -739,6 +751,11 @@
 
     @LargeTest
     public void testReplaceSdcard() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         sampleReplaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING |
                 PackageManager.INSTALL_EXTERNAL);
     }
@@ -863,6 +880,11 @@
 
     @LargeTest
     public void testDeleteSdcard() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         deleteFromRawResource(PackageManager.INSTALL_EXTERNAL, 0);
     }
 
@@ -878,6 +900,11 @@
 
     @LargeTest
     public void testDeleteSdcardRetainData() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         deleteFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.DONT_DELETE_DATA);
     }
 
@@ -976,6 +1003,11 @@
     }
 
     boolean mountMedia() {
+        // We can't mount emulated storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return true;
+        }
+
         if (checkMediaState(Environment.MEDIA_MOUNTED)) {
             return true;
         }
@@ -1010,6 +1042,11 @@
     }
 
     private boolean unmountMedia() {
+        // We can't unmount emulated storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return true;
+        }
+
         if (checkMediaState(Environment.MEDIA_UNMOUNTED)) {
             return true;
         }
@@ -1099,6 +1136,11 @@
      */
     @LargeTest
     public void testMountSdNormalInternal() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         assertTrue(mountFromRawResource());
     }
 
@@ -1136,6 +1178,11 @@
 
     @LargeTest
     public void testManifestInstallLocationSdcard() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
                 0, true, false, -1, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
     }
@@ -1154,6 +1201,11 @@
 
     @LargeTest
     public void testManifestInstallLocationFwdLockedFlagSdcard() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         installFromRawResource("install.apk", R.raw.install_loc_unspecified,
                 PackageManager.INSTALL_FORWARD_LOCK |
                 PackageManager.INSTALL_EXTERNAL, true, true,
@@ -1163,6 +1215,11 @@
 
     @LargeTest
     public void testManifestInstallLocationFwdLockedSdcard() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
                 PackageManager.INSTALL_FORWARD_LOCK, true, false,
                 -1,
@@ -1176,6 +1233,11 @@
      */
     @LargeTest
     public void testReplaceFlagInternalSdcard() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         int iFlags = 0;
         int rFlags = PackageManager.INSTALL_EXTERNAL;
         InstallParams ip = sampleInstallFromRawResource(iFlags, false);
@@ -1198,6 +1260,11 @@
      */
     @LargeTest
     public void testReplaceFlagSdcardInternal() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         int iFlags = PackageManager.INSTALL_EXTERNAL;
         int rFlags = 0;
         InstallParams ip = sampleInstallFromRawResource(iFlags, false);
@@ -1215,6 +1282,11 @@
 
     @LargeTest
     public void testManifestInstallLocationReplaceInternalSdcard() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         int iFlags = 0;
         int iApk = R.raw.install_loc_internal;
         int rFlags = 0;
@@ -1238,6 +1310,11 @@
 
     @LargeTest
     public void testManifestInstallLocationReplaceSdcardInternal() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         int iFlags = 0;
         int iApk = R.raw.install_loc_sdcard;
         int rFlags = 0;
@@ -1470,6 +1547,11 @@
 
     @LargeTest
     public void testMoveAppInternalToExternal() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         int installFlags = PackageManager.INSTALL_INTERNAL;
         int moveFlags = PackageManager.MOVE_EXTERNAL_MEDIA;
         boolean fail = false;
@@ -1488,30 +1570,53 @@
 
     @LargeTest
     public void testMoveAppExternalToExternal() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         int installFlags = PackageManager.INSTALL_EXTERNAL;
         int moveFlags = PackageManager.MOVE_EXTERNAL_MEDIA;
         boolean fail = true;
         int result = PackageManager.MOVE_FAILED_INVALID_LOCATION;
         sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
     }
+
     @LargeTest
     public void testMoveAppExternalToInternal() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         int installFlags = PackageManager.INSTALL_EXTERNAL;
         int moveFlags = PackageManager.MOVE_INTERNAL;
         boolean fail = false;
         int result = PackageManager.MOVE_SUCCEEDED;
         sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
     }
+
     @LargeTest
     public void testMoveAppForwardLocked() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         int installFlags = PackageManager.INSTALL_FORWARD_LOCK;
         int moveFlags = PackageManager.MOVE_EXTERNAL_MEDIA;
         boolean fail = true;
         int result = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
         sampleMoveFromRawResource(installFlags, moveFlags, fail, result);
     }
+
     @LargeTest
     public void testMoveAppFailInternalToExternalDelete() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         int installFlags = 0;
         int moveFlags = PackageManager.MOVE_EXTERNAL_MEDIA;
         boolean fail = true;
@@ -1540,12 +1645,18 @@
             setInstallLoc(origDefaultLoc);
         }
     }
+
     /*
      * Test that an install error code is returned when media is unmounted
      * and package installed on sdcard via package manager flag.
      */
     @LargeTest
     public void testInstallSdcardUnmount() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         boolean origState = checkMediaState(Environment.MEDIA_MOUNTED);
         try {
             // Unmount sdcard
@@ -1571,6 +1682,11 @@
      */
     @LargeTest
     public void testInstallManifestSdcardUnmount() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         boolean origState = checkMediaState(Environment.MEDIA_MOUNTED);
         try {
             // Unmount sdcard
@@ -1598,71 +1714,83 @@
     * User: UserI, UserE, UserA, User suffix absent if not existing.
     *
     */
-   /*
-    * Install an app on internal flash
-    */
-   @LargeTest
-   public void testFlagI() {
-       sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, true);
-   }
-   /*
-    * Install an app on sdcard.
-    */
-   @LargeTest
-   public void testFlagE() {
-       sampleInstallFromRawResource(PackageManager.INSTALL_EXTERNAL, true);
-   }
 
-   /*
-    * Install an app on sdcard.
-    */
-   @LargeTest
-   public void testFlagF() {
-       sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, true);
-   }
-   /*
-    * Install an app with both internal and external flags set. should fail
-    */
-   @LargeTest
-   public void testFlagIE() {
-       installFromRawResource("install.apk", R.raw.install,
-               PackageManager.INSTALL_EXTERNAL | PackageManager.INSTALL_INTERNAL,
-               false,
-               true, PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION,
-               PackageInfo.INSTALL_LOCATION_AUTO);
-   }
+    /*
+     * Install an app on internal flash
+     */
+    @LargeTest
+    public void testFlagI() {
+        sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, true);
+    }
 
-   /*
-    * Install an app with both internal and external flags set. should fail
-    */
-   @LargeTest
-   public void testFlagIF() {
-       sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK |
-               PackageManager.INSTALL_INTERNAL, true);
-   }
-   /*
-    * Install an app with both internal and external flags set. should fail
-    */
-   @LargeTest
-   public void testFlagEF() {
-       installFromRawResource("install.apk", R.raw.install,
-               PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_EXTERNAL,
-               false,
-               true, PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION,
-               PackageInfo.INSTALL_LOCATION_AUTO);
-   }
-   /*
-    * Install an app with both internal and external flags set. should fail
-    */
-   @LargeTest
-   public void testFlagIEF() {
-       installFromRawResource("install.apk", R.raw.install,
-               PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_INTERNAL |
-               PackageManager.INSTALL_EXTERNAL,
-               false,
-               true, PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION,
-               PackageInfo.INSTALL_LOCATION_AUTO);
-   }
+    /*
+     * Install an app on sdcard.
+     */
+    @LargeTest
+    public void testFlagE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        sampleInstallFromRawResource(PackageManager.INSTALL_EXTERNAL, true);
+    }
+
+    /*
+     * Install an app forward-locked.
+     */
+    @LargeTest
+    public void testFlagF() {
+        sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, true);
+    }
+
+    /*
+     * Install an app with both internal and external flags set. should fail
+     */
+    @LargeTest
+    public void testFlagIE() {
+        installFromRawResource("install.apk", R.raw.install,
+                PackageManager.INSTALL_EXTERNAL | PackageManager.INSTALL_INTERNAL,
+                false,
+                true, PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+                PackageInfo.INSTALL_LOCATION_AUTO);
+    }
+
+    /*
+     * Install an app with both internal and forward-lock flags set.
+     */
+    @LargeTest
+    public void testFlagIF() {
+        sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK
+                | PackageManager.INSTALL_INTERNAL, true);
+    }
+
+    /*
+     * Install an app with both external and forward-lock flags set. should fail
+     */
+    @LargeTest
+    public void testFlagEF() {
+        installFromRawResource("install.apk", R.raw.install,
+                PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_EXTERNAL,
+                false,
+                true, PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+                PackageInfo.INSTALL_LOCATION_AUTO);
+    }
+
+    /*
+     * Install an app with both internal and external flags set with forward
+     * lock. Should fail.
+     */
+    @LargeTest
+    public void testFlagIEF() {
+        installFromRawResource("install.apk", R.raw.install,
+                PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_INTERNAL |
+                PackageManager.INSTALL_EXTERNAL,
+                false,
+                true, PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+                PackageInfo.INSTALL_LOCATION_AUTO);
+    }
+
    /*
     * Install an app with both internal and manifest option set.
     * should install on internal.
@@ -1705,321 +1833,402 @@
     */
    @LargeTest
    public void testFlagEManifestI() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
        installFromRawResource("install.apk", R.raw.install_loc_internal,
                PackageManager.INSTALL_EXTERNAL,
                true,
                false, -1,
                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
    }
+
    /*
     * Install an app with both external and manifest preference for
     * preferExternal. Should install externally.
     */
    @LargeTest
    public void testFlagEManifestE() {
-       installFromRawResource("install.apk", R.raw.install_loc_sdcard,
-               PackageManager.INSTALL_EXTERNAL,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
-   /*
-    * Install an app with both external and manifest preference for
-    * auto. should install on external media.
-    */
-   @LargeTest
-   public void testFlagEManifestA() {
-       installFromRawResource("install.apk", R.raw.install_loc_auto,
-               PackageManager.INSTALL_EXTERNAL,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
-   /*
-    * Install an app with fwd locked flag set and install location set to
-    * internal. should install internally.
-    */
-   @LargeTest
-   public void testFlagFManifestI() {
-       installFromRawResource("install.apk", R.raw.install_loc_internal,
-               PackageManager.INSTALL_EXTERNAL,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
-   /*
-    * Install an app with fwd locked flag set and install location set to
-    * preferExternal. should install internally.
-    */
-   @LargeTest
-   public void testFlagFManifestE() {
-       installFromRawResource("install.apk", R.raw.install_loc_sdcard,
-               PackageManager.INSTALL_EXTERNAL,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
-   /*
-    * Install an app with fwd locked flag set and install location set to
-    * auto. should install internally.
-    */
-   @LargeTest
-   public void testFlagFManifestA() {
-       installFromRawResource("install.apk", R.raw.install_loc_auto,
-               PackageManager.INSTALL_EXTERNAL,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
-   /* The following test functions verify install location for existing apps.
-    * ie existing app can be installed internally or externally. If install
-    * flag is explicitly set it should override current location. If manifest location
-    * is set, that should over ride current location too. if not the existing install
-    * location should be honoured.
-    * testFlagI/E/F/ExistingI/E -
-    */
-   @LargeTest
-   public void testFlagIExistingI() {
-       int iFlags = PackageManager.INSTALL_INTERNAL;
-       int rFlags = PackageManager.INSTALL_INTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               -1);
-       // Replace now
-       installFromRawResource("install.apk", R.raw.install,
-               rFlags,
-               true,
-               false, -1,
-               -1);
-   }
-   @LargeTest
-   public void testFlagIExistingE() {
-       int iFlags = PackageManager.INSTALL_EXTERNAL;
-       int rFlags = PackageManager.INSTALL_INTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               -1);
-       // Replace now
-       installFromRawResource("install.apk", R.raw.install,
-               rFlags,
-               true,
-               false, -1,
-               -1);
-   }
-   @LargeTest
-   public void testFlagEExistingI() {
-       int iFlags = PackageManager.INSTALL_INTERNAL;
-       int rFlags = PackageManager.INSTALL_EXTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               -1);
-       // Replace now
-       installFromRawResource("install.apk", R.raw.install,
-               rFlags,
-               true,
-               false, -1,
-               -1);
-   }
-   @LargeTest
-   public void testFlagEExistingE() {
-       int iFlags = PackageManager.INSTALL_EXTERNAL;
-       int rFlags = PackageManager.INSTALL_EXTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               -1);
-       // Replace now
-       installFromRawResource("install.apk", R.raw.install,
-               rFlags,
-               true,
-               false, -1,
-               -1);
-   }
-   @LargeTest
-   public void testFlagFExistingI() {
-       int iFlags = PackageManager.INSTALL_INTERNAL;
-       int rFlags = PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               -1);
-       // Replace now
-       installFromRawResource("install.apk", R.raw.install,
-               rFlags,
-               true,
-               false, -1,
-               -1);
-   }
-   @LargeTest
-   public void testFlagFExistingE() {
-       int iFlags = PackageManager.INSTALL_EXTERNAL;
-       int rFlags = PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               -1);
-       // Replace now
-       installFromRawResource("install.apk", R.raw.install,
-               rFlags,
-               true,
-               false, -1,
-               -1);
-   }
-   /*
-    * The following set of tests verify the installation of apps with
-    * install location attribute set to internalOnly, preferExternal and auto.
-    * The manifest option should dictate the install location.
-    * public void testManifestI/E/A
-    * TODO out of memory fall back behaviour.
-    */
-   @LargeTest
-   public void testManifestI() {
-       installFromRawResource("install.apk", R.raw.install_loc_internal,
-               0,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
-   }
-   @LargeTest
-   public void testManifestE() {
-       installFromRawResource("install.apk", R.raw.install_loc_sdcard,
-               0,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
-   @LargeTest
-   public void testManifestA() {
-       installFromRawResource("install.apk", R.raw.install_loc_auto,
-               0,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
-   }
-   /*
-    * The following set of tests verify the installation of apps
-    * with install location attribute set to internalOnly, preferExternal and auto
-    * for already existing apps. The manifest option should take precedence.
-    * TODO add out of memory fall back behaviour.
-    * testManifestI/E/AExistingI/E
-    */
-   @LargeTest
-   public void testManifestIExistingI() {
-       int iFlags = PackageManager.INSTALL_INTERNAL;
-       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               -1);
-       // Replace now
-       installFromRawResource("install.apk", R.raw.install_loc_internal,
-               rFlags,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
-   }
-   @LargeTest
-   public void testManifestIExistingE() {
-       int iFlags = PackageManager.INSTALL_EXTERNAL;
-       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               -1);
-       // Replace now
-       installFromRawResource("install.apk", R.raw.install_loc_internal,
-               rFlags,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
-   }
-   @LargeTest
-   public void testManifestEExistingI() {
-       int iFlags = PackageManager.INSTALL_INTERNAL;
-       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               -1);
-       // Replace now
-       installFromRawResource("install.apk", R.raw.install_loc_sdcard,
-               rFlags,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
-   @LargeTest
-   public void testManifestEExistingE() {
-       int iFlags = PackageManager.INSTALL_EXTERNAL;
-       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               -1);
-       // Replace now
-       installFromRawResource("install.apk", R.raw.install_loc_sdcard,
-               rFlags,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
-   @LargeTest
-   public void testManifestAExistingI() {
-       int iFlags = PackageManager.INSTALL_INTERNAL;
-       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               -1);
-       // Replace now
-       installFromRawResource("install.apk", R.raw.install_loc_auto,
-               rFlags,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_AUTO);
-   }
-   @LargeTest
-   public void testManifestAExistingE() {
-       int iFlags = PackageManager.INSTALL_EXTERNAL;
-       int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
-       // First install.
-       installFromRawResource("install.apk", R.raw.install,
-               iFlags,
-               false,
-               false, -1,
-               -1);
-       // Replace now
-       installFromRawResource("install.apk", R.raw.install_loc_auto,
-               rFlags,
-               true,
-               false, -1,
-               PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+                PackageManager.INSTALL_EXTERNAL,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
+
+    /*
+     * Install an app with both external and manifest preference for
+     * auto. should install on external media.
+     */
+    @LargeTest
+    public void testFlagEManifestA() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        installFromRawResource("install.apk", R.raw.install_loc_auto,
+                PackageManager.INSTALL_EXTERNAL,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
+
+    /*
+     * Install an app with fwd locked flag set and install location set to
+     * internal. should install internally.
+     */
+    @LargeTest
+    public void testFlagFManifestI() {
+        installFromRawResource("install.apk", R.raw.install_loc_internal,
+                PackageManager.INSTALL_FORWARD_LOCK,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
+
+    /*
+     * Install an app with fwd locked flag set and install location set to
+     * preferExternal. should install internally.
+     */
+    @LargeTest
+    public void testFlagFManifestE() {
+        installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+                PackageManager.INSTALL_FORWARD_LOCK,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
+
+    /*
+     * Install an app with fwd locked flag set and install location set to
+     * auto. should install internally.
+     */
+    @LargeTest
+    public void testFlagFManifestA() {
+        installFromRawResource("install.apk", R.raw.install_loc_auto,
+                PackageManager.INSTALL_FORWARD_LOCK,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
+
+    /* The following test functions verify install location for existing apps.
+     * ie existing app can be installed internally or externally. If install
+     * flag is explicitly set it should override current location. If manifest location
+     * is set, that should over ride current location too. if not the existing install
+     * location should be honoured.
+     * testFlagI/E/F/ExistingI/E -
+     */
+    @LargeTest
+    public void testFlagIExistingI() {
+        int iFlags = PackageManager.INSTALL_INTERNAL;
+        int rFlags = PackageManager.INSTALL_INTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                -1);
+        // Replace now
+        installFromRawResource("install.apk", R.raw.install,
+                rFlags,
+                true,
+                false, -1,
+                -1);
+    }
+
+    @LargeTest
+    public void testFlagIExistingE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int iFlags = PackageManager.INSTALL_EXTERNAL;
+        int rFlags = PackageManager.INSTALL_INTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                -1);
+        // Replace now
+        installFromRawResource("install.apk", R.raw.install,
+                rFlags,
+                true,
+                false, -1,
+                -1);
+    }
+
+    @LargeTest
+    public void testFlagEExistingI() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int iFlags = PackageManager.INSTALL_INTERNAL;
+        int rFlags = PackageManager.INSTALL_EXTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                -1);
+        // Replace now
+        installFromRawResource("install.apk", R.raw.install,
+                rFlags,
+                true,
+                false, -1,
+                -1);
+    }
+
+    @LargeTest
+    public void testFlagEExistingE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int iFlags = PackageManager.INSTALL_EXTERNAL;
+        int rFlags = PackageManager.INSTALL_EXTERNAL | PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                -1);
+        // Replace now
+        installFromRawResource("install.apk", R.raw.install,
+                rFlags,
+                true,
+                false, -1,
+                -1);
+    }
+
+    @LargeTest
+    public void testFlagFExistingI() {
+        int iFlags = PackageManager.INSTALL_INTERNAL;
+        int rFlags = PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                -1);
+        // Replace now
+        installFromRawResource("install.apk", R.raw.install,
+                rFlags,
+                true,
+                false, -1,
+                -1);
+    }
+
+    @LargeTest
+    public void testFlagFExistingE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int iFlags = PackageManager.INSTALL_EXTERNAL;
+        int rFlags = PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                -1);
+        // Replace now
+        installFromRawResource("install.apk", R.raw.install,
+                rFlags,
+                true,
+                false, -1,
+                -1);
+    }
+
+    /*
+     * The following set of tests verify the installation of apps with
+     * install location attribute set to internalOnly, preferExternal and auto.
+     * The manifest option should dictate the install location.
+     * public void testManifestI/E/A
+     * TODO out of memory fall back behaviour.
+     */
+    @LargeTest
+    public void testManifestI() {
+        installFromRawResource("install.apk", R.raw.install_loc_internal,
+                0,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+    }
+
+    @LargeTest
+    public void testManifestE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+                0,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
+
+    @LargeTest
+    public void testManifestA() {
+        installFromRawResource("install.apk", R.raw.install_loc_auto,
+                0,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+    }
+
+    /*
+     * The following set of tests verify the installation of apps
+     * with install location attribute set to internalOnly, preferExternal and auto
+     * for already existing apps. The manifest option should take precedence.
+     * TODO add out of memory fall back behaviour.
+     * testManifestI/E/AExistingI/E
+     */
+    @LargeTest
+    public void testManifestIExistingI() {
+        int iFlags = PackageManager.INSTALL_INTERNAL;
+        int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                -1);
+        // Replace now
+        installFromRawResource("install.apk", R.raw.install_loc_internal,
+                rFlags,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+    }
+
+    @LargeTest
+    public void testManifestIExistingE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int iFlags = PackageManager.INSTALL_EXTERNAL;
+        int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                -1);
+        // Replace now
+        installFromRawResource("install.apk", R.raw.install_loc_internal,
+                rFlags,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+    }
+
+    @LargeTest
+    public void testManifestEExistingI() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int iFlags = PackageManager.INSTALL_INTERNAL;
+        int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                -1);
+        // Replace now
+        installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+                rFlags,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
+
+    @LargeTest
+    public void testManifestEExistingE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int iFlags = PackageManager.INSTALL_EXTERNAL;
+        int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                -1);
+        // Replace now
+        installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+                rFlags,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
+
+    @LargeTest
+    public void testManifestAExistingI() {
+        int iFlags = PackageManager.INSTALL_INTERNAL;
+        int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                -1);
+        // Replace now
+        installFromRawResource("install.apk", R.raw.install_loc_auto,
+                rFlags,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_AUTO);
+    }
+
+    @LargeTest
+    public void testManifestAExistingE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int iFlags = PackageManager.INSTALL_EXTERNAL;
+        int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
+        // First install.
+        installFromRawResource("install.apk", R.raw.install,
+                iFlags,
+                false,
+                false, -1,
+                -1);
+        // Replace now
+        installFromRawResource("install.apk", R.raw.install_loc_auto,
+                rFlags,
+                true,
+                false, -1,
+                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
+
    /*
     * The following set of tests check install location for existing
     * application based on user setting.
@@ -2066,36 +2275,62 @@
        int iFlags = PackageManager.INSTALL_INTERNAL;
        setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
    }
-   @LargeTest
-   public void testExistingIUserE() {
-       int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
-       int iFlags = PackageManager.INSTALL_INTERNAL;
-       setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
-   }
+
+    @LargeTest
+    public void testExistingIUserE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
+        int iFlags = PackageManager.INSTALL_INTERNAL;
+        setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+    }
+
    @LargeTest
    public void testExistingIUserA() {
        int userSetting = PackageHelper.APP_INSTALL_AUTO;
        int iFlags = PackageManager.INSTALL_INTERNAL;
        setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
    }
-   @LargeTest
-   public void testExistingEUserI() {
-       int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
-       int iFlags = PackageManager.INSTALL_EXTERNAL;
-       setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
-   @LargeTest
-   public void testExistingEUserE() {
-       int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
-       int iFlags = PackageManager.INSTALL_EXTERNAL;
-       setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
-   @LargeTest
-   public void testExistingEUserA() {
-       int userSetting = PackageHelper.APP_INSTALL_AUTO;
-       int iFlags = PackageManager.INSTALL_EXTERNAL;
-       setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
-   }
+
+    @LargeTest
+    public void testExistingEUserI() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
+        int iFlags = PackageManager.INSTALL_EXTERNAL;
+        setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
+
+    @LargeTest
+    public void testExistingEUserE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
+        int iFlags = PackageManager.INSTALL_EXTERNAL;
+        setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
+
+    @LargeTest
+    public void testExistingEUserA() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int userSetting = PackageHelper.APP_INSTALL_AUTO;
+        int iFlags = PackageManager.INSTALL_EXTERNAL;
+        setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+    }
+
    /*
     * The following set of tests verify that the user setting defines
     * the install location.
@@ -2139,12 +2374,19 @@
        int iloc = getExpectedInstallLocation(userSetting);
        setUserX(true, userSetting, iloc);
    }
-   @LargeTest
-   public void testUserE() {
-       int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
-       int iloc = getExpectedInstallLocation(userSetting);
-       setUserX(true, userSetting, iloc);
-   }
+
+    @LargeTest
+    public void testUserE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
+        int iloc = getExpectedInstallLocation(userSetting);
+        setUserX(true, userSetting, iloc);
+    }
+
    @LargeTest
    public void testUserA() {
        int userSetting = PackageHelper.APP_INSTALL_AUTO;
@@ -2161,12 +2403,19 @@
        int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
        setUserX(false, userSetting, iloc);
    }
-   @LargeTest
-   public void testUserPrefOffUserE() {
-       int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
-       int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
-       setUserX(false, userSetting, iloc);
-   }
+
+    @LargeTest
+    public void testUserPrefOffUserE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
+        int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+        setUserX(false, userSetting, iloc);
+    }
+
    @LargeTest
    public void testUserPrefOffA() {
        int userSetting = PackageHelper.APP_INSTALL_AUTO;
@@ -2378,6 +2627,11 @@
      */
     @LargeTest
     public void testInstallSdcardStaleContainer() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         boolean origMediaState = checkMediaState(Environment.MEDIA_MOUNTED);
         try {
             // Mount media first
@@ -2422,6 +2676,11 @@
      */
     @LargeTest
     public void testInstallSdcardStaleContainerReinstall() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         boolean origMediaState = checkMediaState(Environment.MEDIA_MOUNTED);
         try {
             // Mount media first
@@ -2457,6 +2716,7 @@
             }
         }
     }
+
     /*
      * The following series of tests are related to upgrading apps with
      * different certificates.
@@ -2838,6 +3098,172 @@
         installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
                 fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
+
+    @LargeTest
+    public void testUsesFeatureMissingFeature() {
+        int retCode = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
+        installFromRawResource("install.apk", R.raw.install_uses_feature, 0, true, true, retCode,
+                PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Nonexistent() {
+        try {
+            final PackageManager pm = getPm();
+
+            // Invalid Java package name.
+            pm.getPackageObbPaths("=non-existent");
+
+            fail("Should not be able to get package OBB paths for non-existent package");
+        } catch (IllegalArgumentException e) {
+            // pass
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Initial() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            assertEquals("Initial obb paths should be null",
+                    null, pm.getPackageObbPaths(ip.pkg.packageName));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Null() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            pm.setPackageObbPaths(ip.pkg.packageName, null);
+
+            assertEquals("Returned paths should be null",
+                    null, pm.getPackageObbPaths(ip.pkg.packageName));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Empty() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            final String[] paths = new String[0];
+
+            pm.setPackageObbPaths(ip.pkg.packageName, paths);
+
+            assertEquals("Empty list should be interpreted as null",
+                    null, pm.getPackageObbPaths(ip.pkg.packageName));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Single() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            final String[] paths = new String[] {
+                "/example/test",
+            };
+
+            pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+            assertTrue("Previously set paths should be the same as the returned paths.",
+                    Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Multiple() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            final String[] paths = new String[] {
+                    "/example/test1",
+                    "/example/test2",
+            };
+
+            pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+            assertTrue("Previously set paths should be the same as the returned paths.",
+                    Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Twice() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            final String[] paths = new String[] {
+                    "/example/test1",
+                    "/example/test2",
+            };
+
+            pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+            assertTrue("Previously set paths should be the same as the returned paths.",
+                    Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+
+            paths[0] = "/example/test3";
+            pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+            assertTrue("Previously set paths should be the same as the returned paths.",
+                    Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_ReplacePackage() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            final String[] paths = new String[] {
+                    "/example/test1",
+                    "/example/test2",
+            };
+
+            pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+            Log.i(TAG, "Creating replaceReceiver");
+            final GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
+
+            final int flags = PackageManager.INSTALL_REPLACE_EXISTING;
+            invokeInstallPackage(ip.packageURI, flags, receiver);
+            assertInstall(ip.pkg, flags, ip.pkg.installLocation);
+
+            assertTrue("Previously set paths should be the same as the returned paths.",
+                    Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
     /*---------- Recommended install location tests ----*/
     /*
      * TODO's
diff --git a/core/tests/coretests/src/android/database/DatabaseCursorTest.java b/core/tests/coretests/src/android/database/DatabaseCursorTest.java
index 0733229..d5b9ee6 100644
--- a/core/tests/coretests/src/android/database/DatabaseCursorTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseCursorTest.java
@@ -37,6 +37,7 @@
 import android.util.Log;
 
 import java.io.File;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Random;
 
@@ -581,4 +582,35 @@
         c.deactivate();
         c.requery();
     }
+    /**
+     * sometimes CursorWindow creation fails due to non-availability of memory create
+     * another CursorWindow object. One of the scenarios of its occurrence is when
+     * there are too many CursorWindow objects already opened by the process.
+     * This test is for that scenario.
+     */
+    @LargeTest
+    public void testCursorWindowFailureWhenTooManyCursorWindowsLeftOpen() {
+        mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);");
+        mDatabase.execSQL("INSERT INTO test values(1, 'test');");
+        int N = 1024;
+        ArrayList<Cursor> cursorList = new ArrayList<Cursor>();
+        // open many cursors until a failure occurs
+        for (int i = 0; i < N; i++) {
+            try {
+                Cursor cursor = mDatabase.rawQuery("select * from test", null);
+                cursor.getCount();
+                cursorList.add(cursor);
+            } catch (CursorWindowAllocationException e) {
+                // got the exception we wanted
+                break;
+            } catch (Exception e) {
+                fail("unexpected exception: " + e.getMessage());
+                e.printStackTrace();
+                break;
+            }
+        }
+        for (Cursor c : cursorList) {
+            c.close();
+        }
+    }
 }
diff --git a/core/tests/coretests/src/android/net/http/AbstractProxyTest.java b/core/tests/coretests/src/android/net/http/AbstractProxyTest.java
new file mode 100644
index 0000000..2fb833c
--- /dev/null
+++ b/core/tests/coretests/src/android/net/http/AbstractProxyTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.http;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.util.List;
+import junit.framework.TestCase;
+import libcore.javax.net.ssl.TestSSLContext;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.conn.params.ConnRoutePNames;
+import org.apache.http.conn.params.ConnRouteParams;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import tests.http.MockResponse;
+import tests.http.MockWebServer;
+import tests.http.RecordedRequest;
+
+public abstract class AbstractProxyTest extends TestCase {
+
+    private MockWebServer server = new MockWebServer();
+
+    protected abstract HttpClient newHttpClient();
+
+    @Override protected void tearDown() throws Exception {
+        System.clearProperty("proxyHost");
+        System.clearProperty("proxyPort");
+        System.clearProperty("http.proxyHost");
+        System.clearProperty("http.proxyPort");
+        System.clearProperty("https.proxyHost");
+        System.clearProperty("https.proxyPort");
+
+        server.shutdown();
+        super.tearDown();
+    }
+
+    public void testConnectToHttps() throws Exception {
+        TestSSLContext testSSLContext = TestSSLContext.create();
+
+        server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
+        server.enqueue(new MockResponse()
+                .setResponseCode(200)
+                .setBody("this response comes via HTTPS"));
+        server.play();
+
+        HttpClient httpClient = newHttpClient();
+
+        SSLSocketFactory sslSocketFactory = newSslSocketFactory(testSSLContext);
+        sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier());
+        httpClient.getConnectionManager().getSchemeRegistry()
+                .register(new Scheme("https", sslSocketFactory, server.getPort()));
+
+        HttpResponse response = httpClient.execute(
+                new HttpGet("https://localhost:" + server.getPort() + "/foo"));
+        assertEquals("this response comes via HTTPS", contentToString(response));
+
+        RecordedRequest request = server.takeRequest();
+        assertEquals("GET /foo HTTP/1.1", request.getRequestLine());
+    }
+
+    private SSLSocketFactory newSslSocketFactory(TestSSLContext testSSLContext) throws Exception {
+        // call through to Apache HTTP's non-public SSLSocketFactory constructor
+        return SSLSocketFactory.class.getConstructor(javax.net.ssl.SSLSocketFactory.class)
+                .newInstance(testSSLContext.clientContext.getSocketFactory());
+    }
+
+    /**
+     * We had bugs where proxy system properties weren't being honored.
+     * http://b/3254717
+     */
+    public void testConnectViaProxyUsingProxySystemProperty() throws Exception {
+        testConnectViaProxy(ProxyConfig.PROXY_SYSTEM_PROPERTY);
+    }
+
+    public void testConnectViaProxyUsingHttpProxySystemProperty() throws Exception {
+        testConnectViaProxy(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY);
+    }
+
+    public void testConnectViaProxyUsingRequestParameter() throws Exception {
+        testConnectViaProxy(ProxyConfig.REQUEST_PARAMETER);
+    }
+
+    public void testConnectViaProxyUsingClientParameter() throws Exception {
+        testConnectViaProxy(ProxyConfig.CLIENT_PARAMETER);
+    }
+
+    /**
+     * http://code.google.com/p/android/issues/detail?id=2690
+     */
+    private void testConnectViaProxy(ProxyConfig proxyConfig) throws Exception {
+        MockResponse mockResponse = new MockResponse()
+                .setResponseCode(200)
+                .setBody("this response comes via a proxy");
+        server.enqueue(mockResponse);
+        server.play();
+
+        HttpClient httpProxyClient = newHttpClient();
+
+        HttpGet request = new HttpGet("http://android.com/foo");
+        proxyConfig.configure(server, httpProxyClient, request);
+
+        HttpResponse response = httpProxyClient.execute(request);
+        assertEquals("this response comes via a proxy", contentToString(response));
+
+        RecordedRequest get = server.takeRequest();
+        assertEquals("GET http://android.com/foo HTTP/1.1", get.getRequestLine());
+        assertContains(get.getHeaders(), "Host: android.com");
+    }
+
+    public void testConnectViaHttpProxyToHttpsUsingProxySystemProperty() throws Exception {
+        testConnectViaHttpProxyToHttps(ProxyConfig.PROXY_SYSTEM_PROPERTY);
+    }
+
+    public void testConnectViaHttpProxyToHttpsUsingHttpsProxySystemProperty() throws Exception {
+        testConnectViaHttpProxyToHttps(ProxyConfig.HTTPS_PROXY_SYSTEM_PROPERTY);
+    }
+
+    public void testConnectViaHttpProxyToHttpsUsingClientParameter() throws Exception {
+        testConnectViaHttpProxyToHttps(ProxyConfig.CLIENT_PARAMETER);
+    }
+
+    public void testConnectViaHttpProxyToHttpsUsingRequestParameter() throws Exception {
+        testConnectViaHttpProxyToHttps(ProxyConfig.REQUEST_PARAMETER);
+    }
+
+    private void testConnectViaHttpProxyToHttps(ProxyConfig proxyConfig) throws Exception {
+        TestSSLContext testSSLContext = TestSSLContext.create();
+
+        server.useHttps(testSSLContext.serverContext.getSocketFactory(), true);
+        MockResponse connectResponse = new MockResponse()
+                .setResponseCode(200);
+        connectResponse.getHeaders().clear();
+        server.enqueue(connectResponse);
+        server.enqueue(new MockResponse()
+                .setResponseCode(200)
+                .setBody("this response comes via a secure proxy"));
+        server.play();
+
+        HttpClient httpProxyClient = newHttpClient();
+        SSLSocketFactory sslSocketFactory = newSslSocketFactory(testSSLContext);
+        sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier());
+        httpProxyClient.getConnectionManager().getSchemeRegistry()
+                .register(new Scheme("https", sslSocketFactory, 443));
+
+        HttpGet request = new HttpGet("https://android.com/foo");
+        proxyConfig.configure(server, httpProxyClient, request);
+
+        HttpResponse response = httpProxyClient.execute(request);
+        assertEquals("this response comes via a secure proxy", contentToString(response));
+
+        RecordedRequest connect = server.takeRequest();
+        assertEquals("Connect line failure on proxy " + proxyConfig,
+                "CONNECT android.com:443 HTTP/1.1", connect.getRequestLine());
+        assertContains(connect.getHeaders(), "Host: android.com");
+
+        RecordedRequest get = server.takeRequest();
+        assertEquals("GET /foo HTTP/1.1", get.getRequestLine());
+        assertContains(get.getHeaders(), "Host: android.com");
+    }
+
+    public void testClientParamPreferredOverSystemProperty() throws Exception {
+        testParamPreferredOverSystemProperty(ProxyConfig.CLIENT_PARAMETER);
+    }
+
+    public void testRequestParamPreferredOverSystemProperty() throws Exception {
+        testParamPreferredOverSystemProperty(ProxyConfig.REQUEST_PARAMETER);
+    }
+
+    private void testParamPreferredOverSystemProperty(ProxyConfig proxyConfig) throws Exception {
+        server.enqueue(new MockResponse().setBody("Via request parameter proxy!"));
+        server.play();
+        System.setProperty("http.proxyHost", "proxy.foo");
+        System.setProperty("http.proxyPort", "8080");
+
+        HttpClient client = newHttpClient();
+        HttpGet request = new HttpGet("http://origin.foo/bar");
+        proxyConfig.configure(server, client, request);
+        HttpResponse response = client.execute(request);
+        assertEquals("Via request parameter proxy!", contentToString(response));
+
+        RecordedRequest recordedRequest = server.takeRequest();
+        assertEquals("GET http://origin.foo/bar HTTP/1.1", recordedRequest.getRequestLine());
+    }
+
+    public void testExplicitNoProxyCancelsSystemProperty() throws Exception {
+        server.enqueue(new MockResponse().setBody("Via the origin server!"));
+        server.play();
+        System.setProperty("http.proxyHost", "proxy.foo");
+        System.setProperty("http.proxyPort", "8080");
+
+        HttpClient client = newHttpClient();
+        HttpGet request = new HttpGet(server.getUrl("/bar").toURI());
+        request.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, ConnRouteParams.NO_HOST);
+        HttpResponse response = client.execute(request);
+        assertEquals("Via the origin server!", contentToString(response));
+
+        RecordedRequest recordedRequest = server.takeRequest();
+        assertEquals("GET /bar HTTP/1.1", recordedRequest.getRequestLine());
+    }
+
+    enum ProxyConfig {
+        PROXY_SYSTEM_PROPERTY() {
+            @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) {
+                System.setProperty("proxyHost", "localhost");
+                System.setProperty("proxyPort", Integer.toString(server.getPort()));
+            }
+        },
+        HTTP_PROXY_SYSTEM_PROPERTY() {
+            @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) {
+                System.setProperty("http.proxyHost", "localhost");
+                System.setProperty("http.proxyPort", Integer.toString(server.getPort()));
+            }
+        },
+        HTTPS_PROXY_SYSTEM_PROPERTY() {
+            @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) {
+                System.setProperty("https.proxyHost", "localhost");
+                System.setProperty("https.proxyPort", Integer.toString(server.getPort()));
+            }
+        },
+        CLIENT_PARAMETER() {
+            @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) {
+                client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
+                        new HttpHost("localhost", server.getPort()));
+            }
+        },
+        REQUEST_PARAMETER() {
+            @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) {
+                request.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
+                        new HttpHost("localhost", server.getPort()));
+            }
+        };
+
+        abstract void configure(MockWebServer proxy, HttpClient client, HttpRequest request);
+    }
+
+    private void assertContains(List<String> headers, String header) {
+        assertTrue(headers.toString(), headers.contains(header));
+    }
+
+    private String contentToString(HttpResponse response) throws IOException {
+        StringWriter writer = new StringWriter();
+        char[] buffer = new char[1024];
+        Reader reader = new InputStreamReader(response.getEntity().getContent());
+        int length;
+        while ((length = reader.read(buffer)) != -1) {
+            writer.write(buffer, 0, length);
+        }
+        reader.close();
+        return writer.toString();
+    }
+}
diff --git a/core/tests/coretests/src/android/net/http/AndroidHttpClientProxyTest.java b/core/tests/coretests/src/android/net/http/AndroidHttpClientProxyTest.java
new file mode 100644
index 0000000..b33bdb8
--- /dev/null
+++ b/core/tests/coretests/src/android/net/http/AndroidHttpClientProxyTest.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.http;
+
+import org.apache.http.client.HttpClient;
+
+public final class AndroidHttpClientProxyTest extends AbstractProxyTest {
+
+    @Override protected HttpClient newHttpClient() {
+        return AndroidHttpClient.newInstance(AbstractProxyTest.class.getName());
+    }
+}
diff --git a/core/tests/coretests/src/android/net/http/DefaultHttpClientProxyTest.java b/core/tests/coretests/src/android/net/http/DefaultHttpClientProxyTest.java
new file mode 100644
index 0000000..d6313ec
--- /dev/null
+++ b/core/tests/coretests/src/android/net/http/DefaultHttpClientProxyTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.http;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.impl.client.DefaultHttpClient;
+
+public final class DefaultHttpClientProxyTest extends AbstractProxyTest {
+
+    @Override protected HttpClient newHttpClient() {
+        return new DefaultHttpClient();
+    }
+}
diff --git a/core/tests/coretests/src/android/net/http/DefaultHttpClientTest.java b/core/tests/coretests/src/android/net/http/DefaultHttpClientTest.java
new file mode 100644
index 0000000..ad3ec3d
--- /dev/null
+++ b/core/tests/coretests/src/android/net/http/DefaultHttpClientTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.http;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import junit.framework.TestCase;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import tests.http.MockResponse;
+import tests.http.MockWebServer;
+import tests.http.SocketPolicy;
+import static tests.http.SocketPolicy.DISCONNECT_AT_END;
+import static tests.http.SocketPolicy.SHUTDOWN_INPUT_AT_END;
+import static tests.http.SocketPolicy.SHUTDOWN_OUTPUT_AT_END;
+
+public final class DefaultHttpClientTest extends TestCase {
+
+    private MockWebServer server = new MockWebServer();
+
+    @Override protected void tearDown() throws Exception {
+        server.shutdown();
+        super.tearDown();
+    }
+
+    public void testServerClosesSocket() throws Exception {
+        testServerClosesOutput(DISCONNECT_AT_END);
+    }
+
+    public void testServerShutdownInput() throws Exception {
+        testServerClosesOutput(SHUTDOWN_INPUT_AT_END);
+    }
+
+    /**
+     * DefaultHttpClient fails if the server shutdown the output after the
+     * response was sent. http://b/2612240
+     */
+    public void testServerShutdownOutput() throws Exception {
+        testServerClosesOutput(SHUTDOWN_OUTPUT_AT_END);
+    }
+
+    private void testServerClosesOutput(SocketPolicy socketPolicy) throws Exception {
+        server.enqueue(new MockResponse()
+                .setBody("This connection won't pool properly")
+                .setSocketPolicy(socketPolicy));
+        server.enqueue(new MockResponse()
+                .setBody("This comes after a busted connection"));
+        server.play();
+
+        DefaultHttpClient client = new DefaultHttpClient();
+
+        HttpResponse a = client.execute(new HttpGet(server.getUrl("/a").toURI()));
+        assertEquals("This connection won't pool properly", contentToString(a));
+        assertEquals(0, server.takeRequest().getSequenceNumber());
+
+        HttpResponse b = client.execute(new HttpGet(server.getUrl("/b").toURI()));
+        assertEquals("This comes after a busted connection", contentToString(b));
+        // sequence number 0 means the HTTP socket connection was not reused
+        assertEquals(0, server.takeRequest().getSequenceNumber());
+    }
+
+    private String contentToString(HttpResponse response) throws IOException {
+        StringWriter writer = new StringWriter();
+        char[] buffer = new char[1024];
+        Reader reader = new InputStreamReader(response.getEntity().getContent());
+        int length;
+        while ((length = reader.read(buffer)) != -1) {
+            writer.write(buffer, 0, length);
+        }
+        reader.close();
+        return writer.toString();
+    }
+}
diff --git a/core/tests/coretests/src/android/net/http/ProxyTest.java b/core/tests/coretests/src/android/net/http/ProxyTest.java
deleted file mode 100644
index 8175531..0000000
--- a/core/tests/coretests/src/android/net/http/ProxyTest.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.http;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.util.List;
-import junit.framework.TestCase;
-import libcore.javax.net.ssl.TestSSLContext;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.conn.params.ConnRoutePNames;
-import org.apache.http.conn.params.ConnRouteParams;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.impl.client.DefaultHttpClient;
-import tests.http.MockResponse;
-import tests.http.MockWebServer;
-import tests.http.RecordedRequest;
-
-public class ProxyTest extends TestCase {
-
-    private MockWebServer server = new MockWebServer();
-
-    @Override protected void tearDown() throws Exception {
-        System.clearProperty("proxyHost");
-        System.clearProperty("proxyPort");
-        System.clearProperty("http.proxyHost");
-        System.clearProperty("http.proxyPort");
-        System.clearProperty("https.proxyHost");
-        System.clearProperty("https.proxyPort");
-
-        server.shutdown();
-        super.tearDown();
-    }
-
-    public void testConnectToHttps() throws IOException, InterruptedException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
-
-        server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
-        server.enqueue(new MockResponse()
-                .setResponseCode(200)
-                .setBody("this response comes via HTTPS"));
-        server.play();
-
-        HttpClient httpClient = new DefaultHttpClient();
-        SSLSocketFactory sslSocketFactory = new SSLSocketFactory(
-                testSSLContext.clientContext.getSocketFactory());
-        sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier());
-        httpClient.getConnectionManager().getSchemeRegistry()
-                .register(new Scheme("https", sslSocketFactory, server.getPort()));
-
-        HttpResponse response = httpClient.execute(
-                new HttpGet("https://localhost:" + server.getPort() + "/foo"));
-        assertEquals("this response comes via HTTPS", contentToString(response));
-
-        RecordedRequest request = server.takeRequest();
-        assertEquals("GET /foo HTTP/1.1", request.getRequestLine());
-    }
-
-    /**
-     * We had bugs where proxy system properties weren't being honored.
-     * http://b/3254717
-     */
-    public void testConnectViaProxyUsingProxySystemProperty() throws Exception {
-        testConnectViaProxy(ProxyConfig.PROXY_SYSTEM_PROPERTY);
-    }
-
-    public void testConnectViaProxyUsingHttpProxySystemProperty() throws Exception {
-        testConnectViaProxy(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY);
-    }
-
-    public void testConnectViaProxyUsingRequestParameter() throws Exception {
-        testConnectViaProxy(ProxyConfig.REQUEST_PARAMETER);
-    }
-
-    public void testConnectViaProxyUsingClientParameter() throws Exception {
-        testConnectViaProxy(ProxyConfig.CLIENT_PARAMETER);
-    }
-
-    /**
-     * http://code.google.com/p/android/issues/detail?id=2690
-     */
-    private void testConnectViaProxy(ProxyConfig proxyConfig) throws Exception {
-        MockResponse mockResponse = new MockResponse()
-                .setResponseCode(200)
-                .setBody("this response comes via a proxy");
-        server.enqueue(mockResponse);
-        server.play();
-
-        HttpClient httpProxyClient = new DefaultHttpClient();
-
-        HttpGet request = new HttpGet("http://android.com/foo");
-        proxyConfig.configure(server, httpProxyClient, request);
-
-        HttpResponse response = httpProxyClient.execute(request);
-        assertEquals("this response comes via a proxy", contentToString(response));
-
-        RecordedRequest get = server.takeRequest();
-        assertEquals("GET http://android.com/foo HTTP/1.1", get.getRequestLine());
-        assertContains(get.getHeaders(), "Host: android.com");
-    }
-
-    public void testConnectViaHttpProxyToHttpsUsingProxySystemProperty() throws Exception {
-        testConnectViaHttpProxyToHttps(ProxyConfig.PROXY_SYSTEM_PROPERTY);
-    }
-
-    public void testConnectViaHttpProxyToHttpsUsingHttpsProxySystemProperty() throws Exception {
-        testConnectViaHttpProxyToHttps(ProxyConfig.HTTPS_PROXY_SYSTEM_PROPERTY);
-    }
-
-    public void testConnectViaHttpProxyToHttpsUsingClientParameter() throws Exception {
-        testConnectViaHttpProxyToHttps(ProxyConfig.CLIENT_PARAMETER);
-    }
-
-    public void testConnectViaHttpProxyToHttpsUsingRequestParameter() throws Exception {
-        testConnectViaHttpProxyToHttps(ProxyConfig.REQUEST_PARAMETER);
-    }
-
-    private void testConnectViaHttpProxyToHttps(ProxyConfig proxyConfig) throws Exception {
-        TestSSLContext testSSLContext = TestSSLContext.create();
-
-        server.useHttps(testSSLContext.serverContext.getSocketFactory(), true);
-        MockResponse connectResponse = new MockResponse()
-                .setResponseCode(200);
-        connectResponse.getHeaders().clear();
-        server.enqueue(connectResponse);
-        server.enqueue(new MockResponse()
-                .setResponseCode(200)
-                .setBody("this response comes via a secure proxy"));
-        server.play();
-
-        HttpClient httpProxyClient = new DefaultHttpClient();
-        SSLSocketFactory sslSocketFactory = new SSLSocketFactory(
-                testSSLContext.clientContext.getSocketFactory());
-        sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier());
-        httpProxyClient.getConnectionManager().getSchemeRegistry()
-                .register(new Scheme("https", sslSocketFactory, 443));
-
-        HttpGet request = new HttpGet("https://android.com/foo");
-        proxyConfig.configure(server, httpProxyClient, request);
-
-        HttpResponse response = httpProxyClient.execute(request);
-        assertEquals("this response comes via a secure proxy", contentToString(response));
-
-        RecordedRequest connect = server.takeRequest();
-        assertEquals("Connect line failure on proxy " + proxyConfig,
-                "CONNECT android.com:443 HTTP/1.1", connect.getRequestLine());
-        assertContains(connect.getHeaders(), "Host: android.com");
-
-        RecordedRequest get = server.takeRequest();
-        assertEquals("GET /foo HTTP/1.1", get.getRequestLine());
-        assertContains(get.getHeaders(), "Host: android.com");
-    }
-
-    public void testClientParamPreferredOverSystemProperty() throws Exception {
-        testParamPreferredOverSystemProperty(ProxyConfig.CLIENT_PARAMETER);
-    }
-
-    public void testRequestParamPreferredOverSystemProperty() throws Exception {
-        testParamPreferredOverSystemProperty(ProxyConfig.REQUEST_PARAMETER);
-    }
-
-    private void testParamPreferredOverSystemProperty(ProxyConfig proxyConfig) throws Exception {
-        server.enqueue(new MockResponse().setBody("Via request parameter proxy!"));
-        server.play();
-        System.setProperty("http.proxyHost", "proxy.foo");
-        System.setProperty("http.proxyPort", "8080");
-
-        HttpClient client = new DefaultHttpClient();
-        HttpGet request = new HttpGet("http://origin.foo/bar");
-        proxyConfig.configure(server, client, request);
-        HttpResponse response = client.execute(request);
-        assertEquals("Via request parameter proxy!", contentToString(response));
-
-        RecordedRequest recordedRequest = server.takeRequest();
-        assertEquals("GET http://origin.foo/bar HTTP/1.1", recordedRequest.getRequestLine());
-    }
-
-    public void testExplicitNoProxyCancelsSystemProperty() throws Exception {
-        server.enqueue(new MockResponse().setBody("Via the origin server!"));
-        server.play();
-        System.setProperty("http.proxyHost", "proxy.foo");
-        System.setProperty("http.proxyPort", "8080");
-
-        HttpClient client = new DefaultHttpClient();
-        HttpGet request = new HttpGet(server.getUrl("/bar").toURI());
-        request.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, ConnRouteParams.NO_HOST);
-        HttpResponse response = client.execute(request);
-        assertEquals("Via the origin server!", contentToString(response));
-
-        RecordedRequest recordedRequest = server.takeRequest();
-        assertEquals("GET /bar HTTP/1.1", recordedRequest.getRequestLine());
-    }
-
-    enum ProxyConfig {
-        PROXY_SYSTEM_PROPERTY() {
-            @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) {
-                System.setProperty("proxyHost", "localhost");
-                System.setProperty("proxyPort", Integer.toString(server.getPort()));
-            }
-        },
-        HTTP_PROXY_SYSTEM_PROPERTY() {
-            @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) {
-                System.setProperty("http.proxyHost", "localhost");
-                System.setProperty("http.proxyPort", Integer.toString(server.getPort()));
-            }
-        },
-        HTTPS_PROXY_SYSTEM_PROPERTY() {
-            @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) {
-                System.setProperty("https.proxyHost", "localhost");
-                System.setProperty("https.proxyPort", Integer.toString(server.getPort()));
-            }
-        },
-        CLIENT_PARAMETER() {
-            @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) {
-                client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
-                        new HttpHost("localhost", server.getPort()));
-            }
-        },
-        REQUEST_PARAMETER() {
-            @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) {
-                request.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
-                        new HttpHost("localhost", server.getPort()));
-            }
-        };
-
-        abstract void configure(MockWebServer proxy, HttpClient client, HttpRequest request);
-    }
-
-    private void assertContains(List<String> headers, String header) {
-        assertTrue(headers.toString(), headers.contains(header));
-    }
-
-    private String contentToString(HttpResponse response) throws IOException {
-        StringWriter writer = new StringWriter();
-        char[] buffer = new char[1024];
-        Reader reader = new InputStreamReader(response.getEntity().getContent());
-        int length;
-        while ((length = reader.read(buffer)) != -1) {
-            writer.write(buffer, 0, length);
-        }
-        reader.close();
-        return writer.toString();
-    }
-}
diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java
index 216a772..b5c2c27 100644
--- a/core/tests/coretests/src/android/util/JsonReaderTest.java
+++ b/core/tests/coretests/src/android/util/JsonReaderTest.java
@@ -16,11 +16,10 @@
 
 package android.util;
 
-import java.util.Arrays;
-import junit.framework.TestCase;
-
 import java.io.IOException;
 import java.io.StringReader;
+import java.util.Arrays;
+import junit.framework.TestCase;
 
 public final class JsonReaderTest extends TestCase {
 
@@ -677,7 +676,7 @@
         try {
             reader.nextString();
             fail();
-        } catch (IOException expected) {
+        } catch (MalformedJsonException expected) {
         }
     }
 
@@ -811,4 +810,50 @@
         reader.nextNull();
         reader.endArray();
     }
+
+    public void testStrictMultipleTopLevelValues() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[] []"));
+        reader.beginArray();
+        reader.endArray();
+        try {
+            reader.peek();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientMultipleTopLevelValues() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[] true {}"));
+        reader.setLenient(true);
+        reader.beginArray();
+        reader.endArray();
+        assertEquals(true, reader.nextBoolean());
+        reader.beginObject();
+        reader.endObject();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testStrictTopLevelValueType() {
+        JsonReader reader = new JsonReader(new StringReader("true"));
+        try {
+            reader.nextBoolean();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientTopLevelValueType() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("true"));
+        reader.setLenient(true);
+        assertEquals(true, reader.nextBoolean());
+    }
+
+    public void testStrictNonExecutePrefix() {
+        JsonReader reader = new JsonReader(new StringReader(")]}'\n []"));
+        try {
+            reader.beginArray();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
 }
diff --git a/core/tests/coretests/src/android/util/JsonWriterTest.java b/core/tests/coretests/src/android/util/JsonWriterTest.java
index fa84023..b29e2fd 100644
--- a/core/tests/coretests/src/android/util/JsonWriterTest.java
+++ b/core/tests/coretests/src/android/util/JsonWriterTest.java
@@ -16,10 +16,11 @@
 
 package android.util;
 
-import junit.framework.TestCase;
-
 import java.io.IOException;
 import java.io.StringWriter;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import junit.framework.TestCase;
 
 public final class JsonWriterTest extends TestCase {
 
@@ -119,7 +120,7 @@
         JsonWriter jsonWriter = new JsonWriter(stringWriter);
         jsonWriter.beginObject();
         jsonWriter.name("a");
-        jsonWriter.value(null);
+        jsonWriter.value((String) null);
         jsonWriter.endObject();
         assertEquals("{\"a\":null}", stringWriter.toString());
     }
@@ -145,6 +146,27 @@
         }
     }
 
+    public void testNonFiniteBoxedDoubles() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        try {
+            jsonWriter.value(new Double(Double.NaN));
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            jsonWriter.value(new Double(Double.NEGATIVE_INFINITY));
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            jsonWriter.value(new Double(Double.POSITIVE_INFINITY));
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
     public void testDoubles() throws IOException {
         StringWriter stringWriter = new StringWriter();
         JsonWriter jsonWriter = new JsonWriter(stringWriter);
@@ -189,6 +211,22 @@
                 + "9223372036854775807]", stringWriter.toString());
     }
 
+    public void testNumbers() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.value(new BigInteger("0"));
+        jsonWriter.value(new BigInteger("9223372036854775808"));
+        jsonWriter.value(new BigInteger("-9223372036854775809"));
+        jsonWriter.value(new BigDecimal("3.141592653589793238462643383"));
+        jsonWriter.endArray();
+        jsonWriter.close();
+        assertEquals("[0,"
+                + "9223372036854775808,"
+                + "-9223372036854775809,"
+                + "3.141592653589793238462643383]", stringWriter.toString());
+    }
+
     public void testBooleans() throws IOException {
         StringWriter stringWriter = new StringWriter();
         JsonWriter jsonWriter = new JsonWriter(stringWriter);
diff --git a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
index 955f5e8..4edd127 100644
--- a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
+++ b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
@@ -19,6 +19,7 @@
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Intent;
 import android.os.Handler;
 import android.os.Looper;
@@ -29,6 +30,8 @@
 import android.view.KeyEvent;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
 
 /**
  * This is a test for the behavior of the {@link AccessibilityInjector}
@@ -60,6 +63,17 @@
     /** Lock for locking the test. */
     private static final Object sTestLock = new Object();
 
+    /** Key bindings used for testing. */
+    private static final String TEST_KEY_DINDINGS =
+        "0x13=0x01000100;" +
+        "0x14=0x01010100;" +
+        "0x15=0x04000000;" +
+        "0x16=0x04000000;" +
+        "0x200000013=0x03020701:0x03010201:0x03000101:0x03030001:0x03040001:0x03050001:0x03060001;" +
+        "0x200000014=0x03010001:0x03020101:0x03070201:0x03030701:0x03040701:0x03050701:0x03060701;" +
+        "0x200000015=0x03040301:0x03050401:0x03060501:0x03000601:0x03010601:0x03020601:0x03070601;" +
+        "0x200000016=0x03050601:0x03040501:0x03030401:0x03020301:0x03070301:0x03010301:0x03000301;";
+
     /** Handle to the test for use by the mock service. */
     private static AccessibilityInjectorTest sInstance;
 
@@ -75,6 +89,9 @@
     /** Handle to the {@link WebView} to load data in. */
     private WebView mWebView;
 
+    /** Used for caching the default bindings so they can be restored. */
+    private String mDefaultKeyBindings;
+
     /** The received selection string for assertion checking. */
     private static String sReceivedSelectionString = SELECTION_STRING_UNKNOWN;
 
@@ -87,6 +104,7 @@
             // until JUnit4 comes to play with @BeforeTest
             disableAccessibilityAndMockAccessibilityService();
             enableAccessibilityAndMockAccessibilityService();
+            injectTestWebContentKeyBindings();
         }
     }
 
@@ -98,6 +116,7 @@
         if (sExecutedTestCount == TEST_CASE_COUNT) {
             // until JUnit4 comes to play with @AfterTest
             disableAccessibilityAndMockAccessibilityService();
+            restoreDefaultWebContentKeyBindings();
         }
         super.tearDown();
     }
@@ -852,6 +871,26 @@
     }
 
     /**
+     * Injects web content key bindings used for testing. This is required
+     * to ensure that this test will be agnostic to changes of the bindings.
+     */
+    private void injectTestWebContentKeyBindings() {
+        ContentResolver contentResolver = getContext().getContentResolver();
+        mDefaultKeyBindings = Settings.Secure.getString(contentResolver,
+                Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS);
+        Settings.Secure.putString(contentResolver,
+                Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS, TEST_KEY_DINDINGS);
+    }
+
+    /**
+     * Restores the default web content key bindings.
+     */
+    private void restoreDefaultWebContentKeyBindings() {
+        Settings.Secure.putString(getContext().getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS, mDefaultKeyBindings);
+    }
+
+    /**
      * This is a worker thread responsible for creating the {@link WebView}.
      */
     private class Worker implements Runnable {
diff --git a/core/tests/coretests/src/android/widget/TextViewWordLimitsTest.java b/core/tests/coretests/src/android/widget/TextViewWordLimitsTest.java
new file mode 100644
index 0000000..20305bf
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/TextViewWordLimitsTest.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package android.widget;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.text.InputType;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.SpannableString;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * TextViewPatchTest tests {@link TextView}'s definition of word. Finds and
+ * verifies word limits to be in strings containing different kinds of
+ * characters.
+ */
+public class TextViewWordLimitsTest extends AndroidTestCase {
+
+    TextView mTv = null;
+    Method mGetWordLimits, mSelectCurrentWord;
+    Field mContextMenuTriggeredByKey, mSelectionControllerEnabled;
+
+
+    /**
+     * Sets up common fields used in all test cases.
+     * @throws NoSuchFieldException
+     * @throws SecurityException
+     */
+    @Override
+    protected void setUp() throws NoSuchMethodException, SecurityException, NoSuchFieldException {
+        mTv = new TextView(getContext());
+        mTv.setInputType(InputType.TYPE_CLASS_TEXT);
+
+        mGetWordLimits = mTv.getClass().getDeclaredMethod("getWordLimitsAt",
+                new Class[] {int.class});
+        mGetWordLimits.setAccessible(true);
+
+        mSelectCurrentWord = mTv.getClass().getDeclaredMethod("selectCurrentWord", new Class[] {});
+        mSelectCurrentWord.setAccessible(true);
+
+        mContextMenuTriggeredByKey = mTv.getClass().getDeclaredField("mContextMenuTriggeredByKey");
+        mContextMenuTriggeredByKey.setAccessible(true);
+        mSelectionControllerEnabled = mTv.getClass().getDeclaredField("mSelectionControllerEnabled");
+        mSelectionControllerEnabled.setAccessible(true);
+    }
+
+    /**
+     * Calculate and verify word limits. Depends on the TextView implementation.
+     * Uses a private method and internal data representation.
+     *
+     * @param text         Text to select a word from
+     * @param pos          Position to expand word around
+     * @param correctStart Correct start position for the word
+     * @param correctEnd   Correct end position for the word
+     * @throws InvocationTargetException
+     * @throws IllegalAccessException
+     * @throws IllegalArgumentException
+     * @throws InvocationTargetException
+     * @throws IllegalAccessException
+     */
+    private void verifyWordLimits(String text, int pos, int correctStart, int correctEnd)
+    throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+        mTv.setText(text, TextView.BufferType.SPANNABLE);
+
+        long limits = (Long)mGetWordLimits.invoke(mTv, new Object[] {new Integer(pos)});
+        int actualStart = (int)(limits >>> 32);
+        int actualEnd = (int)(limits & 0x00000000FFFFFFFFL);
+        assertEquals(correctStart, actualStart);
+        assertEquals(correctEnd, actualEnd);
+    }
+
+
+    private void verifySelectCurrentWord(Spannable text, int selectionStart, int selectionEnd, int correctStart,
+            int correctEnd) throws InvocationTargetException, IllegalAccessException {
+        mTv.setText(text, TextView.BufferType.SPANNABLE);
+
+        Selection.setSelection((Spannable)mTv.getText(), selectionStart, selectionEnd);
+        mContextMenuTriggeredByKey.setBoolean(mTv, true);
+        mSelectionControllerEnabled.setBoolean(mTv, true);
+        mSelectCurrentWord.invoke(mTv);
+
+        assertEquals(correctStart, mTv.getSelectionStart());
+        assertEquals(correctEnd, mTv.getSelectionEnd());
+    }
+
+
+    /**
+     * Corner cases for string length.
+     */
+    @LargeTest
+    public void testLengths() throws Exception {
+        final String ONE_TWO = "one two";
+        final String EMPTY   = "";
+        final String TOOLONG = "ThisWordIsTooLongToBeDefinedAsAWordInTheSenseUsedInTextView";
+
+        // Select first word
+        verifyWordLimits(ONE_TWO, 0, 0, 3);
+        verifyWordLimits(ONE_TWO, 3, 0, 3);
+
+        // Select last word
+        verifyWordLimits(ONE_TWO, 4, 4, 7);
+        verifyWordLimits(ONE_TWO, 7, 4, 7);
+
+        // Empty string
+        verifyWordLimits(EMPTY, 0, -1, -1);
+
+        // Too long word
+        verifyWordLimits(TOOLONG, 0, -1, -1);
+    }
+
+    /**
+     * Unicode classes included.
+     */
+    @LargeTest
+    public void testIncludedClasses() throws Exception {
+        final String LOWER          = "njlj";
+        final String UPPER          = "NJLJ";
+        final String TITLECASE      = "\u01C8\u01CB\u01F2"; // Lj Nj Dz
+        final String OTHER          = "\u3042\u3044\u3046"; // Hiragana AIU
+        final String MODIFIER       = "\u02C6\u02CA\u02CB"; // Circumflex Acute Grave
+
+        // Each string contains a single valid word
+        verifyWordLimits(LOWER, 1, 0, 4);
+        verifyWordLimits(UPPER, 1, 0, 4);
+        verifyWordLimits(TITLECASE, 1, 0, 3);
+        verifyWordLimits(OTHER, 1, 0, 3);
+        verifyWordLimits(MODIFIER, 1, 0, 3);
+    }
+
+    /**
+     * Unicode classes included if combined with a letter.
+     */
+    @LargeTest
+    public void testPartlyIncluded() throws Exception {
+        final String NUMBER           = "123";
+        final String NUMBER_LOWER     = "1st";
+        final String APOSTROPHE       = "''";
+        final String APOSTROPHE_LOWER = "'Android's'";
+
+        // Pure decimal number is ignored
+        verifyWordLimits(NUMBER, 1, -1, -1);
+
+        // Number with letter is valid
+        verifyWordLimits(NUMBER_LOWER, 1, 0, 3);
+
+        // Stand apostrophes are ignore
+        verifyWordLimits(APOSTROPHE, 1, -1, -1);
+
+        // Apostrophes are accepted if they are a part of a word
+        verifyWordLimits(APOSTROPHE_LOWER, 1, 0, 11);
+    }
+
+    /**
+     * Unicode classes included if combined with a letter.
+     */
+    @LargeTest
+    public void testFinalSeparator() throws Exception {
+        final String PUNCTUATION = "abc, def.";
+
+        // Starting from the comma
+        verifyWordLimits(PUNCTUATION, 3, 0, 3);
+        verifyWordLimits(PUNCTUATION, 4, 0, 4);
+
+        // Starting from the final period
+        verifyWordLimits(PUNCTUATION, 8, 5, 8);
+        verifyWordLimits(PUNCTUATION, 9, 5, 9);
+    }
+
+    /**
+     * Unicode classes other than listed in testIncludedClasses and
+     * testPartlyIncluded act as word separators.
+     */
+    @LargeTest
+    public void testNotIncluded() throws Exception {
+        // Selection of character classes excluded
+        final String MARK_NONSPACING        = "a\u030A";       // a Combining ring above
+        final String PUNCTUATION_OPEN_CLOSE = "(c)";           // Parenthesis
+        final String PUNCTUATION_DASH       = "non-fiction";   // Hyphen
+        final String PUNCTUATION_OTHER      = "b&b";           // Ampersand
+        final String SYMBOL_OTHER           = "Android\u00AE"; // Registered
+        final String SEPARATOR_SPACE        = "one two";       // Space
+
+        // "a"
+        verifyWordLimits(MARK_NONSPACING, 1, 0, 1);
+
+        // "c"
+        verifyWordLimits(PUNCTUATION_OPEN_CLOSE, 1, 1, 2);
+
+        // "non-"
+        verifyWordLimits(PUNCTUATION_DASH, 3, 0, 3);
+        verifyWordLimits(PUNCTUATION_DASH, 4, 4, 11);
+
+        // "b"
+        verifyWordLimits(PUNCTUATION_OTHER, 0, 0, 1);
+        verifyWordLimits(PUNCTUATION_OTHER, 1, 0, 1);
+        verifyWordLimits(PUNCTUATION_OTHER, 2, 0, 3); // & is considered a punctuation sign.
+        verifyWordLimits(PUNCTUATION_OTHER, 3, 2, 3);
+
+        // "Android"
+        verifyWordLimits(SYMBOL_OTHER, 7, 0, 7);
+        verifyWordLimits(SYMBOL_OTHER, 8, -1, -1);
+
+        // "one"
+        verifyWordLimits(SEPARATOR_SPACE, 1, 0, 3);
+    }
+
+    /**
+     * Surrogate characters are treated as their code points.
+     */
+    @LargeTest
+    public void testSurrogate() throws Exception {
+        final String SURROGATE_LETTER   = "\uD800\uDC00\uD800\uDC01\uD800\uDC02"; // Linear B AEI
+        final String SURROGATE_SYMBOL   = "\uD83D\uDE01\uD83D\uDE02\uD83D\uDE03"; // Three smileys
+
+        // Letter Other is included even when coded as surrogate pairs
+        verifyWordLimits(SURROGATE_LETTER, 0, 0, 6);
+        verifyWordLimits(SURROGATE_LETTER, 1, 0, 6);
+        verifyWordLimits(SURROGATE_LETTER, 2, 0, 6);
+        verifyWordLimits(SURROGATE_LETTER, 3, 0, 6);
+        verifyWordLimits(SURROGATE_LETTER, 4, 0, 6);
+        verifyWordLimits(SURROGATE_LETTER, 5, 0, 6);
+        verifyWordLimits(SURROGATE_LETTER, 6, 0, 6);
+
+        // Not included classes are ignored even when coded as surrogate pairs
+        verifyWordLimits(SURROGATE_SYMBOL, 0, -1, -1);
+        verifyWordLimits(SURROGATE_SYMBOL, 1, -1, -1);
+        verifyWordLimits(SURROGATE_SYMBOL, 2, -1, -1);
+        verifyWordLimits(SURROGATE_SYMBOL, 3, -1, -1);
+        verifyWordLimits(SURROGATE_SYMBOL, 4, -1, -1);
+        verifyWordLimits(SURROGATE_SYMBOL, 5, -1, -1);
+        verifyWordLimits(SURROGATE_SYMBOL, 6, -1, -1);
+    }
+
+    /**
+     * Selection is used if present and valid word.
+     */
+    @LargeTest
+    public void testSelectCurrentWord() throws Exception {
+        SpannableString textLower       = new SpannableString("first second");
+        SpannableString textOther       = new SpannableString("\u3042\3044\3046"); // Hiragana AIU
+        SpannableString textDash        = new SpannableString("non-fiction");      // Hyphen
+        SpannableString textPunctOther  = new SpannableString("b&b");              // Ampersand
+        SpannableString textSymbolOther = new SpannableString("Android\u00AE");    // Registered
+
+        // Valid selection - Letter, Lower
+        verifySelectCurrentWord(textLower, 2, 5, 0, 5);
+
+        // Adding the space spreads to the second word
+        verifySelectCurrentWord(textLower, 2, 6, 0, 12);
+
+        // Valid selection -- Letter, Other
+        verifySelectCurrentWord(textOther, 1, 2, 0, 5);
+
+        // Zero-width selection is interpreted as a cursor and the selection is ignored
+        verifySelectCurrentWord(textLower, 2, 2, 0, 5);
+
+        // Hyphen is part of selection
+        verifySelectCurrentWord(textDash, 2, 5, 0, 11);
+
+        // Ampersand part of selection or not
+        verifySelectCurrentWord(textPunctOther, 1, 2, 0, 3);
+        verifySelectCurrentWord(textPunctOther, 1, 3, 0, 3);
+
+        // (R) part of the selection
+        verifySelectCurrentWord(textSymbolOther, 2, 7, 0, 7);
+        verifySelectCurrentWord(textSymbolOther, 2, 8, 0, 8);
+    }
+}
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
index 7206f4a..a419068 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
@@ -18,8 +18,7 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
-				   ../../../coretests/src/android/app/DownloadManagerBaseTest.java
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-common frameworks-core-util-lib
 LOCAL_SDK_VERSION := current
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerBaseTest.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerBaseTest.java
new file mode 100644
index 0000000..acd2a18
--- /dev/null
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerBaseTest.java
@@ -0,0 +1,816 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.frameworks.downloadmanagertests;
+
+import android.app.DownloadManager;
+import android.app.DownloadManager.Query;
+import android.app.DownloadManager.Request;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.Cursor;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
+import android.os.ParcelFileDescriptor.AutoCloseInputStream;
+import android.provider.Settings;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.concurrent.TimeoutException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+import java.util.Vector;
+
+import junit.framework.AssertionFailedError;
+
+import coretestutils.http.MockResponse;
+import coretestutils.http.MockWebServer;
+
+/**
+ * Base class for Instrumented tests for the Download Manager.
+ */
+public class DownloadManagerBaseTest extends InstrumentationTestCase {
+
+    protected DownloadManager mDownloadManager = null;
+    protected MockWebServer mServer = null;
+    protected String mFileType = "text/plain";
+    protected Context mContext = null;
+    protected MultipleDownloadsCompletedReceiver mReceiver = null;
+    protected static final int DEFAULT_FILE_SIZE = 10 * 1024;  // 10kb
+    protected static final int FILE_BLOCK_READ_SIZE = 1024 * 1024;
+
+    protected static final String LOG_TAG = "android.net.DownloadManagerBaseTest";
+    protected static final int HTTP_OK = 200;
+    protected static final int HTTP_REDIRECT = 307;
+    protected static final int HTTP_PARTIAL_CONTENT = 206;
+    protected static final int HTTP_NOT_FOUND = 404;
+    protected static final int HTTP_SERVICE_UNAVAILABLE = 503;
+    protected String DEFAULT_FILENAME = "somefile.txt";
+
+    protected static final int DEFAULT_MAX_WAIT_TIME = 2 * 60 * 1000;  // 2 minutes
+    protected static final int DEFAULT_WAIT_POLL_TIME = 5 * 1000;  // 5 seconds
+
+    protected static final int WAIT_FOR_DOWNLOAD_POLL_TIME = 1 * 1000;  // 1 second
+    protected static final int MAX_WAIT_FOR_DOWNLOAD_TIME = 5 * 60 * 1000; // 5 minutes
+    protected static final int MAX_WAIT_FOR_LARGE_DOWNLOAD_TIME = 15 * 60 * 1000; // 15 minutes
+
+    protected static final int DOWNLOAD_TO_SYSTEM_CACHE = 1;
+    protected static final int DOWNLOAD_TO_DOWNLOAD_CACHE_DIR = 2;
+
+    // Just a few popular file types used to return from a download
+    protected enum DownloadFileType {
+        PLAINTEXT,
+        APK,
+        GIF,
+        GARBAGE,
+        UNRECOGNIZED,
+        ZIP
+    }
+
+    protected enum DataType {
+        TEXT,
+        BINARY
+    }
+
+    public static class LoggingRng extends Random {
+
+        /**
+         * Constructor
+         *
+         * Creates RNG with self-generated seed value.
+         */
+        public LoggingRng() {
+            this(SystemClock.uptimeMillis());
+        }
+
+        /**
+         * Constructor
+         *
+         * Creats RNG with given initial seed value
+
+         * @param seed The initial seed value
+         */
+        public LoggingRng(long seed) {
+            super(seed);
+            Log.i(LOG_TAG, "Seeding RNG with value: " + seed);
+        }
+    }
+
+    public static class MultipleDownloadsCompletedReceiver extends BroadcastReceiver {
+        private volatile int mNumDownloadsCompleted = 0;
+        private Set<Long> downloadIds = Collections.synchronizedSet(new HashSet<Long>());
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equalsIgnoreCase(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
+                synchronized(this) {
+                    long id = intent.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
+                    Log.i(LOG_TAG, "Received Notification for download: " + id);
+                    if (!downloadIds.contains(id)) {
+                        ++mNumDownloadsCompleted;
+                        Log.i(LOG_TAG, "MultipleDownloadsCompletedReceiver got intent: " +
+                                intent.getAction() + " --> total count: " + mNumDownloadsCompleted);
+                        downloadIds.add(id);
+
+                        DownloadManager dm = (DownloadManager)context.getSystemService(
+                                Context.DOWNLOAD_SERVICE);
+
+                        Cursor cursor = dm.query(new Query().setFilterById(id));
+                        try {
+                            if (cursor.moveToFirst()) {
+                                int status = cursor.getInt(cursor.getColumnIndex(
+                                        DownloadManager.COLUMN_STATUS));
+                                Log.i(LOG_TAG, "Download status is: " + status);
+                            } else {
+                                fail("No status found for completed download!");
+                            }
+                        } finally {
+                            cursor.close();
+                        }
+                    } else {
+                        Log.i(LOG_TAG, "Notification for id: " + id + " has already been made.");
+                    }
+                }
+            }
+        }
+
+        /**
+         * Gets the number of times the {@link #onReceive} callback has been called for the
+         * {@link DownloadManager.ACTION_DOWNLOAD_COMPLETED} action, indicating the number of
+         * downloads completed thus far.
+         *
+         * @return the number of downloads completed so far.
+         */
+        public int numDownloadsCompleted() {
+            return mNumDownloadsCompleted;
+        }
+
+        /**
+         * Gets the list of download IDs.
+         * @return A Set<Long> with the ids of the completed downloads.
+         */
+        public Set<Long> getDownloadIds() {
+            synchronized(this) {
+                Set<Long> returnIds = new HashSet<Long>(downloadIds);
+                return returnIds;
+            }
+        }
+
+    }
+
+    public static class WiFiChangedReceiver extends BroadcastReceiver {
+        private Context mContext = null;
+
+        /**
+         * Constructor
+         *
+         * Sets the current state of WiFi.
+         *
+         * @param context The current app {@link Context}.
+         */
+        public WiFiChangedReceiver(Context context) {
+            mContext = context;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equalsIgnoreCase(ConnectivityManager.CONNECTIVITY_ACTION)) {
+                Log.i(LOG_TAG, "ConnectivityManager state change: " + intent.getAction());
+                synchronized (this) {
+                    this.notify();
+                }
+            }
+        }
+
+        /**
+         * Gets the current state of WiFi.
+         *
+         * @return Returns true if WiFi is on, false otherwise.
+         */
+        public boolean getWiFiIsOn() {
+            ConnectivityManager connManager = (ConnectivityManager)mContext.getSystemService(
+                    Context.CONNECTIVITY_SERVICE);
+            NetworkInfo info = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+            Log.i(LOG_TAG, "WiFi Connection state is currently: " + info.isConnected());
+            return info.isConnected();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setUp() throws Exception {
+        mContext = getInstrumentation().getContext();
+        mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE);
+        mServer = new MockWebServer();
+        mReceiver = registerNewMultipleDownloadsReceiver();
+        // Note: callers overriding this should call mServer.play() with the desired port #
+    }
+
+    /**
+     * Helper to enqueue a response from the MockWebServer.
+     *
+     * @param status The HTTP status code to return for this response
+     * @param body The body to return in this response
+     * @return Returns the mock web server response that was queued (which can be modified)
+     */
+    private MockResponse enqueueResponse(int status, byte[] body) {
+        return doEnqueueResponse(status).setBody(body);
+
+    }
+
+    /**
+     * Helper to enqueue a response from the MockWebServer.
+     *
+     * @param status The HTTP status code to return for this response
+     * @param bodyFile The body to return in this response
+     * @return Returns the mock web server response that was queued (which can be modified)
+     */
+    private MockResponse enqueueResponse(int status, File bodyFile) {
+        return doEnqueueResponse(status).setBody(bodyFile);
+    }
+
+    /**
+     * Helper for enqueue'ing a response from the MockWebServer.
+     *
+     * @param status The HTTP status code to return for this response
+     * @return Returns the mock web server response that was queued (which can be modified)
+     */
+    private MockResponse doEnqueueResponse(int status) {
+        MockResponse response = new MockResponse().setResponseCode(status);
+        response.addHeader("Content-type", mFileType);
+        mServer.enqueue(response);
+        return response;
+    }
+
+    /**
+     * Helper to generate a random blob of bytes using a given RNG.
+     *
+     * @param size The size of the data to generate
+     * @param type The type of data to generate: currently, one of {@link DataType.TEXT} or
+     *         {@link DataType.BINARY}.
+     * @param rng (optional) The RNG to use; pass null to use
+     * @return The random data that is generated.
+     */
+    private byte[] generateData(int size, DataType type, Random rng) {
+        int min = Byte.MIN_VALUE;
+        int max = Byte.MAX_VALUE;
+
+        // Only use chars in the HTTP ASCII printable character range for Text
+        if (type == DataType.TEXT) {
+            min = 32;
+            max = 126;
+        }
+        byte[] result = new byte[size];
+        Log.i(LOG_TAG, "Generating data of size: " + size);
+
+        if (rng == null) {
+            rng = new LoggingRng();
+        }
+
+        for (int i = 0; i < size; ++i) {
+            result[i] = (byte) (min + rng.nextInt(max - min + 1));
+        }
+        return result;
+    }
+
+    /**
+     * Helper to verify the size of a file.
+     *
+     * @param pfd The input file to compare the size of
+     * @param size The expected size of the file
+     */
+    protected void verifyFileSize(ParcelFileDescriptor pfd, long size) {
+        assertEquals(pfd.getStatSize(), size);
+    }
+
+    /**
+     * Helper to verify the contents of a downloaded file versus a byte[].
+     *
+     * @param actual The file of whose contents to verify
+     * @param expected The data we expect to find in the aforementioned file
+     * @throws IOException if there was a problem reading from the file
+     */
+    private void verifyFileContents(ParcelFileDescriptor actual, byte[] expected)
+            throws IOException {
+        AutoCloseInputStream input = new ParcelFileDescriptor.AutoCloseInputStream(actual);
+        long fileSize = actual.getStatSize();
+
+        assertTrue(fileSize <= Integer.MAX_VALUE);
+        assertEquals(expected.length, fileSize);
+
+        byte[] actualData = new byte[expected.length];
+        assertEquals(input.read(actualData), fileSize);
+        compareByteArrays(actualData, expected);
+    }
+
+    /**
+     * Helper to compare 2 byte arrays.
+     *
+     * @param actual The array whose data we want to verify
+     * @param expected The array of data we expect to see
+     */
+    private void compareByteArrays(byte[] actual, byte[] expected) {
+        assertEquals(actual.length, expected.length);
+        int length = actual.length;
+        for (int i = 0; i < length; ++i) {
+            // assert has a bit of overhead, so only do the assert when the values are not the same
+            if (actual[i] != expected[i]) {
+                fail("Byte arrays are not equal.");
+            }
+        }
+    }
+
+    /**
+     * Gets the MIME content string for a given type
+     *
+     * @param type The MIME type to return
+     * @return the String representation of that MIME content type
+     */
+    protected String getMimeMapping(DownloadFileType type) {
+        switch (type) {
+            case APK:
+                return "application/vnd.android.package-archive";
+            case GIF:
+                return "image/gif";
+            case ZIP:
+                return "application/x-zip-compressed";
+            case GARBAGE:
+                return "zip\\pidy/doo/da";
+            case UNRECOGNIZED:
+                return "application/new.undefined.type.of.app";
+        }
+        return "text/plain";
+    }
+
+    /**
+     * Gets the Uri that should be used to access the mock server
+     *
+     * @param filename The name of the file to try to retrieve from the mock server
+     * @return the Uri to use for access the file on the mock server
+     */
+    private Uri getServerUri(String filename) throws Exception {
+        URL url = mServer.getUrl("/" + filename);
+        return Uri.parse(url.toString());
+    }
+
+    /**
+     * Helper to create and register a new MultipleDownloadCompletedReciever
+     *
+     * This is used to track many simultaneous downloads by keeping count of all the downloads
+     * that have completed.
+     *
+     * @return A new receiver that records and can be queried on how many downloads have completed.
+     */
+    protected MultipleDownloadsCompletedReceiver registerNewMultipleDownloadsReceiver() {
+        MultipleDownloadsCompletedReceiver receiver = new MultipleDownloadsCompletedReceiver();
+        mContext.registerReceiver(receiver, new IntentFilter(
+                DownloadManager.ACTION_DOWNLOAD_COMPLETE));
+        return receiver;
+    }
+
+    /**
+     * Enables or disables WiFi.
+     *
+     * Note: Needs the following permissions:
+     *  android.permission.ACCESS_WIFI_STATE
+     *  android.permission.CHANGE_WIFI_STATE
+     * @param enable true if it should be enabled, false if it should be disabled
+     */
+    protected void setWiFiStateOn(boolean enable) throws Exception {
+        Log.i(LOG_TAG, "Setting WiFi State to: " + enable);
+        WifiManager manager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
+
+        manager.setWifiEnabled(enable);
+
+        String timeoutMessage = "Timed out waiting for Wifi to be "
+            + (enable ? "enabled!" : "disabled!");
+
+        WiFiChangedReceiver receiver = new WiFiChangedReceiver(mContext);
+        mContext.registerReceiver(receiver, new IntentFilter(
+                ConnectivityManager.CONNECTIVITY_ACTION));
+
+        synchronized (receiver) {
+            long timeoutTime = SystemClock.elapsedRealtime() + DEFAULT_MAX_WAIT_TIME;
+            boolean timedOut = false;
+
+            while (receiver.getWiFiIsOn() != enable && !timedOut) {
+                try {
+                    receiver.wait(DEFAULT_WAIT_POLL_TIME);
+
+                    if (SystemClock.elapsedRealtime() > timeoutTime) {
+                        timedOut = true;
+                    }
+                }
+                catch (InterruptedException e) {
+                    // ignore InterruptedExceptions
+                }
+            }
+            if (timedOut) {
+                fail(timeoutMessage);
+            }
+        }
+        assertEquals(enable, receiver.getWiFiIsOn());
+    }
+
+    /**
+     * Helper to enables or disables airplane mode. If successful, it also broadcasts an intent
+     * indicating that the mode has changed.
+     *
+     * Note: Needs the following permission:
+     *  android.permission.WRITE_SETTINGS
+     * @param enable true if airplane mode should be ON, false if it should be OFF
+     */
+    protected void setAirplaneModeOn(boolean enable) throws Exception {
+        int state = enable ? 1 : 0;
+
+        // Change the system setting
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
+                state);
+
+        String timeoutMessage = "Timed out waiting for airplane mode to be " +
+                (enable ? "enabled!" : "disabled!");
+
+        // wait for airplane mode to change state
+        int currentWaitTime = 0;
+        while (Settings.System.getInt(mContext.getContentResolver(),
+                Settings.System.AIRPLANE_MODE_ON, -1) != state) {
+            timeoutWait(currentWaitTime, DEFAULT_WAIT_POLL_TIME, DEFAULT_MAX_WAIT_TIME,
+                    timeoutMessage);
+        }
+
+        // Post the intent
+        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+        intent.putExtra("state", true);
+        mContext.sendBroadcast(intent);
+    }
+
+    /**
+     * Helper to wait for a particular download to finish, or else a timeout to occur
+     *
+     * Does not wait for a receiver notification of the download.
+     *
+     * @param id The download id to query on (wait for)
+     */
+    private void waitForDownloadOrTimeout_skipNotification(long id) throws TimeoutException,
+            InterruptedException {
+        waitForDownloadOrTimeout(id, WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME);
+    }
+
+    /**
+     * Helper to wait for a particular download to finish, or else a timeout to occur
+     *
+     * Also guarantees a notification has been posted for the download.
+     *
+     * @param id The download id to query on (wait for)
+     */
+    protected void waitForDownloadOrTimeout(long id) throws TimeoutException,
+            InterruptedException {
+        waitForDownloadOrTimeout_skipNotification(id);
+        waitForReceiverNotifications(1);
+    }
+
+    /**
+     * Helper to wait for a particular download to finish, or else a timeout to occur
+     *
+     * Also guarantees a notification has been posted for the download.
+     *
+     * @param id The download id to query on (wait for)
+     * @param poll The amount of time to wait
+     * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete
+     */
+    protected void waitForDownloadOrTimeout(long id, long poll, long timeoutMillis)
+            throws TimeoutException, InterruptedException {
+        doWaitForDownloadsOrTimeout(new Query().setFilterById(id), poll, timeoutMillis);
+        waitForReceiverNotifications(1);
+    }
+
+    /**
+     * Helper to wait for all downloads to finish, or else a specified timeout to occur
+     *
+     * Makes no guaranee that notifications have been posted for all downloads.
+     *
+     * @param poll The amount of time to wait
+     * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete
+     */
+    protected void waitForDownloadsOrTimeout(long poll, long timeoutMillis) throws TimeoutException,
+            InterruptedException {
+        doWaitForDownloadsOrTimeout(new Query(), poll, timeoutMillis);
+    }
+
+    /**
+     * Helper to wait for all downloads to finish, or else a timeout to occur, but does not throw
+     *
+     * Also guarantees a notification has been posted for the download.
+     *
+     * @param id The id of the download to query against
+     * @param poll The amount of time to wait
+     * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete
+     * @return true if download completed successfully (didn't timeout), false otherwise
+     */
+    private boolean waitForDownloadOrTimeoutNoThrow(long id, long poll, long timeoutMillis) {
+        try {
+            doWaitForDownloadsOrTimeout(new Query().setFilterById(id), poll, timeoutMillis);
+            waitForReceiverNotifications(1);
+        } catch (TimeoutException e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Helper function to synchronously wait, or timeout if the maximum threshold has been exceeded.
+     *
+     * @param currentTotalWaitTime The total time waited so far
+     * @param poll The amount of time to wait
+     * @param maxTimeoutMillis The total wait time threshold; if we've waited more than this long,
+     *          we timeout and fail
+     * @param timedOutMessage The message to display in the failure message if we timeout
+     * @return The new total amount of time we've waited so far
+     * @throws TimeoutException if timed out waiting for SD card to mount
+     */
+    private int timeoutWait(int currentTotalWaitTime, long poll, long maxTimeoutMillis,
+            String timedOutMessage) throws TimeoutException {
+        long now = SystemClock.elapsedRealtime();
+        long end = now + poll;
+
+        // if we get InterruptedException's, ignore them and just keep sleeping
+        while (now < end) {
+            try {
+                Thread.sleep(end - now);
+            } catch (InterruptedException e) {
+                // ignore interrupted exceptions
+            }
+            now = SystemClock.elapsedRealtime();
+        }
+
+        currentTotalWaitTime += poll;
+        if (currentTotalWaitTime > maxTimeoutMillis) {
+            throw new TimeoutException(timedOutMessage);
+        }
+        return currentTotalWaitTime;
+    }
+
+    /**
+     * Helper to wait for all downloads to finish, or else a timeout to occur
+     *
+     * @param query The query to pass to the download manager
+     * @param poll The poll time to wait between checks
+     * @param timeoutMillis The max amount of time (in ms) to wait for the download(s) to complete
+     */
+    private void doWaitForDownloadsOrTimeout(Query query, long poll, long timeoutMillis)
+            throws TimeoutException {
+        int currentWaitTime = 0;
+        while (true) {
+            query.setFilterByStatus(DownloadManager.STATUS_PENDING | DownloadManager.STATUS_PAUSED
+                    | DownloadManager.STATUS_RUNNING);
+            Cursor cursor = mDownloadManager.query(query);
+
+            try {
+                if (cursor.getCount() == 0) {
+                    Log.i(LOG_TAG, "All downloads should be done...");
+                    break;
+                }
+                currentWaitTime = timeoutWait(currentWaitTime, poll, timeoutMillis,
+                        "Timed out waiting for all downloads to finish");
+            } finally {
+                cursor.close();
+            }
+        }
+    }
+
+    /**
+     * Synchronously waits for external store to be mounted (eg: SD Card).
+     *
+     * @throws InterruptedException if interrupted
+     * @throws Exception if timed out waiting for SD card to mount
+     */
+    protected void waitForExternalStoreMount() throws Exception {
+        String extStorageState = Environment.getExternalStorageState();
+        int currentWaitTime = 0;
+        while (!extStorageState.equals(Environment.MEDIA_MOUNTED)) {
+            Log.i(LOG_TAG, "Waiting for SD card...");
+            currentWaitTime = timeoutWait(currentWaitTime, DEFAULT_WAIT_POLL_TIME,
+                    DEFAULT_MAX_WAIT_TIME, "Timed out waiting for SD Card to be ready!");
+            extStorageState = Environment.getExternalStorageState();
+        }
+    }
+
+    /**
+     * Synchronously waits for a download to start.
+     *
+     * @param dlRequest the download request id used by Download Manager to track the download.
+     * @throws Exception if timed out while waiting for SD card to mount
+     */
+    protected void waitForDownloadToStart(long dlRequest) throws Exception {
+        Cursor cursor = getCursor(dlRequest);
+        try {
+            int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
+            int value = cursor.getInt(columnIndex);
+            int currentWaitTime = 0;
+
+            while (value != DownloadManager.STATUS_RUNNING &&
+                    (value != DownloadManager.STATUS_FAILED) &&
+                    (value != DownloadManager.STATUS_SUCCESSFUL)) {
+                Log.i(LOG_TAG, "Waiting for download to start...");
+                currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME,
+                        MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for download to start!");
+                cursor.requery();
+                assertTrue(cursor.moveToFirst());
+                columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
+                value = cursor.getInt(columnIndex);
+            }
+            assertFalse("Download failed immediately after start",
+                    value == DownloadManager.STATUS_FAILED);
+        } finally {
+            cursor.close();
+        }
+    }
+
+    /**
+     * Synchronously waits for our receiver to receive notification for a given number of
+     * downloads.
+     *
+     * @param targetNumber The number of notifications for unique downloads to wait for; pass in
+     *         -1 to not wait for notification.
+     * @throws Exception if timed out while waiting
+     */
+    private void waitForReceiverNotifications(int targetNumber) throws TimeoutException {
+        int count = mReceiver.numDownloadsCompleted();
+        int currentWaitTime = 0;
+
+        while (count < targetNumber) {
+            Log.i(LOG_TAG, "Waiting for notification of downloads...");
+            currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME,
+                    MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for download notifications!"
+                    + " Received " + count + "notifications.");
+            count = mReceiver.numDownloadsCompleted();
+        }
+    }
+
+    /**
+     * Synchronously waits for a file to increase in size (such as to monitor that a download is
+     * progressing).
+     *
+     * @param file The file whose size to track.
+     * @throws Exception if timed out while waiting for the file to grow in size.
+     */
+    protected void waitForFileToGrow(File file) throws Exception {
+        int currentWaitTime = 0;
+
+        // File may not even exist yet, so wait until it does (or we timeout)
+        while (!file.exists()) {
+            Log.i(LOG_TAG, "Waiting for file to exist...");
+            currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME,
+                    MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for file to be created.");
+        }
+
+        // Get original file size...
+        long originalSize = file.length();
+
+        while (file.length() <= originalSize) {
+            Log.i(LOG_TAG, "Waiting for file to be written to...");
+            currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME,
+                    MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for file to be written to.");
+        }
+    }
+
+    /**
+     * Helper to remove all downloads that are registered with the DL Manager.
+     *
+     * Note: This gives us a clean slate b/c it includes downloads that are pending, running,
+     * paused, or have completed.
+     */
+    protected void removeAllCurrentDownloads() {
+        Log.i(LOG_TAG, "Removing all current registered downloads...");
+        Cursor cursor = mDownloadManager.query(new Query());
+        try {
+            if (cursor.moveToFirst()) {
+                do {
+                    int index = cursor.getColumnIndex(DownloadManager.COLUMN_ID);
+                    long downloadId = cursor.getLong(index);
+
+                    mDownloadManager.remove(downloadId);
+                } while (cursor.moveToNext());
+            }
+        } finally {
+            cursor.close();
+        }
+    }
+
+    /**
+     * Helper to perform a standard enqueue of data to the mock server.
+     * download is performed to the downloads cache dir (NOT systemcache dir)
+     *
+     * @param body The body to return in the response from the server
+     */
+    private long doStandardEnqueue(byte[] body) throws Exception {
+        // Prepare the mock server with a standard response
+        enqueueResponse(HTTP_OK, body);
+        return doCommonStandardEnqueue();
+    }
+
+    /**
+     * Helper to perform a standard enqueue of data to the mock server.
+     *
+     * @param body The body to return in the response from the server, contained in the file
+     */
+    private long doStandardEnqueue(File body) throws Exception {
+        // Prepare the mock server with a standard response
+        enqueueResponse(HTTP_OK, body);
+        return doCommonStandardEnqueue();
+    }
+
+    /**
+     * Helper to do the additional steps (setting title and Uri of default filename) when
+     * doing a standard enqueue request to the server.
+     */
+    private long doCommonStandardEnqueue() throws Exception {
+        Uri uri = getServerUri(DEFAULT_FILENAME);
+        Request request = new Request(uri).setTitle(DEFAULT_FILENAME);
+        return mDownloadManager.enqueue(request);
+    }
+
+    /**
+     * Helper to verify an int value in a Cursor
+     *
+     * @param cursor The cursor containing the query results
+     * @param columnName The name of the column to query
+     * @param expected The expected int value
+     */
+    private void verifyInt(Cursor cursor, String columnName, int expected) {
+        int index = cursor.getColumnIndex(columnName);
+        int actual = cursor.getInt(index);
+        assertEquals(expected, actual);
+    }
+
+    /**
+     * Performs a query based on ID and returns a Cursor for the query.
+     *
+     * @param id The id of the download in DL Manager; pass -1 to query all downloads
+     * @return A cursor for the query results
+     */
+    protected Cursor getCursor(long id) throws Exception {
+        Query query = new Query();
+        if (id != -1) {
+            query.setFilterById(id);
+        }
+
+        Cursor cursor = mDownloadManager.query(query);
+        int currentWaitTime = 0;
+
+        try {
+            while (!cursor.moveToFirst()) {
+                Thread.sleep(DEFAULT_WAIT_POLL_TIME);
+                currentWaitTime += DEFAULT_WAIT_POLL_TIME;
+                if (currentWaitTime > DEFAULT_MAX_WAIT_TIME) {
+                    fail("timed out waiting for a non-null query result");
+                }
+                cursor.requery();
+            }
+        } catch (Exception e) {
+            cursor.close();
+            throw e;
+        }
+        return cursor;
+    }
+}
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
index e1d7b4c..ba5ee2c 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
@@ -18,7 +18,6 @@
 import android.app.DownloadManager;
 import android.app.DownloadManager.Query;
 import android.app.DownloadManager.Request;
-import android.app.DownloadManagerBaseTest;
 import android.content.Context;
 import android.content.Intent;
 import android.database.Cursor;
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index f458576..ea91c21 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -58,14 +58,14 @@
         <group gid="sdcard_rw" />
     </permission>
 
-    <permission name="android.permission.WRITE_MEDIA_STORAGE" >
-        <group gid="media_rw" />
-    </permission>
-
     <permission name="android.permission.ACCESS_USB" >
         <group gid="usb" />
     </permission>
 
+    <permission name="android.permission.ACCESS_MTP" >
+        <group gid="mtp" />
+    </permission>
+
     <!-- The group that /cache belongs to, linked to the permission
          set on the applications that can access /cache -->
     <permission name="android.permission.ACCESS_CACHE_FILESYSTEM" >
diff --git a/data/fonts/AndroidClock.ttf b/data/fonts/AndroidClock.ttf
new file mode 100644
index 0000000..03e36cb
--- /dev/null
+++ b/data/fonts/AndroidClock.ttf
Binary files differ
diff --git a/data/fonts/AndroidClock_Highlight.ttf b/data/fonts/AndroidClock_Highlight.ttf
new file mode 100644
index 0000000..8fb31ba
--- /dev/null
+++ b/data/fonts/AndroidClock_Highlight.ttf
Binary files differ
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 34d0331..b8a93e8 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -26,4 +26,6 @@
     frameworks/base/data/fonts/DroidSerif-BoldItalic.ttf:system/fonts/DroidSerif-BoldItalic.ttf \
     frameworks/base/data/fonts/DroidSansMono.ttf:system/fonts/DroidSansMono.ttf \
     frameworks/base/data/fonts/Clockopia.ttf:system/fonts/Clockopia.ttf \
-    frameworks/base/data/fonts/DroidSansFallback.ttf:system/fonts/DroidSansFallback.ttf
+    frameworks/base/data/fonts/DroidSansFallback.ttf:system/fonts/DroidSansFallback.ttf \
+    frameworks/base/data/fonts/AndroidClock.ttf:system/fonts/AndroidClock.ttf \
+    frameworks/base/data/fonts/AndroidClock_Highlight.ttf:system/fonts/AndroidClock_Highlight.ttf 
diff --git a/data/keyboards/AVRCP.kl b/data/keyboards/AVRCP.kl
index 4c91ece..736b43c 100644
--- a/data/keyboards/AVRCP.kl
+++ b/data/keyboards/AVRCP.kl
@@ -14,8 +14,8 @@
 
 # Key layout used for Bluetooth AVRCP support.
 
-key 200   MEDIA_PLAY_PAUSE    WAKE
-key 201   MEDIA_PLAY_PAUSE    WAKE
+key 200   MEDIA_PLAY          WAKE
+key 201   MEDIA_PAUSE         WAKE
 key 166   MEDIA_STOP          WAKE
 key 163   MEDIA_NEXT          WAKE
 key 165   MEDIA_PREVIOUS      WAKE
diff --git a/data/sounds/AudioPackage6.mk b/data/sounds/AudioPackage6.mk
index bceaba8..e39a02e 100755
--- a/data/sounds/AudioPackage6.mk
+++ b/data/sounds/AudioPackage6.mk
@@ -25,26 +25,18 @@
 	$(LOCAL_PATH)/effects/Undock.ogg:system/media/audio/ui/Undock.ogg \
 	$(LOCAL_PATH)/effects/Lock.ogg:system/media/audio/ui/Lock.ogg \
 	$(LOCAL_PATH)/effects/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
-	$(LOCAL_PATH)/notifications/Aldebaran.ogg:system/media/audio/notifications/Aldebaran.ogg \
-	$(LOCAL_PATH)/notifications/Altair.ogg:system/media/audio/notifications/Altair.ogg \
-	$(LOCAL_PATH)/notifications/Antares.ogg:system/media/audio/notifications/Antares.ogg \
-	$(LOCAL_PATH)/notifications/arcturus.ogg:system/media/audio/notifications/arcturus.ogg \
-	$(LOCAL_PATH)/notifications/Betelgeuse.ogg:system/media/audio/notifications/Betelgeuse.ogg \
-	$(LOCAL_PATH)/notifications/Canopus.ogg:system/media/audio/notifications/Canopus.ogg \
-	$(LOCAL_PATH)/notifications/Capella.ogg:system/media/audio/notifications/Capella.ogg \
-	$(LOCAL_PATH)/notifications/Castor.ogg:system/media/audio/notifications/Castor.ogg \
-	$(LOCAL_PATH)/notifications/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
-	$(LOCAL_PATH)/notifications/Deneb.ogg:system/media/audio/notifications/Deneb.ogg \
-	$(LOCAL_PATH)/notifications/Electra.ogg:system/media/audio/notifications/Electra.ogg \
-	$(LOCAL_PATH)/notifications/Fomalhaut.ogg:system/media/audio/notifications/Fomalhaut.ogg \
-	$(LOCAL_PATH)/notifications/Merope.ogg:system/media/audio/notifications/Merope.ogg \
-	$(LOCAL_PATH)/notifications/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
-	$(LOCAL_PATH)/notifications/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
-	$(LOCAL_PATH)/notifications/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \
-	$(LOCAL_PATH)/notifications/regulus.ogg:system/media/audio/notifications/regulus.ogg \
-	$(LOCAL_PATH)/notifications/sirius.ogg:system/media/audio/notifications/sirius.ogg \
-	$(LOCAL_PATH)/notifications/Sirrah.ogg:system/media/audio/notifications/Sirrah.ogg \
-	$(LOCAL_PATH)/notifications/vega.ogg:system/media/audio/notifications/vega.ogg \
+	$(LOCAL_PATH)/notifications/aidos.ogg:system/media/audio/notifications/aidos.ogg \
+	$(LOCAL_PATH)/notifications/nomos1.ogg:system/media/audio/notifications/nomos1.ogg \
+	$(LOCAL_PATH)/notifications/hypnos1.ogg:system/media/audio/notifications/hypnos1.ogg \
+	$(LOCAL_PATH)/notifications/thrasos1.ogg:system/media/audio/notifications/thrasos1.ogg \
+	$(LOCAL_PATH)/notifications/nomos2.ogg:system/media/audio/notifications/nomos2.ogg \
+	$(LOCAL_PATH)/notifications/horkos.ogg:system/media/audio/notifications/horkos.ogg \
+	$(LOCAL_PATH)/notifications/kratos1.ogg:system/media/audio/notifications/kratos1.ogg \
+	$(LOCAL_PATH)/notifications/circios.ogg:system/media/audio/notifications/circios.ogg \
+	$(LOCAL_PATH)/notifications/ouranos.ogg:system/media/audio/notifications/ouranos.ogg \
+	$(LOCAL_PATH)/notifications/poros.ogg:system/media/audio/notifications/poros.ogg \
+	$(LOCAL_PATH)/notifications/phantasos.ogg:system/media/audio/notifications/phantasos.ogg \
+	$(LOCAL_PATH)/notifications/kratos2.ogg:system/media/audio/notifications/kratos2.ogg \
 	$(LOCAL_PATH)/ringtones/ANDROMEDA.ogg:system/media/audio/ringtones/ANDROMEDA.ogg \
 	$(LOCAL_PATH)/ringtones/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
 	$(LOCAL_PATH)/ringtones/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
@@ -70,21 +62,6 @@
 	$(LOCAL_PATH)/ringtones/Testudo.ogg:system/media/audio/ringtones/Testudo.ogg \
 	$(LOCAL_PATH)/ringtones/URSAMINOR.ogg:system/media/audio/ringtones/URSAMINOR.ogg \
 	$(LOCAL_PATH)/ringtones/Vespa.ogg:system/media/audio/ringtones/Vespa.ogg \
-	$(LOCAL_PATH)/notifications/alert01.ogg:system/media/audio/notifications/alert01.ogg \
-	$(LOCAL_PATH)/notifications/alert02.ogg:system/media/audio/notifications/alert02.ogg \
-	$(LOCAL_PATH)/notifications/alert03.ogg:system/media/audio/notifications/alert03.ogg \
-	$(LOCAL_PATH)/notifications/alert04.ogg:system/media/audio/notifications/alert04.ogg \
-	$(LOCAL_PATH)/notifications/alert05.ogg:system/media/audio/notifications/alert05.ogg \
-	$(LOCAL_PATH)/notifications/alert06.ogg:system/media/audio/notifications/alert06.ogg \
-	$(LOCAL_PATH)/notifications/alert07.ogg:system/media/audio/notifications/alert07.ogg \
-	$(LOCAL_PATH)/notifications/alert08.ogg:system/media/audio/notifications/alert08.ogg \
-	$(LOCAL_PATH)/notifications/alert09.ogg:system/media/audio/notifications/alert09.ogg \
-	$(LOCAL_PATH)/notifications/alert10.ogg:system/media/audio/notifications/alert10.ogg \
-	$(LOCAL_PATH)/notifications/alert11.ogg:system/media/audio/notifications/alert11.ogg \
-	$(LOCAL_PATH)/notifications/alert12.ogg:system/media/audio/notifications/alert12.ogg \
-	$(LOCAL_PATH)/notifications/alert13.ogg:system/media/audio/notifications/alert13.ogg \
-	$(LOCAL_PATH)/notifications/alert14.ogg:system/media/audio/notifications/alert14.ogg \
-	$(LOCAL_PATH)/notifications/alert15.ogg:system/media/audio/notifications/alert15.ogg \
 	$(LOCAL_PATH)/ringtones/ringtone18.ogg:system/media/audio/ringtones/ringtone18.ogg \
 	$(LOCAL_PATH)/ringtones/ringtone19.ogg:system/media/audio/ringtones/ringtone19.ogg \
 	$(LOCAL_PATH)/ringtones/ringtone20.ogg:system/media/audio/ringtones/ringtone20.ogg \
diff --git a/data/sounds/notifications/aidos.ogg b/data/sounds/notifications/aidos.ogg
new file mode 100755
index 0000000..d2aec75
--- /dev/null
+++ b/data/sounds/notifications/aidos.ogg
Binary files differ
diff --git a/data/sounds/notifications/alert01.ogg b/data/sounds/notifications/alert01.ogg
deleted file mode 100755
index 4b900b0..0000000
--- a/data/sounds/notifications/alert01.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert02.ogg b/data/sounds/notifications/alert02.ogg
deleted file mode 100755
index 469ea6a..0000000
--- a/data/sounds/notifications/alert02.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert03.ogg b/data/sounds/notifications/alert03.ogg
deleted file mode 100755
index 58f418b..0000000
--- a/data/sounds/notifications/alert03.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert04.ogg b/data/sounds/notifications/alert04.ogg
deleted file mode 100755
index 4730d6d..0000000
--- a/data/sounds/notifications/alert04.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert05.ogg b/data/sounds/notifications/alert05.ogg
deleted file mode 100755
index 663da31..0000000
--- a/data/sounds/notifications/alert05.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert06.ogg b/data/sounds/notifications/alert06.ogg
deleted file mode 100755
index 2861b84..0000000
--- a/data/sounds/notifications/alert06.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert07.ogg b/data/sounds/notifications/alert07.ogg
deleted file mode 100644
index 6fe905d..0000000
--- a/data/sounds/notifications/alert07.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert08.ogg b/data/sounds/notifications/alert08.ogg
deleted file mode 100644
index ee30c26..0000000
--- a/data/sounds/notifications/alert08.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert09.ogg b/data/sounds/notifications/alert09.ogg
deleted file mode 100644
index 86b2f2e..0000000
--- a/data/sounds/notifications/alert09.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert10.ogg b/data/sounds/notifications/alert10.ogg
deleted file mode 100644
index 1d93143..0000000
--- a/data/sounds/notifications/alert10.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert11.ogg b/data/sounds/notifications/alert11.ogg
deleted file mode 100644
index c7327db..0000000
--- a/data/sounds/notifications/alert11.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert12.ogg b/data/sounds/notifications/alert12.ogg
deleted file mode 100644
index 352a049..0000000
--- a/data/sounds/notifications/alert12.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert13.ogg b/data/sounds/notifications/alert13.ogg
deleted file mode 100644
index 0987360..0000000
--- a/data/sounds/notifications/alert13.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert14.ogg b/data/sounds/notifications/alert14.ogg
deleted file mode 100644
index 6e49307..0000000
--- a/data/sounds/notifications/alert14.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/alert15.ogg b/data/sounds/notifications/alert15.ogg
deleted file mode 100644
index b140427..0000000
--- a/data/sounds/notifications/alert15.ogg
+++ /dev/null
Binary files differ
diff --git a/data/sounds/notifications/circios.ogg b/data/sounds/notifications/circios.ogg
new file mode 100755
index 0000000..68a1871
--- /dev/null
+++ b/data/sounds/notifications/circios.ogg
Binary files differ
diff --git a/data/sounds/notifications/horkos.ogg b/data/sounds/notifications/horkos.ogg
new file mode 100755
index 0000000..171b3cb
--- /dev/null
+++ b/data/sounds/notifications/horkos.ogg
Binary files differ
diff --git a/data/sounds/notifications/hypnos1.ogg b/data/sounds/notifications/hypnos1.ogg
new file mode 100755
index 0000000..4a7fc26
--- /dev/null
+++ b/data/sounds/notifications/hypnos1.ogg
Binary files differ
diff --git a/data/sounds/notifications/kratos1.ogg b/data/sounds/notifications/kratos1.ogg
new file mode 100755
index 0000000..3e1fe64
--- /dev/null
+++ b/data/sounds/notifications/kratos1.ogg
Binary files differ
diff --git a/data/sounds/notifications/kratos2.ogg b/data/sounds/notifications/kratos2.ogg
new file mode 100755
index 0000000..93d3149e
--- /dev/null
+++ b/data/sounds/notifications/kratos2.ogg
Binary files differ
diff --git a/data/sounds/notifications/nomos1.ogg b/data/sounds/notifications/nomos1.ogg
new file mode 100755
index 0000000..5eb719a
--- /dev/null
+++ b/data/sounds/notifications/nomos1.ogg
Binary files differ
diff --git a/data/sounds/notifications/nomos2.ogg b/data/sounds/notifications/nomos2.ogg
new file mode 100755
index 0000000..544cb4c
--- /dev/null
+++ b/data/sounds/notifications/nomos2.ogg
Binary files differ
diff --git a/data/sounds/notifications/ouranos.ogg b/data/sounds/notifications/ouranos.ogg
new file mode 100755
index 0000000..d0efc3a
--- /dev/null
+++ b/data/sounds/notifications/ouranos.ogg
Binary files differ
diff --git a/data/sounds/notifications/phantasos.ogg b/data/sounds/notifications/phantasos.ogg
new file mode 100755
index 0000000..ea19882
--- /dev/null
+++ b/data/sounds/notifications/phantasos.ogg
Binary files differ
diff --git a/data/sounds/notifications/poros.ogg b/data/sounds/notifications/poros.ogg
new file mode 100755
index 0000000..0a50a12
--- /dev/null
+++ b/data/sounds/notifications/poros.ogg
Binary files differ
diff --git a/data/sounds/notifications/thrasos1.ogg b/data/sounds/notifications/thrasos1.ogg
new file mode 100755
index 0000000..9b7e621
--- /dev/null
+++ b/data/sounds/notifications/thrasos1.ogg
Binary files differ
diff --git a/docs/html/guide/appendix/api-levels.jd b/docs/html/guide/appendix/api-levels.jd
index 5898fe5..6ab0fc2 100644
--- a/docs/html/guide/appendix/api-levels.jd
+++ b/docs/html/guide/appendix/api-levels.jd
@@ -294,12 +294,11 @@
 <p>To run your application against different platform versions in the emulator,
 create an AVD for each platform version that you want to test. For more
 information about AVDs, see <a
-href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a>. If
+href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</a>. If
 you are using a physical device for testing, ensure that you know the API Level
 of the Android platform it runs. See the table at the top of this document for
 a list of platform versions and their API Levels. </p>
 
-
 <h2 id="provisional">Using a Provisional API Level</h2>
 
 <p>In some cases, an "Early Look" Android SDK platform may be available. To let
diff --git a/docs/html/guide/appendix/faq/commontasks.jd b/docs/html/guide/appendix/faq/commontasks.jd
index 38a89ef..b3dc236 100644
--- a/docs/html/guide/appendix/faq/commontasks.jd
+++ b/docs/html/guide/appendix/faq/commontasks.jd
@@ -655,7 +655,7 @@
         and <code>STRIKE</code> (strikethrough).
         So, for example, in res/values/strings.xml you could declare this:<br />
         <code>&lt;resource&gt;<br />
-        &nbsp;&nbsp;&nbsp;&nbsp;&lt;string&gt;id=&quot;@+id/styled_welcome_message&quot;&gt;We
+        &nbsp;&nbsp;&nbsp;&nbsp;&lt;string&nbsp;id=&quot;@+id/styled_welcome_message&quot;&gt;We
         are &lt;b&gt;&lt;i&gt;so&lt;/i&gt;&lt;/b&gt; glad to see you.&lt;/string&gt;<br />
         &lt;/resources&gt;</code></li>
     <li>To style text on the fly, or to add highlighting or more complex styling,
diff --git a/docs/html/guide/appendix/glossary.jd b/docs/html/guide/appendix/glossary.jd
index 97669ba..06fdef2 100644
--- a/docs/html/guide/appendix/glossary.jd
+++ b/docs/html/guide/appendix/glossary.jd
@@ -91,8 +91,7 @@
     with the SDK. It provides screen capture, log dump, and process
     examination capabilities. If you are developing in Eclipse using the ADT
     Plugin, DDMS is integrated into your development environment. See <a
-    href="{@docRoot}guide/developing/tools/ddms.html">Dalvik Debug Monitor
-    Server</a> to learn more about the program.</dd>
+    href="{@docRoot}guide/developing/debugging/ddms.html">Using DDMS</a> to learn more about the program.</dd>
 
     <dt id="dialog">Dialog</dt> <dd> A floating window that that acts as a lightweight
     form. A dialog can have button controls only and is intended to perform a
diff --git a/docs/html/guide/developing/building/building-cmdline.jd b/docs/html/guide/developing/building/building-cmdline.jd
new file mode 100644
index 0000000..f40ad04
--- /dev/null
+++ b/docs/html/guide/developing/building/building-cmdline.jd
@@ -0,0 +1,306 @@
+page.title=Building and Running Apps on the Command Line
+@jd:body
+
+ <div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li><a href="#DebugMode">Building in debug mode</a></li>
+
+        <li><a href="#ReleaseMode">Building in release mode</a></li>
+
+        <li><a href="#RunningOnEmulator">Running on an emulator</a></li>
+
+        <li><a href="#RunningOnDevice">Running on a device</a></li>
+      </ol>
+    </div>
+  </div>
+
+  <p>There are two ways to build your application using the Ant build script: one for
+  testing/debugging your application &mdash; <em>debug mode</em> &mdash; and one for building your
+  final package for release &mdash; <em>release mode</em>. Regardless of which way you build your application,
+  it must be signed before it can install on an emulator or device&mdash;with a debug key when building
+  in debug mode and with your own private key when building in release mode.</p>
+
+  <p>Whether you're building in debug mode or release mode, you need to use the Ant tool to compile
+  and build your project. This will create the .apk file that you can install on an emulator or device.
+  When you build in debug mode, the .apk file is automatically signed by the SDK tools with
+  a debug key, so it's instantly ready for installation onto an emulator or attached
+  development device. You cannot distribute an application that is signed with a debug key.
+  When you build in release mode, the .apk file is <em>unsigned</em>, so you
+  must manually sign it with your own private key, using Keytool and Jarsigner.</p>
+
+  <p>It's important that you read and understand <a href=
+  "{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>, particularly once
+  you're ready to release your application and share it with end-users. That document describes the
+  procedure for generating a private key and then using it to sign your .apk file. If you're just
+  getting started, however, you can quickly run your applications on an emulator or your own
+  development device by building in debug mode.</p>
+
+  <p>If you don't have Ant, you can obtain it from the <a href="http://ant.apache.org/">Apache Ant
+  home page</a>. Install it and make sure it is in your executable PATH. Before calling Ant, you
+  need to declare the JAVA_HOME environment variable to specify the path to where the JDK is
+  installed.</p>
+
+  <p class="note"><strong>Note:</strong> When installing JDK on Windows, the default is to install
+  in the "Program Files" directory. This location will cause <code>ant</code> to fail, because of
+  the space. To fix the problem, you can specify the JAVA_HOME variable like this: 
+  <pre>set JAVA_HOME=c:\Progra~1\Java\&lt;jdkdir&gt;
+  </pre>
+  
+  The easiest solution, however, is to install JDK in a non-space directory, for example:
+  
+  <pre>c:\java\jdk1.6.0_02</pre>
+
+  <h2 id="DebugMode">Building in debug mode</h2>
+
+  <p>For immediate application testing and debugging, you can build your application in debug mode
+  and immediately install it on an emulator. In debug mode, the build tools automatically sign your
+  application with a debug key and optimize the package with {@code zipalign}.</p>
+
+  <p>To build in debug mode:</p>
+
+  <ol>
+    <li>Open a command-line and navigate to the root of your project directory.</li>
+    <li>Use Ant to compile your project in debug mode:
+      <pre>
+ant debug
+</pre>
+
+      <p>This creates your debug <code>.apk</code> file inside the project <code>bin/</code> directory, named
+      <code>&lt;your_project_name&gt;-debug.apk</code>. The file is already signed with
+      the debug key and has been aligned with
+      <a href="{@docRoot}/guide/developing/tools/zipalign.html"><code>zipalign</code></a>.
+      </p>
+    </li>
+  </ol>
+
+  <p>Each time you change a source file or resource, you must run Ant again in order to package up
+  the latest version of the application.</p>
+
+  <p>To install and run your application on an emulator, see the following section about <a href=
+  "#RunningOnEmulator">Running on the Emulator</a>.</p>
+
+  <h2 id="ReleaseMode">Building in release mode</h2>
+
+  <p>When you're ready to release and distribute your application to end-users, you must build your
+  application in release mode. Once you have built in release mode, it's a good idea to perform
+  additional testing and debugging with the final .apk.</p>
+
+  <p>Before you start building your application in release mode, be aware that you must sign the
+  resulting application package with your private key, and should then align it using the {@code
+  zipalign} tool. There are two approaches to building in release mode: build an unsigned package
+  in release mode and then manually sign and align the package, or allow the build script to sign
+  and align the package for you.</p>
+
+  <h3 id="ManualReleaseMode">Build unsigned</h3>
+
+  <p>If you build your application <em>unsigned</em>, then you will need to manually sign and align
+  the package.</p>
+
+  <p>To build an <em>unsigned</em> .apk in release mode:</p>
+
+  <ol>
+    <li>Open a command-line and navigate to the root of your project directory.</li>
+
+    <li>Use Ant to compile your project in release mode:
+      <pre>
+ant release
+</pre>
+    </li>
+  </ol>
+
+  <p>This creates your Android application .apk file inside the project <code>bin/</code>
+  directory, named <code><em>&lt;your_project_name&gt;</em>-unsigned.apk</code>.</p>
+
+  <p class="note"><strong>Note:</strong> The .apk file is <em>unsigned</em> at this point and can't
+  be installed until signed with your private key.</p>
+
+  <p>Once you have created the unsigned .apk, your next step is to sign the .apk with your private
+  key and then align it with {@code zipalign}. To complete this procedure, read <a href=
+  "{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>.</p>
+
+  <p>When your <code>.apk</code> has been signed and aligned, it's ready to be distributed to end-users.
+  You should test the final build on different devices or AVDs to ensure that it
+  runs properly on different platforms.</p>
+
+  <h3 id="AutoReleaseMode">Build signed and aligned</h3>
+
+  <p>If you would like, you can configure the Android build script to automatically sign and align
+  your application package. To do so, you must provide the path to your keystore and the name of
+  your key alias in your project's {@code build.properties} file. With this information provided,
+  the build script will prompt you for your keystore and alias password when you build in release
+  mode and produce your final application package, which will be ready for distribution.</p>
+
+  <p class="caution"><strong>Caution:</strong> Due to the way Ant handles input, the password that
+  you enter during the build process <strong>will be visible</strong>. If you are concerned about
+  your keystore and alias password being visible on screen, then you may prefer to perform the
+  application signing manually, via Jarsigner (or a similar tool). To instead perform the signing
+  procedure manually, <a href="#ManualReleaseMode">build unsigned</a> and then continue with
+  <a href="{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>.</p>
+
+  <p>To specify your keystore and alias, open the project {@code build.properties} file (found in
+  the root of the project directory) and add entries for {@code key.store} and {@code key.alias}.
+  For example:</p>
+  <pre>
+key.store=path/to/my.keystore
+key.alias=mykeystore
+</pre>
+
+  <p>Save your changes. Now you can build a <em>signed</em> .apk in release mode:</p>
+
+  <ol>
+    <li>Open a command-line and navigate to the root of your project directory.</li>
+
+    <li>Use Ant to compile your project in release mode:
+      <pre>
+ant release
+</pre>
+    </li>
+
+    <li>When prompted, enter you keystore and alias passwords.
+
+      <p class="caution"><strong>Caution:</strong> As described above, your password will be
+      visible on the screen.</p>
+    </li>
+  </ol>
+
+  <p>This creates your Android application .apk file inside the project <code>bin/</code>
+  directory, named <code><em>&lt;your_project_name&gt;</em>-release.apk</code>. This .apk file has
+  been signed with the private key specified in {@code build.properties} and aligned with {@code
+  zipalign}. It's ready for installation and distribution.</p>
+
+  <h3>Once built and signed in release mode</h3>
+
+  <p>Once you have signed your application with a private key, you can install and run it on an
+  <a href="#RunningOnEmulator">emulator</a> or <a href="#RunningOnDevice">device</a>. You can 
+  also try installing it onto a device from a web server. Simply upload the signed .apk to a web 
+  site, then load the .apk URL in your Android web browser to download the application and begin 
+  installation. (On your device, be sure you have enabled 
+  <em>Settings &gt; Applications &gt; Unknown sources</em>.)</p>
+
+  <h2 id="RunningOnEmulator">Running on the emulator</h2>
+
+  <p>Before you can run your application on the Android Emulator, you must <a href=
+  "{@docRoot}guide/developing/devices/managing-avds.html">create an AVD</a>.</p>
+
+  <p>To run your application:</p>
+
+  <ol>
+    <li>
+      <strong>Open the SDK and AVD Manager and launch a virtual device</strong>
+
+      <p>From your SDK's <code>platform-tools/</code> directory, execute the {@code android} tool with no
+      arguments:</p>
+      <pre>
+android
+</pre>
+
+      <p>In the <em>Virtual Devices</em> view, select an AVD and click <strong>Start</strong>.</p>
+    </li>
+
+    <li>
+      <strong>Install your application</strong>
+
+      <p>From your SDK's <code>tools/</code> directory, install the {@code .apk} on the
+      emulator:</p>
+      <pre>
+adb install <em>&lt;path_to_your_bin&gt;</em>.apk
+</pre>
+
+      <p>Your .apk file (signed with either a release or debug key) is in your project {@code bin/}
+      directory after you build your application.</p>
+
+      <p>If there is more than one emulator running, you must specify the emulator upon which to
+      install the application, by its serial number, with the <code>-s</code> option. For
+      example:</p>
+      <pre>
+adb -s emulator-5554 install <em>path/to/your/app</em>.apk
+</pre>
+
+      <p>To see a list of available device serial numbers, execute {@code adb devices}.</p>
+    </li>
+  </ol>
+
+  <p>If you don't see your application on the emulator, try closing the emulator and launching the
+  virtual device again from the SDK and AVD Manager. Sometimes when you install an application for the
+  first time, it won't show up in the application launcher or be accessible by other applications.
+  This is because the package manager usually examines manifests completely only on emulator
+  startup.</p>
+
+  <p>Be certain to create multiple AVDs upon which to test your application. You should have one
+  AVD for each platform and screen type with which your application is compatible. For instance, if
+  your application compiles against the Android 1.5 (API Level 3) platform, you should create an
+  AVD for each platform equal to and greater than 1.5 and an AVD for each <a href=
+  "{@docRoot}guide/practices/screens_support.html">screen type</a> you support, then test your
+  application on each one.</p>
+
+  <p class="note"><strong>Tip:</strong> If you have <em>only one</em> emulator running, you can
+  build your application and install it on the emulator in one simple step. Navigate to the root of
+  your project directory and use Ant to compile the project with <em>install mode</em>: <code>ant
+  install</code>. This will build your application, sign it with the debug key, and install it on
+  the currently running emulator.</p>
+
+  <h2 id="RunningOnDevice">Running on a device</h2>
+
+  <p>Before you can run your application on a device, you must perform some basic setup for your
+  device:</p>
+
+  <ul>
+    <li>Ensure that your application is debuggable by setting the
+    <code>android:debuggable</code> attribute of the <code>&lt;application&gt;</code>
+    element to <code>true</code>. As of ADT 8.0, this is done by default when you build in debug mode.</li>
+
+    <li>Enable USB Debugging on your device. You can find the setting on most Android devices by
+    going to <strong>Settings > Applications > Development > USB debugging</strong>.</li>
+
+    <li>Ensure that your development computer can detect your device when connected via USB</li>
+  </ul>
+
+  <p>Read <a href="{@docRoot}guide/developing/device.html#setting-up">Setting up a Device for
+  Development</a> for more information.</p>
+
+  <p>Once your device is set up and connected via USB, navigate to your SDK's <code>platform-tools/</code>
+  directory and install the <code>.apk</code> on the device:</p>
+  <pre>
+adb -d install <em>path/to/your/app</em>.apk 
+</pre>
+
+  <p>The {@code -d} flag specifies that you want to use the attached device (in case you also have
+  an emulator running).</p>
+
+  <p>For more information on the tools used above, please see the following documents:</p>
+
+  <ul>
+    <li><a href="{@docRoot}guide/developing/tools/android.html">android Tool</a></li>
+
+    <li><a href="{@docRoot}guide/developing/devices/emulator.html">Android Emulator</a></li>
+
+    <li><a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> (ADB)</li>
+  </ul>
+
+  <h2 id="Signing">Application Signing</h2>
+
+  <p>As you begin developing Android applications, understand that all Android applications must be
+  digitally signed before the system will install them on an emulator or device. There are two ways
+  to do this: with a <em>debug key</em> (for immediate testing on an emulator or development
+  device) or with a <em>private key</em> (for application distribution).</p>
+
+  <p>The Android build tools help you get started by automatically signing your .apk files with a
+  debug key at build time. This means that you can compile your application and install it on the
+  emulator without having to generate your own private key. However, please note that if you intend
+  to publish your application, you <strong>must</strong> sign the application with your own private
+  key, rather than the debug key generated by the SDK tools.</p>
+
+  <p>The ADT plugin helps you get started quickly by signing your .apk files with a debug key,
+  prior to installing them on an emulator or development device. This means that you can quickly
+  run your application from Eclipse without having to generate your own private key. No specific
+  action on your part is needed, provided ADT has access to Keytool.However, please note that if
+  you intend to publish your application, you <strong>must</strong> sign the application with your
+  own private key, rather than the debug key generated by the SDK tools.</p>
+
+  <p>Please read <a href="{@docRoot}guide/publishing/app-signing.html">Signing Your
+  Applications</a>, which provides a thorough guide to application signing on Android and what it
+  means to you as an Android application developer. The document also includes a guide to exporting
+  and signing your application with the ADT's Export Wizard.</p>
\ No newline at end of file
diff --git a/docs/html/guide/developing/building/building-eclipse.jd b/docs/html/guide/developing/building/building-eclipse.jd
new file mode 100644
index 0000000..2c610c1
--- /dev/null
+++ b/docs/html/guide/developing/building/building-eclipse.jd
@@ -0,0 +1,163 @@
+page.title=Building and Running Apps in Eclipse
+@jd:body
+
+<div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li><a href="#RunningOnEmulatorEclipse">Running on an Emulator</a></li>
+
+        <li><a href="#RunningOnDeviceEclipse">Running on a Device</a></li>
+
+        <li><a href="#RunConfig">Creating a Run Configuration</a></li>
+      </ol>
+    </div>
+  </div>
+
+  <p>Eclipse and ADT provide an environment where most of the details of the build process are
+  hidden from you. By default, the build process constantly runs in the background as you make
+  changes to your project.</p>
+
+  <p>When Eclipse automatically builds your application, it enables debugging and signs the
+  <code>.apk</code> with a debug key, by default. When you run the application,
+  Eclipse invokes ADB and installs your application to a device or emulator, so you do not have to
+  manually perform these tasks. Since most of the build process is taken care of by Eclipse, the
+  following topics show you how to run an application, which will automatically build your
+  application as well.</p>
+
+  <p>To distribute your application, however, you must build your application in release mode and sign the
+  <code>.apk</code> file with your own private key.</p>
+  
+   <p>This document shows you how to run your application on an emulator or a real device 
+   from Eclipse&mdash;all of which is done using the debug version of your application. 
+   For more information about how to sign your application with a private key for release, see <a href=
+  "{@docRoot}guide/publishing/app-signing.html#ExportWizard">Signing Your Applications</a></p>
+
+  <h2 id="RunningOnEmulatorEclipse">Running on the emulator</h2>
+
+  <p>Before you can run your application on the Android Emulator, you must <a href=
+  "{@docRoot}guide/developing/devices/managing-avds.html">create an AVD</a>.</p>
+
+  <p>To run (or debug) your application, select <strong>Run</strong> &gt; <strong>Run</strong> (or
+  <strong>Run</strong> &gt; <strong>Debug</strong>) from the Eclipse menu bar. The ADT plugin will
+  automatically create a default run configuration for the project. Eclipse will then perform the
+  following:</p>
+
+  <ol>
+    <li>Compile the project (if there have been changes since the last build).</li>
+
+    <li>Create a default run configuration (if one does not already exist for the project).</li>
+
+    <li>Install and start the application on an emulator (or device), based on the Deployment
+    Target defined by the run configuration.
+
+      <p>By default, Android run configurations use an "automatic target" mode for selecting a
+      device target. For information on how automatic target mode selects a deployment target, see
+      <a href="#AutoAndManualTargetModes">Automatic and manual target modes</a> below.</p>
+    </li>
+  </ol>
+
+  <p>If you run the application with the Debug option, the application will start in the "Waiting For Debugger" mode. Once the debugger
+  is attached, Eclipse opens the Debug perspective and starts the application's main activity. Otherwise, if you run the
+  application with the normal Run option, Eclipse installs the application on the device and launches the main activity.</p>
+
+  <p>To set or change the run configuration used for your project, use the run configuration
+  manager. See the section below about <a href="#RunConfig">Creating a Run Configuration</a> for more information.</p>
+
+  <p>Be certain to create multiple AVDs upon which to test your application. You should have one
+  AVD for each platform and screen type with which your application is compatible. For instance, if
+  your application compiles against the Android 1.5 (API Level 3) platform, you should create an
+  AVD for each platform equal to and greater than 1.5 and an AVD for each <a href=
+  "{@docRoot}guide/practices/screens_support.html">screen type</a> you support, then test your
+  application on each one.</p>
+
+  <h2 id="RunningOnDeviceEclipse">Running on a device</h2>
+
+  <p>Before you can run your application on a device, you must perform some basic setup for your
+  device:</p>
+
+  <ul>
+    <li>Ensure that your application is debuggable by setting the
+    <code>android:debuggable</code> attribute of the <code>&lt;application&gt;</code>
+    element to <code>true</code>. As of ADT 8.0, this is done by default when you build in debug mode.</li>
+
+    <li>Enable USB Debugging on your device. You can find the setting on most Android devices by
+    going to <strong>Settings > Applications > Development > USB debugging</strong>.</li>
+
+    <li>Ensure that your development computer can detect your device when connected via USB</li>
+  </ul>
+
+  <p>Read <a href="{@docRoot}guide/developing/device.html">Connecting Hardware Devices</a>
+  for more information.</p>
+
+  <p>Once set up and your device is connected via USB, install your application on the device by
+  selecting <strong>Run</strong> &gt; <strong>Run</strong> (or <strong>Run</strong> &gt;
+  <strong>Debug</strong>) from the Eclipse menu bar.</p>
+
+  <h2 id="RunConfig">Creating a Run Configuration</h2>
+
+  <p>The run configuration specifies the project to run, the Activity to start, the emulator or
+  connected device to use, and so on. When you first run a project as an <em>Android
+  Application</em>, ADT will automatically create a run configuration. The default run
+  configuration will launch the default project Activity and use automatic target mode for device
+  selection (with no preferred AVD). If the default settings don't suit your project, you can
+  customize the run configuration or even create a new one.</p>
+
+  <p>To create or modify a run configuration, refer to the Eclipse documentation on how to create Run configurations.
+  The following steps highlight the important things you need to do for an Android project:</p>
+
+  <ol>
+    <li>Open the run configuration manager from the Run Menu.</li>
+
+    <li>Expand the <strong>Android Application</strong> item and create a new configuration or open
+    an existing one.
+    </li>
+
+    <li>With the Run Configuration selected, adjust your desired run configuration settings:
+      <ul>
+      <li>In the Android tab, specify the Project and Activity to launch.
+      </li>
+      <li><p>In the Target tab, consider whether you'd like to use Manual or Automatic mode when
+      selecting an AVD to run your application. See the following section on <a href=
+      "#AutoAndManualTargetModes">Automatic and manual target modes</a>).</p>
+
+      <p>You can specify any emulator options to the Additional Emulator Command Line Options
+      field. For example, you could add <code>-scale 96dpi</code> to scale the AVD's screen to an
+      accurate size, based on the dpi of your computer monitor. For a full list of emulator
+      options, see the <a href="{@docRoot}guide/developing/tools/emulator.html">Android
+      Emulator</a> document.</p>
+      </li>
+      </ul>
+    </li>
+  </ol>
+
+  <h4 id="AutoAndManualTargetModes">Automatic and manual target modes</h4>
+
+  <p>By default, a run configuration uses the <strong>automatic</strong> target mode in order to
+  select an AVD. In this mode, ADT will select an AVD for the application in the following
+  manner:</p>
+
+  <ol>
+    <li>If there's a device or emulator already running and its AVD configuration meets the
+    requirements of the application's build target, the application is installed and run upon
+    it.</li>
+
+    <li>If there's more than one device or emulator running, each of which meets the requirements
+    of the build target, a "device chooser" is shown to let you select which device to use.</li>
+
+    <li>If there are no devices or emulators running that meet the requirements of the build
+    target, ADT looks at the available AVDs. If there is an AVD that matches the build target of the project,
+    ADT chooses that AVD. If the AVD versions are newer than the build target of the project, ADT chooses
+    the oldest possible version of an AVD that meets the project's build target requirement.</li>
+
+    <li>If there are no suitable AVDs, the application is not installed a console error warning tells
+    you that there is no existing AVD that meets the build target requirements.</li>
+  </ol>
+
+  <p>However, if a "preferred AVD" is selected in the run configuration, then the application will
+  <em>always</em> be deployed to that AVD. If it's not already running, then a new emulator will be
+  launched.</p>
+
+  <p>If your run configuration uses <strong>manual</strong> mode, then the "device chooser" is
+  presented every time that your application is run, so that you can select which AVD to use.</p>
\ No newline at end of file
diff --git a/docs/html/guide/developing/building/index.jd b/docs/html/guide/developing/building/index.jd
new file mode 100644
index 0000000..b001ebc
--- /dev/null
+++ b/docs/html/guide/developing/building/index.jd
@@ -0,0 +1,81 @@
+page.title=Building and Running Apps
+@jd:body
+
+<div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+      <ol>
+        <li><a href="#detailed-build">A Detailed Look at the Build Process</a></li>
+      </ol>
+    </div>
+  </div>
+  
+ <p>During the build process, your Android projects are compiled and packaged into an .apk file,
+  the container for your application binary. It contains all of the information necessary to run
+  your application on a device or emulator, such as compiled <code>.dex</code> files (<code>.class</code> files
+  converted to Dalvik byte code), a binary version of the <code>AndroidManifest.xml</code> file, compiled
+  resources (<code>resources.arsc</code>) and uncompiled resource files for your application.</p>
+
+  <p>If you are developing in Eclipse, the ADT plugin incrementally builds your project as you
+  make changes to the source code. Eclipse outputs an <code>.apk</code> file automatically to the bin folder of
+  the project, so you do not have to do anything extra to generate the <code>.apk</code>.</p>
+
+  <p>If you are developing in a non-Eclipse environment, you can build your project with the
+  generated <code>build.xml</code> Ant file that is in the project directory. The Ant file calls targets that
+  automatically call the build tools for you.</p>
+
+  <p>To run an application on an emulator or device, the application must be signed using debug or
+  release mode. You typically want to sign your application in debug mode when you develop and test
+  your application, because the build tools use a debug key with a known password so you do not have
+  to enter it every time you build. When you are ready to release the application to Android
+  Market, you must sign the application in release mode, using your own private key.</p>
+
+  <p>Fortunately, Eclipse or your Ant build script signs the application for you in debug mode
+  when you build your application. You can also easily setup Eclipse or your Ant build to sign your
+  application in release mode as well. For more information on signing applications, see <a href=
+  "{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>.</p>
+  
+  <p>The following diagram depicts the components involved in building and running an application:</p>
+
+  <img src="/images/build-simplified.png" />
+
+  <h2 id="detailed-build">A Detailed Look at the Build Process</h2>
+
+  <p>The build process involves many tools and processes that generate intermediate files on the
+  way to producing an <code>.apk</code>. If you are developing in Eclipse, the complete build process is
+  automatically done periodically as you develop and save your code changes. If you are using other
+  IDEs, this build process is done every time you run the generated Ant build script for your
+  project. It is useful, however, to understand what is happening under the hood since much of the
+  tools and processes are masked from you. The following diagram depicts the different tools and
+  processes that are involved in a build:</p>
+
+  <p><img src="/images/build.png" /></p>
+
+  <p>The general process for a typical build is outlined below:</p>
+
+  <ul>
+  
+    <li>The Android Asset Packaging Tool (aapt) takes your application resource files, such as the
+    <code>AndroidManifest.xml</code> file and the XML files for your Activities, and compiles them. An <code>R.java</code> is
+    also produced so you can reference your resources from your Java code.</li>
+
+    <li>The aidl tool converts any <code>.aidl</code> interfaces that you have into Java interfaces.</li>
+
+    <li>All of your Java code, including the <code>R.java</code> and <code>.aidl</code> files, are compiled by the Java
+    compiler and .class files are output.</li>
+
+    <li>The dex tool converts the .class files to Dalvik byte code. Any 3rd party libraries and
+    .class files that you have included in your project are also converted into <code>.dex</code> files so that
+    they can be packaged into the final <code>.apk</code> file.</li>
+
+    <li>All non-compiled resources (such as images), compiled resources, and the .dex files are
+    sent to the apkbuilder tool to be packaged into an <code>.apk</code> file.</li>
+
+    <li>Once the <code>.apk</code> is built, it must be signed with either a debug or release key before it can
+    be installed to a device.</li>
+
+    <li>Finally, if the application is being signed in release mode, you must align the <code>.apk</code> with
+    the zipalign tool. Aligning the final <code>.apk</code> decreases memory usage when the application is
+    running on a device.</li>
+  </ul>
+
diff --git a/docs/html/guide/developing/debug-tasks.html b/docs/html/guide/developing/debug-tasks.html
new file mode 100644
index 0000000..4e73804
--- /dev/null
+++ b/docs/html/guide/developing/debug-tasks.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0;url=http://developer.android.com/guide/developing/debugging/index.html">
+<title>Redirecting...</title>
+</head>
+<body>
+<p>You should be redirected. Please <a
+href="http://developer.android.com/guide/developing/debugging/index.html">click here</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/guide/developing/debug-tasks.jd b/docs/html/guide/developing/debug-tasks.jd
deleted file mode 100644
index f0bf84c..0000000
--- a/docs/html/guide/developing/debug-tasks.jd
+++ /dev/null
@@ -1,232 +0,0 @@
-page.title=Debugging Tasks
-@jd:body
-
-<div id="qv-wrapper">
-<div id="qv">
-  <h2>In this document</h2>
-  <ol>
-    <li><a href="#tools">Tools</a></li>
-    <li><a href="#additionaldebugging">Debug with Dev Tools</a></li>
-    <li><a href="#DebuggingWebPages">Debugging Web Pages</a></li>
-    <li><a href="#toptips">Top Debugging Tips</a></li>
-    <li><a href="#ide-debug-port">Configuring Your IDE to Attach to the Debugging Port</a></li>
-  </ol>
-</div>
-</div>
-
-<p>This document offers some helpful guidance to debugging applications on Android.
-
-
-<h2 id="tools">Tools</h2>
-
-<p>The Android SDK includes a set of tools to help you debug and profile
-your applications. Here are some tools that you'll use most often:</p>
-
-<dl>
-  <dt><strong><a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge
-(ADB)</a></strong></dt>
-  <dd>Provides various device management capabilities, including
-    moving and syncing files to the emulator, forwarding ports, and running a UNIX
-    shell on the emulator.</dd>
-  <dt><strong><a href="{@docRoot}guide/developing/tools/ddms.html">Dalvik Debug Monitor Server
-(DDMS)</a></strong></dt>
-  <dd>A graphical program that
-        supports port forwarding (so you can set up breakpoints in your code in your
-        IDE), screen captures on the emulator, thread and stack information,
-        and many other features. You can also run logcat to retrieve your Log messages.</dd>
-  </dd>
-  <dt><strong><a href="{@docRoot}guide/developing/tools/traceview.html">Traceview</a></strong></dt>
-  <dd>A graphical viewer that displays trace file data for method calls and times saved by
-  your application, which can help you profile the performance of your application.</dd>
-  <dt><strong><a href="{@docRoot}guide/developing/tools/ddms.html#logcat">logcat</a></strong></dt>
-  <dd>Dumps a log of system
-      messages. The messages include a stack trace when the device throws an error,
-      as well as {@link android.util.Log} messages you've written from your application. To run
-      logcat, execute <code>adb logcat</code> from your Android SDK {@code tools/} directory or,
-from DDMS, select <strong>Device > Run
-      logcat</strong>. When using the <a href="{@docRoot}sdk/eclipse-adt.html">ADT plugin for
-Eclipse</a>, you can also view logcat messages by opening the Logcat view, available from
-<strong>Window > Show View > Other > Android > Logcat</strong>.
-      <p>{@link android.util.Log} is a logging
-      class you can use to print out messages to the logcat. You can read messages
-      in real time if you run logcat on DDMS (covered next). Common logging methods include:
-      {@link android.util.Log#v(String,String)} (verbose), {@link
-      android.util.Log#d(String,String)} (debug), {@link android.util.Log#i(String,String)}
-      (information), {@link android.util.Log#w(String,String)} (warning) and {@link
-      android.util.Log#e(String,String)} (error). For example:</p>
-<pre class="no-pretty-print">
-Log.i("MyActivity", "MyClass.getView() &mdash; get item number " + position);
-</pre>
-      <p>The logcat will then output something like:</p>
-<pre class="no-pretty-print">
-I/MyActivity( 1557): MyClass.getView() &mdash; get item number 1
-</pre>
-      <p>Logcat is also the place to look when debugging a web page in the Android Browser app. See
-<a href="#DebuggingWebPages">Debugging Web Pages</a> below.</p>
-</dl>
-
-<p>For more information about all the development tools provided with the Android SDK, see the <a
-href="{@docRoot}guide/developing/tools/index.html">Tools</a> document.</p>
-
-<p>In addition to the above tools, you may also find the following useful for debugging:
-<dl>
-  <dt><a href="{@docRoot}guide/developing/eclipse-adt.html"><strong>Eclipse ADT
-plugin</strong></a></dt>
-  <dd>The ADT Plugin for Eclipse integrates a number of the Android development tools (ADB, DDMS,
-logcat output, and other functionality), so that you won't work with them directly but will utilize
-them through the Eclipse IDE.</dd>
-  <dt><strong>Developer Settings in the Dev Tools app</strong></dt>
-  <dd>The Dev Tools application included in the emulator system image exposes several settings
-        that provide useful information such as CPU usage and frame rate. See <a
-href="#additionaldebugging">Debugging and Testing with Dev Tools</a> below.</dd>
-</dl>
-
-<h2 id="additionaldebugging">Debugging and Testing with Dev Tools</h2>
-
-<p>With the Dev Tools application, you can enable a number of settings on your device that will
-make it easier to test and debug your applications.</p>
-
-<p>The Dev Tools application is installed by default
-on all system images included with the SDK, so you can use it with the Android Emulator. If you'd
-like to install the Dev Tools application on a real development device, you can copy the
-application from your emulator and then install it on your device using ADB. To copy the
-application from a running emulator, execute:
-</p>
-<pre>
-adb -e pull /system/app/Development.apk ./Development.apk
-</pre>
-<p>This copies the .apk file into the current directory. Then install it on your connected device
-with:</p>
-<pre>
-adb -d install Development.apk
-</pre>
-
-<p>To get started, launch the Dev Tools application and
-select Development Settings. This will open the Development Settings page with the
-following options (among others):</p>
-
-<dl>
-    <dt><strong>Debug app</strong></dt>
-    <dd>Lets you select the application to debug. You do not need to set this to attach a debugger,
-    but setting this value has two effects:
-        <ul>
-            <li>It will prevent Android from throwing an error if you pause on
-                    a breakpoint for a long time while debugging.</li>
-            <li>It will enable you to select the <em>Wait for Debugger</em> option
-                to pause application startup until your debugger attaches (described
-                next). </li>
-        </ul>
-    </dd>
-    <dt><strong>Wait for debugger</strong></dt>
-    <dd>Blocks the selected application from loading until a debugger attaches. This
-            way you can set a breakpoint in onCreate(), which is important to debug
-            the startup process of an Activity. When you change this option, any
-            currently running instances of the selected application will be killed.
-            In order to check this box, you must have selected a debug application
-            as described in the previous option. You can do the same thing by adding
-            {@link android.os.Debug#waitForDebugger()} to your code.</dd>
-    <dt><strong>Show screen updates</strong></dt>
-    <dd>Flashes a momentary pink rectangle on any screen sections that are being
-            redrawn. This is very useful for discovering unnecessary screen drawing.</dd>
-    <dt><strong>Immediately destroy activities</strong></dt>
-    <dd>Tells the
-        system to destroy an activity as soon as it is stopped (as if Android had to
-        reclaim memory).&nbsp; This is very useful for testing the {@link android.app.Activity#onSaveInstanceState}
-        / {@link android.app.Activity#onCreate(android.os.Bundle)} code path, which would
-        otherwise be difficult to force. Choosing this option will probably reveal
-        a number of problems in your application due to not saving state.</dd>
-    <dt><strong>Show CPU usage</strong></dt>
-    <dd>Displays CPU meters at the
-        top of the screen, showing how much the CPU is being used. The top red bar
-        shows overall CPU usage, and the green bar underneath it shows the CPU time
-        spent in compositing the screen. <em>Note: You cannot turn this feature off
-        once it is on, without restarting the emulator.</em> </dd>
-    <dt><strong>Show background</strong></dt>
-    <dd>Displays a background pattern
-        when no activity screens are visible. This typically does not happen, but
-        can happen during debugging.</dd>
-</dl>
-
-<p>These settings will be remembered across emulator restarts.</p>
-
-<h2 id="DebuggingWebPages">Debugging Web Pages</h2>
-
-<p>See the <a href="{@docRoot}guide/webapps/debugging.html">Debugging Web Apps</a> document.</p>
-
-
-<h2 id="toptips">Top Debugging Tips</h2>
-
-<dl>
-<dt><strong>Dump the stack trace</strong></dt>
-<dd>To obtain a stack dump from emulator, you can log
-in with <code>adb shell</code>, use &quot;ps&quot; to find the process you
-want, and then &quot;kill -3 &quot;. The stack trace appears in the log file.
-</dd>
-
-<dt><strong>Display useful info on the emulator screen</strong></dt>
-<dd>The device can display useful information such as CPU usage or highlights
-around redrawn areas. Turn these features on and off in the developer settings
-window as described in <a href="#additionaldebugging">Setting debug and test
-configurations on the emulator</a>.
-</dd>
-
-<dt><strong>Get system state information from the emulator (dumpstate)</strong></dt>
-<dd>You can access dumpstate information from the Dalvik Debug Monitor Service
-tool. See <a href="{@docRoot}guide/developing/tools/adb.html#dumpsys">dumpsys and
-dumpstate</a> on the adb topic page.</dd>
-
-<dt><strong>Get application state information from the emulator (dumpsys)</strong></dt>
-<dd>You can access dumpsys information from the Dalvik Debug Monitor Service
-tool. See <a href="{@docRoot}guide/developing/tools/adb.html#dumpsys">dumpsys and
-dumpstate</a> on the adb topic page.</dd>
-
-<dt><strong>Get wireless connectivity information</strong></dt>
-<dd>You can get information about wireless connectivity using the Dalvik Debug
-Monitor Service tool. From the <strong>Device</strong> menu, select &quot;Dump
-radio state&quot;.</dd>
-
-<dt><strong>Log trace data</strong></dt>
-<dd>You can log method calls and other tracing data in an activity by calling
-{@link android.os.Debug#startMethodTracing(String) startMethodTracing()}. See <a
-href="{@docRoot}guide/developing/tools/traceview.html">Running the Traceview Debugging
-Program</a> for details. </dd>
-
-<dt><strong>Log radio data</strong></dt>
-<dd>By default, radio information is not logged to the system (it is a lot of
-data). However, you can enable radio logging using the following commands:
-
-<pre class="no-pretty-print">
-adb shell
-logcat -b radio
-</pre>
-</dd>
-
-<dt><strong>Capture screenshots</strong></dt>
-<dd>The Dalvik Debug Monitor Server (DDMS) can capture screenshots from the emulator. Select
-<strong>Device > Screen capture</strong>.</dd>
-
-<dt><strong>Use debugging helper classes</strong></dt>
-<dd>Android provides debug helper classes such as {@link android.util.Log
-    util.Log} and {@link android.os.Debug} for your convenience. </dd>
-</dl>
-
-<p>Also see the <a href="{@docRoot}resources/faq/troubleshooting.html">Troubleshooting</a> document
-for answers to some common developing and debugging issues.</p>
-
-
-<h2 id="ide-debug-port">Configuring Your IDE to Attach to the Debugging Port</h2>
-
-<p>DDMS will assign a specific debugging port to every virtual machine that it
-    finds on the emulator. You must either attach your IDE to that
-    port (listed on the Info tab for that VM), or you can use a default port 8700
-    to connect to whatever application is currently selected on the list of discovered
-    virtual machines.</p>
-<p>Your IDE should attach to your application running on the emulator, showing you
-    its threads and allowing you to suspend them, inspect their state, and set breakpoints.
-    If you selected &quot;Wait for debugger&quot; in the Development settings panel
-    the application will run when Eclipse connects, so you will need to set any breakpoints
-    you want before connecting.</p>
-<p>Changing either the application being debugged or the &quot;Wait for debugger&quot;
-    option causes the system to kill the selected application if it is currently
-        running. You can use this to kill your application if it is in a bad state
-        by simply going to the settings and toggling the checkbox.</p>
diff --git a/docs/html/guide/developing/debugging/ddms.jd b/docs/html/guide/developing/debugging/ddms.jd
new file mode 100644
index 0000000..8f5e706
--- /dev/null
+++ b/docs/html/guide/developing/debugging/ddms.jd
@@ -0,0 +1,284 @@
+page.title=Using DDMS
+@jd:body
+
+ <div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+      <li><a href="#running">Running DDMS</a></li>
+        <li><a href="#how-ddms-works">How DDMS Interacts with a Debugger</a></li>
+
+        <li><a href="#using-ddms">Using DDMS</a></li>
+      </ol>
+    </div>
+  </div>
+
+  <p>Android ships with a debugging tool called the Dalvik Debug Monitor Server (DDMS), which
+  provides port-forwarding services, screen capture on the device, thread and heap information on
+  the device, logcat, process, and radio state information, incoming call and SMS spoofing,
+  location data spoofing, and more. This page provides a modest discussion of DDMS features; it is
+  not an exhaustive exploration of all the features and capabilities.</p>
+  
+  <h2 id="running">Running DDMS</h2>
+  <p>DDMS is integrated into Eclipse and is also shipped in the <code>tools/</code> directory of the
+  SDK. DDMS works with both the emulator and a connected device. If both are connected and running simultaneously, 
+  DDMS defaults to the emulator.</p>
+  
+  <ul>
+    <li>From Eclipse: Click <strong>Window > Open Perspective > Other... > DDMS</strong>.</li>
+    <li>From the command line: Type <code>ddms</code> (or <code>./ddms</code> on Mac/Linux) from the <code>tools/</code>
+    directory. </li>
+  </ul>
+
+
+  <h2 id="how-ddms-works">How DDMS Interacts with a Debugger</h2>
+
+  <p>On Android, every application runs in its own process, each of which runs in its own virtual machine
+  (VM). Each VM exposes a unique port that a debugger can attach to.</p>
+
+  <p>When DDMS starts, it connects to <a href="{@docRoot}guide/developing/tools/adb.html">adb</a>.
+  When a device is connected, a VM monitoring service is created between
+  <code>adb</code> and DDMS, which notifies DDMS when a VM on the device is started or terminated. Once a VM
+  is running, DDMS retrieves the the VM's process ID (pid), via <code>adb</code>, and opens a connection to the
+  VM's debugger, through the adb daemon (adbd) on the device. DDMS can now talk to the VM using a
+  custom wire protocol.</p>
+
+  <p>DDMS assigns a debugging port to each VM on the device. Typically,
+  DDMS assigns port 8600 for the first debuggable VM, the next on 8601, and so on. When a debugger
+  connects to one of these ports, all traffic is forwarded to the debugger from the associated
+  VM. You can only attach a single debugger to a single port, but DDMS can handle multiple, attached
+  debuggers.</p>
+
+  <p>By default, DDMS also listens on another debugging port, the DDMS "base port" (8700, by default).
+  The base port is a port forwarder, which can accept VM traffic from any debugging port and forward
+  it to the debugger on port 8700. This allows you to attach one debugger to port 8700, and debug
+  all the VMs on a device. The traffic that is forwarded is determined by the currently selected process
+  in the DDMS Devices view.</p>
+
+  <p>The following screenshot shows a typical DDMS screen in Eclipse. If you are starting DDMS from
+  the command line, the screen is slightly different, but much of the functionality is identical.
+  Notice that the highlighted process, <code>com.example.android.notepad</code>, that is running in the emulator
+  has the debugging port 8700 assigned to it as well as 8609. This signifies that DDMS is currently
+  forwarding port 8609 to the static debugging port of 8700.</p>
+
+  <img src="{@docRoot}images/debug-ddms.png"
+       width="1024" />
+  <p class="img-caption"><strong>Figure 1.</strong> 
+  Screenshot of DDMS</p> 
+
+  <p>If you are not using Eclipse and ADT, read <a href=
+  "{@docRoot}guide/developing/debugging/debugging-projects-cmdline.html#debuggingPort">Configuring
+  your IDE to attach to the debugging port</a>, for more information on attaching your
+  debugger.</p>
+
+  <p class="note"><strong>Tip:</strong> You can set a number of DDMS preferences in
+  <strong>File</strong> &gt; <strong>Preferences</strong>. Preferences are saved to
+  <code>$HOME/.ddmsrc</code>.</p>
+
+  <p class="warning"><strong>Known debugging issues with Dalvik</strong><br />
+  Debugging an application in the Dalvik VM should work the same as it does in other VMs. However,
+  when single-stepping out of synchronized code, the "current line" cursor may jump to the last
+  line in the method for one step.</p>
+
+  <h2 id="using-ddms">Using DDMS</h2>
+  The following sections describe how to use DDMS and the various tabs and panes that are part of the
+  DDMS GUI. The Eclipse version and the command line version have minor UI differences, but the 
+  same functionality. For information on running DDMS, see the previous section in this document,
+  <a href="#running">Running DDMS</a>.
+  
+  
+  <h3>Viewing heap usage for a process</h3>
+
+  <p>DDMS allows you to view how much heap memory a process is using. This information is useful in
+  tracking heap usage at a certain point of time during the execution of your application.</p>
+  <p>To view heap usage for a process:</p>
+  <ol>
+    <li>In the Devices tab, select the process that you want to see the heap information for.</li>
+
+    <li>Click the <strong>Update Heap</strong> button to enable heap information for the
+    process.</li>
+
+    <li>In the Heap tab, click <strong>Cause GC</strong> to invoke garbage collection, which
+    enables the collection of heap data. When the operation completes, you will see a group of
+    object types and the memory that has been allocated for each type. You can click <strong>Cause
+    GC</strong> again to refresh the data.</li>
+
+    <li>Click on an object type in the list to see a bar graph that shows the number of objects
+    allocated for a particular memory size in bytes.</li>
+  </ol>
+
+  <h3>Tracking memory allocation of objects</h3>
+
+  <p>DDMS provides a feature to track objects that are being allocated to memory and to see which
+  classes and threads are allocating the objects. This allows you to track, in real time, where
+  objects are being allocated when you perform certain actions in your application. This
+  information is valuable for assessing memory usage that can affect application performance.
+  If you want more granular control over where allocation data is collected, use the
+  {@link android.os.Debug#startAllocCounting()} and {@link android.os.Debug#stopAllocCounting()}
+  methods.</p>
+  
+  <p>To track memory allocation of objects:</p>
+  <ol>
+    <li>In the Devices tab, select the process that you want to enable allocation tracking
+    for.</li>
+
+    <li>In the Allocation Tracker tab, click the <strong>Start Tracking</strong> button to begin
+    allocation tracking. At this point, anything you do in your application will be tracked.</li>
+
+    <li>Click <strong>Get Allocations</strong> to see a list of objects that have been allocated
+    since you clicked on the <strong>Start Tracking</strong> button. You can click on <strong>Get
+    Allocations</strong> again to append to the list new objects that that have been
+    allocated.</li>
+
+    <li>To stop tracking or to clear the data and start over, click the <strong>Stop Tracking
+    button</strong>.</li>
+
+    <li>Click on a specific row in the list to see more detailed information such as the method and
+    line number of the code that allocated the object.</li>
+  </ol>
+
+  <h3>Working with an emulator or device's file system</h3>
+
+  <p>DDMS provides a File Explorer tab that allows you to view, copy, and delete files on the
+  device. This feature is useful in examining files that are created by your application or if you
+  want to transfer files to and from the device.</p>
+  
+  <p>To work with an emulator or device's file system:</p>
+  <ol>
+    <li>In the Devices tab, select the emulator that you want to view the file system for.</li>
+
+    <li>To copy a file from the device, locate the file in the File Explorer and click the
+    <strong>Pull file</strong> button.</li>
+
+    <li>To copy a file to the device, click the <strong>Push file</strong> button on the File
+    Explorer tab.</li>
+  </ol>
+  
+  <!-- Need to elaborate more on where things are stored in the file system,
+   databases, apks, user info, files that are important to look at -->
+
+  <h3>Examining thread information</h3>
+
+  <p>The Threads tab in DDMS shows you the currently running threads for a selected process.</p>
+
+  <ol>
+    <li>In the Devices tab, select the process that you want to examine the threads for.</li>
+
+    <li>Click the <strong>Update Threads</strong> button.</li>
+
+    <li>In the Threads tab, you can view the thread information for the selected process.</li>
+  </ol>
+
+  <h3 id="profiling">Starting method profiling</h3>
+
+  <p>Method profiling is a means to track certain metrics about a method, such as number of calls,
+  execution time, and time spent executing the method. If you want more granular control over 
+  where profiling data is collected, use the {@link android.os.Debug#startMethodTracing()} and 
+  {@link android.os.Debug#stopMethodTracing()} methods. For more information about generating trace logs, see 
+  <a href="debugging-tracing.html">Profiling and Debugging UIs</a>.</p>
+  
+  <p>Before you start method profiling in DDMS, be aware of the following restrictions:</p>
+    <ul>
+      <li>Android 1.5 devices are not supported.</li>
+      <li>Android 2.1 and earlier devices must
+      have an SD card present and your application must have permission to write to the SD card.
+      <li>Android 2.2 and later devices do not need an SD card. The trace log files are 
+      streamed directly to your development machine.</li>
+    </ul>
+  
+  <p>To start method profiling:</p>
+  <ol>
+    <li>On the Devices tab, select the process that you want to enable method profiling for.</li>
+
+    <li>Click the <strong>Start Method Profiling</strong> button.</li>
+
+    <li>Interact with your application to start the methods that you want to profile.</li>
+
+    <li>Click the <strong>Stop Method Profiling</strong> button. DDMS stops profiling your
+    application and opens <a href="{@docRoot}guide/developing/debugging/debugging-ui.html">Traceview</a>
+    with the method profiling information that was collected
+    between the time you clicked on <strong>Start Method Profiling</strong> and <strong>Stop Method
+    Profiling</strong>.</li>
+  </ol>
+
+  <h3 id="logcat">Using LogCat</h3>
+
+  <p>LogCat is integrated into DDMS, and outputs the messages that you print out using the {@link android.util.Log}
+  class along with other system messages such as stack traces when exceptions are thrown. View the
+  <a href="{@docRoot}guide/developing/debugging/debugging-log.html">Reading and
+  Writing Log Messages.</a> topic for more information on how to log messages to the LogCat.</p>
+
+  <p>When you have set up your logging, you can use the LogCat feature of DDMS to filter certain
+  messages with the following buttons:</p>
+
+  <ul>
+    <li>Verbose</li>
+
+    <li>Debug</li>
+
+    <li>Info</li>
+
+    <li>Warn</li>
+
+    <li>Error</li>
+  </ul>
+  
+  <p>You can also setup your own custom filter to specify more details such as filtering messages
+  with the log tags or with the process id that generated the log message. The add filter,
+  edit filter, and delete filter buttons let you manage your custom filters.</p>
+
+  <h3>Emulating phone operations and location</h3>
+  <p>The Emulator control tab lets you simulate a
+  phone's voice and data network status. This is useful when you want to test your application's
+  robustness in differing network environments.</p>
+
+  <h4>Changing network state, speed, and latency</h4>
+  <p>The Telephony Status section of the Emulator
+  controls tab lets you change different aspects of the phone's networks status, speed and latency.
+  The following options are available to you and are effective immediately after you set them:</p>
+
+  <ul>
+    <li>Voice - unregistered, home, roaming, searching, denied</li>
+
+    <li>Data - unregistered, home, roaming, searching, denied</li>
+
+    <li>Speed - Full, GSM, HSCSD, GPRS, EDGE, UMTS, HSDPA</li>
+
+    <li>Latency - GPRS, EDGE, UMTS</li>
+  </ul>
+
+  <h4>Spoofing calls or SMS text messages</h4>
+  <p>The Telephony Actions section of the Emulator
+  controls tab lets you spoof calls and messages. This is useful when you want to to test your
+  application's robustness in responding to incoming calls and messages that are sent to the phone.
+  The following actions are available to you:</p>
+
+  <ul>
+    <li>Voice - Enter a number in the <strong>Incoming number</strong> field and click 
+    <strong>Call</strong> to send a simulated call to the emulator or phone. Click the
+    <strong>Hang up</strong> button to terminate the call.</li>
+
+    <li>SMS - Enter a number in the <strong>Incoming number</strong> field and a message in the
+    <strong>Message:</strong> field and click the <strong>Send</strong> button to send the
+    message.</li>
+  </ul>
+
+  <h4>Setting the location of the phone</h4>
+  <p>If your application depends on the location of the phone, you can have DDMS send your
+  device or AVD a mock location. This is useful if you
+  want to test different aspects of your application's location specific features without
+  physically moving. The following geolocation data types are available to you:</p>
+
+  <ul>
+    <li>Manual - set the location by manually specifying decimal or sexagesimal longitude and
+    latitude values.</li>
+
+    <li>GPX - GPS eXchange file</li>
+
+    <li>KML - Keyhole Markup Language file</li>
+  </ul>
+  
+  For more information about providing mock location data, see 
+  <a href="{@docRoot}guide/topics/location/obtaining-user-location.html#MockData">Obtaining User Location</a>.
+  
diff --git a/docs/html/guide/developing/debugging/debugging-devtools.jd b/docs/html/guide/developing/debugging/debugging-devtools.jd
new file mode 100644
index 0000000..88e6005
--- /dev/null
+++ b/docs/html/guide/developing/debugging/debugging-devtools.jd
@@ -0,0 +1,82 @@
+page.title=Using the Dev Tools App
+@jd:body
+
+<p>The Dev Tools application is installed by default on all system images included with the SDK,
+  so you can use it with the Android Emulator. With the Dev Tools application, you can enable a
+  number of settings on your device that will make it easier to test and debug your applications.</p>
+
+  <p> If you'd like to install the Dev Tools application
+  on a real development device, you can copy the application from your emulator and then install it
+  on your device using ADB. To copy the application from a running emulator, execute:</p>
+  <pre>
+adb -e pull /system/app/Development.apk ./Development.apk
+</pre>
+
+  <p>This copies the .apk file into the current directory. Then install it on your connected device
+  with:</p>
+  <pre>
+adb -d install Development.apk
+</pre>
+
+  <p>To get started, launch the Dev Tools application and select <strong>Development Settings</strong>. This will
+  open the Development Settings page with the following options (among others):</p>
+
+  <dl>
+    <dt><strong>Debug app</strong></dt>
+
+    <dd>
+      Lets you select the application to debug. You do not need to set this to attach a debugger,
+      but setting this value has two effects:
+
+      <ul>
+        <li>It will prevent Android from throwing an error if you pause on a breakpoint for a long
+        time while debugging.</li>
+
+        <li>It will enable you to select the <em>Wait for Debugger</em> option to pause application
+        startup until your debugger attaches (described next).</li>
+      </ul>
+    </dd>
+
+    <dt><strong>Wait for debugger</strong></dt>
+
+    <dd>Blocks the selected application from loading until a debugger attaches. This way you can
+    set a breakpoint in {@link android.app.Activity#onCreate onCreate()}, 
+    which is important to debug the startup process of an Activity.
+    When you change this option, any currently running instances of the selected application will
+    be killed. In order to check this box, you must have selected a debug application as described
+    in the previous option. You can do the same thing by adding {@link
+    android.os.Debug#waitForDebugger()} to your code.</dd>
+
+    <dt><strong>Show screen updates</strong></dt>
+
+    <dd>Flashes a momentary pink rectangle on any screen sections that are being redrawn. This is
+    very useful for discovering unnecessary screen drawing.</dd>
+
+    <dt><strong>Immediately destroy activities</strong></dt>
+
+    <dd>Tells the system to destroy an activity as soon as it is stopped (as if Android had to
+    reclaim memory).&nbsp; This is very useful for testing the {@link
+    android.app.Activity#onSaveInstanceState} / {@link
+    android.app.Activity#onCreate(android.os.Bundle)} code path, which would otherwise be difficult
+    to force. Choosing this option will probably reveal a number of problems in your application
+    due to not saving state. For more information about saving an application's state, see 
+    <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime Changes</a>.</dd>
+
+    <dt><strong>Show CPU usage</strong></dt>
+
+    <dd>Displays CPU meters at the top of the screen, showing how much the CPU is being used. The
+    top red bar shows overall CPU usage, and the green bar underneath it shows the CPU time spent
+    in compositing the screen. 
+    <p class="note">Note: You cannot turn this feature off once it is on, without
+    restarting the emulator.</p></dd>
+
+    <dt><strong>Show background</strong></dt>
+
+    <dd>Displays a background pattern when no activity screens are visible. This typically does not
+    happen, but can happen during debugging.</dd>
+  </dl>
+
+  <p>These settings will be remembered across emulator restarts.</p>
+
+
+
diff --git a/docs/html/guide/developing/debugging/debugging-log.jd b/docs/html/guide/developing/debugging/debugging-log.jd
new file mode 100644
index 0000000..6ee69c7
--- /dev/null
+++ b/docs/html/guide/developing/debugging/debugging-log.jd
@@ -0,0 +1,305 @@
+page.title=Reading and Writing Log Messages
+@jd:body
+
+<div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li><a href="#logClass">The Log class</a></li>
+
+        <li><a href="#startingLogcat">Starting LogCat</a></li>
+
+        <li><a href="#filteringOutput">Filtering Log Output</a></li>
+
+        <li><a href="#outputFormat">Controlling Log Output Format</a></li>
+
+        <li><a href="#alternativeBuffers">Viewing Alternative Log Output Buffers</a></li>
+
+        <li><a href="#viewingStd">Viewing stdout and stderr</a></li>
+
+        <li><a href="#DebuggingWebPages">Debugging Web Pages</a></li>
+      </ol>
+    </div>
+  </div>
+
+  <p>The Android logging system provides a mechanism for collecting and viewing system debug
+  output. Logcat dumps a log of system messages, which include things such as stack traces when the
+  emulator throws an error and messages that you have written from your application by using the
+  {@link android.util.Log} class. You can run LogCat through ADB or from DDMS, which allows you to
+  read the messages in real time.</p>
+
+  <h2 id="logClass">The <code>Log</code> class</h2>
+
+  <p>{@link android.util.Log} is a logging class that you can utilize in your code to print out
+  messages to the LogCat. Common logging methods include:</p>
+
+  <ul>
+    <li>{@link android.util.Log#v(String,String)} (verbose)</li>
+
+    <li>{@link android.util.Log#d(String,String)} (debug)</li>
+
+    <li>{@link android.util.Log#i(String,String)} (information)</li>
+
+    <li>{@link android.util.Log#w(String,String)} (warning)</li>
+
+    <li>{@link android.util.Log#e(String,String)} (error)</li>
+  </ul>For example:
+  <pre class="no-pretty-print">
+Log.i("MyActivity", "MyClass.getView() &mdash; get item number " + position);
+</pre>
+
+  <p>The LogCat will then output something like:</p>
+  <pre class="no-pretty-print">
+I/MyActivity( 1557): MyClass.getView() &mdash; get item number 1
+</pre>
+
+  <h2 id="startingLogcat">Using LogCat</h2>
+
+  <p>You can use LogCat from within DDMS or call it on an ADB shell. For more information on how to
+  use LogCat within DDMS, see <a href="{@docRoot}guide/developing/debugging/ddms.html#logcat">Using
+  DDMS</a>. To run LogCat, through the ADB shell, the general usage is:</p>
+  <pre>
+[adb] logcat [&lt;option&gt;] ... [&lt;filter-spec&gt;] ...
+</pre>
+
+  <p>You can use the <code>logcat</code> command from your development computer or from a remote
+  adb shell in an emulator/device instance. To view log output in your development computer, you
+  use</p>
+  <pre>
+$ adb logcat
+</pre>
+
+  <p>and from a remote adb shell you use</p>
+  <pre>
+# logcat
+</pre>
+
+  <p>The following table describes the <code>logcat</code> command line options:</p>
+
+  <table>
+    <tr>
+      <td><code>-c</code></td>
+
+      <td>Clears (flushes) the entire log and exits.</td>
+    </tr>
+
+    <tr>
+      <td><code>-d</code></td>
+
+      <td>Dumps the log to the screen and exits.</td>
+    </tr>
+
+    <tr>
+      <td><code>-f&nbsp;&lt;filename&gt;</code></td>
+
+      <td>Writes log message output to <code>&lt;filename&gt;</code>. The default is
+      <code>stdout</code>.</td>
+    </tr>
+
+    <tr>
+      <td><code>-g</code></td>
+      <td>Prints the size of the specified log buffer and exits.</td>
+    </tr>
+
+    <tr>
+      <td><code>-n&nbsp;&lt;count&gt;</code></td>
+
+      <td>Sets the maximum number of rotated logs to <code>&lt;count&gt;</code>. The default value
+      is 4. Requires the <code>-r</code> option.</td>
+    </tr>
+
+    <tr>
+      <td><code>-r&nbsp;&lt;kbytes&gt;</code></td>
+
+      <td>Rotates the log file every <code>&lt;kbytes&gt;</code> of output. The default value is
+      16. Requires the <code>-f</code> option.</td>
+    </tr>
+
+    <tr>
+      <td><code>-s</code></td>
+
+      <td>Sets the default filter spec to silent.</td>
+    </tr>
+
+    <tr>
+      <td><code>-v&nbsp;&lt;format&gt;</code></td>
+
+      <td>Sets the output format for log messages. The default is <code>brief</code> format. For a
+      list of supported formats, see <a href="#outputFormat">Controlling Log Output
+      Format</a>.</td>
+    </tr>
+  </table>
+
+  <h3 id="filteringOutput">Filtering Log Output</h3>
+
+  <p>Every Android log message has a <em>tag</em> and a <em>priority</em> associated with it.</p>
+
+  <ul>
+    <li>The tag of a log message is a short string indicating the system component from which the
+    message originates (for example, "View" for the view system).</li>
+
+    <li>The priority is one of the following character values, ordered from lowest to highest
+    priority:</li>
+
+    <li style="list-style: none; display: inline">
+      <ul>
+        <li><code>V</code> &mdash; Verbose (lowest priority)</li>
+
+        <li><code>D</code> &mdash; Debug</li>
+
+        <li><code>I</code> &mdash; Info</li>
+
+        <li><code>W</code> &mdash; Warning</li>
+
+        <li><code>E</code> &mdash; Error</li>
+
+        <li><code>F</code> &mdash; Fatal</li>
+
+        <li><code>S</code> &mdash; Silent (highest priority, on which nothing is ever printed)</li>
+      </ul>
+    </li>
+  </ul>
+
+  <p>You can obtain a list of tags used in the system, together with priorities, by running
+  LogCat and observing the first two columns of each message, given as
+  <code>&lt;priority&gt;/&lt;tag&gt;</code>.</p>
+
+  <p>Here's an example of logcat output that shows that the message relates to priority level "I"
+  and tag "ActivityManager":</p>
+  <pre>
+I/ActivityManager(  585): Starting activity: Intent { action=android.intent.action...}
+</pre>
+
+  <p>To reduce the log output to a manageable level, you can restrict log output using <em>filter
+  expressions</em>. Filter expressions let you indicate to the system the tags-priority
+  combinations that you are interested in &mdash; the system suppresses other messages for the
+  specified tags.</p>
+
+  <p>A filter expression follows this format <code>tag:priority ...</code>, where <code>tag</code>
+  indicates the tag of interest and <code>priority</code> indicates the <em>minimum</em> level of
+  priority to report for that tag. Messages for that tag at or above the specified priority are
+  written to the log. You can supply any number of <code>tag:priority</code> specifications in a
+  single filter expression. The series of specifications is whitespace-delimited.</p>
+
+  <p>Here's an example of a filter expression that suppresses all log messages except those with
+  the tag "ActivityManager", at priority "Info" or above, and all log messages with tag "MyApp",
+  with priority "Debug" or above:</p>
+  <pre>
+adb logcat ActivityManager:I MyApp:D *:S
+</pre>
+
+  <p>The final element in the above expression, <code>*:S</code>, sets the priority level for all
+  tags to "silent", thus ensuring only log messages with "View" and "MyApp" are displayed. Using
+  <code>*:S</code> is an excellent way to ensure that log output is restricted to the filters that
+  you have explicitly specified &mdash; it lets your filters serve as a "whitelist" for log
+  output.</p>
+
+  <p>The following filter expression displays all log messages with priority level "warning" and higher, on all tags:</p>
+  <pre>
+adb logcat *:W
+</pre>
+
+  <p>If you're running LogCat from your development computer (versus running it on a
+  remote adb shell), you can also set a default filter expression by exporting a value for the
+  environment variable <code>ANDROID_LOG_TAGS</code>:</p>
+  <pre>
+export ANDROID_LOG_TAGS="ActivityManager:I MyApp:D *:S"
+</pre>
+
+  <p>Note that <code>ANDROID_LOG_TAGS</code> filter is not exported to the emulator/device
+  instance, if you are running LogCat from a remote shell or using <code>adb shell
+  logcat</code>.</p>
+
+  <h3 id="outputFormat">Controlling Log Output Format</h3>
+
+  <p>Log messages contain a number of metadata fields, in addition to the tag and priority. You can
+  modify the output format for messages so that they display a specific metadata field. To do so,
+  you use the <code>-v</code> option and specify one of the supported output formats listed
+  below.</p>
+
+  <ul>
+    <li><code>brief</code> &mdash; Display priority/tag and PID of originating process (the default
+    format).</li>
+
+    <li><code>process</code> &mdash; Display PID only.</li>
+
+    <li><code>tag</code> &mdash; Display the priority/tag only.</li>
+
+    <li><code>thread</code> &mdash; Display process:thread and priority/tag only.</li>
+
+    <li><code>raw</code> &mdash; Display the raw log message, with no other metadata fields.</li>
+
+    <li><code>time</code> &mdash; Display the date, invocation time, priority/tag, and PID of the
+    originating process.</li>
+
+    <li><code>long</code> &mdash; Display all metadata fields and separate messages with blank
+    lines.</li>
+  </ul>
+
+  <p>When starting LogCat, you can specify the output format you want by using the
+  <code>-v</code> option:</p>
+  <pre>
+[adb] logcat [-v &lt;format&gt;]
+</pre>
+
+  <p>Here's an example that shows how to generate messages in <code>thread</code> output
+  format:</p>
+  <pre>
+adb logcat -v thread
+</pre>
+
+  <p>Note that you can only specify one output format with the <code>-v</code> option.</p>
+
+  <h3 id="alternativeBuffers">Viewing Alternative Log Buffers</h3>
+
+  <p>The Android logging system keeps multiple circular buffers for log messages, and not all of
+  the log messages are sent to the default circular buffer. To see additional log messages, you can
+  run the <code>logcat</code> command with the <code>-b</code> option, to request viewing of an alternate
+  circular buffer. You can view any of these alternate buffers:</p>
+
+  <ul>
+    <li><code>radio</code> &mdash; View the buffer that contains radio/telephony related
+    messages.</li>
+
+    <li><code>events</code> &mdash; View the buffer containing events-related messages.</li>
+
+    <li><code>main</code> &mdash; View the main log buffer (default)</li>
+  </ul>
+
+  <p>The usage of the <code>-b</code> option is:</p>
+  <pre>
+[adb] logcat [-b &lt;buffer&gt;]
+</pre>
+
+  <p>Here's an example of how to view a log buffer containing radio and telephony messages:</p>
+  <pre>
+adb logcat -b radio
+</pre><a name="stdout"
+        id="stdout"></a>
+
+  <h2 id="viewingStd">Viewing stdout and stderr</h2>
+
+  <p>By default, the Android system sends <code>stdout</code> and <code>stderr</code>
+  (<code>System.out</code> and <code>System.err</code>) output to <code>/dev/null</code>. In
+  processes that run the Dalvik VM, you can have the system write a copy of the output to the log
+  file. In this case, the system writes the messages to the log using the log tags
+  <code>stdout</code> and <code>stderr</code>, both with priority <code>I</code>.</p>
+
+  <p>To route the output in this way, you stop a running emulator/device instance and then use the
+  shell command <code>setprop</code> to enable the redirection of output. Here's how you do it:</p>
+  <pre>
+$ adb shell stop
+$ adb shell setprop log.redirect-stdio true
+$ adb shell start
+</pre>
+
+  <p>The system retains this setting until you terminate the emulator/device instance. To use the
+  setting as a default on the emulator/device instance, you can add an entry to
+  <code>/data/local.prop</code> on the device.</p>
+
+  <h2 id="DebuggingWebPages">Debugging Web Apps</h2>
+  <p>
+  If you're developing a web application for Android, you can debug your JavaScript using the console JavaScript APIs,
+  which output messages to LogCat. For more information, see
+  <a href="{@docRoot}guide/webapps/debugging.html">Debugging Web Apps</a>.</p>
\ No newline at end of file
diff --git a/docs/html/guide/developing/debugging/debugging-projects-cmdline.jd b/docs/html/guide/developing/debugging/debugging-projects-cmdline.jd
new file mode 100644
index 0000000..72bb16d
--- /dev/null
+++ b/docs/html/guide/developing/debugging/debugging-projects-cmdline.jd
@@ -0,0 +1,76 @@
+page.title=Debugging in other IDEs
+@jd:body
+
+
+ <div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li><a href="#start-debugging">Starting a Debugging Environment</a>
+        <ul>
+          <li><a href="#debuggingPort">Configuring Your IDE to Attach to the Debugging Port</a></li>
+        </ul>
+        </li>
+      </ol>
+    </div>
+  </div>
+ 
+  <p>If you are not using Eclipse to develop, you can still take advantage of all the tools that
+  the Android SDK provides for debugging. A basic debugging environment consists of:</p>
+
+  <ul>
+    <li><a href="{@docRoot}guide/developing/tools/adb.html">ADB</a></li>
+
+    <li><a href="{@docRoot}guide/developing/debugging/ddms.html">DDMS</a></li>
+
+    <li>Java Debugger</li>
+  </ul>
+  
+  <p>You need to obtain a JDWP-compliant Java debugger to properly debug your application.
+  Most Java IDEs will already have one included, or you can use a command line debugger,
+  such as JDB, if you are using a simple text editor to develop applications.</p>
+
+  <h2 id="start-debugging">Starting a debugging environment</h2>
+  <p>A Java Debugger assists you in finding problems with
+  your code by letting you set breakpoints, step through execution of your application, and examine
+  variable values. Since you are not using Eclipse, you have to manually start up the debugging
+  environment yourself by running a few tools that are provided in the Android SDK. To begin
+  debugging your application, follow these general steps:</p>
+
+  <ol>
+    <li>Load an AVD with the Android emulator or connect a device to your computer.</li>
+    
+    <li>Start DDMS from the sdk <code>/tools</code> directory. This also starts ADB if it is 
+    not already started. You should see your device appear in DDMS.</li>
+
+    <li>Install and run your <code>.apk</code> file on the device or emulator. In DDMS, you should see your
+    application running under the device that you installed it to.</li>
+
+    <li>Attach your debugger to the debugging port 8700, or to the specific port shown for the
+    application in DDMS.</li>
+  </ol>
+
+  <h3 id="debuggingPort">Configuring Your IDE to Attach to the Debugging Port</h3>
+
+  <p>DDMS assigns a specific debugging port to every virtual machine that it finds on the
+  emulator. You must either attach your IDE to that port (listed on the Info tab for that VM), or
+  you can use a default port 8700 to connect to whatever application is currently selected on the
+  list of discovered virtual machines.</p>
+
+  <p>Your IDE should attach to your application running on the emulator, showing you its threads
+  and allowing you to suspend them, inspect their state, and set breakpoints. If you selected "Wait
+  for debugger" in the Development settings panel the application will run when Eclipse connects,
+  so you will need to set any breakpoints you want before connecting.</p>
+
+  <p>Changing either the application being debugged or the "Wait for debugger" option causes the
+  system to kill the selected application if it is currently running. You can use this to kill your
+  application if it is in a bad state by simply going to the settings and toggling the
+  checkbox.</p>
+
+
+
+
+
+
+
diff --git a/docs/html/guide/developing/debugging/debugging-projects.jd b/docs/html/guide/developing/debugging/debugging-projects.jd
new file mode 100644
index 0000000..0e14999
--- /dev/null
+++ b/docs/html/guide/developing/debugging/debugging-projects.jd
@@ -0,0 +1,65 @@
+page.title=Debugging in Eclipse
+@jd:body
+
+ <div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li><a href="#tools">The Debug Perspective</a></li>
+
+        <li><a href="#toptips">The DDMS Perspective</a></li>
+      </ol>
+    </div>
+  </div>
+  
+  <p>If you are developing in Eclipse with the ADT plugin, you can use the built-in Java Debugger,
+  along with DDMS, to debug your applications. To access the debugger and
+  DDMS, Eclipse displays the debugger and DDMS features as perspectives, which are customized
+  Eclipse views that display certain tabs and windows depending on the perspective that you are in.
+  Eclipse also takes care of starting the ADB host daemon for you, so you do not have to run this
+  manually.</p>
+
+  <h2>The Debug Perspective in Eclipse</h2>
+
+  <p>The Debug Perspective in Eclipse gives you access to the following tabs:</p>
+
+  <ul>
+    <li>Debug - Displays previously and currently debugged Android applications and its currently
+    running threads</li>
+
+    <li>Variables - When breakpoints are set, displays variable values during code execution</li>
+
+    <li>Breakpoints - Displays a list of the set breakpoints in your application code</li>
+
+    <li>LogCat - Allows you to view system log messages in real time. The LogCat tab is also
+    available in the DDMS perspective.</li>
+  </ul>
+  <p>You can access the Debug Perspective by clicking <strong>Window &gt; Open Perspective &gt;
+  Debug</strong>. Refer to the appropriate documentation for the Eclipse debugger for more
+  information.</p>
+
+  <h2>The DDMS Perspective</h2>
+  <p>The DDMS Perspective in Eclipse lets you access all of the features
+  of DDMS from within the Eclipse IDE. The following sections of DDMS are available to you:</p>
+
+  <ul>
+    <li>Devices - Shows the list of devices and AVDs that are connected to ADB.</li>
+
+    <li>Emulator Control - Lets you carry out device functions.</li>
+
+    <li>LogCat - Lets you view system log messages in real time.</li>
+
+    <li>Threads - Shows currently running threads within a VM.</li>
+
+    <li>Heap - Shows heap usage for a VM.</li>
+
+    <li>Allocation Tracker - Shows the memory allocation of objects.</li>
+
+    <li>File Explorer - Lets you explore the device's file system.</li>
+  </ul>
+  <p>To access the DDMS perspective, go to <strong>Window &gt; Open Perspective &gt;
+  DDMS</strong>. If DDMS does not appear, go to <strong>Window &gt; Open Perspective &gt; Other
+  ...</strong> and select <strong>DDMS</strong> from the Open Perspective window that appears. For
+  more information on using DDMS, see <a href="ddms.html">Using the Dalvik Debug Monitor Server</a>.
+  </p>
\ No newline at end of file
diff --git a/docs/html/guide/developing/debugging/debugging-tracing.jd b/docs/html/guide/developing/debugging/debugging-tracing.jd
new file mode 100644
index 0000000..dcc889d
--- /dev/null
+++ b/docs/html/guide/developing/debugging/debugging-tracing.jd
@@ -0,0 +1,400 @@
+page.title=Profiling with Traceview and dmtracedump
+@jd:body
+
+ <div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li>
+          <a href="#traceviewLayout">Traceview Layout</a>
+
+          <ol>
+            <li><a href="#timelinepanel">Timeline Panel</a></li>
+
+            <li><a href="#profilepanel">Profile Panel</a></li>
+          </ol>
+        </li>
+
+        <li>
+          <a href="#format">Traceview File Format</a>
+          <ol>
+            <li><a href="#datafileformat">Data File Format</a></li>
+
+            <li><a href="#keyfileformat">Key File Format</a></li>
+          </ol>
+        </li>
+
+        <li><a href="#creatingtracefiles">Creating Trace Files</a></li>
+
+        <li><a href="#copyingfiles">Copying Trace Files to a Host Machine</a></li>
+
+        <li><a href="#runningtraceview">Viewing Trace Files in Traceview</a></li>
+
+        <li><a href="#dmtracedump">Using dmtracedump</a></li>
+        
+        <li><a href="#knownissues">Traceview Known Issues</a></li>
+      </ol>
+    </div>
+  </div>
+
+  <p>Traceview is a graphical viewer for execution logs that you create by using the {@link
+  android.os.Debug} class to log tracing information in your code. Traceview can help you debug
+  your application and profile its performance.</p>
+
+  <h2 id="traceviewLayout">Traceview Layout</h2>
+
+  <p>When you have a trace log file (generated by adding tracing code to your application or by DDMS),
+  you can have Traceview load the log files and display their data in a window visualizes your application
+  in two panels:</p>
+
+  <ul>
+    <li>A <a href="#timelinepanel">timeline panel</a> -- describes when each thread and method
+    started and stopped</li>
+
+    <li>A <a href="#timelinepanel">profile panel</a> -- provides a summary of what happened inside
+    a method</li>
+  </ul>
+
+  <p>The sections below provide addition information about the traceview output panes.</p>
+  
+  <h3 id="timelinepanel">Timeline Panel</h3>
+
+  <p>The image below shows a close up of the timeline panel. Each thread&rsquo;s execution is shown
+  in its own row, with time increasing to the right. Each method is shown in another color (colors
+  are reused in a round-robin fashion starting with the methods that have the most inclusive time).
+  The thin lines underneath the first row show the extent (entry to exit) of all the calls to the
+  selected method. The method in this case is <code>LoadListener.nativeFinished()</code> and it was selected in
+  the profile view.</p>
+
+  <img src="/images/traceview_timeline.png"
+       alt="Traceview timeline panel"
+       width="893"
+       height="284" />
+       <p class="img-caption"><strong>Figure 1.</strong> The Traceview Timeline Panel</p>
+
+  <h3 id="profilepanel">Profile Panel</h3>
+
+  <p>Figure 2 shows the profile pane, a summary of all the time spent
+  in a method. The table shows both the inclusive and exclusive times (as well as the percentage of
+  the total time). Exclusive time is the time spent in the method. Inclusive time is the time spent
+  in the method plus the time spent in any called functions. We refer to calling methods as
+  "parents" and called methods as "children." When a method is selected (by clicking on it), it
+  expands to show the parents and children. Parents are shown with a purple background and children
+  with a yellow background. The last column in the table shows the number of calls to this method
+  plus the number of recursive calls. The last column shows the number of calls out of the total
+  number of calls made to that method. In this view, we can see that there were 14 calls to
+  <code>LoadListener.nativeFinished();</code> looking at the timeline panel shows that one of those calls took
+  an unusually long time.</p>
+
+  <img src="/images/traceview_profile.png"
+       alt="Traceview profile panel."
+       width="892"
+       height="630" />
+  <p class="img-caption"><strong>Figure 2.</strong> The Traceview Profile Panel</p>
+
+  <h2 id="format">Traceview File Format</h2>
+
+  <p>Tracing creates two distinct pieces of output: a <em>data</em> file, which holds the trace
+  data, and a <em>key</em> file, which provides a mapping from binary identifiers to thread and
+  method names. The files are concatenated when tracing completes, into a single <em>.trace</em>
+  file.</p>
+
+  <p class="note"><strong>Note:</strong> The previous version of Traceview did not concatenate
+  these files for you. If you have old key and data files that you'd still like to trace, you can
+  concatenate them yourself with <code>cat mytrace.key mytrace.data &gt;
+  mytrace.trace</code>.</p>
+
+  <h3 id="datafileformat">Data File Format</h3>
+
+  <p>The data file is binary, structured as follows (all values are stored in little-endian
+  order):</p>
+  <pre>
+* File format:
+* header
+* record 0
+* record 1
+* ...
+*
+* Header format:
+* u4 magic 0x574f4c53 ('SLOW')
+* u2 version
+* u2 offset to data
+* u8 start date/time in usec
+*
+* Record format:
+* u1 thread ID
+* u4 method ID | method action
+* u4 time delta since start, in usec
+</pre>
+
+  <p>The application is expected to parse all of the header fields, then seek to "offset to data"
+  from the start of the file. From there it just reads 9-byte records until EOF is reached.</p>
+
+  <p><em>u8 start date/time in usec</em> is the output from <code>gettimeofday()</code>. It's mainly there so
+  that you can tell if the output was generated yesterday or three months ago.</p>
+
+  <p><em>method action</em> sits in the two least-significant bits of the <em>method</em> word. The
+  currently defined meanings are:</p>
+
+  <ul>
+    <li>0 - method entry</li>
+
+    <li>1 - method exit</li>
+
+    <li>2 - method "exited" when unrolled by exception handling</li>
+
+    <li>3 - (reserved)</li>
+  </ul>
+
+  <p>An unsigned 32-bit integer can hold about 70 minutes of time in microseconds.</p>
+
+  <h3 id="keyfileformat">Key File Format</h3>
+
+  <p>The key file is a plain text file divided into three sections. Each section starts with a
+  keyword that begins with '*'. If you see a '*' at the start of a line, you have found the start
+  of a new section.</p>
+
+  <p>An example file might look like this:</p>
+  <pre>
+*version
+1
+clock=global
+*threads
+1 main
+6 JDWP Handler
+5 Async GC
+4 Reference Handler
+3 Finalizer
+2 Signal Handler
+*methods
+0x080f23f8 java/io/PrintStream write ([BII)V
+0x080f25d4 java/io/PrintStream print (Ljava/lang/String;)V
+0x080f27f4 java/io/PrintStream println (Ljava/lang/String;)V
+0x080da620 java/lang/RuntimeException   &lt;init&gt;    ()V
+[...]
+0x080f630c android/os/Debug startMethodTracing ()V
+0x080f6350 android/os/Debug startMethodTracing (Ljava/lang/String;Ljava/lang/String;I)V
+*end
+</pre>
+<p>The following list describes the major sections of a key file:</p>
+  <dl>
+    <dt><em>version section</em></dt>
+
+    <dd>The first line is the file version number, currently 1. The second line,
+    <code>clock=global</code>, indicates that we use a common clock across all threads. A future
+    version may use per-thread CPU time counters that are independent for every thread.</dd>
+
+    <dt><em>threads section</em></dt>
+
+    <dd>One line per thread. Each line consists of two parts: the thread ID, followed by a tab,
+    followed by the thread name. There are few restrictions on what a valid thread name is, so
+    include everything to the end of the line.</dd>
+
+    <dt><em>methods section</em></dt>
+
+    <dd>One line per method entry or exit. A line consists of four pieces, separated by tab marks:
+    <em>method-ID</em> [TAB] <em>class-name</em> [TAB] <em>method-name</em> [TAB]
+    <em>signature</em> . Only the methods that were actually entered or exited are included in the
+    list. Note that all three identifiers are required to uniquely identify a method.</dd>
+  </dl>
+
+  <p>Neither the threads nor methods sections are sorted.</p>
+
+  <h2 id="creatingtracefiles">Creating Trace Files</h2>
+
+  <p>To use Traceview, you need to generate log files containing the trace information you want to
+  analyze.</p>
+  
+  <p>There are two ways to generate trace logs:</p>
+  <ul>
+    <li>Include the {@link android.os.Debug} class in your code and call its
+  methods to start and stop logging of trace information to disk. This method is very precise because
+  you can specify in your code exactly where to start and stop logging trace data.</li>
+    <li>Use the method profiling feature of DDMS to generate trace logs. This method is less
+    precise since you do not modify code, but rather specify when to start and stop logging with
+    a DDMS. Although you have less control on exactly where the data is logged, this method is useful 
+    if you don't have access to the application's code, or if you do not need the precision of the first method.
+    </li>
+  </ul>
+  
+  <p>Before you start generating trace logs, be aware of the following restrictions:</p>
+  <ul>
+    <li>If you are using the {@link android.os.Debug} class, your device or emulator must have an SD card
+     and your application must have permission to write to the SD card. </li>
+    <li>If you are using DDMS, Android 1.5 devices are not supported.</li>
+    <li>If you are using DDMS, Android 2.1 and earlier devices must
+    have an SD card present and your application must have permission to write to the SD card.
+    <li>If you are using DDMS, Android 2.2 and later devices do not need an SD card. The trace log files are 
+    streamed directly to your development machine.</li>
+  </ul>
+  
+  <p>This document focuses on using the {@link android.os.Debug} class to generate trace data.  For more information on using DDMS
+  to generate trace data, see <a href="ddms.html#profiling">Using the Dalvik Debug Monitor Server.</a>
+  </p>
+  
+  <p>To create the trace files, include the {@link android.os.Debug} class and call one of the
+  {@link android.os.Debug#startMethodTracing() startMethodTracing()} methods. In the call, you
+  specify a base name for the trace files that the system generates. To stop tracing, call {@link
+  android.os.Debug#stopMethodTracing() stopMethodTracing()}. These methods start and stop method
+  tracing across the entire virtual machine. For example, you could call 
+  {@link android.os.Debug#startMethodTracing() startMethodTracing()} in
+  your activity's {@link android.app.Activity#onCreate onCreate()} method, and call
+  {@link android.os.Debug#stopMethodTracing() stopMethodTracing()} in that activity's
+  {@link android.app.Activity#onDestroy()} method.</p>
+  <pre>
+    // start tracing to "/sdcard/calc.trace"
+    Debug.startMethodTracing("calc");
+    // ...
+    // stop tracing
+    Debug.stopMethodTracing();
+</pre>
+
+  <p>When your application calls startMethodTracing(), the system creates a file called
+  <code>&lt;trace-base-name&gt;.trace</code>. This contains the binary method trace data and a
+  mapping table with thread and method names.</p>
+
+  <p>The system then begins buffering the generated trace data, until your application calls
+  stopMethodTracing(), at which time it writes the buffered data to the output file. If the system
+  reaches the maximum buffer size before stopMethodTracing() is called, the system stops tracing
+  and sends a notification to the console.</p>
+
+  <p>Interpreted code will run more slowly when profiling is enabled. Don't try to generate
+  absolute timings from the profiler results (i.e. "function X takes 2.5 seconds to run"). The
+  times are only useful in relation to other profile output, so you can see if changes have made
+  the code faster or slower.</p>
+
+  <p>When using the Android emulator, you must specify an SD card when you create your AVD because the trace files
+  are written to the SD card. Your application must have permission to write to the SD card as well.
+
+  <p>The format of the trace files is previously described <a href="#format">in this
+  document</a>.</p>
+
+  <h2 id="copyingfiles">Copying Trace Files to a Host Machine</h2>
+
+  <p>After your application has run and the system has created your trace files
+  <code>&lt;trace-base-name&gt;.trace</code> on a device or emulator, you must copy those files to
+  your development computer. You can use <code>adb pull</code> to copy the files. Here's an example
+  that shows how to copy an example file, calc.trace, from the default location on the emulator to
+  the /tmp directory on the emulator host machine:</p>
+  <pre>
+adb pull /sdcard/calc.trace /tmp
+</pre>
+
+  <h2 id="runningtraceview">Viewing Trace Files in Traceview</h2>
+
+  <p>To run Traceview and view the trace files, enter <code>traceview
+  &lt;trace-base-name&gt;</code>. For example, to run Traceview on the example files copied in the
+  previous section, use:</p>
+  <pre>
+traceview /tmp/calc
+</pre>
+
+  <p class="note"><strong>Note:</strong> If you are trying to view the trace logs of an application 
+  that is built with ProGuard enabled (release mode build), some method and member names might be obfuscated.
+  You can use the Proguard <code>mapping.txt</code> file to figure out the original unobfuscated names. For more information
+  on this file, see the <a href="{@docRoot}guide/developing/tools/proguard.html">Proguard</a> documentation.</p>
+
+      <h2 id="dmtracedump">Using dmtracdedump</h2>
+
+      <p><code>dmtracedump</code> is a tool that gives you an alternate way of generating
+      graphical call-stack diagrams from trace log files. The tool uses the Graphviz Dot utility to
+      create the graphical output, so you need to install Graphviz before running dmtracedump.</p>
+
+      <p>The dmtracedump tool generates the call stack data as a tree diagram, with each call
+      represented as a node. It shows call flow (from parent node to child nodes) using arrows. The
+      diagram below shows an example of dmtracedump output.</p>
+      <img src=
+      "{@docRoot}images/tracedump.png"
+          width="485"
+          height="401" />
+       <p class="image-caption"><strong>Figure 3.</strong> Screenshot of dmtracedump</p>
+
+      <p>For each node, dmtracedump shows <code>&lt;ref&gt;
+      <em>callname</em> (&lt;inc-ms&gt;, &lt;exc-ms&gt;,&lt;numcalls&gt;)</code>, where</p>
+
+      <ul>
+        <li><code>&lt;ref&gt;</code> -- Call reference number, as used in trace logs</li>
+
+        <li><code>&lt;inc-ms&gt;</code> -- Inclusive elapsed time (milliseconds spent in method,
+        including all child methods)</li>
+
+        <li><code>&lt;exc-ms&gt;</code> -- Exclusive elapsed time (milliseconds spent in method,
+        not including any child methods)</li>
+
+        <li><code>&lt;numcalls&gt;</code> -- Number of calls</li>
+      </ul>
+
+      <p>The usage for dmtracedump is:</p>
+      <pre>
+dmtracedump [-ho] [-s sortable] [-d trace-base-name] [-g outfile] &lt;trace-base-name&gt;
+</pre>
+
+      <p>The tool then loads trace log data from <code>&lt;trace-base-name&gt;.data</code> and
+      <code>&lt;trace-base-name&gt;.key</code>. The table below lists the options for dmtracedump.</p>
+
+      <table>
+        <tr>
+          <th>Option</th>
+
+          <th>Description</th>
+        </tr>
+
+        <tr>
+          <td><code>-d&nbsp;&lt;trace-base-name&gt;</code></td>
+
+          <td>Diff with this trace name</td>
+        </tr>
+
+        <tr>
+          <td><code>-g&nbsp;&lt;outfile&gt;</code></td>
+
+          <td>Generate output to &lt;outfile&gt;</td>
+        </tr>
+
+        <tr>
+          <td><code>-h</code></td>
+
+          <td>Turn on HTML output</td>
+        </tr>
+
+        <tr>
+          <td><code>-o</code></td>
+
+          <td>Dump the trace file instead of profiling</td>
+        </tr>
+
+        <tr>
+          <td><code>-d&nbsp;&lt;trace-base-name&gt;</code></td>
+
+          <td>URL base to the location of the sortable javascript file</td>
+        </tr>
+
+        <tr>
+          <td><code>-t&nbsp;&lt;percent&gt;</code></td>
+
+          <td>Minimum threshold for including child nodes in the graph (child's inclusive time as a
+          percentage of parent inclusive time). If this option is not used, the default threshold
+          is 20%.</td>
+        </tr>
+      </table>
+  
+  
+    
+  <h2 id="knownissues">Traceview Known Issues</h2>
+
+  <dl>
+    <dt>Threads</dt>
+
+    <dd>
+      Traceview logging does not handle threads well, resulting in these two problems:
+
+      <ol>
+        <li>If a thread exits during profiling, the thread name is not emitted;</li>
+
+        <li>The VM reuses thread IDs. If a thread stops and another starts, they may get the same
+        ID.</li>
+      </ol>
+    </dd>
+
+    </dl>
\ No newline at end of file
diff --git a/docs/html/guide/developing/debugging/debugging-ui.jd b/docs/html/guide/developing/debugging/debugging-ui.jd
new file mode 100644
index 0000000..9b02d34
--- /dev/null
+++ b/docs/html/guide/developing/debugging/debugging-ui.jd
@@ -0,0 +1,202 @@
+page.title=Debugging and Profiling User Interfaces
+@jd:body
+
+ <div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li>
+          <a href="#hierarchyViewer">Debugging and Optimizing User Interfaces with Hierarchy
+          Viewer</a>
+          <ol>
+            <li><a href="#layoutview">Layout View</a></li>
+            <li><a href="#pixelperfect">Pixel Perfect View</a></li>
+          </ol>       
+        </li>
+
+        <li><a href="#layoutopt">Optimizing Layouts with <code>layoutopt</code></a></li>
+      </ol>
+    </div>
+  </div>
+
+  <p>Sometimes your application's layout can slow down your application. 
+  To help debug issues in your layout, the Android SDK provides the Hierarchy Viewer and 
+  <code>layoutopt</code> tools.
+  </p>
+  
+  <p>The Hierarchy Viewer application allows you to debug and optimize your user interface. It
+  provides a visual representation of the layout's View hierarchy (the Layout View) and a magnified
+  inspector of the display (the Pixel Perfect View).</p>
+
+  <p><code>layoutopt</code> is a command-line tool that helps you optimize the layouts and layout
+  hierarchies of your applications. You can run it against your layout files or resource
+  directories to quickly check for inefficiencies or other types of problems that could be
+  affecting the performance of your application.</p>
+
+  <h2 id="hierarchyViewer">Debugging and Optimizing User Interfaces with Hierarchy Viewer</h2>
+
+  <p>To get the Hierarchy Viewer started:</p>
+
+  <ol>
+    <li>Connect your device or launch an emulator.</li>
+
+    <li>From a terminal, launch <code>hierarchyviewer</code> from the <code>&lt;sdk&gt;/tools/</code>
+    directory.</li>
+
+    <li>In the window that opens, you'll see a list of <strong>Devices</strong>. When a device is
+    selected, a list of currently active <strong>Windows</strong> is displayed on the right. The
+    <em>&lt;Focused Window&gt;</em> is the window currently in the foreground, and also the default
+    window loaded if you do not select another.</li>
+
+    <li>Select the window that you'd like to inspect and click <strong>Load View
+    Hierarchy</strong>. The Layout View will be loaded. You can then load the Pixel Perfect View by
+    clicking the second icon at the bottom-left of the window.</li>
+  </ol>
+
+  <p>If you've navigated to a different window on the device, press <strong>Refresh
+  Windows</strong> to refresh the list of available windows on the right.</p>
+
+
+  <h3 id="layoutview">Layout View</h3>
+
+  <p>The Layout View offers a look at the View layout and properties. It has three views:</p>
+
+  <ul>
+    <li>Tree View: a hierarchy diagram of the Views, on the left.</li>
+
+    <li>Properties View: a list of the selected View's properties, on the top-right.</li>
+
+    <li>Wire-frame View: a wire-frame drawing of the layout, on the bottom-right.</li>
+  </ul><br />
+  <img src="{@docRoot}images/hierarchyviewer-layout.png"
+        alt=""
+        height="509"
+        width="700" />
+  <p class="img-caption"><strong>Figure 1.</strong> Screenshot of Hierarchy Viewer</p>
+
+  <p>Select a node in the Tree View to display the properties of that element in the Properties
+  View. When a node is selected, the Wire-frame View also indicates the bounds of the element with
+  a red rectangle. Double click a node in the tree (or select it, and click <strong>Display
+  View</strong>) to open a new window with a rendering of that element.</p>
+
+  <p>The Layout View includes a couple other helpful features for debugging your layout:
+  <strong>Invalidate</strong> and <strong>Request Layout</strong>. These buttons execute the
+  respective View calls, {@link android.view.View#invalidate()} and {@link
+  android.view.View#requestLayout()}, on the View element currently selected in the tree. Calling
+  these methods on any View can be very useful when simultaneously running a debugger on your
+  application.</p>
+
+  <p>The Tree View can be resized by adjusting the zoom slider, below the diagram. The number of
+  View elements in the window is also given here. You should look for ways to minimize the number
+  of Views. The fewer View elements there are in a window, the faster it will perform.</p>
+
+  <p>If you interact with the device and change the focused View, the diagram will not
+  automatically refresh. You must reload the Layout View by clicking <strong>Load View
+  Hierarchy</strong>.</p>
+
+  <h3 id="pixelperfect">Pixel Perfect View</h3>
+
+  <p>The Pixel Perfect View provides a magnified look at the current device window. It helps you
+  design your UI better by giving you a closer look at your UI's image quality, alignment, and other
+  aesthetic qualities. It has three views:</p>
+
+  <ul>
+    <li>Explorer View: shows the View hierarchy as a list, on the left.</li>
+
+    <li>Normal View: a normal view of the device window, in the middle.</li>
+
+    <li>Loupe View: a magnified, pixel-grid view of the device window, on the right.</li>
+  </ul><br />
+  <img src="{@docRoot}images/hierarchyviewer-pixelperfect.png"
+        alt=""
+        height="509"
+        width="700" />
+
+  <p>Click on an element in the Explorer View and a "layout box" will be drawn in the Normal View
+  to indicate the layout position of that element. The layout box uses multiple rectangles, to
+  indicate the normal bounds, the padding and the margin (as needed). The purple or green rectangle
+  indicates the normal bounds of the element (the height and width). The inner white or black
+  rectangle indicates the content bounds, when padding is present. A black or white rectangle
+  outside the normal purple/green rectangle indicates any present margins. (There are two colors
+  for each rectangle, in order to provide the best contrast based on the colors currently in the
+  background.)</p>
+
+  <p>A very handy feature for designing your UI is the ability to overlay an image in the Normal
+  and Loupe Views. For example, you might have a mock-up image of how you'd like to layout your
+  interface. By selecting <strong>Load...</strong> from the controls in the Normal View, you can
+  choose the image from your computer and it will be placed atop the preview. Your chosen image
+  will anchor at the bottom left corner of the screen. You can then adjust the opacity of the
+  overlay and begin fine-tuning your layout to match the mock-up.</p>
+
+  <p>The Normal View and Loupe View refresh at regular intervals (5 seconds by default), but the
+  Explorer View does not. If you navigate away and focus on a different View, then you should
+  refresh the Explorer's hierarchy by clicking <strong>Load View Hierarchy</strong>. This is even
+  true when you're working in a window that holds multiple Views that are not always visible. If
+  you do not, although the previews will refresh, clicking a View in the Explorer will not provide
+  the proper layout box in the Normal View, because the hierarchy believes you are still focused on
+  the prior View.</p>
+
+  <p>Optional controls include:</p>
+
+  <ul>
+    <li><strong>Overlay</strong>: Load an overlay image onto the view and adjust its opacity.</li>
+
+    <li><strong>Refresh Rate</strong>: Adjust how often the Normal and Loupe View refresh their
+    display.</li>
+
+    <li><strong>Zoom</strong>: Adjust the zoom level of the Loupe View.</li>
+  </ul>
+
+  <h2 id="layoutopt">Optimizing layouts with layoutopt</h2>
+  <p>The <code>layoutopt</code> tool lets you analyze the XML files that represent your application's layout
+  and finds ineffiencies in the view hierarchy.</p>
+  
+  <p>To run the tool, open a terminal and launch <code>layoutopt &lt;resources&gt;</code> from your
+  SDK <code>tools/</code> directory. In the command, supply a list of uncompiled resource xml files
+  or directories that you want to analyze.</p>
+
+  <p>When run, the tool loads the specified XML files and analyzes their layout structures and
+  hierarchies according to a set of predefined rules. If it detects issues, it outputs information
+  about the issues, giving filename, line numbers, description of issue, and for some types of
+  issues a suggested resolution.</p>
+
+  <p>Here's an example of the output:</p>
+  <pre>
+$ layoutopt samples/
+samples/compound.xml
+   7:23 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
+   11:21 This LinearLayout layout or its FrameLayout parent is useless
+samples/simple.xml
+   7:7 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
+samples/too_deep.xml
+   -1:-1 This layout has too many nested layouts: 13 levels, it should have &lt;= 10!
+   20:81 This LinearLayout layout or its LinearLayout parent is useless
+   24:79 This LinearLayout layout or its LinearLayout parent is useless
+   28:77 This LinearLayout layout or its LinearLayout parent is useless
+   32:75 This LinearLayout layout or its LinearLayout parent is useless
+   36:73 This LinearLayout layout or its LinearLayout parent is useless
+   40:71 This LinearLayout layout or its LinearLayout parent is useless
+   44:69 This LinearLayout layout or its LinearLayout parent is useless
+   48:67 This LinearLayout layout or its LinearLayout parent is useless
+   52:65 This LinearLayout layout or its LinearLayout parent is useless
+   56:63 This LinearLayout layout or its LinearLayout parent is useless
+samples/too_many.xml
+   7:413 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
+   -1:-1 This layout has too many views: 81 views, it should have &lt;= 80!
+samples/useless.xml
+   7:19 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
+   11:17 This LinearLayout layout or its FrameLayout parent is useless
+</pre>
+
+<p>
+For more information on running the tool, see the
+<a href="${@docRoot}guide/developing/debugging/debugging-ui.html#layoutopt">layoutopt</a> reference.</p>
+  
+    
+
+
+
+
+
+
diff --git a/docs/html/guide/developing/debugging/index.jd b/docs/html/guide/developing/debugging/index.jd
new file mode 100644
index 0000000..f9202ce
--- /dev/null
+++ b/docs/html/guide/developing/debugging/index.jd
@@ -0,0 +1,185 @@
+page.title=Debugging 
+@jd:body
+
+
+ <div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li><a href="#stack">Debugging Environment</a></li>
+
+        <li><a href="#addltools">Additional Debugging Tools</a></li>
+        
+        <li><a href="#tips">Debugging Tips</a></li>
+      </ol>
+    </div>
+  </div>
+
+  <p>The Android SDK provides most of the tools that you need to debug your applications. You need
+  a JDWP-compliant debugger if you want to be able to do things such as step through code,
+  view variable values, and pause execution of an application. If you are using Eclipse, a
+  JDWP-compliant debugger is already included and there is no setup required. If you are using
+  another IDE, you can use the debugger that comes with it and attach the debugger to a special
+  port so it can communicate with the application VMs on your devices. The main components that
+  comprise a typical Android debugging environment are:</p>
+
+  <dl>
+    <dt><a href="{@docRoot}guide/developing/tools/adb.html"><strong>adb</strong></a></dt>
+
+    <dd><code>adb</code> acts as a middleman between a device and your development system. It provides various
+    device management capabilities, including moving and syncing files to the emulator, running a
+    UNIX shell on the device or emulator, and providing a general means to communicate with
+    connected emulators and devices.</dd>
+
+    <dt><a href="{@docRoot}guide/developing/debugging/ddms.html"><strong>Dalvik Debug Monitor
+    Server</strong></a></dt>
+
+    <dd>DDMS is a graphical program that communicates with your devices through <code>adb</code>. DDMS can
+    capture screenshots, gather thread and stack information, spoof incoming calls and SMS
+    messages, and has many other features.</dd>
+
+    <dt><strong><a href="{@docRoot}guide/developing/device.html">Device</a> or
+    <a href="{@docRoot}guide/developing/devices/index.html">Android Virtual Device</a></strong></dt>
+
+    <dd>Your application must run in a device or in an AVD so that it can be debugged. An <code>adb</code> device
+    daemon runs on the device or emulator and provides a means for the <code>adb</code> host daemon to
+    communicate with the device or emulator.</dd>
+
+    <dt><strong>JDWP debugger</strong></dt>
+
+    <dd>The Dalvik VM (Virtual Machine) supports the JDWP protocol to allow debuggers to attach to
+    a VM. Each application runs in a VM and exposes a unique port that you can attach a debugger to
+    via DDMS. If you want to debug multiple applications, attaching to each port might become 
+    tedious, so DDMS provides a port forwarding feature that can forward a specific VM's debugging
+    port to port 8700. You can switch freely from application to application by highlighting it in the
+    Devices tab of DDMS. DDMS forwards the appropriate port to port 8700. Most modern Java IDEs include a JDWP debugger,
+    or you can use a command line debugger such as <a href="http://download.oracle.com/javase/6/docs/technotes/tools/">
+    <code>jdb</code></a>.</dd>
+  </dl>
+
+  <h2>Debugging Environment</h2>
+
+  <p>Figure 1 shows how the various debugging tools work together in a typical
+  debugging environment.</p>
+  <img src="/images/debugging.png"
+        alt="Debugging workflow" />
+  <p class="img-caption><strong>Figure 1. </strong> Debugging Workflow</p>
+
+  <p>On your emulator or device, each application runs in its own instance of a Dalvik VM. The <code>adb</code>
+  device daemon allows communication with the VMs from an outside party.</p>
+
+  <p>On your development machine, the <code>adb</code> host daemon communicates with the <code>adb</code> device daemon and
+  allows tools such as DDMS to communicate with the device or emulator. The <code>adb</code> host daemon also
+  allows you to access shell commands on the device as well as providing capabilities such as
+  application installation and file transferring.</p>
+
+  <p>Each application VM on the device or emulator exposes a debugging port that you can attach to
+  via DDMS. DDMS can forward any of these ports to a static debugging port (typically port 8700) by
+  selecting the application that you want to debug in the DDMS user interface. A JDWP debugger can
+  attach to this static debugging port and debug all the applications that are running on the
+  device or emulator without having to attach to multiple ports.</p>
+
+  <p>If you are using Eclipse, much of these interconnections are hidden from you. DDMS, <code>adb</code>, and a
+  JDWP debugger are all setup for you and you can access them through the Debug and DDMS
+  perspectives in Eclipse. If you are developing in a non-Eclipse environment, you have to invoke
+  these tools manually.</p>
+
+  <h2 id="addltools">Additional Debugging Tools</h2>
+
+  <p>In addition to the main debugging tools, the Android SDK provides additional tools to help you
+  debug and profile your applications:</p>
+
+  <dl>
+    <dt><strong><a href="{@docRoot}guide/developing/debugging/debugging-ui.html">Heirarchy Viewer
+    and layoutopt</a></strong></dt>
+
+    <dd>Graphical programs that let you debug and profile user interfaces.</dd>
+
+    <dt><strong><a href=
+    "{@docRoot}guide/developing/debugging/debugging-tracing.html">Traceview</a></strong></dt>
+
+    <dd>A graphical viewer that displays trace file data for method calls and times saved by your
+    application, which can help you profile the performance of your application.</dd>
+
+    <dt><strong><a href="{@docRoot}guide/developing/debugging/debugging-devtools.html">Dev Tools
+    Android application</a></strong></dt>
+
+    <dd>The Dev Tools application included in the emulator system image exposes several settings
+    that provide useful information such as CPU usage and frame rate. You can also transfer the
+    application to a hardware device.</dd>
+  </dl>
+  
+  
+  <h2 id="tips">Debugging Tips</h2>  
+  
+<p>While debugging, keep these helpful tips in mind to help you figure out common problems with your 
+applications:</p>
+
+<dl>
+<dt><strong>Dump the stack trace</strong></dt>
+<dd>To obtain a stack dump from emulator, you can log
+in with <code>adb shell</code>, use <code>ps</code> to find the process you
+want, and then <code>kill -3</code>. The stack trace appears in the log file.
+</dd>
+
+<dt><strong>Display useful info on the emulator screen</strong></dt>
+<dd>The device can display useful information such as CPU usage or highlights
+around redrawn areas. Turn these features on and off in the developer settings
+window as described in <a href="{@docRoot}guide/developing/debugging/debugging-devtools.html">
+Debugging with the Dev Tools App</a>.
+</dd>
+
+<dt><strong>Get application and system state information from the emulator</strong></dt>
+<dd>You can access dumpstate information from the <code>adb shell</code> commands. See 
+<a href="{@docRoot}guide/developing/tools/adb.html#dumpsys">dumpsys and
+dumpstate</a> on the adb topic page.</dd>
+
+
+
+<dt><strong>Get wireless connectivity information</strong></dt>
+<dd>You can get information about wireless connectivity using DDMS. 
+From the <strong>Device</strong> menu, select <strong>Dump
+radio state</strong>.</dd>
+
+<dt><strong>Log trace data</strong></dt>
+<dd>You can log method calls and other tracing data in an activity by calling
+{@link android.os.Debug#startMethodTracing(String) startMethodTracing()}. See <a
+href="{@docRoot}guide/developing/debugging/debugging-tracing.html">Profiling with Traceview and
+dmtracedump</a> for details. </dd>
+
+<dt><strong>Log radio data</strong></dt>
+<dd>By default, radio information is not logged to the system (it is a lot of
+data). However, you can enable radio logging using the following commands:
+
+<pre class="no-pretty-print">
+adb shell
+logcat -b radio
+</pre>
+</dd>
+
+<dt><strong>Capture screenshots</strong></dt>
+<dd>The Dalvik Debug Monitor Server (DDMS) can capture screenshots from the emulator. Select
+<strong>Device > Screen capture</strong>.</dd>
+
+<dt><strong>Use debugging helper classes</strong></dt>
+<dd>Android provides debug helper classes such as {@link android.util.Log
+    util.Log} and {@link android.os.Debug} for your convenience. </dd>
+</dl>
+
+<p>See the <a href="{@docRoot}resources/faq/troubleshooting.html">Troubleshooting</a> document
+for answers to some common developing and debugging issues.</p>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/html/guide/developing/device.jd b/docs/html/guide/developing/device.jd
index 2e2d803..4bed963c 100644
--- a/docs/html/guide/developing/device.jd
+++ b/docs/html/guide/developing/device.jd
@@ -1,4 +1,4 @@
-page.title=Developing on a Device
+page.title=Connecting Hardware Devices
 @jd:body
 
 <div id="qv-wrapper">
@@ -15,10 +15,6 @@
   <ol>
     <li><a
     href="{@docRoot}sdk/win-usb.html">USB Driver for Windows</a></li>
-    <li><a
-href="{@docRoot}guide/developing/eclipse-adt.html">Developing in Eclipse, with ADT</a></li>
-    <li><a
-href="{@docRoot}guide/developing/other-ide.html">Developing in other IDEs</a></li>
   </ol>
 </div>
 </div>
@@ -30,24 +26,22 @@
 <p>You can use any Android-powered device as an environment for running,
 debugging, and testing your applications. The tools included in the SDK make it easy to install and
 run your application on the device each time you compile. You can install your application on the
-device <a
-href="{@docRoot}guide/developing/eclipse-adt.html#RunningOnDevice">directly from
-Eclipse</a> or <a href="{@docRoot}guide/developing/other-ide.html#RunningOnDevice">from the
-command line</a>. If
+device directly from Eclipse or from the command line with ADB. If
 you don't yet have a device, check with the service providers in your area to determine which
 Android-powered devices are available.</p>
 
 <p>If you want a SIM-unlocked phone, then you might consider either an Android Dev Phone or the
-Google Nexus One. Both are SIM-unlocked so that you can use them on any GSM network using a SIM
+Google Nexus S. These are SIM-unlocked so that you can use them on any GSM network using a SIM
 card. The Android Dev Phones also feature an unlocked bootloader so you can install custom system
-images (great for developing and installing custom versions of the Android platform). To purchase a
-Nexus One, visit <a href="http://www.google.com/phone">google.com/phone</a>. To purchase an Android
+images (great for developing and installing custom versions of the Android platform). To find a
+a place you can purchase the Nexus S, visit <a
+href="http://www.google.com/phone/detail/nexus-s">google.com/phone</a>. To purchase an Android
 Dev Phone, see the <a href="http://market.android.com/publish">Android Market</a> site
 (requires a developer account).</p>
 
 <p class="note"><strong>Note:</strong> When developing on a device, keep in mind that you should
 still use the <a
-href="{@docRoot}guide/developing/tools/emulator.html">Android emulator</a> to test your application
+href="{@docRoot}guide/developing/devices/emulator.html">Android emulator</a> to test your application
 on configurations that are not equivalent to those of your real device. Although the emulator
 does not allow you to test every device feature (such as the accelerometer), it does
 allow you to verify that your application functions properly on different versions of the Android
@@ -104,7 +98,8 @@
 </ol>
 
 <p>You can verify that your device is connected by executing <code>adb devices</code> from your 
-SDK {@code tools/} directory. If connected, you'll see the device name listed as a "device."</p>
+SDK {@code platform-tools/} directory. If connected, you'll see the device name listed as a
+"device."</p>
 
 <p>If using Eclipse, run or debug as usual. You will be presented
 with a <b>Device Chooser</b> dialog that lists the available emulator(s) and connected device(s).
diff --git a/docs/html/guide/developing/devices/emulator.jd b/docs/html/guide/developing/devices/emulator.jd
new file mode 100644
index 0000000..a3cd5c5
--- /dev/null
+++ b/docs/html/guide/developing/devices/emulator.jd
@@ -0,0 +1,1765 @@
+page.title=Using the Android Emulator
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+  <h2>In this document</h2>
+    <ol>
+      <li><a href="#overview">Overview</a></li>
+      <li><a href="#starting">Starting and Stopping the Emulator</a></li>
+      <li><a href="#starting">Android Virtual Devices and the Emulator</a></li>
+      <li><a href="#controlling">Controlling the Emulator</a></li>
+      <li><a href="#startup-options">Emulator Startup Options</a></li>
+      <li><a href="#diskimages">Working with Emulator Disk Images</a>
+	      <ol>
+	        <li><a href="#defaultimages">Default Images</a></li>
+	        <li><a href="#runtimeimages">Runtime Images: User Data and SD Card</a></li>
+	        <li><a href="#temporaryimages">Temporary Images</a></li>
+	      </ol>
+	    </li>
+      <li><a href="#emulatornetworking">Emulator Networking</a>
+	      <ol>
+          <li><a href="#networkaddresses">Network Address Space</a></li>
+          <li><a href="#networkinglimitations">Local Networking Limitations</a></li>
+          <li><a href="#redirections">Using Network Redirections</a></li>
+          <li><a href="#dns">Configuring the Emulator's DNS Settings</a></li>
+          <li><a href="#proxy">Using the Emulator with a Proxy</a></li>
+          <li><a href="#connecting">Interconnecting Emulator Instances</a></li>
+          <li><a href="#calling">Sending a Voice Call or SMS to Another Emulator Instance</a></li>
+        </ol>
+      </li>
+    </ol>
+</div>
+</div>
+
+<img src="/images/emulator-wvga800l.png" alt="Image of the Android Emulator"
+width="367" height="349" style="margin-left:2em;float:right;"/>
+<p>The Android SDK includes a virtual mobile device emulator
+that runs on your computer. The emulator lets you prototype, develop, and test
+Android applications without using a physical device. </p>
+
+<p>The Android emulator mimics all of the hardware and software features
+of a typical mobile device, except that it cannot place actual phone
+calls. It provides a variety of navigation and control keys, which you can "press"
+using your mouse or keyboard to generate events for your application. It also
+provides a screen in which your application is displayed, together with any other
+Android applications running. </p>
+
+<p>To let you model and test your application more easily, the emulator utilizes
+Android Virtual Device (AVD) configurations. AVDs let you define certain hardware
+aspects of your emulated phone and allow you to create many configurations to test
+many Android platforms and hardware permutations. Once your application is running on
+the emulator, it can use the services of the Android platform to invoke other
+applications, access the network, play audio and video, store and retrieve data,
+notify the user, and render graphical transitions and themes. </p>
+
+<p>The emulator also includes a variety of debug capabilities, such as a console 
+from which you can log kernel output, simulate application interrupts (such as 
+arriving SMS messages or phone calls), and simulate latency effects and dropouts 
+on the data channel.</p>
+
+
+
+
+
+<h2  id="overview">Overview</h2>
+
+<p>The Android emulator is a QEMU-based application that provides a virtual ARM
+mobile device on which you can run your Android applications. It runs a full
+Android system stack, down to the kernel level, that includes a set of
+preinstalled applications (such as the dialer) that you can access from your
+applications. You can choose what version of the Android system you want to
+run in the emulator by configuring AVDs, and you can also customize the
+mobile device skin and key mappings. When launching the emulator and at runtime,
+you can use a variety of commands and options to control the its behaviors.
+</p>
+
+<p>The Android system image distributed in the SDK contains ARM machine code for
+the Android Linux kernel, the native libraries, the Dalvik VM, and the various
+Android package files (such as for for the Android framework and preinstalled
+applications). The emulator's QEMU layers provide dynamic binary translation of
+the ARM machine code to the OS and processor architecture of your development
+machine. </p>
+
+<p>Adding custom capabilities to the underlying QEMU services, the Android
+emulator supports many hardware features likely to be found on mobile devices,
+including: </p>
+
+<ul>
+  <li>An ARMv5 CPU and the corresponding memory-management unit (MMU)</li>
+  <li>A 16-bit LCD display</li>
+  <li>One or more keyboards (a Qwerty-based keyboard and associated Dpad/Phone
+buttons)</li>
+  <li>A sound chip with output and input capabilities</li>
+  <li>Flash memory partitions (emulated through disk image files on the
+development machine)</li>
+  <li>A GSM modem, including a simulated SIM Card</li>
+</ul>
+
+<p>The sections below provide more information about the emulator and how to use
+it for developing Android applications.</p>
+
+
+<a name="avds"></a>
+
+<h2>Android Virtual Devices and the Emulator</h2>
+
+<p>To use the emulator, you first must create one or more AVD configurations. In each
+configuration, you specify an Android platform to run in the emulator and the set of hardware
+options and emulator skin you want to use. Then, when you launch the emulator, you specify
+the AVD configuration that you want to load. </p>
+
+<p>To specify the AVD you want to load when starting the emulator, you use the
+<code>-avd</code> argument, as shown in the previous section. </p>
+
+<p>Each AVD functions as an independent device, with its own private storage for
+user data, SD card, and so on. When you launch the emulator with an AVD configuration,
+it automatically loads the user data and SD card data from the AVD directory. By default,
+the emulator stores the user data, SD card data, and cache in the AVD directory.</p>
+
+<p>To create and manage AVDs you use the AVD Manager UI or the <code>android</code> tool
+that is included in the SDK. 
+For complete information about how to set up AVDs, see <a
+href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</a>.</p>
+
+<a name="starting"></a>
+
+<h2>Starting and Stopping the Emulator</h2>
+
+<p>During development and testing of your application, you install and run your
+application in the Android emulator. You can launch the emulator as a standalone
+application, from a command line, or you can use it as part of your Eclipse
+development environment. In either case, you specify the AVD configuration to
+load and any startup options you want to use, as described in this document.
+</p>
+
+<p>You can run your application on a single instance of the emulator or,
+depending on your needs, you can start multiple emulator instances and run your
+application in more than one emulated device. You can use the emulator's
+built-in commands to simulate GSM phone calling or SMS between emulator
+instances, and you can set up network redirections that allow emulators to send
+data to one another. For more information, see <a href="#telephony">Telephony
+Emulation</a>, <a href="#sms">SMS Emulation</a>, and
+<a href="#emulatornetworking">Emulator Networking</a></p>
+
+<p>To start an instance of the emulator from the command line, change to the
+<code>tools/</code> folder of the SDK. Enter <code>emulator</code> command
+like this: </p>
+
+<pre>emulator -avd &lt;avd_name&gt;</pre>
+
+<p>This initializes the emulator and loads an AVD configuration (see the next
+section for more information about AVDs). You will see the emulator window
+appear on your screen. </p>
+
+<p>If you are working in Eclipse, the ADT plugin for Eclipse installs your
+application and starts the emulator automatically, when you run or debug
+the application. You can specify emulator startup options in the Run/Debug
+dialog, in the Target tab. When the emulator is running, you can issue
+console commands as described later in this document.</p>
+
+<p>If you are not working in Eclipse, see <a href="#apps">Installing Applications
+on the Emulator</a> for information about how to install your application.</p>
+
+<p>To stop an emulator instance, just close the emulator's window.</p>
+
+
+
+
+
+
+
+<a name="controlling"></a>
+
+
+<h2>Controlling the Emulator</h2>
+
+<p>You can use emulator <a href="#startup-options">startup options</a> and <a
+href="#console">console commands</a> to control the behaviors and
+characteristics of the emulated environment itself.
+</p>
+
+<p>When the emulator is running, you can interact with the emulated mobile
+device just as you would an actual mobile device, except that you use your mouse
+pointer to &quot;touch&quot; the touchscreen and your keyboard keys to
+&quot;press&quot; the simulated device keys. </p>
+
+<p>The table below summarizes the mappings between the emulator keys and and
+the keys of your keyboard. </p>
+
+<table  border="0" style="clear:left;">
+  <tr>
+    <th>Emulated Device Key </th>
+    <th>Keyboard Key </th>
+  </tr>
+  <tr>
+    <td>Home</td>
+    <td>HOME</td>
+  </tr>
+  <tr>
+    <td>Menu (left softkey)</td>
+    <td>F2 <em>or</em> Page-up button</td>
+  </tr>
+  <tr>
+    <td>Star (right softkey)</td>
+    <td>Shift-F2 <em>or </em>Page Down</td>
+  </tr>
+  <tr>
+    <td>Back</td>
+    <td>ESC</td>
+  </tr>
+  <tr>
+    <td>Call/dial button </td>
+    <td>F3</td>
+  </tr>
+  <tr>
+    <td>Hangup/end call button</td>
+    <td>F4</td>
+  </tr>
+  <tr>
+    <td>Search</td>
+    <td>F5 </td>
+  </tr>
+  <tr>
+    <td>Power button</td>
+    <td>F7 </td>
+  </tr>
+  <tr>
+    <td>Audio volume up button</td>
+    <td>KEYPAD_PLUS, Ctrl-5</td>
+  </tr>
+
+  <tr>
+    <td>Audio volume down button</td>
+    <td>KEYPAD_MINUS, Ctrl-F6</td>
+  </tr>
+  <tr>
+    <td>Camera button</td>
+    <td>Ctrl-KEYPAD_5, Ctrl-F3</td>
+  </tr>
+  <tr>
+    <td>Switch to previous layout orientation (for example, portrait, landscape)</td>
+    <td>KEYPAD_7, Ctrl-F11</td>
+  </tr>
+  <tr>
+    <td>Switch to next layout orientation (for example, portrait, landscape)</td>
+    <td>KEYPAD_9, Ctrl-F12</td>
+  </tr>
+  <tr>
+    <td>Toggle cell networking on/off</td>
+    <td>F8</td>
+  </tr>
+  <tr>
+    <td>Toggle code profiling</td>
+    <td>F9 (only with <code>-trace</code> startup option)</td>
+  </tr>
+  <tr>
+    <td>Toggle fullscreen mode</td>
+    <td>Alt-Enter</td>
+  </tr>
+  <tr>
+    <td>Toggle trackball mode</td>
+    <td>F6</td>
+  </tr>
+  <tr>
+    <td>Enter trackball mode temporarily (while key is pressed)</td>
+    <td>Delete</td>
+  </tr>
+  <tr>
+    <td>DPad left/up/right/down</td>
+    <td>KEYPAD_4/8/6/2</td>
+  </tr>
+  <tr>
+    <td>DPad center click</td>
+    <td>KEYPAD_5</td>
+  </tr>
+  <tr>
+    <td>Onion alpha increase/decrease</td>
+    <td>KEYPAD_MULTIPLY(*) / KEYPAD_DIVIDE(/)</td>
+  </tr>
+</table>
+
+<p>Note that, to use keypad keys, you must first disable NumLock on your development computer. </p>
+
+<h2 id="emulator">Emulator Startup Options</h2>
+
+<p>The emulator supports a variety of options that you can specify
+when launching the emulator, to control its appearance or behavior.
+Here's the command-line usage for launching the emulator with options: </p>
+
+<pre>emulator -avd &lt;avd_name&gt; [-&lt;option&gt; [&lt;value&gt;]] ... [-&lt;qemu args&gt;]</pre>
+
+<p>The table below summarizes the available options.</p>
+
+<table>
+<tr>
+  <th width="10%" >Category</th>
+  <th width="20%" >Option</th>
+    <th width="30%" >Description</th>
+    <th width="40%" >Comments</th>
+</tr>
+
+<tr>
+  <td rowspan="9">Help</td>
+  <td><code>-help</code></td>
+  <td>Print a list of all emulator options.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-help-all</code></td>
+  <td>Print help for all startup options.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-help-&lt;option&gt;</code></td>
+  <td>Print help for a specific startup option.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-help-debug-tags</code></td>
+  <td>Print a list of all tags for <code>-debug &lt;tags&gt;</code>.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-help-disk-images</code></td>
+  <td>Print help for using emulator disk images.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-help-environment</code></td>
+  <td>Print help for emulator environment variables.</td>
+  <td>&nbsp;</td>
+</tr><tr>
+  <td><code>-help-keys</code></td>
+  <td>Print the current mapping of keys.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-help-keyset-file</code></td>
+  <td>Print help for defining a custom key mappings file.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-help-virtual-device</code></td>
+  <td>Print help for Android Virtual Device usage.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td>AVD</td>
+  <td><code>-avd &lt;avd_name&gt;</code> or <br>
+      <code>@&lt;avd_name&gt;</code></td>
+  <td><strong>Required</strong>. Specifies the AVD to load for this emulator
+      instance.</td>
+  <td>You must create an AVD configuration before launching the emulator. For
+      information, see <a href="{@docRoot}guide/developing/devices/managing-avds.html">Creating and Managing
+      Virtual Devices with AVD Manager</a>.</td>
+<tr>
+  <td rowspan="7">Disk Images</td>
+  <td><code>-cache&nbsp;&lt;filepath&gt;</code></td>
+  <td>Use &lt;filepath&gt; as the working cache partition image. </td>
+  <td>Optionally, you can specify a path relative to the current working directory.
+  If no cache file is specified, the emulator's default behavior is to use a temporary file instead.
+  <p>For more information on disk images, use <code>-help-disk-images</code>.</p>
+</td></tr>
+<tr>
+  <td><code>-data&nbsp;&lt;filepath&gt;</code></td>
+  <td>Use &lt;filepath&gt; as the working user-data disk image. </td>
+  <td>Optionally, you can specify a path relative to the current working directory.
+  If <code>-data</code> is not used, the emulator looks for a file named &quot;userdata-qemu.img&quot;
+  in the storage area of the AVD being used (see <code>-avd</code>).
+</td></tr>
+<!--
+<tr>
+  <td><code>-datadir &lt;dir&gt;</code></td>
+  <td>Search for the user-data disk image specified in <code>-data</code> in &lt;dir&gt;</td>
+  <td><code>&lt;dir&gt;</code> is a path relative to the current working directory.
+
+<p>If you do not specify <code>-datadir</code>, the emulator looks for the user-data image
+in the storage area of the AVD being used (see <code>-avd</code>)</p><p>For more information
+on disk images, use <code>-help-disk-images</code>.</p>
+</td></tr>
+-->
+<!-- 
+<tr>
+  <td><code>-image&nbsp;&lt;filepath&gt;</code></td>
+  <td>Use &lt;filepath&gt; as the system image.</td>
+  <td>Optionally, you can specify a path relative to the current working directory.
+   Default is &lt;system&gt;/system.img.</td>
+</tr>
+-->
+<tr>
+  <td><code>-initdata&nbsp;&lt;filepath&gt;</code></td>
+  <td>When resetting the user-data image (through <code>-wipe-data</code>), copy the contents
+  of this file to the new user-data disk image. By default, the emulator copies the <code>&lt;system&gt;/userdata.img</code>.</td>
+  <td>Optionally, you can specify a path relative to the current working directory. See also <code>-wipe-data</code>.
+  <p>For more information on disk images, use <code>-help-disk-images</code>.</p></td>
+</tr>
+<!--
+<tr>
+  <td><code>-kernel&nbsp;&lt;filepath&gt;</code></td>
+  <td>Use &lt;filepath&gt; as the emulated kernel.</td>
+  <td>Optionally, you can specify a path relative to the current working directory. </td>
+</tr>
+-->
+<tr>
+  <td><code>-nocache</code></td>
+  <td>Start the emulator without a cache partition.</td>
+  <td>See also <code>-cache &lt;file&gt;</code>.</td>
+</tr>
+<tr>
+  <td><code>-ramdisk&nbsp;&lt;filepath&gt;</code></td>
+  <td>Use &lt;filepath&gt; as the ramdisk image.</td>
+  <td>Default value is <code>&lt;system&gt;/ramdisk.img</code>.
+  <p>Optionally, you can specify a path relative to the current working directory. 
+  For more information on disk images, use <code>-help-disk-images</code>.</p>
+</td>
+</tr>
+<tr>
+  <td><code>-sdcard&nbsp;&lt;filepath&gt;</code></td>
+  <td>Use &lt;file&gt; as the SD card image.</td>
+  <td>Default value is <code>&lt;system&gt;/sdcard.img</code>.
+  <p>Optionally, you can specify a path relative to the current working directory. For more information on disk images, use <code>-help-disk-images</code>.</p>
+</td>
+</tr>
+<!--
+<tr>
+ <td><code>-system&nbsp;&lt;dirpath&gt;</code></td>
+ <td>Search for system, ramdisk and user data images in &lt;dir&gt;.</td>
+ <td><code>&lt;dir&gt;</code> is a directory path relative to the current 
+  working directory.</td>
+</tr>
+-->
+<tr>
+  <td><code>-wipe-data</code></td>
+  <td>Reset the current user-data disk image (that is, the file specified by <code>-datadir</code> and 
+  <code>-data</code>, or the default file). The emulator deletes all data from the user data image file, 
+  then copies the contents of the file at <code>-inidata</code> data to the image file before starting. 
+  </td>
+  <td>See also <code>-initdata</code>. 
+  <p>For more information on disk images, use <code>-help-disk-images</code>.</p>
+</td>
+</tr>
+<tr>
+  <td rowspan="9">Debug</td>
+  <td><code>-debug &lt;tags&gt;</code></td>
+  <td>Enable/disable debug messages for the specified debug tags.</td>
+  <td><code>&lt;tags&gt;</code> is a space/comma/column-separated list of debug component names. 
+  Use <code>-help-debug-tags</code> to print a list of debug component names that you can use. </td>
+</tr>
+<tr>
+  <td><code>-debug-&lt;tag&gt;</code></td>
+  <td>Enable/disable debug messages for the specified debug tag.</td>
+  <td rowspan="2">Use <code>-help-debug-tags</code> to print a list of debug component names that you can use in <code>&lt;tag&gt;</code>. </td>
+</tr>
+<tr>
+  <td><code>-debug-no-&lt;tag&gt;</code></td>
+  <td>Disable debug messages for the specified debug tag.</td>
+</tr>
+<tr>
+  <td><code>-logcat &lt;logtags&gt;</code></td>
+  <td>Enable logcat output with given tags.</td>
+  <td>If the environment variable ANDROID_LOG_TAGS is defined and not
+    empty, its value will be used to enable logcat output by default.</td>
+</tr>
+<tr>
+  <td><code>-shell</code></td>
+  <td>Create a root shell console on the current terminal.</td>
+  <td>You can use this command even if the adb daemon in the emulated system is broken. 
+  Pressing Ctrl-c from the shell stops the emulator instead of the shell.</td>
+</tr>
+<tr>
+  <td><code>-shell-serial&nbsp;&lt;device&gt;</code></td>
+  <td>Enable the root shell (as in <code>-shell</code> and specify the QEMU character 
+  device to use for communication with the shell.</td>
+  <td>&lt;device&gt; must be a QEMU device type. See the documentation for '-serial <em>dev</em>' at 
+  <a href="http://www.nongnu.org/qemu/qemu-doc.html#SEC10">http://www.bellard.org/qemu/qemu-doc.html#SEC10</a> 
+  for a list of device types.
+
+<p>Here are some examples: </p>
+<ul>
+  <li><code>-shell-serial stdio</code> is identical to <code>-shell</code></li>
+  <li><code>-shell-serial tcp::4444,server,nowait</code> lets you communicate with the shell over TCP port 4444</li>
+  <li><code>-shell-serial fdpair:3:6</code> lets a parent process communicate with the shell using fds 3 (in) and 6 (out)</li>
+  <li><code>-shell-serial fdpair:0:1</code> uses the normal stdin and stdout fds, except that QEMU won't tty-cook the data.</li>
+  </ul>
+</td>
+</tr>
+<tr>
+  <td><code>-show-kernel &lt;name&gt;</code></td>
+  <td>Display kernel messages.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-trace &lt;name&gt;</code></td>
+  <td>Enable code profiling (press F9 to start), written to a specified file.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-verbose</code></td>
+  <td>Enable verbose output.</td>
+  <td>Equivalent to <code>-debug-init</code>. 
+<p>You can define the default verbose output options used by emulator instances in the Android environment variable 
+ANDROID_VERBOSE. Define the options you want to use in a comma-delimited list, specifying only the stem of each option: 
+<code>-debug-&lt;tags&gt;.</code> </p>
+<p>Here's an example showing ANDROID_VERBOSE defined with the <code>-debug-init</code> and <code>-debug-modem</code> options: 
+<p><code>ANDROID_VERBOSE=init,modem</code></p>
+<p>For more information about debug tags, use <code>&lt;-help-debug-tags&gt;</code>.</p>
+</td>
+</tr>
+<tr>
+  <td rowspan="6">Media</td>
+  <td><code>-audio &lt;backend&gt;</code></td>
+  <td>Use the specified audio backend.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-audio-in &lt;backend&gt;</code></td>
+  <td>Use the specified audio-input backend.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-audio-out &lt;backend&gt;</code></td>
+  <td>Use the specified audio-output backend.</td>
+  <td>&nbsp;</td>
+</tr>
+<!--<tr>
+  <td><code>-mic &lt;device or file&gt;</code></td>
+  <td>Use device or WAV file for audio input.</td>
+  <td>&nbsp;</td>
+</tr>
+-->
+<tr>
+  <td><code>-noaudio</code></td>
+  <td>Disable audio support in the current emulator instance.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-radio &lt;device&gt;</code></td>
+  <td>Redirect radio modem interface to a host character device.</td>
+  <td>&nbsp;</td></tr>
+<tr>
+  <td><code>-useaudio</code></td>
+  <td>Enable audio support in the current emulator instance.</td>
+  <td>Enabled by default. </td>
+</tr>
+
+<tr>
+  <td rowspan="7">Network</td>
+  <td><code>-dns-server &lt;servers&gt;</code></td>
+  <td>Use the specified DNS server(s). </td>
+  <td>The value of <code>&lt;servers&gt;</code> must be a comma-separated list of up to 4 DNS server names or
+  IP addresses.</td>
+</tr>
+<tr>
+  <td><code>-http-proxy &lt;proxy&gt;</code></td>
+  <td>Make all TCP connections through a specified HTTP/HTTPS proxy</td>
+  <td>The value of <code>&lt;proxy&gt;</code> can be one of the following:<br>
+     <code>http://&lt;server&gt;:&lt;port&gt;</code><br>
+     <code>http://&lt;username&gt;:&lt;password&gt;@&lt;server&gt;:&lt;port&gt;</code>
+  <p>The <code>http://</code> prefix can be omitted. If the <code>-http-proxy &lt;proxy&gt;</code> command is not supplied,
+  the emulator looks up the <code>http_proxy</code> environment variable and automatically uses any value matching
+  the <code>&lt;proxy&gt;</code> format described above.</p></td>
+</tr>
+<tr>
+  <td><code>-netdelay &lt;delay&gt;</code></td>
+  <td>Set network latency emulation to &lt;delay&gt;.</td>
+  <td>Default value is <code>none</code>. See the table in <a href="#netdelay">Network Delay Emulation</a> for 
+  supported <code>&lt;delay&gt;</code> values. </td>
+</tr>
+<tr>
+  <td><code>-netfast</code></td>
+  <td>Shortcut for <code>-netspeed full -netdelay none</code></td>
+  <td>&nbsp;</td></tr>
+<tr>
+  <td><code>-netspeed &lt;speed&gt;</code></td>
+  <td>Set network speed emulation to &lt;speed&gt;.</td>
+  <td>Default value is <code>full</code>. See the table in <a href="#netspeed">Network Speed Emulation</a> for 
+  supported <code>&lt;speed&gt;</code> values. </td>
+</tr>
+<tr>
+  <td><code>-port &lt;port&gt;</code></td>
+  <td>Set the console port number for this emulator instance to <code>&lt;port&gt;</code>.</td>
+  <td>The console port number must be an even integer between 5554 and 5584, inclusive. <code>&lt;port&gt;</code>+1 
+  must also be free and will be reserved for ADB.</td>
+</tr>
+<tr>
+  <td><code>-report-console &lt;socket&gt;</code></td>
+  <td>Report the assigned console port for this emulator instance to a remote third party 
+  before starting the emulation. </td>
+  <td><code>&lt;socket&gt;</code> must use one of these formats:
+
+<p><code>tcp:&lt;port&gt;[,server][,max=&lt;seconds&gt;]</code></br>
+<code>unix:&lt;port&gt;[,server][,max=&lt;seconds&gt;]</code></p>
+
+<p>Use <code>-help-report-console</code></p> to view more information about this topic. </td>
+</tr>
+<tr>
+  <td rowspan="8">System</td>
+  <td><code>-cpu-delay &lt;delay&gt;</code></td>
+  <td>Slow down emulated CPU speed by &lt;delay&gt; </td>
+  <td>Supported values for &lt;delay&gt; are integers between 0 and 1000.
+
+<p>Note that the &lt;delay&gt; does not correlate to clock speed or other absolute metrics 
+&mdash; it simply represents an abstract, relative delay factor applied non-deterministically 
+in the emulator. Effective performance does not always 
+scale in direct relationship with &lt;delay&gt; values.</p>
+</td>
+</tr>
+<tr>
+  <td><code>-gps &lt;device&gt;</code></td>
+  <td>Redirect NMEA GPS to character device.</td>
+  <td>Use this command to emulate an NMEA-compatible GPS unit connected to
+  an external character device or socket. The format of <code>&lt;device&gt;</code> must be QEMU-specific 
+  serial device specification. See the documentation for 'serial -dev' at 
+  <a href="http://www.bellard.org/qemu/qemu-doc.html#SEC10">http://www.bellard.org/qemu/qemu-doc.html#SEC10</a>.
+</td>
+</tr>
+<tr>
+  <td><code>-nojni</code></td>
+  <td>Disable JNI checks in the Dalvik runtime.</td><td>&nbsp;</td></tr>
+<tr>
+  <td><code>-qemu</code></td>
+  <td>Pass arguments to qemu.</td>
+  <td>&nbsp;</td></tr>
+<tr>
+  <td><code>-qemu -h</code></td>
+  <td>Display qemu help.</td>
+  <td></td></tr>
+<tr>
+  <td><code>-radio &lt;device&gt;</code></td>
+  <td>Redirect radio mode to the specified character device.</td>
+  <td>The format of <code>&lt;device&gt;</code> must be QEMU-specific 
+  serial device specification. See the documentation for 'serial -dev' at 
+<a href="http://www.bellard.org/qemu/qemu-doc.html#SEC10">http://www.bellard.org/qemu/qemu-doc.html#SEC10</a>.
+</td>
+</tr>
+<tr>
+ <td><code>-timezone &lt;timezone&gt;</code></td>
+ <td>Set the timezone for the emulated device to &lt;timezone&gt;, instead of the host's timezone.</td>
+ <td><code>&lt;timezone&gt;</code> must be specified in zoneinfo format. For example:
+<p>"America/Los_Angeles"<br>
+"Europe/Paris"</p>
+</td>
+</tr>
+<tr>
+ <td><code>-version</code></td>
+ <td>Display the emulator's version number.</td>
+ <td>&nbsp;</td>
+</tr>
+<tr>
+  <td rowspan="12">UI</td>
+  <td><code>-dpi-device &lt;dpi&gt;</code></td>
+  <td>Scale the resolution of the emulator to match the screen size
+  of a physical device.</td>
+  <td>The default value is 165. See also <code>-scale</code>.</td>
+</tr>
+<tr>
+  <td><code>-no-boot-anim</code></td>
+  <td>Disable the boot animation during emulator startup.</td>
+  <td>Disabling the boot animation can speed the startup time for the emulator.</td>
+</tr>
+<tr>
+  <td><code>-no-window</code></td>
+  <td>Disable the emulator's graphical window display.</td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>-scale &lt;scale&gt;</code></td>
+  <td>Scale the emulator window. </td>
+  <td><code>&lt;scale&gt;</code> is a number between 0.1 and 3 that represents the desired scaling factor. You can 
+  also specify scale as a DPI value if you add the suffix "dpi" to the scale value. A value of "auto" 
+  tells the emulator to select the best window size.</td>
+</tr>
+<tr>
+  <td><code>-raw-keys</code></td>
+  <td>Disable Unicode keyboard reverse-mapping.</td>
+  <td>&nbsp;</td></tr>
+<tr>
+  <td><code>-noskin</code></td>
+  <td>Don't use any emulator skin.</td>
+  <td>&nbsp;</td></tr>
+<tr>
+  <td><code>-keyset &lt;file&gt;</code></td>
+  <td>Use the specified keyset file instead of the default.</td>
+  <td>The keyset file defines the list of key bindings between the emulator and the host keyboard. 
+  For more information, use <code>-help-keyset</code> to print information about this topic.
+</td>
+</tr>
+<tr>
+  <td><code>-onion &lt;image&gt;</code></td>
+  <td>Use overlay image over screen.</td>
+  <td>No support for JPEG. Only PNG is supported.</td></tr>
+<tr>
+  <td><code>-onion-alpha &lt;percent&gt;</code></td>
+  <td>Specify onion skin translucency  value (as percent).
+  <td>Default is 50.</td>
+</tr>
+<tr>
+  <td><code>-onion-rotation &lt;position&gt;</code></td>
+  <td>Specify onion skin rotation.
+  <td><code>&lt;position&gt;</code> must be one of the values 0, 1, 2, 3.</td>
+</tr>
+<tr>
+  <td><code>-skin &lt;skinID&gt;</code></td>
+  <td>This emulator option is deprecated. </td>
+  <td>Please set skin options using AVDs, rather than by using this emulator
+option. Using this option may yield unexpected and in some cases misleading
+results, since the density with which to render the skin may not be defined.
+AVDs let you associate each skin with a default density and override the default
+as needed. For more information, see <a
+href="{@docRoot}guide/developing/devices/managing-avds.html">Creating and Managing Virtual Devices
+with AVD Manager</a>.
+</td>
+</tr>
+<tr>
+  <td><code>-skindir &lt;dir&gt;</code></td>
+  <td>This emulator option is deprecated. </td>
+  <td>See comments for <code>-skin</code>, above.</td></tr>
+</table>
+
+
+<a name="diskimages"></a>
+
+<h2>Working with Emulator Disk Images</h2>
+
+<p>The emulator uses mountable disk images stored on your development machine to
+simulate flash (or similar) partitions on an actual device. For example, it uses
+disk image containing an emulator-specific kernel, the Android system, a
+ramdisk image, and writeable images for user data and simulated SD card.</p>
+
+<p>To run properly, the emulator requires access to a specific set of disk image
+files. By default, the Emulator always looks for the disk images in the 
+private storage area of the AVD in use. If no images exist there when 
+the Emulator is launched, it creates the images in the AVD directory based on 
+default versions stored in the SDK. </p>
+
+<p class="note"><strong>Note:</strong> The default storage location for 
+AVDs is in <code>~/.android/avd</code> on OS X and Linux, <code>C:\Documents and 
+Settings\&lt;user&gt;\.android\</code> on Windows XP, and 
+<code>C:\Users\&lt;user&gt;\.android\</code>
+on Windows Vista.</p>
+
+<p>To let you use alternate or custom versions of the image files, the emulator
+provides startup options that override the default locations and filenames of
+the image files. When you use the options, the emulator searches for the image
+file under the image name or location that you specify; if it can not locate the
+image, it reverts to using the default names and location.</p>
+
+<p>The emulator uses three types of image files: default image files, runtime
+image files, and temporary image files. The sections below describe how to
+override the location/name of each type of file. </p>
+
+<a name="defaultimages"></a>
+<h3>Default Images</h3>
+
+<p>When the emulator launches but does not find an existing user data image in
+the active AVD's storage area, it creates a new one from a default version
+included in the SDK. The default user data image is read-only. The image 
+files are read-only.</p>
+
+<p>The emulator provides the <code>-system &lt;dir&gt;</code> startup option to
+let you override the location under which the emulator looks for the default
+user data image. </p>
+
+<p>The emulator also provides a startup option that lets you override the name
+of the default user data image, as described in the table below. When you use the 
+option, the emulator looks in the default directory, or in a custom location
+(if you specified <code>-system &lt;dir&gt;</code>). </p>
+
+
+<table>
+<tr>
+  <th width="10%" >Name</th>
+    <th width="30%" >Description</th>
+    <th width="40%" >Comments</th>
+</tr>
+
+<!--
+<tr>
+  <td><code>kernel-qemu.img</code></td>
+  <td>The emulator-specific Linux kernel image</td>
+  <td>Override using <code>-kernel &lt;file&gt;</code></td>
+</tr>
+
+<tr>
+  <td><code>ramdisk.img</code></td>
+  <td>The ramdisk image used to boot the system.</td>
+  <td>Override using <code>-ramdisk &lt;file&gt;</code></td>
+</tr>
+
+<tr>
+  <td><code>system.img</code></td>
+  <td>The <em>initial</em> Android system image.</td>
+  <td>Override using <code>-image &lt;file&gt;</code></td>
+</tr>
+-->
+<tr>
+  <td><code>userdata.img</code></td>
+  <td>The <em>initial</em> user-data disk image</td>
+  <td>Override using <code>-initdata &lt;file&gt;</code>. Also see
+<code>-data &lt;file&gt;</code>, below.</td>
+</tr>
+
+</table>
+
+<a name="runtimeimages"></a>
+<h3>Runtime Images: User Data and SD Card</h3>
+
+<p>At runtime, the emulator reads and writes data on two disk images: a
+user-data image and (optionally) an SD card image. This emulates the user-data
+partition and removable storage media on actual device. </p>
+
+<p>The emulator provides a default user-data disk image. At startup, the emulator 
+creates the default image as a copy of the system user-data image (user-data.img), 
+described above. The emulator stores the new image with the files of the active AVD.</p>
+
+<!--
+<p>The emulator provides a startup option, <code>-datadir &lt;dir&gt;</code>, 
+that you can use to override the location under which the emulator looks for the runtime
+image files. </p>
+-->
+
+<p>The emulator provides startup options to let you override the actual names and storage 
+locations of the runtime images to load, as described in the table below. When you use one 
+of these options, the emulator looks for the specified file(s) in the current working directory,
+in the AVD directory, or in a custom location (if you specified a path with the filename). </p>
+
+<table>
+<tr>
+  <th width="10%" >Name</th>
+    <th width="30%" >Description</th>
+    <th width="40%" >Comments</th>
+</tr>
+<tr>
+  <td><code>userdata-qemu.img</code></td>
+  <td>An image to which the emulator writes runtime user-data for a unique user.</td>
+  <td>Override using <code>-data &lt;filepath&gt;</code>, where <code>&lt;filepath&gt;</code> is the
+path the image, relative to the current working directory. If you supply a filename only, 
+the emulator looks for the file in the current working directory. If the file at <code>&lt;filepath&gt;</code> does
+not exist, the emulator creates an image from the default userdata.img, stores it under the name you
+specified, and persists user data to it at shutdown. </td>
+</tr>
+
+<tr>
+  <td><code>sdcard.img</code></td>
+  <td>An image representing an SD card inserted into the emulated device.</td>
+  <td>Override using <code>-sdcard &lt;filepath&gt;</code>, where <code>&lt;filepath&gt;</code> is the
+path the image, relative to the current working directory. If you supply a filename only, 
+the emulator looks for the file in the current working directory. </td>
+</tr>
+
+</table>
+
+<h4>User-Data Image</h4>
+
+<p>Each emulator instance uses a writeable user-data image to store user- and
+session-specific data. For example, it uses the image to store a unique user's
+installed application data, settings, databases, and files. </p>
+
+<p>At startup, the emulator attempts to load a user-data image stored during 
+a previous session. It looks for the file in the current working directory, 
+in the AVD directory as described above, and at the custom location/name 
+that you specified at startup. </p>
+
+<ul>
+<li>If it finds a user-data image, it mounts the image and makes it available 
+to the system for reading/writing of user data. </li>
+<li>If it does not find one, it creates an image by copying the system user-data
+image (userdata.img), described above. At device power-off, the system persists
+the user data to the image, so that it will be available in the next session. 
+Note that the emulator stores the new disk image at the location/name that you
+specify in <code>-data</code> startup option.</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> Because of the AVD configurations used in the emulator,
+each emulator instance now gets its own dedicated storage. There is no need 
+to use the <code>-d</code> option to specify an instance-specific storage area.</p>
+
+<h4>SD Card</h4>
+
+<P>Optionally, you can create a writeable disk image that the emulator can use
+to simulate removeable storage in an actual device. For information about how to create an 
+emulated SD card and load it in the emulator, see <a href="#sdcard">SD Card Emulation</a></p>
+
+<p>You can also use the android tool to automatically create an SD Card image
+for you, when creating an AVD. For more information, see <a 
+href="{@docRoot}guide/developing/devices/managing-avds.html">Creating and Managing Virtual Devices with AVD Manager</a>.
+
+<a name="temporaryimages"></a>
+<h3>Temporary Images</h3>
+
+<p>The emulator creates two writeable images at startup that it deletes at
+device power-off. The images are: </p>
+
+<ul>
+  <li>A writable copy of the Android system image</li>
+  <li>The <code>/cache</code> partition image</li>
+</ul>
+
+<p>The emulator does not permit renaming the temporary system image or
+persisting it at device power-off. </p>
+
+<p>The <code>/cache</code> partition image is initially empty, and is used by
+the browser to cache downloaded web pages and images. The emulator provides an 
+<code>-cache &lt;file&gt;</code>, which specifies the name of the file at which 
+to persist the <code>/cache</code> image at device power-off. If <code>&lt;file&gt;
+</code> does not exist, the emulator creates it as an empty file. </p>
+
+<p>You can also disable the use of the cache partition by specifying the
+<code>-nocache</code> option at startup. </p>
+
+
+<a name="emulatornetworking"></a>
+<h2>Emulator Networking</h2>
+
+<p>The emulator provides versatile networking capabilities that you can use to
+set up complex modeling and testing environments for your application. The
+sections below introduce the emulator's network architecture and capabilities.
+</p>
+
+<a name="networkaddresses"></a>
+<h3>Network Address Space</h3>
+
+<p>Each instance of the emulator runs behind a virtual router/firewall service
+that isolates it from your development machine's network interfaces and settings
+and from the internet. An emulated device can not see your development machine
+or other emulator instances on the network. Instead, it sees only that it is
+connected through Ethernet to a router/firewall.</p>
+
+<p>The virtual router for each instance manages the 10.0.2/24 network address
+space &mdash; all addresses managed by the router are in the form of
+10.0.2.&lt;xx&gt;, where &lt;xx&gt; is a number. Addresses within this space are
+pre-allocated by the emulator/router as follows:</p>
+
+<table>
+  <tr>
+    <th>Network Address</th>
+    <th>Description</th>
+  </tr>
+  <tr>
+    <td>10.0.2.1</td>
+    <td>Router/gateway address </td>
+  </tr>
+  <tr>
+    <td>10.0.2.2</td>
+    <td>Special alias to your host loopback interface (i.e., 127.0.0.1 on your
+development machine)</td>
+  </tr>
+  <tr>
+    <td>10.0.2.3</td>
+    <td>First DNS server</td>
+  </tr>
+  <tr>
+    <td>10.0.2.4 / 10.0.2.5 / 10.0.2.6</td>
+    <td>Optional second, third and fourth DNS server (if any) </td>
+  </tr>
+  <tr>
+    <td>10.0.2.15</td>
+    <td>The emulated device's own network/ethernet interface</td>
+  </tr>
+  <tr>
+    <td>127.0.0.1</td>
+    <td>The emulated device's own loopback interface </td>
+  </tr>
+</table>
+
+<p>Note that the same address assignments are used by all running emulator
+instances. That means that if you have two instances running concurrently on
+your machine, each will have its own router and, behind that, each will have an
+IP address of 10.0.2.15. The instances are isolated by a router and can
+<em>not</em> see each other on the same network. For information about how to
+let emulator instances communicate over TCP/UDP, see <a
+href="#connecting">Connecting Emulator Instances</a>.</p>
+
+<p>Also note that the address 127.0.0.1 on your development machine corresponds
+to the emulator's own loopback interface. If you want to access services running
+on your development machine's loopback interface (a.k.a. 127.0.0.1 on your
+machine), you should use the special address 10.0.2.2 instead.</p>
+
+<p>Finally, note that each emulated device's pre-allocated addresses are
+specific to the Android emulator and will probably be very different on real
+devices (which are also very likely to be NAT-ed, i.e., behind a
+router/firewall)</p>
+
+<a name="networkinglimitations"></a>
+<h3>Local Networking Limitations</h3>
+
+<p>Each emulator instance runs behind a virtual router, but unlike an actual
+device connected to a physical router, the emulated device doesn't have access
+to a physical network. Instead it runs as part of a normal application on your
+development machine. This means that it is subject to the same networking
+limitations as other applications on your machine:</p>
+
+<ul>
+  <li>Communication with the emulated device may be blocked by a firewall
+program running on your machine.</li>
+  <li>Communication with the emulated device may be blocked by another
+(physical) firewall/router to which your machine is connected.</li>
+</ul>
+
+<p>The emulator's virtual router should be able to handle all outbound TCP and
+UDP connections/messages on behalf of the emulated device, provided your
+development machine's network environment allows it to do so. There are no
+built-in limitations on port numbers or ranges except the one imposed by your
+host operating system and network.</p>
+
+<p>Depending on the environment, the emulator may not be able to support other
+protocols (such as ICMP, used for "ping") might not be supported. Currently, the
+emulator does not support IGMP or multicast. </p>
+
+<a name="redirections"></a>
+<h3>Using Network Redirections</h3>
+
+<p>To communicate with an emulator instance behind its virtual router, you need
+to set up network redirections on the virtual router. Clients can then connect
+to a specified guest port on the router, while the router directs traffic
+to/from that port to the emulated device's host port. </p>
+
+<p>To set up the network redirections, you create a mapping of host and guest
+ports/addresses on the the emulator instance. There are two ways to set up
+network redirections: using emulator console commands and using the ADB tool, as
+described below. </p>
+
+<a name="consoleredir"></a>
+<h4>Setting up Redirections through the Emulator Console</h4>
+
+<p>Each emulator instance provides a control console the you can connect to, to
+issue commands that are specific to that instance. You can use the
+<code>redir</code> console command to set up redirections as needed for an
+emulator instance. </p>
+
+<p>First, determine the console port number for the target emulator instance.
+For example, the console port number for the first emulator instance launched is
+5554. Next, connect to the console of the target emulator instance, specifying
+its console port number, as follows: </p>
+
+<pre><code>telnet localhost 5554</code></pre>
+
+<p>Once connected, use the <code>redir</code> command to work with redirections.
+To add a redirection, use:</p>
+
+<pre><code>add&nbsp;&lt;protocol&gt;:&lt;host-port&gt;:&lt;guest-port&gt;</code>
+</pre>
+
+<p>where <code>&lt;protocol&gt;</code> is either <code>tcp</code> or <code>udp</code>, 
+and <code>&lt;host-port&gt;</code> and <code>&lt;guest-port&gt;</code> sets the 
+mapping between your own machine and the emulated system, respectively. </p>
+
+<p>For example, the following command sets up a redirection that will handle all
+incoming TCP connections to your host (development) machine on 127.0.0.1:5000
+and will pass them through to the emulated system's 10.0.2.15:6000.:</p>
+
+<pre>redir add tcp:5000:6000</pre>
+
+<p>To delete a redirection, you can use the <code>redir del</code> command. To
+list all redirections for a specific instance, you can use <code>redir
+list</code>. For more information about these and other console commands, see 
+<a href="#console">Using the Emulator Console</a>. </p>
+
+<p>Note that port numbers are restricted by your local environment. this typically
+means that you cannot use host port numbers under 1024 without special
+administrator privileges.  Also, you won't be able to set up a redirection for a
+host port that is already in use by another process on your machine. In that
+case, <code>redir</code> generates an error message to that effect. </p>
+
+<a name="adbredir"></a>
+<h4>Setting Up Redirections through ADB</h4>
+
+<p>The Android Debug Bridge (ADB) tool provides port forwarding, an alternate
+way for you to set up network redirections. For more information, see <a
+href="{@docRoot}guide/developing/tools/adb.html#forwardports">Forwarding Ports</a> in the ADB
+documentation.</p>
+
+<p>Note that ADB does not currently offer any way to remove a redirection,
+except by killing the ADB server.</p>
+
+<a name="dns"></a>
+<h3>Configuring the Emulator's DNS Settings</h3>
+
+<p>At startup, the emulator reads the list of DNS servers that your system is
+currently using. It then stores the IP addresses of up to four servers on this
+list and sets up aliases to them on the emulated addresses 10.0.2.3, 10.0.2.4,
+10.0.2.5 and 10.0.2.6 as needed.  </p>
+
+<p>On Linux and OS X, the emulator obtains the DNS server addresses by parsing 
+the file <code>/etc/resolv.conf</code>. On Windows, the emulator obtains the 
+addresses by calling the <code>GetNetworkParams()</code> API. Note that this 
+usually means that the emulator ignores the content of your "hosts" file 
+(<code>/etc/hosts</code> on Linux/OS X, <code>%WINDOWS%/system32/HOSTS</code>
+ on Windows).</P>
+
+<p>When starting the emulator at the command line, you can also use the
+<code>-dns-server &lt;serverList&gt;</code> option to manually specify the
+addresses of DNS servers to use, where &lt;serverList&gt; is a comma-separated
+list of server names or IP addresses. You might find this option useful if you
+encounter DNS resolution problems in the emulated network (for example, an
+"Unknown Host error" message that appears when using the web browser).</p>
+
+<a name="proxy"></a>
+<h3>Using the Emulator with a Proxy</h3>
+
+<p>If your emulator must access the Internet through a proxy server, you can use
+the <code>-http-proxy &lt;proxy&gt;</code> option when starting the emulator, to
+set up the appropriate redirection. In this case, you specify proxy information
+in <code>&lt;proxy&gt;</code> in one of these formats:</p>
+
+<pre>http://&lt;machineName&gt;:&lt;port&gt;</pre>
+
+<p>or</p>
+
+<pre>http://&lt;username&gt;:&lt;password&gt;@&lt;machineName&gt;:&lt;port&gt;</pre>
+
+<p>The <code>-http-proxy</code> option forces the emulator to use the specified
+HTTP/HTTPS proxy for all outgoing TCP connections. Redirection for UDP is not
+currently supported.</p>
+
+<p>Alternatively, you can define the environment variable
+<code>http_proxy</code> to the value you want to use for
+<code>&lt;proxy&gt;</code>. In this case, you do not need to specify a value for
+<code>&lt;proxy&gt;</code> in the <code>-http-proxy</code> command &mdash; the
+emulator checks the value of the <code>http_proxy</code> environment variable at
+startup and uses its value automatically, if defined. </p>
+
+<p>You can use the <code>-verbose-proxy</code> option to diagnose proxy
+connection problems.</p>
+
+<a name="connecting"></a>
+<h3>Interconnecting Emulator Instances</h3>
+
+<p>To allow one emulator instance to communicate with another, you must set up
+the necessary network redirections as illustrated below. </p>
+
+<p>Assume that your environment is</p>
+
+<ul>
+  <li>A is you development machine</li>
+  <li>B is your first emulator instance, running on A</li>
+  <li>C is your second emulator instance, running on A too</li>
+</ul>
+
+<p>and you want to run a server on B, to which C will connect, here is how you
+could set it up: </p>
+
+<ol>
+  <li>Set up the server on B, listening to
+<code>10.0.2.15:&lt;serverPort&gt;</code></li>
+  <li>On B's console, set up a redirection from
+<code>A:localhost:&lt;localPort&gt;</code> to <code>
+B:10.0.2.15:&lt;serverPort&gt;</code></li>
+  <li>On C, have the client connect to <code>10.0.2.2:&lt;localPort&gt;</code></li>
+</ol>
+
+<p>For example, if you wanted to run an HTTP server, you can select
+<code>&lt;serverPort&gt;</code> as 80 and <code>&lt;localPort&gt;</code> as
+8080:</p>
+
+<ul>
+  <li>B listens on 10.0.2.15:80</li>
+  <li>On B's console, issue <code>redir add tcp:8080:80</code></li>
+  <li>C connects to 10.0.2.2:8080</li>
+</ul>
+
+<a name="calling"></a>
+<h3>Sending a Voice Call or SMS to Another Emulator Instance</h3>
+
+<p>The emulator automatically forwards simulated voice calls and SMS messages from one instance to another. To send a voice call or SMS, you use the dialer application and SMS application (if available) installed on one emulator </p>
+
+<p>To initiate a simulated voice call to another emulator instance:</p>
+<ol>
+<li>Launch the dialer application on the originating emulator instance.</li>
+<li>As the number to dial, enter the console port number of the instance you'd like to call. You can determine
+  the console port number of the target instance by checking its window title, where the
+  console port number is reported as "Android Emulator (&lt;port&gt;). </li>
+<li>Press "Dial". A new inbound call appears in the target emulator instance. </li>
+</ol>
+
+<p>To send an SMS message to another emulator instance, launch the SMS application (if available). Specify the console port number of the target emulator instance as as the SMS address, enter the message text, and send the message. The message is delivered to the target emulator instance. </p>
+
+<p>You can also connect to an emulator instance's console to simulate an incoming voice call or SMS. For more information, see <a href="#telephony">Telephony Emulation</a> and <a href="#sms">SMS Emulation</a>.
+
+<a name="console"></a>
+
+<h2>Using the Emulator Console</h2>
+
+<p>Each running emulator instance includes a console facility that lets you dynamically query and control the simulated device environment. For example, you can use the console to dynamically manage port redirections and network characteristics and simulate telephony events. To access the console and enter commands, you use telnet to connect to the console's port number. </p>
+<p>To connect to the console of any running emulator instance at any time, use this command: </p>
+
+<pre>telnet localhost &lt;console-port&gt;</pre>
+
+<p>An emulator instance occupies a pair of adjacent ports: a console port and an adb port. The port numbers differ by 1, with the adb port having the higher port number. The console of the first emulator instance running on a given machine uses console port 5554 and adb port 5555. Subsequent instances use port numbers increasing by two &mdash; for example, 5556/5557, 5558/5559, and so on. Up to 16 concurrent emulator instances can run a console facility. </p>
+
+<p>To connect to the emulator console, you must specify a valid console port. If multiple emulator instances are running, you need to determine the console port of the emulator instance you want to connect to. You can find the instance's console port listed in the title of the instance window. For example, here's the window title for an instance whose console port is 5554:</p>
+
+<p><code>Android Emulator (5554)</code></p>
+
+<p>Alternatively, you can use the <code>adb devices</code> command, which prints a list of running emulator instances and their console port numbers. For more information, see <a href="{@docRoot}guide/developing/tools/adb.html#devicestatus">Querying for Emulator/Device Instances</a> in the adb documentation.</p>
+
+<p class="note">Note: The emulator listens for connections on ports 5554-5587 and accepts connections only from localhost.</p>
+
+<p>Once you are connected to the console, you can then enter <code>help [command]</code> to see a list of console commands and learn about specific commands. </p>
+
+<p>To exit the console session, use <code>quit</code> or <code>exit</code>.</p>
+
+<p>The sections below describe the major functional areas of the console.</p>
+
+<a name="portredirection"></a>
+
+<h3>Port Redirection</h3>
+<p>You can use the console to add and remove port redirections while the emulator is running. After connecting to the console, you can manage port redirections in this way:</p>
+<pre>redir &lt;list|add|del&gt; </pre>
+
+<p>The <code>redir</code> command supports the subcommands listed in the table below. </p>
+
+<table>
+<tr>
+  <th width="25%" >Subcommand
+  <th width="30%" >Description</th>
+  <th width="35%">Comments</th>
+</tr>
+  
+  <tr>
+    <td><code>list</code></td>
+    <td>List the current port redirections.</td>
+  <td>&nbsp;</td>
+  </tr>
+
+  
+<tr>
+ <td><code>add&nbsp;&lt;protocol&gt;:&lt;host-port&gt;:&lt;guest-port&gt;</code></td>
+  <td>Add a new port redirection.</td>
+<td><ul><li>&lt;protocol&gt; must be either &quot;tcp&quot; or &quot;udp&quot;</li>
+<li>&lt;host-port&gt; is the port number to open on the host</li>
+<li>&lt;guest-port&gt; is the port number to route data to on the emulator/device</li>
+</ul></td>
+</tr>
+<tr>
+  <td><code>del &lt;protocol&gt;:&lt;host-port&gt;</code></td>
+  <td>Delete a port redirection.</td>
+<td>See above for meanings of &lt;protocol&gt; and &lt;host-port&gt;.</td>
+</tr>
+</table>
+
+<a name="geo"></a>
+<h3>Geo Location Provider Emulation</h3>
+
+<p>The console provides commands to let you set the geo position used by an emulator emulated device.
+You can use the <code>geo</code> command to send a simple GPS fix to the emulator, without needing to
+use NMEA 1083 formatting. The usage for the command is:</p>
+
+<pre>geo &lt;fix|nmea&gt;</pre>
+
+<p>The <code>geo</code> command supports the subcommands listed in the table below.</p>
+
+<table>
+<tr>
+  <th width="25%" >Subcommand
+  <th width="30%" >Description</th>
+  <th width="35%">Comments</th>
+</tr>
+  
+  <tr>
+    <td><code>fix &lt;longitude&gt; &lt;latitude&gt; [&lt;altitude&gt;]</code></td>
+    <td>Send a simple GPS fix to the emulator instance.</td>
+  <td>Specify longitude and latitude in decimal degrees. Specify altitude in meters.</td>
+  </tr>
+<tr>
+  <td><code>nmea &lt;sentence&gt;</code></td>
+  <td>Send an NMEA 0183 sentence to the emulated device, as if it were sent from an emulated GPS modem.</td>
+<td><code>&lt;sentence&gt;</code> must begin with '$GP'. Only '$GPGGA' and '$GPRCM' sentences are currently supported.</td>
+</tr>
+</table>
+
+<p>You can issue the <code>geo</code> command to fix the GPS location as soon as an emulator instance is running.
+The emulator creates a mock location provider that sends it to GPS-aware applications as soon as they start and
+register location listeners. Any application can query the location manager to obtain the current GPS fix for the
+emulated device by calling:
+
+<pre>LocationManager.getLastKnownLocation("gps")</pre>
+
+<p>For more information about the Location Manager, see {@link android.location.LocationManager} and its methods.</p>
+
+<a name="events"></a>
+<h3>Hardware Events Emulation</h3>
+
+<p>You can use the <code>event</code> command to send various events to the emulator.The usage for the command is: </p>
+
+<pre>event &lt;send|types|codes|text&gt;</pre>
+
+<p>The <code>event</code> command supports the subcommands listed in the table below. </p>
+
+<table>
+<tr>
+  <th width="25%" >Subcommand
+  <th width="30%" >Description</th>
+  <th width="35%">Comments</th>
+</tr>
+  
+  <tr>
+    <td><code>send &lt;type&gt;:&lt;code&gt;:&lt;value&gt; [...]</code></td>
+    <td>Send one or more events to the Android kernel. </td>
+  <td>You can use text names or integers for <code>&lt;type&gt;</code> and <code>&lt;value&gt;</code>.</td>
+  </tr>
+<tr>
+  <td><code>types</code></td>
+  <td>List all <code>&lt;type&gt;</code> string aliases supported by the <code>event</code> subcommands.</td>
+<td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>codes &lt;type&gt;</code></td>
+  <td>List all <code>&lt;codes&gt;</code> string aliases supported by the <code>event</code> 
+   subcommands for the specified <code>&lt;type&gt;</code>.</td>
+<td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>event text &lt;message&gt;</code></td>
+  <td>Simulate keypresses to send the specified string of characters as a message,</td>
+<td>The message must be a UTF-8 string. Unicode posts will be reverse-mapped according to the current device keyboard. Unsupported characters will be discarded silently.</td>
+</tr>
+</table>
+
+<a name="power"></a>
+<h3>Device Power Characteristics</h3>
+
+<p>You can use the <code>power</code> command to control the simulated power state of the emulator instance.The usage for the command is: </p>
+
+<pre>power &lt;display|ac|status|present|health|capacity&gt;</pre>
+
+<p>The <code>event</code> command supports the subcommands listed in the table below. </p>
+
+<table>
+<tr>
+  <th width="25%" >Subcommand </th>
+  <th width="30%" >Description</th>
+  <th width="35%">Comments</th>
+</tr>
+  
+  <tr>
+    <td><code>display</code></td>
+    <td>Display battery and charger state.</td>
+  <td>&nbsp;</td>
+  </tr>
+<tr>
+  <td><code>ac &lt;on|off&gt;</code></td>
+  <td>Set AC charging state to on or off. </td>
+<td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>status &lt;unknown|charging|discharging|not-charging|full&gt;</code></td>
+  <td>Change battery status as specified.</td>
+<td>&nbsp;</td>
+</tr>
+
+<tr>
+  <td><code>present &lt;true|false&gt;</code></td>
+  <td>Set battery presence state.</td>
+<td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>health &lt;unknown|good|overheat|dead|overvoltage|failure&gt;</code></td>
+  <td>Set battery health state.</td>
+<td>&nbsp;</td>
+</tr>
+<tr>
+  <td><code>power health &lt;percent&gt;</code></td>
+  <td>Set remaining battery capacity state (0-100).</td>
+<td>&nbsp;</td>
+</tr>
+</table>
+
+<a name="netstatus"></a>
+<h3>Network Status</h3>
+
+<p>You can use the console to check the network status and current delay and speed characteristics. To do so, connect to the console and use the <code>netstatus</code> command. Here's an example of the command and its output. </p>
+
+<pre>network status
+</pre>
+
+<a name="netdelay"></a>
+<h3>Network Delay Emulation</h3>
+
+<p>The emulator lets you simulate various network latency levels, so that you can test your application in an environment more typical of the actual conditions in which it will run. You can set a latency level or range at emulator startup or you can use the console to change the latency dynamically, while the application is running in the emulator. </p>
+<p>To set latency at emulator startup, use the  <code>-netdelay</code> emulator option with a supported <code>&lt;delay&gt;</code> value, as listed in the table below. Here are some examples:</p>
+<pre>emulator -netdelay gprs
+emulator -netdelay 40 100</pre>
+
+<p>To make dynamic changes to  network delay while the emulator is running, connect to the console and use the <code>netdelay</code> command with a supported <code>&lt;delay&gt;</code> value from the table below.  </p>
+
+<pre>network delay gprs</pre>
+
+<p>The format of network &lt;delay&gt; is one of the following (numbers are milliseconds):</p>
+
+<table style="clear:right;width:100%;">
+<tr>
+  <th width="30%" >Value</th>
+  <th width="35%" >Description</th><th width="35%">Comments</th></tr>
+  
+  <tr><td><code>gprs</code></td><td>GPRS</td>
+  <td>(min 150, max 550)</td>
+  </tr>
+
+<tr><td><code>edge</code></td><td>EDGE/EGPRS</td>
+<td>(min 80, max 400)</td>
+</tr>
+<tr><td><code>umts</code></td><td>UMTS/3G</td>
+<td>(min 35, max 200)</td>
+</tr>
+<tr><td><code>none</code></td><td>No latency</td><td>(min 0, max 0)</td></tr>
+<tr><td><code>&lt;num&gt;</code></td>
+<td>Emulate an exact latency  (milliseconds).</td>
+<td>&nbsp;</td></tr>
+<tr><td><code>&lt;min&gt;:&lt;max&gt;</code></td>
+<td>Emulate an specified latency range (min, max milliseconds).</td>
+<td>&nbsp;</td></tr>
+</table>
+
+<a name="netspeed"></a>
+<h3>Network Speed Emulation</h3>
+
+<p>The emulator also lets you simulate various network transfer rates. 
+You can set a transfer rate or range at emulator startup or you can use the console to change the rate dynamically,
+while the application is running in the emulator.</p>
+
+<p>To set the network speed at emulator startup, use the  <code>-netspeed</code> emulator option with a supported
+<code>&lt;speed&gt;</code> value, as listed in the table below. Here are some examples:</p>
+<pre>emulator -netspeed gsm
+emulator -netspeed 14.4 80</pre>
+
+<p>To make dynamic changes to  network speed while the emulator is running, connect to the console and use the <code>netspeed</code> command with a supported <code>&lt;speed&gt;</code> value from the table below.  </p>
+
+<pre>network speed 14.4 80</pre>
+
+<p>The format of network <code>&lt;speed&gt;</code> is one of the following (numbers are
+kilobits/sec):</p>
+<table style="clear:right;width:100%;">
+<tbody>
+<tr>
+  <th width="30%">Value</th>
+  <th width="35%">Description</th><th width="35%">Comments</th></tr>
+  
+  <tr>
+  <td><code>gsm</code></td>
+  <td>GSM/CSD</td><td>(Up: 14.4, down: 14.4)</td></tr>
+<tr>
+  <td><code>hscsd</code></td>
+  <td>HSCSD</td><td>(Up: 14.4, down: 43.2)</td></tr>
+<tr>
+  <td><code>gprs</code></td>
+  <td>GPRS</td><td>(Up: 40.0, down: 80.0)</td></tr>
+<tr>
+  <td><code>edge</code></td>
+  <td>EDGE/EGPRS</td>
+  <td>(Up: 118.4, down: 236.8)</td>
+</tr>
+<tr>
+  <td><code>umts</code></td>
+  <td>UMTS/3G</td><td>(Up: 128.0, down: 1920.0)</td></tr>
+<tr>
+  <td><code>hsdpa</code></td>
+  <td>HSDPA</td><td>(Up: 348.0, down: 14400.0)</td></tr>
+<tr>
+  <td><code>full</code></td>
+  <td>no limit</td><td>(Up: 0.0, down: 0.0)</td></tr>
+<tr>
+  <td><code>&lt;num&gt;</code></td>
+  <td>Set an exact rate used for both upload and download.</td><td></td></tr>
+<tr>
+  <td><code>&lt;up&gt;:&lt;down&gt;</code></td>
+  <td>Set exact rates for upload and download separately.</td><td></td></tr>
+</table>
+
+<a name="telephony"></a>
+
+<h3>Telephony Emulation</h3>
+
+<p>The Android emulator includes its own GSM emulated modem that lets you simulate telephony functions in the emulator. For example, you can simulate inbound phone calls and establish/terminate data connections. The Android system handles simulated calls exactly as it would actual calls. The emulator does not support call audio in this release. </p>
+<p>You can use the console to access the emulator's telephony functions. After connecting to the console, you can use</p>
+<pre>gsm &lt;call|accept|busy|cancel|data|hold|list|voice|status&gt; </pre>
+<p>to invoke telephony functions. </p>
+<p>The <code>gsm</code> command supports the subcommands listed in the table below. </p>
+<table>
+  <tr>
+    <th>Subcommand </th>
+    <th width="25%">Description</th>
+    <th>Comments</th>
+  </tr>
+  <tr>
+    <td><code>call &lt;phonenumber&gt;</code></td>
+    <td>Simulate an inbound phone call from &lt;phonenumber&gt;.</td>
+    <td>&nbsp;</td>
+  </tr>
+  <tr>
+    <td><code>accept &lt;phonenumber&gt;</code></td>
+    <td>Accept an inbound call from &lt;phonenumber&gt; and change the call's state "active".</td>
+    <td>You can change a call's state to "active" only if its current state is "waiting" or "held".</td>
+  </tr>
+  <tr>
+    <td><code>busy &lt;phonenumber&gt;</code></td>
+    <td>Close an outbound call to &lt;phonenumber&gt; and change the call's state to "busy".</td>
+    <td>You can change a call's state to "busy" only if its current state is "waiting".</td>
+  </tr>
+  <tr>
+    <td><code>cancel &lt;phonenumber&gt;</code></td>
+    <td>Terminate an inbound or outbound phone call to/from &lt;phonenumber&gt;.</td>
+    <td>&nbsp;</td>
+  </tr>
+  <tr>
+    <td><code>data &lt;state&gt;</code></td>
+    <td>Change the state of the GPRS data connection to &lt;state&gt;.</td>
+    <td>Supported &lt;state&gt; values are:<br />
+    <ul>
+          <li><code>unregistered</code> -- No network available</li>
+          <li><code>home</code> -- On local network, non-roaming</li>
+          <li><code>roaming</code> -- On roaming network</li>
+          <li><code>searching</code> -- Searching networks</li>
+          <li><code>denied</code> -- Emergency calls only</li>
+          <li><code>off</code> -- Same as 'unregistered'</li>
+      <li><code>on</code> -- same as 'home'</li>
+    </ul>
+          </td>
+  </tr>
+  <tr>
+    <td><code>hold</code></td>
+    <td>Change the state of a call to "held". </td>
+    <td>You can change a call's state to "held" only if its current state is	 "active" or "waiting". </td>
+  </tr>
+  <tr>
+    <td><code>list</code></td>
+    <td>List all inbound and outbound calls and their states.</td>
+    <td>&nbsp;</td>
+  </tr>
+  <tr>
+    <td><code>voice &lt;state&gt;</code></td>
+    <td>Change the state of the GPRS voice connection to &lt;state&gt;.</td>
+    <td>Supported &lt;state&gt; values are:<br />
+    <ul>
+    <li><code>unregistered</code> -- No network available</li>
+    <li><code>home</code> -- On local network, non-roaming</li>
+    <li><code>roaming</code> -- On roaming network</li>
+    <li><code>searching</code> -- Searching networks</li>
+    <li><code>denied</code> -- Emergency calls only</li>
+    <li><code>off</code> -- Same as 'unregistered'</li>
+    <li><code>on</code> -- Same as 'home'</li>
+    </ul>
+    </td>
+  </tr>
+
+  <tr>
+    <td><code>status</code></td>
+    <td>Report the current GSM voice/data state.</td>
+    <td>Values are those described for the <code>voice</code> and <code>data</code> commands.</td>
+  </tr>
+</table>
+
+<a name="sms"></a>
+
+<h3>SMS Emulation</h3>
+
+<p>The Android emulator console lets you generate an SMS message and direct it to an emulator instance. Once you connect to an emulator instance, you can generate an emulated incoming SMS using this command:</p>
+
+<pre>sms send &lt;senderPhoneNumber&gt; &lt;textmessage&gt;</pre>
+
+<p>where <code>&lt;senderPhoneNumber&gt;</code> contains an arbitrary numeric string. </p>
+
+<p>The console forwards the SMS message to the Android framework, which passes it through to an application that handles that message type. </p>
+
+<a name="vm"></a>
+
+<h3>VM State</h3>
+
+<p>You can use the <code>vm</code> command to control the VM on an emulator instance.The usage for the command is: </p>
+
+<pre>vm &lt;start|stop|status&gt;</pre>
+
+<p>The <code>vm</code> command supports the subcommands listed in the table below. </p>
+
+<table>
+<tr>
+  <th width="25%" >Subcommand </th>
+  <th width="30%" >Description</th>
+  <th width="35%">Comments</th>
+</tr>
+<tr>
+    <td><code>start</code></td>
+    <td>Start the VM on the instance. </td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+    <td><code>stop</code></td>
+    <td>Stop the VM on the instance. </td>
+  <td>&nbsp;</td>
+</tr>
+<tr>
+    <td><code>start</code></td>
+    <td>Display the current status of the VM (running or stopped). </td>
+  <td>&nbsp;</td>
+</tr>
+</table>
+
+
+<a name="window"></a>
+
+<h3>Emulator Window</h3>
+
+<p>You can use the <code>window</code> command to manage the emulator window. The usage for the command is: </p>
+
+<pre>window &lt;scale&gt;</pre>
+
+<p>The <code>vm</code> command supports the subcommands listed in the table below. </p>
+
+<table>
+<tr>
+  <th width="25%" >Subcommand
+  <th width="30%" >Description</th>
+  <th width="35%">Comments</th>
+</tr>
+<tr>
+    <td><code>scale &lt;scale&gt;</code></td>
+    <td>Scale the emulator window.</td>
+  <td>&lt;scale&gt; must be a number between 0.1 and 3 that describes the desired scaling factor. You can 
+  also specify scale as a DPI value if you add the suffix "dpi" to the scale value. A value of "auto" 
+  tells the emulator to select the best window size.</td>
+</tr>
+</table>
+
+
+<a name="terminating"></a>
+
+<h3>Terminating an Emulator Instance</h3>
+
+<p>You can terminate an emulator instance through the console, using the <code>kill</code> command.</p>
+
+
+<a name="skins"></a>
+
+<h2>Using Emulator Skins</h2>
+
+<p>The Android SDK includes several Emulator skins that you can use to control the resolution and density of the emulated device's screen. To select a specific skin for running the emulator, create an AVD that uses that skin. Please do not use deprecated emulator options such as <code>-skin</code> to control the skin used by an emulator instance. For more information about AVDs, see <a
+href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</a>.</p>
+
+
+<a name="multipleinstances"></a>
+
+<h2>Running Multiple Emulator Instances</h2>
+
+<p>Through the AVDs configurations used by the emulator, you can run multiple
+instances of the emulator concurrently, each with its own AVD configuration and
+storage area for user data, SD card, and so on. You no longer need to use the
+<code>-d</code> option when launching the emulator, to point to an
+instance-specific storage area. </p>
+
+<a name="apps"></a>
+
+<h2>Installing Applications on the Emulator</h2>
+
+<p>If you don't have access to Eclipse or the ADT Plugin, you can install 
+your application on the emulator <a href="{@docRoot}guide/developing/tools/adb.html#move">using 
+the adb utility</a>. Before installing the application, you need to build and package it 
+into an <code>.apk</code> as described in <a href="{@docRoot}guide/developing/building/index.html">Building and
+Running Apps</a>. Once the application is installed, you can start the emulator from the command 
+line, as described in this document, using any startup options necessary. 
+When the emulator is running, you can also connect to the emulator instance's 
+console to issue commands as needed.</p>
+
+<p>As you update your code, you periodically package and install it on the emulator. 
+The emulator preserves the application and its state data across restarts, 
+in a user-data disk partition. To ensure that the application runs properly 
+as you update it, you may need to delete the emulator's user-data partition. 
+To do so, start the emulator with the <code>-wipe-data</code> option. 
+For more information about the user-data partition and other emulator storage, 
+see <a href="#diskimages">Working with Emulator Disk Images</a>.</p>
+
+<a name="sdcard"></a>
+<a name="creating"></a>
+
+<h2>SD Card Emulation</h2>
+
+<p>You can create a disk image and then load it to the emulator at startup, to
+simulate the presence of a user's SD card in the device. To do this, you can use
+the android tool to create a new SD card image with a new AVD, or you can use
+the mksdcard utility included in the SDK. </p>
+
+<p>The sections below describe how to create an SD card disk image, how to copy
+files to it, and how to load it in the emulator at startup. </p>
+
+<p>Note that you can only load disk image at emulator startup. Similarly, you
+can not remove a simulated SD card from a running emulator. However, you can
+browse, send files to, and copy/remove files from a simulated SD card either
+with adb or the emulator. </p>
+
+<p>The emulator supports emulated SDHC cards, so you can create an SD card image
+of any size up to 128 gigabytes.</p>
+
+<h3 id="creatinga">Creating an SD card image using the android tool</h3>
+
+<p>The easiest way to create a new SD card is to use the android tool. When
+creating an AVD, you simply specify the <code>-c</code> option, like this: </p>
+
+<pre>android create avd -n &lt;avd_name&gt; -t &lt;targetID&gt; -c &lt;size&gt;[K|M]</pre>
+
+<p>You can also use the <code>-c</code> option to specify a path to an SD card
+image to use in the new AVD. For more information, see <a
+href="{@docRoot}guide/developing/devices/managing-avds-cmdline.html">Creating and Managing Virtual Devices on the Command Line</a>.
+</p>
+
+<h3 id="creatingm">Creating an SD card image using mksdcard</h3>
+
+<p>You can use the mksdcard tool, included in the SDK, to create a FAT32 disk
+image that you can load in the emulator at startup. You can access mksdcard in
+the tools/ directory of the SDK and create a disk image like this: </p>
+
+<pre>mksdcard &lt;size&gt; &lt;file&gt;</pre>
+
+<p>For example:</p>
+
+<pre>mksdcard 1024M sdcard1.iso</pre>
+
+<p>For more information, see <a href="{@docRoot}guide/developing/tools/mksdcard.html"><code>mksdcard</code></a>.</p>
+
+<a name="copying"></a>
+<h3>Copying Files to a Disk Image</h3>
+
+<p>Once you have created the disk image, you can copy files to it prior to
+loading it in the emulator. To copy files, you can mount the image as a loop
+device and then copy the files to it, or you can use a utility such as mtools to
+copy the files directly to the image. The mtools package is available for Linux,
+Mac, and Windows.</p>
+
+<a name="loading"></a>
+<a name="step3" id="step3"></a>
+
+<h3>Loading the Disk Image at Emulator Startup</h3>
+
+<p>By default, the emulator loads the SD card image that is stored with the active
+AVD (see the <code>-avd</code> startup option).</p>
+
+<p>Alternatively, you ca start the emulator with the
+<code>-sdcard</code> flag and specify the name and path of your image (relative
+to the current working directory): </p>
+
+<pre>emulator -sdcard &lt;filepath&gt;</pre>
+
+<a name="troubleshooting"></a>
+
+<h2>Troubleshooting Emulator Problems</h2>
+
+<p>The adb utility sees the emulator as an actual physical device. For this reason, you might have to use the -d flag with some common adb commands, such as <code>install</code>. The -d flag lets you specify which of several connected devices to use as the target of a command. If you don't specify -d, the emulator will target the first device in its list. For more information about adb, see <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a>.</p>
+
+<p>For emulators running on Mac OS X, if you see an error &quot;Warning: No DNS servers found&quot; when starting the emulator, check to see whether you have an <code>/etc/resolv.conf</code> file. If not, please run the following line in a command window:</p>
+    <pre>ln -s /private/var/run/resolv.conf /etc/resolv.conf</pre>
+
+<p>See <a href="{@docRoot}resources/faq/index.html">Frequently Asked Questions</a> for more troubleshooting information. </p>
+
+<a name="limitations"></a>
+    <h2>Emulator Limitations</h2>
+    <p>In this release, the  limitations of the emulator include: </p>
+    <ul>
+      <li>No support for placing or receiving actual phone calls. You can simulate phone calls (placed and received) through the emulator console, however. </li>
+      <li>No support for USB connections</li>
+      <li>No support for camera/video capture (input).</li>
+      <li>No support for device-attached headphones</li>
+      <li>No support for determining connected state</li>
+      <li>No support for determining battery charge level and AC charging state</li>
+      <li>No support for determining SD card insert/eject</li>
+      <li>No support for Bluetooth</li>
+    </ul>
diff --git a/docs/html/guide/developing/devices/index.jd b/docs/html/guide/developing/devices/index.jd
new file mode 100644
index 0000000..3e73eb0
--- /dev/null
+++ b/docs/html/guide/developing/devices/index.jd
@@ -0,0 +1,78 @@
+page.title=Creating and Managing Virtual Devices
+@jd:body
+
+
+ <p>An Android Virtual Device (AVD) is an emulator configuration that lets you model an actual
+  device by defining hardware and software options to be emulated by the Android Emulator.</p>
+
+  <p>The easiest way to create an AVD is to use the graphical <a href= 
+  "{@docRoot}guide/developing/devices/managing-avds.html">AVD Manager</a>, which you launch
+  from Eclipse by clicking <strong>Window &gt; Android SDK and AVD Manager</strong>. You can also start
+  the AVD Manager from the command line by calling the <code>android</code> tool in the <strong>tools</strong>
+  directory of the Android SDK.</p>
+
+  <p>You can also create AVDs on the command line by passing the <code>android</code> tool options.
+  For more information on how to create AVDs in this manner, see <a href= 
+  "{@docRoot}guide/developing/devices/managing-avds-cmdline.html">Creating and Managing Virtual
+  Devices on the Command Line</a>.</p>
+
+  <p>An AVD consists of:</p>
+
+  <ul>
+    <li>A hardware profile: Defines the hardware features of the virtual
+    device. For example, you can define whether the device has a camera, whether it uses a physical
+    QWERTY keyboard or a dialing pad, how much memory it has, and so on.</li>
+
+    <li>A mapping to a system image: You can define what version of the Android platform will run
+    on the virtual device. You can choose a version of the standard Android platform or the system
+    image packaged with an SDK add-on.</li>
+
+    <li>Other options: You can specify the emulator skin you want to use with the AVD, which lets
+    you control the screen dimensions, appearance, and so on. You can also specify the emulated SD
+    card to use with the AVD.</li>
+
+    <li>A dedicated storage area on your development machine: the device's user data (installed
+    applications, settings, and so on) and emulated SD card are stored in this area.</li>
+  </ul>
+
+  <p>You can create as many AVDs as you need, based on the types of device you want to model. 
+  To thoroughly test your application, you should create an AVD for each general device configuration
+  (for example, different screen sizes and platform versions) with which your application is compatible
+  and test your application on each one.</p>
+
+  <p>Keep these points in mind when you are selecting a system image target for your AVD:</p>
+
+  <ul>
+    <li>The API Level of the target is important, because your application will not be able to run
+    on a system image whose API Level is less than that required by your application, as specified
+    in the <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">
+    <code>minSdkVersion</code></a> attribute of the application's manifest file. For more
+    information about the relationship between system API Level and application
+    <code>minSdkVersion</code>, see <a href=
+    "{@docRoot}guide/publishing/versioning.html">Specifying Minimum System API Version</a>.</li>
+
+    <li>You should create at least one AVD that uses a target whose API Level is greater than that required
+    by your application, because it allows you to test the
+    forward-compatibility of your application. Forward-compatibility testing ensures that, when
+    users who have downloaded your application receive a system update, your application will
+    continue to function normally.</li>
+
+    <li>If your application declares a 
+    <a href="{@docRoot}guide/topics/manifest/uses-library-element.html"><code>uses-library</code></a>
+    element in its manifest file, the application can only run on a system image in which that external
+    library is present. If you want to run your application on an emulator, create an AVD that
+    includes the required library. Usually, you must create such an AVD using an Add-on component for the
+    AVD's platform (for example, the Google APIs Add-on contains the Google Maps library).</li>
+  </ul>
+
+  <p>To learn how to manage AVDs using a graphical tool, read <a href=
+  "{@docRoot}guide/developing/devices/managing-avds.html">
+  Creating and Managing AVDs with AVD Manager</a>. To learn how to manage AVDs on the command line, read
+  <a href="{@docRoot}guide/developing/devices/managing-avds-cmdline.html">Creating and Managing AVDs
+  on the Command Line</a>.</p>
+
+
+
+
+
+
diff --git a/docs/html/guide/developing/devices/managing-avds-cmdline.jd b/docs/html/guide/developing/devices/managing-avds-cmdline.jd
new file mode 100644
index 0000000..878ccc9
--- /dev/null
+++ b/docs/html/guide/developing/devices/managing-avds-cmdline.jd
@@ -0,0 +1,312 @@
+page.title=Creating and Managing AVDs on the Command Line
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#listingtargets">Listing targets</a></li>
+    <li><a href="#AVDCmdLine">Creating AVDs</a></li>
+    <li><a href="#moving">Moving an AVD</a></li>
+    <li><a href="#updating">Updating an AVD</a></li>
+    <li><a href="#deleting">Deleting an AVD</a></li>
+  </ol>
+  </div>
+</div>
+
+
+<p>The <code>android</code> tool lets you manage AVDs on the command line. For a complete reference 
+of the command line options that you can use, see the reference for the 
+<a href="{@docRoot}guide/developing/tools/android.html"><code>android</code></a> tool.</p>
+
+
+
+<h2 id="listingtargets">Listing targets</h2>
+
+<p>To generate a list of system image targets, use this command: </p>
+
+<pre>android list targets</pre>
+
+<p>The <code>android</code> tool scans the <code>&lt;sdk&gt;/platforms/</code> and
+<code>&lt;sdk&gt;/add-ons/</code> directories looking for valid system images and
+then generates the list of targets. Here's an example of the command output:
+</p>
+
+<pre>Available Android targets:
+id: 1 or "android-3"
+     Name: Android 1.5
+     Type: Platform
+     API level: 3
+     Revision: 4
+     Skins: QVGA-L, HVGA-L, HVGA (default), HVGA-P, QVGA-P
+id: 2 or "android-4"
+     Name: Android 1.6
+     Type: Platform
+     API level: 4
+     Revision: 3
+     Skins: QVGA, HVGA (default), WVGA800, WVGA854
+id: 3 or "android-7"
+     Name: Android 2.1-update1
+     Type: Platform
+     API level: 7
+     Revision: 2
+     Skins: QVGA, WQVGA400, HVGA (default), WVGA854, WQVGA432, WVGA800
+id: 4 or "android-8"
+     Name: Android 2.2
+     Type: Platform
+     API level: 8
+     Revision: 2
+     Skins: WQVGA400, QVGA, WVGA854, HVGA (default), WVGA800, WQVGA432
+id: 5 or "android-9"
+     Name: Android 2.3
+     Type: Platform
+     API level: 9
+     Revision: 1
+     Skins: HVGA (default), WVGA800, WQVGA432, QVGA, WVGA854, WQVGA400
+</pre>
+
+<h2 id="AVDCmdLine">Creating AVDs</h2> 
+<p>In addition to creating AVDs with the 
+<a href="{@docRoot}guide/developing/devices/managing-avds-cmdline.html">AVD Manager user interface</a>,
+you can also create them by passing in command line arguments to the <code>android</code> tool.
+</p>
+
+<p>Open a terminal window and change to
+the <code>&lt;sdk&gt;/tools/</code> directory, if needed.</p>
+
+<p>To create each AVD, you issue the command <code>android create avd</code>,
+with options that specify a name for the new AVD and the system image you want
+to run on the emulator when the AVD is invoked. You can specify other options on
+the command line also, such as the emulated SD card size, the emulator skin, or a custom
+location for the user data files.</p> 
+
+<p>Here's the command-line usage for creating an AVD: </p>
+
+<pre>android create avd -n &lt;name&gt; -t &lt;targetID&gt; [-&lt;option&gt; &lt;value&gt;] ... </pre>
+
+<p>You can use any name you want for the AVD, but since you are likely to be
+creating multiple AVDs, you should choose a name that lets you recognize the
+general characteristics offered by the AVD. The target ID is an integer assigned by the
+<code>android</code> tool. The target ID is not derived from the system image name, 
+version, or API Level, or other attribute, so you need to run the <code>android list targets</code>
+command to list the target ID of each system image. You should do this <em>before</em> you run
+the <code>android create avd</code> command. See the <a href="{@docRoot}guide/developing/tools/android.html">android</a></p>
+tool documentation for more information on the command line options.  
+
+
+<p>When you've selected the target you want to use and made a note of its ID,
+use the <code>android create avd</code> command to create the AVD, supplying the
+target ID as the <code>-t</code> argument. Here's an example that creates an
+AVD with name "my_android1.5" and target ID "2" (the standard Android 1.5 
+system image in the list above): </p>
+
+<pre>android create avd -n my_android1.5 -t 2</pre>
+
+<p>If the target you selected was a standard Android system image ("Type:
+platform"), the <code>android</code> tool next asks you whether you want to
+create a custom hardware profile. </p>
+<pre>Android 1.5 is a basic Android platform.
+Do you wish to create a custom hardware profile [no]</pre>
+
+<p>If you want to set custom hardware emulation options for the AVD, enter
+"yes" and set values as needed. If you want to use the default hardware
+emulation options for the AVD, just press the return key (the default is "no").
+The <code>android</code> tool creates the AVD with name and system image mapping you
+requested, with the options you specified. For more information, see <a href="#hardwareopts">
+Setting Hardware Emulation Options</a>.
+
+<p class="note"><strong>Note:</strong> If you are creating an AVD whose target is an SDK add-on, the
+<code>android</code> tool does not allow you to set hardware emulation options.
+It assumes that the provider of the add-on has set emulation options
+appropriately for the device that the add-on is modeling, and so prevents you
+from resetting the options. </p>
+
+
+<h3>Default location of AVD files</h3>
+<p>When you create an AVD, the <code>android</code> tool creates a dedicated directory for it
+on your development computer. The directory contains the AVD configuration file,
+the user data image and SD card image (if available), and any other files
+associated with the device. Note that the directory does not contain a system
+image &mdash; instead, the AVD configuration file contains a mapping to the
+system image, which it loads when the AVD is launched. </p>
+
+<p>The <code>android</code> tool also creates an <code>&lt;AVD_name&gt;.ini</code> file for the AVD at the
+root of the <code>.android/avd/</code> directory on your computer. The file specifies the
+location of the AVD directory and always remains at the root the .android 
+directory.</p>
+
+<p>By default, the <code>android</code> tool creates the AVD directory inside
+<code>~/.android/avd/</code> (on Linux/Mac), <code>C:\Documents and
+Settings\&lt;user&gt;\.android\</code> on Windows XP, and 
+<code>C:\Users\&lt;user&gt;\.android\</code> on Windows 7 and Vista. 
+If you want to use a custom location for the AVD directory, you 
+can do so by using the <code>-p &lt;path&gt;</code> option when 
+you create the AVD: </p>
+
+<pre>android create avd -n my_android1.5 -t 2 -p path/to/my/avd</pre>
+
+<p>If the .android directory is hosted on a network drive, we recommend using
+the <code>-p</code> option to place the AVD directory in another location. 
+The  AVD's .ini file remains in the .android directory on the network
+drive, regardless of the location of the AVD directory. 
+
+
+<h3 id="hardwareopts">Setting Hardware Emulation Options</h3>
+
+<p>When you are creating a new AVD that uses a standard Android system image ("Type:
+platform"), the <code>android</code> tool lets you set hardware emulation
+options for virtual device. The table below lists the options available and the
+default values, as well as the names of properties that store the emulated
+hardware options in the AVD's configuration file (the config.ini file in the
+AVD's local directory). </p>
+
+<p class="table-caption"><strong>Table 1.</strong> Available hardware profile options for AVDs and
+the default values </p>
+
+<table>
+<tr>
+<th>Characteristic</th>
+<th>Description</th>
+<th>Property</th>
+</tr>
+
+<tr>
+<td>Device ram size</td>
+<td>The amount of physical RAM on the device, in megabytes. Default value is "96".
+<td>hw.ramSize</td>
+</tr>
+
+<tr>
+<td>Touch-screen support</td>
+<td>Whether there is a touch screen or not on the device. Default value is "yes".</td>
+<td>hw.touchScreen
+
+<tr>
+<td>Trackball support </td>
+<td>Whether there is a trackball on the device. Default value is "yes".</td>
+<td>hw.trackBall</td>
+</tr>
+
+<tr>
+<td>Keyboard support</td>
+<td>Whether the device has a QWERTY keyboard. Default value is "yes".</td>
+<td>hw.keyboard</td>
+</tr>
+
+<tr>
+<td>DPad support</td>
+<td>Whether the device has DPad keys. Default value is "yes".</td>
+<td>hw.dPad</td>
+</tr>
+
+<tr>
+<td>GSM modem support</td>
+<td>Whether there is a GSM modem in the device. Default value is "yes".</td>
+<td>hw.gsmModem</td>
+</tr>
+
+<tr>
+<td>Camera support</td>
+<td>Whether the device has a camera. Default value is "no".</td>
+<td>hw.camera</td>
+</tr>
+
+<tr>
+<td>Maximum horizontal camera pixels</td>
+<td>Default value is "640".</td>
+<td>hw.camera.maxHorizontalPixels</td>
+</tr>
+
+<tr>
+<td>Maximum vertical camera pixels</td>
+<td>Default value is "480".</td>
+<td>hw.camera.maxVerticalPixels</td>
+</tr>
+
+<tr>
+<td>GPS support</td>
+<td>Whether there is a GPS in the device. Default value is "yes".</td>
+<td>hw.gps</td>
+</tr>
+
+<tr>
+<td>Battery support</td>
+<td>Whether the device can run on a battery. Default value is "yes".</td>
+<td>hw.battery</td>
+</tr>
+
+<tr>
+<td>Accelerometer</td>
+<td>Whether there is an accelerometer in the device. Default value is "yes".</td>
+<td>hw.accelerometer</td>
+</tr>
+
+<tr>
+<td>Audio recording support</td>
+<td>Whether the device can record audio. Default value is "yes".</td>
+<td>hw.audioInput</td>
+</tr>
+
+<tr>
+<td>Audio playback support</td>
+<td>Whether the device can play audio. Default value is "yes".</td>
+<td>hw.audioOutput</td>
+</tr>
+
+<tr>
+<td>SD Card support</td>
+<td>Whether the device supports insertion/removal of virtual SD Cards. Default value is "yes".</td>
+<td>hw.sdCard</td>
+</tr>
+
+<tr>
+<td>Cache partition support</td>
+<td>Whether we use a /cache partition on the device. Default value is "yes".</td>
+<td>disk.cachePartition</td>
+</tr>
+
+<tr>
+<td>Cache partition size</td>
+<td>Default value is "66MB".</td>
+<td>disk.cachePartition.size </td>
+</tr>
+
+<tr>
+<td>Abstracted LCD density</td>
+<td>Sets the generalized density characteristic used by the AVD's screen. Default value is "160".</td>
+<td>hw.lcd.density </td>
+</tr>
+
+<tr>
+<td>Trackball support</td>
+<td>Whether there is a trackball present.</td>
+<td>hw.trackBall </td>
+</tr>
+</table>
+
+
+<h2 id="moving">Moving an AVD</h2>
+
+<p>If you want to move or rename an AVD, you can do so using this command:</p>
+
+<pre>android move avd -n &lt;name&gt; [-&lt;option&gt; &lt;value&gt;] ...</pre>
+
+<h2 id="updating">Updating an AVD</h2>
+
+<p>If, for any reason, the platform/add-on root folder has its name changed (maybe because the user has installed an update of the platform/add-on) then the AVD will not be able to load the system image that it is mapped to. In this case, the <code>android list targets</code> command will produce this output: 
+
+<pre>The following Android Virtual Devices could not be loaded: 
+Name: foo 
+Path: &lt;path&gt;/.android/avd/foo.avd 
+Error: Invalid value in image.sysdir. Run 'android update avd -n foo' </pre>
+
+<p>To fix this error, use the <code>android update avd</code> command to recompute the path to the system images.</p>
+
+<h2 id="deleting">Deleting an AVD</h2>
+
+<p>You can use the <code>android</code> tool to delete an AVD. Here is the command usage:</p>
+
+<pre>android delete avd -n &lt;name&gt; </pre>
+
+<p>When you issue the command, the <code>android</code> tool looks for an AVD matching the 
+specified name deletes the AVD's directory and files. </p>
diff --git a/docs/html/guide/developing/devices/managing-avds.jd b/docs/html/guide/developing/devices/managing-avds.jd
new file mode 100644
index 0000000..27d2b55
--- /dev/null
+++ b/docs/html/guide/developing/devices/managing-avds.jd
@@ -0,0 +1,243 @@
+page.title=Creating and Managing AVDs with AVD Manager
+@jd:body
+
+  <div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li><a href="#createavd">Creating an AVD</a>
+          <ol>
+            <li><a href="#hardwareopts">Hardware options</a></li>
+          </ol>
+        </li>        
+      </ol>
+    </div>
+  </div>
+
+  <p>The AVD Manager is an easy to use user interface to manage your AVD (Android Virtual Device)
+  configurations. An AVD is a device configuration for the Android emulator that allows you to
+  model different configurations of Android-powered devices. When you start the AVD Manager in Eclipse 
+  or run the <code>android</code> tool on the command line, you will see the AVD Manager as shown in
+  figure 1:</p>
+  
+  <img src="{@docRoot}images/avd-manager.png">
+  
+  <p class="img-caption"><strong>Figure 1. </strong>Screenshot of the AVD Manager. </p>
+  
+  <p>From the main screen, you can create, delete, repair and start AVDs as well as see the details
+  of each AVD. </p>
+
+  
+  <h2 id="createavd">Creating an AVD</h2>
+
+  <p>You can create as many AVDs as you would like to test on. It is recommended that you test your
+  applications on all API levels higher than the target API level for your application.</p>
+
+  <p>To create an AVD:</p>
+
+  <ol>
+    <li>Start the AVD Manager:
+
+      <ul>
+        <li>In Eclipse: select <strong>Window &gt; Android SDK and AVD Manager</strong>, or click
+        the Android SDK and AVD Manager icon in the Eclipse toolbar.</li>
+
+        <li>In other IDEs: Navigate to your SDK's <code>tools/</code> directory and execute the
+        <code>android</code> tool with no arguments.</li>
+      </ul>
+    </li>
+
+    <li><p>In the <em>Virtual Devices</em> panel, you'll see a list of existing AVDs. Click
+    <strong>New</strong> to create a new AVD. The <strong>Create New AVD</strong> dialog appears.</p>
+      
+      <img src="{@docRoot}images/developing/avd-dialog.png" alt="AVD Dialog">
+      <p class="img-caption"><strong>Figure 2.</strong> Screenshot of the Create AVD window</p>
+    </li>
+
+    <li>Fill in the details for the AVD.
+
+      <p>Give it a name, a platform target, an SD card size, and a skin (HVGA is default). You can
+      also add specific hardware features of the emulated device by clicking the
+      <strong>New...</strong> button and selecting the feature. For a list of hardware features,
+      see <a href="#hardwareopts">Hardware options</a>.</p>
+
+      <p class="note"><strong>Note:</strong> Be sure to define a target for your AVD that satisfies
+      your application's Build Target (the AVD platform target must have an API Level equal to or
+      greater than the API Level that your application compiles against).</p>
+    </li>
+
+    <li>Click <strong>Create AVD</strong>.</li>
+  </ol>
+
+  <p>Your AVD is now ready and you can either close the SDK and AVD Manager, create more AVDs, or
+  launch an emulator with the AVD by selecting a device and clicking <strong>Start</strong>.</p>
+
+<h3 id="hardwareopts">Hardware options</h3>
+<p>If you are creating a new AVD, you can specify the following hardware options for the AVD
+to emulate:</p>
+
+  <table>
+    <tr>
+      <th>Characteristic</th>
+
+      <th>Description</th>
+
+      <th>Property</th>
+    </tr>
+
+    <tr>
+      <td>Device ram size</td>
+
+      <td>The amount of physical RAM on the device, in megabytes. Default value is "96".</td>
+
+      <td>hw.ramSize</td>
+    </tr>
+
+    <tr>
+      <td>Touch-screen support</td>
+
+      <td>Whether there is a touch screen or not on the device. Default value is "yes".</td>
+
+      <td>hw.touchScreen</td>
+    </tr>
+
+    <tr>
+      <td>Trackball support</td>
+
+      <td>Whether there is a trackball on the device. Default value is "yes".</td>
+
+      <td>hw.trackBall</td>
+    </tr>
+
+    <tr>
+      <td>Keyboard support</td>
+
+      <td>Whether the device has a QWERTY keyboard. Default value is "yes".</td>
+
+      <td>hw.keyboard</td>
+    </tr>
+
+    <tr>
+      <td>DPad support</td>
+
+      <td>Whether the device has DPad keys. Default value is "yes".</td>
+
+      <td>hw.dPad</td>
+    </tr>
+
+    <tr>
+      <td>GSM modem support</td>
+
+      <td>Whether there is a GSM modem in the device. Default value is "yes".</td>
+
+      <td>hw.gsmModem</td>
+    </tr>
+
+    <tr>
+      <td>Camera support</td>
+
+      <td>Whether the device has a camera. Default value is "no".</td>
+
+      <td>hw.camera</td>
+    </tr>
+
+    <tr>
+      <td>Maximum horizontal camera pixels</td>
+
+      <td>Default value is "640".</td>
+
+      <td>hw.camera.maxHorizontalPixels</td>
+    </tr>
+
+    <tr>
+      <td>Maximum vertical camera pixels</td>
+
+      <td>Default value is "480".</td>
+
+      <td>hw.camera.maxVerticalPixels</td>
+    </tr>
+
+    <tr>
+      <td>GPS support</td>
+
+      <td>Whether there is a GPS in the device. Default value is "yes".</td>
+
+      <td>hw.gps</td>
+    </tr>
+
+    <tr>
+      <td>Battery support</td>
+
+      <td>Whether the device can run on a battery. Default value is "yes".</td>
+
+      <td>hw.battery</td>
+    </tr>
+
+    <tr>
+      <td>Accelerometer</td>
+
+      <td>Whether there is an accelerometer in the device. Default value is "yes".</td>
+
+      <td>hw.accelerometer</td>
+    </tr>
+
+    <tr>
+      <td>Audio recording support</td>
+
+      <td>Whether the device can record audio. Default value is "yes".</td>
+
+      <td>hw.audioInput</td>
+    </tr>
+
+    <tr>
+      <td>Audio playback support</td>
+
+      <td>Whether the device can play audio. Default value is "yes".</td>
+
+      <td>hw.audioOutput</td>
+    </tr>
+
+    <tr>
+      <td>SD Card support</td>
+
+      <td>Whether the device supports insertion/removal of virtual SD Cards. Default value is
+      "yes".</td>
+
+      <td>hw.sdCard</td>
+    </tr>
+
+    <tr>
+      <td>Cache partition support</td>
+
+      <td>Whether we use a /cache partition on the device. Default value is "yes".</td>
+
+      <td>disk.cachePartition</td>
+    </tr>
+
+    <tr>
+      <td>Cache partition size</td>
+
+      <td>Default value is "66MB".</td>
+
+      <td>disk.cachePartition.size</td>
+    </tr>
+
+    <tr>
+      <td>Abstracted LCD density</td>
+
+      <td>Sets the generalized density characteristic used by the AVD's screen. Default value is
+      "160".</td>
+
+      <td>hw.lcd.density</td>
+    </tr>
+
+    <tr>
+      <td>Trackball support</td>
+
+      <td>Whether there is a trackball present.</td>
+
+      <td>hw.trackBall</td>
+    </tr>
+  </table>
+
diff --git a/docs/html/guide/developing/eclipse-adt.html b/docs/html/guide/developing/eclipse-adt.html
new file mode 100644
index 0000000..879a356
--- /dev/null
+++ b/docs/html/guide/developing/eclipse-adt.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0;url=http://developer.android.com/guide/developing/projects/projects-eclipse.html">
+<title>Redirecting...</title>
+</head>
+<body>
+<p>You should be redirected. Please <a
+href="http://developer.android.com/guide/developing/projects/projects-eclipse.html">click here</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/guide/developing/eclipse-adt.jd b/docs/html/guide/developing/eclipse-adt.jd
deleted file mode 100644
index f8d32e7..0000000
--- a/docs/html/guide/developing/eclipse-adt.jd
+++ /dev/null
@@ -1,860 +0,0 @@
-page.title=Developing In Eclipse, with ADT
-@jd:body
-
-<div id="qv-wrapper">
-  <div id="qv">
-  <h2>In this document</h2>
-  <ol>
-    <li><a href="#CreatingAProject">Creating an Android Project</a></li>
-    <li><a href="#AVD">Creating an AVD</a></li>
-    <li><a href="#Running">Running Your Application</a>
-      <ol>
-        <li><a href="#RunningOnEmulator">Running on the emulator</a></li>
-        <li><a href="#RunningOnDevice">Running on a device</a></li>
-      </ol>
-    </li>
-    <li><a href="#RunConfig">Creating a Run Configuration</a></li>
-    <li><a href="#Signing">Setting Up Application Signing</a></li>
-    <li><a href="#libraryProject">Working with Library Projects</a>
-      <ol>
-        <li><a href="#libraryReqts">Development requirements</a></li>
-        <li><a href="#librarySetup">Setting up a library project</a></li>
-        <li><a href="#libraryReference">Referencing a library project</a></li>
-        <li><a href="#considerations">Development considerations</a></li>
-        <li><a href="#libraryMigrating">Migrating library projects to ADT 0.9.8</a></li>
-      </ol>
-    </li>
-    <li><a href="#Tips">Eclipse Tips</a></li>
-  </div>
-</div>
-
-
-<p>The Android Development Tools (ADT) plugin for Eclipse adds powerful extensions to the Eclipse 
-integrated development environment. It allows you to create and debug Android applications easier 
-and faster. If you use Eclipse, the ADT plugin gives you an incredible boost in developing Android 
-applications:</p>
-
-<ul>
-  <li>It gives you access to other Android development tools from inside the Eclipse IDE. For 
-example, ADT lets you access the many capabilities of the DDMS tool: take screenshots, manage 
-port-forwarding, set breakpoints, and view thread and process information directly from
-Eclipse.</li>
-  <li>It provides a New Project Wizard, which helps you quickly create and set up all of the 
-basic files you'll need for a new Android application.</li>
-  <li>It automates and simplifies the process of building your Android application.</li>
-  <li>It provides an Android code editor that helps you write valid XML for your Android 
-manifest and resource files.</li>
-  <li>It will even export your project into a signed APK, which can be distributed to users.</li>
-</ul>
-
-<p>To begin developing Android applications in the Eclipse IDE with ADT, you first need to 
-download the Eclipse IDE and then download and install the ADT plugin. To do so, follow the 
-steps given in <a href="{@docRoot}sdk/eclipse-adt.html#installing">Installing 
-the ADT Plugin</a>.</p>
-
-<p>If you are already developing applications using a version of ADT earlier than 0.9, make
-sure to upgrade to the latest version before continuing. See the guide to
-<a href="{@docRoot}sdk/eclipse-adt.html#updating">Updating Your ADT Plugin</a>.</p>
-
-<p class="note"><strong>Note:</strong> This guide assumes you are using the latest version of
-the ADT plugin. While most of the information covered also applies to previous 
-versions, if you are using an older version, you may want to consult this document from
-the set of documentation included in your SDK package (instead of the online version).</p>
-
-
-<h2  id="CreatingAProject">Creating an Android Project</h2>
-
-<p>The ADT plugin provides a New Project Wizard that you can use to quickly create a new
-Android project (or a project from existing code). To create a new project:</p>
-
-<ol>
-  <li>Select <strong>File</strong> &gt; <strong>New</strong> &gt; <strong>Project</strong>.</li>
-  <li>Select <strong>Android</strong> &gt; <strong>Android Project</strong>, and click
-    <strong>Next</strong>.</li>
-  <li>Select the contents for the project:
-    <ul>
-      <li>Enter a <em>Project Name</em>. This will be the name of the folder where your
-        project is created.</li>
-      <li>Under Contents, select <strong>Create new project in workspace</strong>.
-        Select your project workspace location.</li>
-      <li>Under Target, select an Android target to be used as the project's Build Target. 
-        The Build Target
-        specifies which Android platform you'd like your application built against.
-        <p>Unless you know that you'll be using new APIs introduced in the latest SDK, you should
-        select a target with the lowest platform version possible.</p>
-        <p class="note"><strong>Note:</strong> You can change your the Build Target for your 
-        project at any time: Right-click the project in the Package Explorer, select
-        <strong>Properties</strong>, select <strong>Android</strong> and then check 
-        the desired Project Target.</p>
-      </li>
-      <li>Under Properties, fill in all necessary fields.
-        <ul>
-          <li>Enter an <em>Application name</em>. This is the human-readable title for your 
-            application &mdash; the name that will appear on the Android device.</li>
-          <li>Enter a <em>Package name</em>. This is the package namespace (following the same rules
-            as for packages in the Java programming language) where all your source code
-            will reside.</li>
-          <li>Select <em>Create Activity</em> (optional, of course, but common) and enter a name
-            for your main Activity class.</li>
-          <li>Enter a <em>Min SDK Version</em>. This is an integer that indicates
-            the minimum API Level required to properly run your application. 
-            Entering this here automatically sets the <code>minSdkVersion</code> attribute in the 
-            <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a>
-            of your Android Manifest file. If you're unsure of the appropriate <a
-href="{@docRoot}guide/appendix/api-levels.html">API Level</a> to use,
-            copy the API Level listed for the Build Target you selected in the Target tab.</li>
-        </ul>
-      </li>
-    </ul>
-  </li>
-  <li>Click <strong>Finish</strong>.</li>
-</ol>
-
-<p class="note"><strong>Tip:</strong>
-You can also start the New Project Wizard from the <em>New</em> icon in the toolbar.</p>
-
-<p>Once you complete the New Project Wizard, ADT creates the following 
-folders and files in your new project:</p>
-  <dl>
-    <dt><code>src/</code></dt>
-      <dd>Includes your stub Activity Java file. All other Java files for your application
-      go here.</dd>
-    <dt><code><em>&lt;Android Version&gt;</em>/</code> (e.g., <code>Android 1.1/</code>)</dt>
-      <dd>Includes the <code>android.jar</code> file that your application will build against. 
-      This is determined by the build target that you have chosen in the <em>New Project
-      Wizard</em>.</dd>
-    <dt><code>gen/</code></dt>
-      <dd>This contains the Java files generated by ADT, such as your <code>R.java</code> file
-      and interfaces created from AIDL files.</dd>
-    <dt><code>assets/</code></dt>
-      <dd>This is empty. You can use it to store raw asset files. </dd>
-    <dt><code>res/</code></dt>
-      <dd>A folder for your application resources, such as drawable files, layout files, string
-      values, etc. See 
-      <a href="{@docRoot}guide/topics/resources/index.html">Application Resources</a>.</dd>
-    <dt><code>AndroidManifest.xml</code></dt>
-      <dd>The Android Manifest for your project. See 
-      <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml 
-      File</a>.</dd>
-    <dt><code>default.properties</code></dt>
-      <dd>This file contains project settings, such as the build target. This files is integral
-      to the project, as such, it should be maintained in a Source Revision Control system. 
-      It should never be edited manually &mdash; to edit project properties, 
-      right-click the project folder and select "Properties".</dd>
-  </dl>
-
-
-<h2 id="AVD">Creating an AVD</h2>
-
-<p>An Android Virtual Device (AVD) is a device configuration for the emulator that
-allows you to model real world devices. In order to run an instance of the emulator, you must create
-an AVD.</p>
-
-<p>To create an AVD from Eclipse:</p>
-
-<ol>
-  <li>Select <strong>Window > Android SDK and AVD Manager</strong>, or click the Android SDK and
-AVD Manager icon in the Eclipse toolbar.</p>
-  </li>
-  <li>In the <em>Virtual Devices</em> panel, you'll see a list of existing AVDs. Click
-<strong>New</strong> to create a new AVD.</li>
-  <li>Fill in the details for the AVD.
-    <p>Give it a name, a platform target, an SD card size, and
-    a skin (HVGA is default).</p>
-    <p class="note"><strong>Note:</strong> Be sure to define
-    a target for your AVD that satisfies your application's Build Target (the AVD
-    platform target must have an API Level equal to or greater than the API Level that your
-application compiles against).</p>
-  </li>
-  <li>Click <strong>Create AVD</strong>.</li>
-</ol>
-
-<p>Your AVD is now ready and you can either close the SDK and AVD Manager, create more AVDs, or
-launch an emulator with the AVD by selecting a device and clicking <strong>Start</strong>.</p>
-
-<p>For more information about AVDs, read the
-<a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a>
-documentation.</p>
-
-
-<h2 id="Running">Running Your Application</h2>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>Use the Emulator to Test Different Configurations</h2>
-<p>Create multiple AVDs that each define a different device configuration with which your
-application is compatible, then launch each AVD into a new emulator from the SDK and AVD Manager.
-Set the target mode in your app's run configuration to manual, so that when you run your
-application, you can select from the available virtual devices.</p>
-</div>
-</div>
-
-<p>Running your application from Eclipse will usually require just a couple clicks, whether you're
-running it on the emulator or on an attached device. The information below describes how to get
-set up and run your application from Eclipse.</p>
-
-<h3 id="RunningOnEmulator">Running on the emulator</h3>
-
-<p>Before you can run your application on the Android Emulator,
-you <strong>must</strong> <a href="#AVD">create an AVD</a>.</p>
-
-<p>To run (or debug) your application, select <strong>Run</strong> &gt; <strong>Run</strong> (or
-<strong>Run</strong> &gt; <strong>Debug</strong>) from the Eclipse menu bar. The ADT plugin
-will automatically create a default launch configuration for the project. Eclipse will then perform
-the following:</p>
-
-<ol>
-  <li>Compile the project (if there have been changes since the last build).</li>
-  <li>Create a default launch configuration (if one does not already exist for the
-project).</li>
-  <li>Install and start the application on an emulator (or device), based on the Deployment
-Target
-    defined by the run configuration.
-    <p>By default, Android run configurations use an "automatic target" mode for
-    selecting a device target. For information on how automatic target mode selects a
-    deployment target, see <a href="#AutoAndManualTargetModes">Automatic and manual
-    target modes</a> below.</p>
-  </li>
-</ol>
-
-<p>If debugging, the application will start in the "Waiting For Debugger" mode. Once the
-debugger is attached, Eclipse will open the Debug perspective.</p>
-
-<p>To set or change the launch configuration used for your project, use the launch configuration
-manager.
-See <a href="#RunConfig">Creating a Run Configuration</a> for information.</p>
-
-<p>Be certain to create multiple AVDs upon which to test your application. You should have one AVD
-for each platform and screen type with which your application is compatible. For
-instance, if your application compiles against the Android 1.5 (API Level 3) platform, you should
-create an AVD for each platform equal to and greater than 1.5 and an AVD for each <a
-href="{@docRoot}guide/practices/screens_support.html">screen type</a> you support, then test
-your application on each one.</p>
-
-
-<h3 id="RunningOnDevice">Running on a device</h3>
-
-<p>Before you can run your application on a device, you must perform some basic setup for your
-device:</p>
-
-<ul>
-  <li>Declare your application as debuggable in your manifest</li>
-  <li>Enable USB Debugging on your device</li>
-  <li>Ensure that your development computer can detect your device when connected via USB</li>
-</ul>
-<p>Read <a href="{@docRoot}guide/developing/device.html#setting-up">Setting up a Device for
-Development</a> for more information.</p>
-
-<p>Once set up and your device is connected via USB, install your application on the device by
-selecting <strong>Run</strong> &gt; <strong>Run</strong> (or
-<strong>Run</strong> &gt; <strong>Debug</strong>) from the Eclipse menu bar.</p>
-
-
-
-<h2 id="RunConfig">Creating a Run Configuration</h2>
-
-<p>The run configuration specifies the project to run, the Activity 
-to start, the emulator or connected device to use, and so on. When you first run a project
-as an <em>Android Application</em>, ADT will automatically create a run configuration.
-The default run configuration will
-launch the default project Activity and use automatic target mode for device selection 
-(with no preferred AVD). If the default settings don't suit your project, you can 
-customize the launch configuration or even create a new.</p>
-
-<p>To create or modify a launch configuration, follow these steps as appropriate 
-for your Eclipse version:</p>
-
-<ol>
-  <li>Open the run configuration manager.
-        <ul>
-          <li>In Eclipse 3.3 (Europa), select <strong>Run</strong> &gt; 
-            <strong>Open Run Dialog</strong> (or <strong>Open Debug Dialog</strong>)
-          </li>
-          <li>In Eclipse 3.4 (Ganymede), select <strong>Run </strong>&gt; 
-            <strong>Run Configurations</strong> (or
-            <strong>Debug Configurations</strong>)
-          </li>
-      </ul>
-  </li>
-  <li>Expand the <strong>Android Application</strong> item and create a new
-  configuration or open an existing one.
-    <ul>
-      <li>To create a new configuration:
-        <ol>
-          <li>Select <strong>Android Application</strong> and click the <em>New launch
-configuration</em>
-          icon above the list (or, right-click  <strong>Android Application</strong> and click 
-          <strong>New</strong>).</li>
-          <li>Enter a Name for your configuration.</li>
-          <li>In the Android tab, browse and select the project you'd like to run with the
-          configuration.</li>
-        </ol>
-      <li>To open an existing configuration, select the configuration name from the list
-      nested below <strong>Android Application</strong>.</li>
-    </ul>
-  </li>
-  <li>Adjust your desired launch configuration settings.
-    <p>In the Target tab, consider whether you'd like to use Manual or Automatic mode
-    when selecting an AVD to run your application.
-    See the following section on <a href="#AutoAndManualTargetModes">Automatic and manual target 
-    modes</a>).</p>
-    <p>You can specify any emulator options to the Additional Emulator Command
-    Line Options field. For example, you could add <code>-scale 96dpi</code> to
-    scale the AVD's screen to an accurate size, based on the dpi of your
-    computer monitor. For a full list of emulator options, see the <a
-    href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a>
-document.</p>
-  </li>
-</ol>
-
-
-<h3 id="AutoAndManualTargetModes">Automatic and manual target modes</h3>
-
-<p>By default, a run configuration uses the <strong>automatic</strong> target mode in order to
-select an AVD. In this mode, ADT will select an AVD for the application in the following manner:</p>
-
-<ol>
-  <li>If there's a device or emulator already running and its AVD configuration
-  meets the requirements of the application's build target, the application is installed
-  and run upon it.</li>
-  <li>If there's more than one device or emulator running, each of which meets the requirements
-  of the build target, a "device chooser" is shown to let you select which device to use.</li>
-  <li>If there are no devices or emulators running that meet the requirements of the build target, 
-  ADT looks at the available AVDs. If one meets the requirements of the build target,
-  the AVD is used to launch a new emulator, upon which the application is installed and run.</li>
-  <li>If all else fails, the application will not be run and you will see a console error warning
-  you that there is no existing AVD that meets the build target requirements.</li>
-</ol>
-
-<p>However, if a "preferred AVD" is selected in the run configuration, then the application 
-will <em>always</em> be deployed to that AVD. If it's not already running, then a new emulator
-will be launched.</p>
-
-<p>If your run configuration uses <strong>manual</strong> mode, then the "device chooser" 
-is presented every time that your application is run, so that you can select which AVD to use.</p>
-
-
-<h2 id="Signing">Signing your Applications</h2>
-
-<p>As you begin developing Android applications, understand that all
-Android applications must be digitally signed before the system will install
-them on an emulator or an actual device. There are two ways to do this:
-with a debug key (for immediate testing on an emulator or development device)
-or with a private key (for application distribution).</p>
-
-<p>The ADT plugin helps you get started quickly by signing your .apk files with
-a debug key, prior to installing them on an emulator or development device. This means that you can
-quickly run your application from Eclipse without having to
-generate your own private key. No specific action on your part is needed, 
-provided ADT has access to Keytool.However, please note that if you intend
-to publish your application, you <strong>must</strong> sign the application with your
-own private key, rather than the debug key generated by the SDK tools.</p>
-
-<p>Please read <a href="{@docRoot}guide/publishing/app-signing.html">Signing Your
-Applications</a>, which provides a thorough guide to application signing on Android
-and what it means to you as an Android application developer. The document also includes
-a guide to exporting and signing your application with the ADT's Export Wizard.</p>
-
-
-<h2 id="libraryProject">Working with Library Projects</h2>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>Library project example code</h2>
-
-<p>The SDK includes an example application called TicTacToeMain that shows how a
-dependent application can use code and resources from an Android Library
-project. The TicTacToeMain application uses code and resources from an example
-library project called TicTacToeLib. 
-
-<p style="margin-top:1em;">To download the sample applications and run them as
-projects in your environment, use the <em>Android SDK and AVD Manager</em> to
-download the "Samples for SDK API 8" component into your SDK. </p>
-
-<p style="margin-top:1em;">For more information and to browse the code of the
-samples, see the <a
-href="{@docRoot}resources/samples/TicTacToeMain/index.html">TicTacToeMain
-application</a>.</p>
-</div>
-</div>
-
-<p>An Android <em>library project</em> is a development project that holds
-shared Android source code and resources. Other Android application projects can
-reference the library project and, at build time, include its compiled sources
-in their <code>.apk</code> files. Multiple application projects can reference
-the same library project and any single application project can reference
-multiple library projects. </p>
-
-<p>If you have source code and resources that are common to multiple application
-projects, you can move them to a library project so that it is easier to
-maintain across applications and versions. Here are some common scenarios in
-which you could make use of library projects: </p>
-
-<ul>
-<li>If you are developing multiple related applications that use some of the
-same components, you could move the redundant components out of their respective
-application projects and create a single, reuseable set of the same components
-in a library project. </li>
-<li>If you are creating an application that exists in both free and paid
-versions, you could move the part of the application that is common to both versions
-into a library project. The two dependent projects, with their different package
-names, will reference the library project and provide only the difference
-between the two application versions.</li>
-</ul>
-
-<p>Structurally, a library project is similar to a standard Android application
-project. For example, it includes a manifest file at the project root, as well
-as <code>src/</code>, <code>res/</code> and similar directories. The project can
-contain the same types of source code and resources as a standard
-Android project, stored in the same way. For example, source code in the library
-project can access its own resources through its <code>R</code> class. </p>
-
-<p>However, a library project differs from an standard Android application
-project in that you cannot compile it directly to its own <code>.apk</code> or
-run it on the Android platform. Similarly, you cannot export the library project
-to a self-contained JAR file, as you would do for a true library. Instead, you
-must compile the library indirectly, by referencing the library from a dependent
-application's build path, then building that application. </p>
-
-<p>When you build an application that depends on a library project, the SDK
-tools compile the library and merge its sources with those in the main project,
-then use the result to generate the <code>.apk</code>. In cases where a resource
-ID is defined in both the application and the library, the tools ensure that the
-resource declared in the application gets priority and that the resource in the
-library project is not compiled into the application <code>.apk</code>. This
-gives your application the flexibility to either use or redefine any resource
-behaviors or values that are defined in any library.</p>
-
-<p>To organize your code further, your application can add references to
-multiple library projects, then specify the relative priority of the resources
-in each library. This lets you build up the resources actually used in your
-application in a cumulative manner. When two libraries referenced from an
-application define the same resource ID, the tools select the resource from the
-library with higher priority and discard the other. </p>
-
-<p>ADT lets you add references to library projects and set their relative
-priority from the application project's Properties. As shown in Figure 2,
-below, once you've added a reference to a library project, you can use the
-<strong>Up</strong> and <strong>Down</strong> controls to change the ordering,
-with the library listed at the top getting the higher priority. At build time,
-the libraries are merged with the application one at a time, starting from the
-lowest priority to the highest. </p>
-
-<p>Note that a library project cannot itself reference another library project
-and that, at build time, library projects are <em>not</em> merged with each
-other before being merged with the application. However, note that a library can
-import an external library (JAR) in the normal way.</p>
-
-<p>The sections below describe how to use ADT to set up and manage library your
-projects. Once you've set up your library projects and moved code into them, you
-can import library classes and resources to your application in the normal way.
-</p>
-
-
-<h3 id="libraryReqts">Development requirements</h3>
-
-<p>Android library projects are a build-time construct, so you can use them to
-build a final application <code>.apk</code> that targets any API level and is
-compiled against any version of the Android library. </p>
-
-<p>However, to use library projects, you need to update your development
-environment to use the latest tools and platforms, since older releases of the
-tools and platforms do not support building with library projects. Specifically,
-you need to download and install the versions listed below:</p>
-
-<p class="table-caption"><strong>Table 1.</strong> Minimum versions of SDK tools
-and plaforms on which you can develop library projects.</p>
-
-<table>
-<tr>
-<th>Component</th>
-<th>Minimum Version</th>
-</tr>
-<tr>
-<td>SDK Tools</td>
-<td>r6 (or higher)</td>
-</tr>
-<tr><td>Android 2.2 platform</td><td>r1 (or higher)</td></tr>
-<tr><td>Android 2.1 platform</td><td>r2 (or higher)</td></tr>
-<tr><td style="color:gray">Android 2.0.1 platform</td><td style="color:gray"><em>not supported</em></td></tr>
-<tr><td style="color:gray">Android 2.0 platform</td><td style="color:gray"><em>not supported</em></td></tr>
-<tr><td>Android 1.6 platform</td><td>r3 (or higher)</td></tr>
-<tr><td>Android 1.5 platform</td><td>r4 (or higher)</td></tr>
-<tr><td>ADT Plugin</td><td>0.9.7 (or higher)</td></tr>
-</table>
-
-<p>You can download the tools and platforms using the <em>Android SDK and AVD
-Manager</em>, as described in <a href="{@docRoot}sdk/adding-components.html">Adding SDK
-Components</a>. To install or update ADT, use the Eclipse Updater as described
-in <a href="{@docRoot}sdk/eclipse-adt.html">ADT Plugin for Eclipse</a>.</p>
-
-
-<h3 id="librarySetup">Setting up a library project</h3>
-
-<p>A library project is a standard Android project, so you can create a new one in the
-same way as you would a new application project. Specifically, you can use
-the New Project Wizard, as described in <a href="#CreatingAProject">Creating an
-Android Project</a>, above. </p>
-
-<p>When you are creating the library project, you can select any application
-name, package, and set other fields as needed, as shown in the diagram below.
-Click Finish to create the project in the workspace.</p>
-
-<p>Next, set the project's Properties to indicate that it is a library project:</p>
-
-<ol>
-<li>In the <strong>Package Explorer</strong>, right-click the library project
-and select <strong>Properties</strong>.</li>
-<li>In the <strong>Properties</strong> window, select the "Android" properties
-group at left and locate the <strong>Library</strong> properties at right. </li>
-<li>Select the "is Library" checkbox and click <strong>Apply</strong>.</li>
-<li>Click <strong>OK</strong> to close the <strong>Properties</strong> window.</li>
-</ol>
-
-<p>The new project is now marked as a library project. You can begin moving
-source code and resources into it, as described in the sections below. </p>
-
-<p>You can also convert an existing application project into a library. To do
-so, simply open the Properties for the project and select the "is Library"
-checkbox. Other application projects can now reference the existing project as a
-library project.</p>
-
-<img src="{@docRoot}images/developing/adt-props-isLib.png" style="margin:0;padding:0;" />
-<p class="img-caption" style="margin-left:3em;margin-bottom:2em;"><strong>Figure 1.</strong>
-Marking a project as an Android library project. </p>
-
-<h4>Creating the manifest file</h4>
-
-<p>A library project's manifest file must declare all of the shared components
-that it includes, just as would a standard Android application. For more
-information, see the documentation for <a
-href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>.</p>
-
-<p>For example, the <a
-href="{@docRoot}resources/samples/TicTacToeLib/AndroidManifest.html">TicTacToeLib</a>
-example library project declares the Activity <code>GameActivity</code>: </p>
-
-<pre>&lt;manifest&gt;
-  ...
-  &lt;application&gt;
-    ...
-    &lt;activity android:name="GameActivity" /&gt;
-    ...
-  &lt;/application&gt;
-&lt;/manifest&gt;</pre>
-
-
-<h3 id="libraryReference">Referencing a library project from an application</h3>
-
-<p>If you are developing an application and want to include the shared code or
-resources from a library project, you can do so easily by adding a reference to
-the library project in the application project's Properties.</p>
-
-<p>To add a reference to a library project, follow these steps: </p>
-
-<ol>
-<li>In the <strong>Package Explorer</strong>, right-click the dependent project
-and select <strong>Properties</strong>.</li>
-<li>In the <strong>Properties</strong> window, select the "Android" properties group
-at left and locate the <strong>Library</strong> properties at right.</li>
-<li>Click <strong>Add</strong> to open the <strong>Project Selection</strong>
-dialog. </li>
-<li>From the list of available library projects, select a project and click
-<strong>OK</strong>.</li>
-<li>When the dialog closes, click <strong>Apply</strong> in the
-<strong>Properties</strong> window.</li>
-<li>Click <strong>OK</strong> to close the <strong>Properties</strong> window.</li>
-</ol>
-
-<p>As soon as the Properties dialog closes, Eclipse rebuilds the project,
-including the contents of the library project. </p>
-
-<p>The figure below shows the Properties dialog that lets you add library
-references and move them up and down in priority. </p>
-
-<img src="{@docRoot}images/developing/adt-props-libRef.png" style="margin:0;padding:0;" />
-<p class="img-caption" style="margin-left:3em;margin-bottom:2em;"><strong>Figure 2.</strong>
-Adding a reference to a library project in the properties of an application project. </p>
-
-<p>If you are adding references to multiple libraries, note that you can set
-their relative priority (and merge order) by selecting a library and using the
-<strong>Up</strong> and <strong>Down</strong> controls. The tools merge the
-referenced libraries with your application starting from lowest priority (bottom
-of the list) to highest (top of the list). If more than one library defines the
-same resource ID, the tools select the resource from the library with higher
-priority. The application itself has highest priority and its resources are
-always used in preference to identical resource IDs defined in libraries.</p>
-
-<h4>Declaring library components in the the manifest file</h4>
-
-<p>In the manifest file of the application project, you must add declarations
-of all components that the application will use that are imported from a library
-project. For example, you must declare any <code>&lt;activity&gt;</code>,
-<code>&lt;service&gt;</code>, <code>&lt;receiver&gt;</code>,
-<code>&lt;provider&gt;</code>, and so on, as well as
-<code>&lt;permission&gt;</code>, <code>&lt;uses-library&gt;</code>, and similar
-elements.</p>
-
-<p>Declarations should reference the library components by their fully-qualified
-package names, where appropriate. </p>
-
-<p>For example, the <a 
-href="{@docRoot}resources/samples/TicTacToeMain/AndroidManifest.html">TicTacToeMain</a>
-example application declares the library Activity <code>GameActivity</code>
-like this: </p>
-
-<pre>&lt;manifest&gt;
-  ...
-  &lt;application&gt;
-    ...
-    &lt;activity android:name="com.example.android.tictactoe.library.GameActivity" /&gt;
-    ...
-  &lt;/application&gt;
-&lt;/manifest&gt;</pre>
-
-<p>For more information about the manifest file, see the documentation for <a
-href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>.</p>
-
-
-<h3 id="considerations">Development considerations</h3>
-
-<p>As you develop your library project and dependent applications, keep the 
-points listed below in mind.</p>
-
-<p><strong>Resource conflicts</strong></p>
-
-<p>Since the tools merge the resources of a library project with those of a
-dependent application project, a given resource ID might be defined in both
-projects. In this case, the tools select the resource from the application, or
-the library with highest priority, and discard the other resource. As you
-develop your applications, be aware that common resource IDs are likely to be
-defined in more than one project and will be merged, with the resource from the
-application or highest-priority library taking precedence.</p>
-
-<p><strong>Using prefixes to avoid resource conflicts</strong></p>
-
-<p>To avoid resource conflicts for common resource IDs, consider using a prefix
-or other consistent naming scheme that is unique to the project (or is  unique
-across all projects). </p>
-
-<p><strong>No export of library project to JAR</strong></p>
-
-<p>A library cannot be distributed as a binary file (such as a jar file). This
-is because the library project is compiled by the main project to use the
-correct resource IDs.</p>
-
-<p><strong>A library project can include a JAR library</strong></p>
-
-<p>You can develop a library project that itself includes a JAR library, however
-you need to manually edit the dependent application project's build path and add
-a path to the JAR file. </p>
-
-<p><strong>A library project can depend on an external JAR library</strong></p>
-
-<p>You can develop a library project that depends on an external library (for
-example, the Maps external library). In this case, the dependent application
-must build against a target that includes the external library (for example, the
-Google APIs Add-On). Note also that both the library project and the dependent
-application must declare the external library their manifest files, in a <a
-href="{@docRoot}guide/topics/manifest/uses-library-element.html"><code>&lt;uses-library&gt;</code></a>
-element. </p>
-
-<p><strong>Library project can not include raw assets</strong></p>
-
-<p>The tools do not support the use of raw asset files in a library project.
-Any asset resources used by an application must be stored in the 
-<code>assets/</code> directory of the application project
-itself.</p>
-
-<p><strong>Targeting different Android platform versions in library project and
-application project</strong></p>
-
-<p>A library is compiled as part of the dependent application project, so the
-API used in the library project must be compatible with the version of the
-Android library used to compile the application project. In general, the library
-project should use an <a href="{@docRoot}guide/appendix/api-levels.html">API level</a>
-that is the same as &mdash; or lower than &mdash; that used by the application.
-If the library project uses an API level that is higher than that of the
-application, the application project will fail to compile. It is perfectly
-acceptable to have a library that uses the Android 1.5 API (API level 3) and
-that is used in an Android 1.6 (API level 4) or Android 2.1 (API level 7)
-project, for instance.</p>
-
-<p><strong>No restriction on library package name</strong></p>
-
-<p>There is no requirement for the package name of a library to be the same as
-that of applications that use it.</p>
-
-<p><strong>Multiple R classes in gen/ folder of application project</strong></p>
-
-<p>When you build the dependent application project, the code of any libraries
-is compiled and merged to the application project. Each library has its own
-<code>R</code> class, named according to the library's package name. The
-<code>R</code> class generated from the resources of the main project and of the
-library is created in all the packages that are needed including the main
-project’s package and the libraries’ packages.</p>
-
-<p><strong>Testing a library project</strong></p>
-
-<p>There are two recommended ways of setting up testing on code and resources in
-a library project: </p>
-
-<ul>
-<li>You can set up a <a
-href="{@docRoot}guide/developing/testing/testing_otheride.html">test project</a>
-that instruments an application project that depends on the library project. You
-can then add tests to the project for library-specific features.</li>
-<li>You can set up a set up a standard application project that depends on the
-library and put the instrumentation in that project. This lets you create a
-self-contained project that contains both the tests/instrumentations and the
-code to test.</li>
-</ul>
-
-<p><strong>Library project storage location</strong></p>
-
-<p>There are no specific requirements on where you should store a library
-project, relative to a dependent application project, as long as the application
-project can reference the library project by a relative link. You can place the
-library project What is important is that the main project can reference the
-library project through a relative link.</p>
-
-<h3 id="libraryMigrating">Migrating library projects to ADT 0.9.8</h3>
-
-<p>This section provides information about how to migrate a library project
-created with ADT 0.9.7 to ADT 0.9.8 (or higher). The migration is needed only if
-you are developing in Eclipse with ADT and assumes that you have also upgraded
-to SDK Tools r7 (or higher). </p>
-
-<p>The way that ADT handles library projects has changed between
-ADT 0.9.7 and ADT 0.9.8. Specifically, in ADT 0.9.7, the <code>src/</code>
-source folder of the library was linked into the dependent application project
-as a folder that had the same name as the library project. This worked because
-of two restrictions on the library projects:</p>
-
-<ul>
-<li>The library was only able to contain a single source folder (excluding the
-special <code>gen/</code> source folder), and</li>
-<li>The source folder was required to have the name <code>src/</code> and be
-stored at the root of the project.</li>
-</ul>
-
-<p>In ADT 0.9.8, both of those restrictions were removed. A library project can
-have as many source folders as needed and each can have any name. Additionally,
-a library project can store source folders in any location of the project. For
-example, you could store sources in a <code>src/java/</code> directory. In order
-to support this, the name of the linked source folders in the main project are
-now called &lt;<em>library-name</em>&gt;_&lt;<em>folder-name</em>&gt; For
-example: <code>MyLibrary_src/</code> or <code>MyLibrary_src_java/</code>.</p>
-
-<p>Additionally, the linking process now flags those folders in order for ADT to
-recognize that it created them. This will allow ADT to automatically migrate the
-project to new versions of ADT, should they contain changes to the handling of
-library projects. ADT 0.9.7 did not flag the linked source folders, so ADT 0.9.8
-cannot be sure whether the old linked folders can be removed safely. After
-upgrading ADT to 0.9.8, you will need to remove the old linked folders manually
-in a simple two-step process, as described below.</p>
-
-<p>Before you begin, make sure to create a backup copy of your application or
-save the latest version to your code version control system. This ensures that
-you will be able to easily revert the migration changes in case there is a
-problem in your environment.</p>
-
-<p>When you first upgrade to ADT 0.9.8, your main project will look as shown
-below, with two linked folders (in this example, <code>MyLibrary</code> and
-<code>MyLibrary_src</code> &mdash; both of which link to
-<code>MyLibrary/src</code>. Eclipse shows an error on one of them because they
-are duplicate links to a single class.</p>
-
-<img src="{@docRoot}images/developing/lib-migration-0.png" alt="">
-
-<p>To fix the error, remove the linked folder that <em>does not</em> contain the
-<code>_src</code> suffix. </p>
-
-<ol>
-<li>Right click the folder that you want to remove (in this case, the
-<code>MyLibrary</code> folder) and choose <strong>Build Path</strong> &gt;
-<strong>Remove from Build Path</strong>, as shown below.</li>
-
-<img src="{@docRoot}images/developing/lib-migration-1.png" style="height:600px"
-alt="">
-
-<li>Next, When asked about unlinking the folder from the project, select
-<strong>Yes</strong>, as shown below.</li>
-
-<img src="{@docRoot}images/developing/lib-migration-2.png" alt="">
-</ol>
-
-<p>This should resolve the error and migrate your library project to the new
-ADT environment. </p>
-
-<h2 id="Tips">Eclipse Tips</h2>
-
-<h3 id="arbitraryexpressions">Executing arbitrary Java expressions in Eclipse</h3>
-
-<p>You can execute arbitrary code when paused at a breakpoint in Eclipse. For example,
-    when in a function with a String argument called &quot;zip&quot;, you can get
-    information about packages and call class methods. You can also invoke arbitrary
-    static methods: for example, entering <code>android.os.Debug.startMethodTracing()</code> will
-    start dmTrace. </p>
-<p>Open a code execution window, select <strong>Window</strong> &gt; <strong>Show
-        View</strong> &gt; <strong>Display</strong> from the main menu to open the
-        Display window, a simple text editor. Type your expression, highlight the
-        text, and click the 'J' icon (or CTRL + SHIFT + D) to run your
-        code. The code runs in the context of the selected thread, which must be
-        stopped at a breakpoint or single-step point. (If you suspend the thread
-        manually, you have to single-step once; this doesn't work if the thread is
-        in Object.wait().)</p>
-<p>If you are currently paused on a breakpoint, you can simply highlight and execute
-    a piece of source code by pressing CTRL + SHIFT + D. </p>
-<p>You can highlight a block of text within the same scope by pressing ALT +SHIFT
-    + UP ARROW to select larger and larger enclosing blocks, or DOWN ARROW to select
-    smaller blocks. </p>
-<p>Here are a few sample inputs and responses in Eclipse using the Display window.</p>
-
-<table width="100%" border="1">
-    <tr>
-        <th scope="col">Input</th>
-        <th scope="col">Response</th>
-    </tr>
-    <tr>
-        <td><code>zip</code></td>
-        <td><code>(java.lang.String) 
-        /work/device/out/linux-x86-debug/android/app/android_sdk.zip</code></td>
-    </tr>
-    <tr>
-        <td><code>zip.endsWith(&quot;.zip&quot;)</code></td>
-        <td><code>(boolean) true</code></td>
-    </tr>
-    <tr>
-        <td><code>zip.endsWith(&quot;.jar&quot;)</code></td>
-        <td><code>(boolean) false</code></td>
-    </tr>
-</table>
-<p>You can also execute arbitrary code when not debugging by using a scrapbook page.
-    Search the Eclipse documentation for &quot;scrapbook&quot;.</p>
-
-
-<h3>Running DDMS Manually</h3>
-
-<p>Although the recommended way to debug is to use the ADT plugin, you can manually run 
-DDMS and configure Eclipse to debug on port 8700. (<strong>Note: </strong>Be sure that you 
-have first started <a href="{@docRoot}guide/developing/tools/ddms.html">DDMS</a>). </p>
-
-
-
-
-<!-- TODO: clean this up and expand it to cover more wizards and features
-<h3>ADT Wizards</h3>
-
-<p>Notice that the "New Android Project" wizard has been expanded to use the multi-platform
-capabilities of the new SDK.</p>
-
-<p>There is now a "New XML File" wizard that lets you create skeleton XML resource
-files for your Android projects. This makes it easier to create a new layout, a new menu, a
-new strings file, etc.</p>
-
-<p>Both wizards are available via <strong>File > New</strong> and new icons in the main
-Eclipse toolbar (located to the left of the Debug and Run icons). 
-If you do not see the new icons, you may need to select <strong>Window > Reset
-Perspective</strong> from the Java perspective.</p>
--->
diff --git a/docs/html/guide/developing/index.jd b/docs/html/guide/developing/index.jd
new file mode 100644
index 0000000..f19f97e
--- /dev/null
+++ b/docs/html/guide/developing/index.jd
@@ -0,0 +1,116 @@
+page.title=Overview
+@jd:body
+
+<p>Developing applications for Android devices is facilitated by a group of tools that are
+  provided with the SDK. You can access these tools through an Eclipse plugin called ADT (Android
+  Development Tools) or from the command line. Developing with Eclipse is the preferred method because
+  it can directly invoke the tools that you need while developing applications.</p>
+
+  <p>However, you may choose to develop with another IDE or a simple text editor and invoke the
+  tools on the command line or with scripts. This is a less streamlined way to develop because you
+  will sometimes have to call command line tools manually, but you will have access to the same
+  amount of features that you would have in Eclipse.</p>
+
+  <p>The basic steps for developing applications with or without Eclipse are the same:</p>
+
+  <ol>
+    <li>Install Eclipse or your own IDE.
+
+      <p>Install Eclipse along with <a href="{@docRoot}sdk/eclipse-adt.html#installing">the ADT
+      Plugin</a>, or install an editor of your choice if you want to use the command line SDK tools.
+      If you are already developing applications, be sure to <a href= 
+      "{@docRoot}sdk/eclipse-adt.html#updating">update Your ADT Plugin</a> to the latest version
+      before continuing.</p>
+    </li>
+
+    <li>Set up Android Virtual Devices or hardware devices</a>.
+
+      <p>You need to create Android Virtual Devices (AVD) or connect hardware devices on which
+      you will install your applications.</p>
+      
+      <p>See <a href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</a>
+      and <a href="{@docRoot}guide/developing/device.html">Connecting Hardware Devices</a> for more information.
+    </li>
+
+    <li>
+      <a href="{@docRoot}guide/developing/projects/index.html">Create an Android project</a>.
+
+      <p>An Android project contains all source code and resource files for your application. It is
+      built into an <code>.apk</code> package that you can install on Android devices.</p>
+    </li>
+
+    <li>
+      <a href="{@docRoot}guide/developing/building/index.html">Build and run your
+      application</a>.
+
+      <p>If you are using Eclipse, builds are generated each time you save changes and you can install
+      your application on a device by clicking <strong>Run</strong>. If you're using another IDE, you can build your
+      project using Ant and install it on a device using <code>adb</code>.</p>
+    </li>
+
+    <li>
+      <a href="{@docRoot}guide/developing/debugging/index.html">Debug your application with the
+      SDK debugging and logging tools</a>.
+
+      <p>Debugging your application involves using a JDWP-compliant debugger along with the
+      debugging and logging tools that are provided with the Android SDK. Eclipse already
+      comes packaged with a compatible debugger.</p>
+    </li>
+
+    <li>
+      <a href="{@docRoot}guide/developing/testing/index.html">Test your application with the
+      Testing and Instrumentation framework</a>.
+
+      <p>The Android SDK provides a testing and instrumnetation framework to help you set up and
+      run tests within an emulator or device.</p>
+    </li>
+  </ol>
+
+  <h2 id="EssentialTools">Essential command line tools</h2>
+
+  <p>When developing in IDEs or editors other than Eclipse, be familiar with
+  all of the tools below, because you will have to run them from the command line.</p>
+
+  <dl>
+    <dt><a href="{@docRoot}guide/developing/tools/android.html">android</a></dt>
+
+    <dd>Create and update Android projects and create, move, and delete AVDs.</dd>
+
+    <dt><a href="{@docRoot}guide/developing/devices/emulator.html">Android Emulator</a></dt>
+
+    <dd>Run your Android applications on an emulated Android platform.</dd>
+
+    <dt><a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a></dt>
+
+    <dd>Interface with your emulator or connected device (install apps, shell the device, issue
+    commands, etc.).</dd>
+  </dl>
+
+  <p>In addition to the above tools that are included with the SDK, you need the following open
+  source and third-party tools:</p>
+
+  <dl>
+    <dt>Ant</dt>
+
+    <dd>To compile and build your Android project into an installable .apk file.</dd>
+
+    <dt>Keytool</dt>
+
+    <dd>To generate a keystore and private key, used to sign your .apk file. Keytool is part of the
+    JDK.</dd>
+
+    <dt>Jarsigner (or similar signing tool)</dt>
+
+    <dd>To sign your .apk file with a private key generated by keytool. Jarsigner is part of the
+    JDK.</dd>
+  </dl>
+  
+  <p>If you are using Eclipse and ADT, tools such as <code>adb</code> and the <code>android</code>
+  are called by Eclipse and ADT under the hood or similar functionality is provided within Eclipse.
+  You need to be familiar with <code>adb</code>, however, because certain functions are not accessible from
+  Eclipse, such as the <code>adb</code> shell commands. You might also need to call Keytool and Jarsigner to
+  sign your applications, but you can set up Eclipse to do this automatically as well.</p>
+  
+  <p>For more information on the tools provided with the Android SDK, see the
+  <a href="{@docRoot}guide/developing/tools/index.html">Tools</a> section of the documentation.</p>
+
diff --git a/docs/html/guide/developing/other-ide.html b/docs/html/guide/developing/other-ide.html
new file mode 100644
index 0000000..41dba05
--- /dev/null
+++ b/docs/html/guide/developing/other-ide.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0;url=http://developer.android.com/guide/developing/projects/projects-cmdline.html">
+<title>Redirecting...</title>
+</head>
+<body>
+<p>You should be redirected. Please <a
+href="http://developer.android.com/guide/developing/projects/projects-cmdline.html">click here</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/guide/developing/other-ide.jd b/docs/html/guide/developing/other-ide.jd
deleted file mode 100644
index 234b18f..0000000
--- a/docs/html/guide/developing/other-ide.jd
+++ /dev/null
@@ -1,936 +0,0 @@
-page.title=Developing In Other IDEs
-@jd:body
-
-<div id="qv-wrapper">
-<div id="qv">
-  <h2>In this document</h2>
-  <ol>
-    <li><a href="#CreatingAProject">Creating an Android Project</a></li>
-    <li><a href="#Signing">Preparing to Sign Your Application</a></li>
-    <li><a href="#Building">Building Your Application</a>
-      <ol>
-        <li><a href="#DebugMode">Building in debug mode</a></li>
-        <li><a href="#ReleaseMode">Building in release mode</a></li>
-      </ol>
-    </li>
-    <li><a href="#AVD">Creating an AVD</a></li>
-    <li><a href="#Running">Running Your Application</a>
-      <ol>
-        <li><a href="#RunningOnEmulator">Running on the emulator</a></li>
-        <li><a href="#RunningOnDevice">Running on a device</a></li>
-      </ol>
-    </li>
-    <li><a href="#libraryProject">Working with Library Projects</a>
-      <ol>
-        <li><a href="#libraryReqts">Development requirements</a></li>
-        <li><a href="#librarySetup">Setting up a library project</a></li>
-        <li><a href="#libraryReference">Referencing a library project</a></li>
-        <li><a href="#depAppBuild">Building a dependent application project</a></li>
-        <li><a href="#considerations">Development considerations</a></li>
-      </ol>
-    </li>
-    <li><a href="#AttachingADebugger">Attaching a Debugger to Your Application</a></li>
-  </ol>
-
-  <h2>See also</h2>
-  <ol>
-    <li><a href="{@docRoot}guide/developing/tools/othertools.html#android">android Tool</a></li>
-    <li><a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a></li>
-    <li><a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a></li>
-  </ol>
-</div>
-</div>
-
-<p>The recommended way to develop an Android application is to use 
-<a href="{@docRoot}guide/developing/eclipse-adt.html">Eclipse with the ADT plugin</a>.
-The ADT plugin provides editing, building, debugging, and .apk packaging and signing functionality 
-integrated right into the IDE.</p>
-
-<p>However, if you'd rather develop your application in another IDE, such as IntelliJ,
-or in a basic editor, such as Emacs, you can do that instead. The SDK
-includes all the tools you need to set up an Android project, build it, debug it and then
-package it for distribution. This document is your guide to using these tools.</p>
-
-
-<h2 id="EssentialTools">Essential Tools</h2>
-
-<p>When developing in IDEs or editors other than Eclipse, you'll require
-familiarity with the following Android SDK tools:</p>
-
-<dl>
-  <dt><a href="{@docRoot}guide/developing/tools/othertools.html#android">android</a></dt>
-    <dd>To create/update Android projects and to create/move/delete AVDs.</dd>
-  <dt><a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a></dt>
-    <dd>To run your Android applications on an emulated Android platform.</dd>
-  <dt><a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a></dt>
-    <dd>To interface with your emulator or connected device (install apps,
-    shell the device, issue commands, etc.).
-    </dd>
-</dl>
-
-<p>In addition to the above tools, included with the SDK, you'll use the following
-open source and third-party tools:</p>
-
-<dl>
-  <dt>Ant</dt>
-    <dd>To compile and build your Android project into an installable .apk file.</dd>
-  <dt>Keytool</dt>
-    <dd>To generate a keystore and private key, used to sign your .apk file.</dd>
-  <dt>Jarsigner (or similar signing tool)</dt>
-    <dd>To sign your .apk file with a private key generated by keytool.</dd>
-</dl>
-
-<p>In the topics that follow, you'll be introduced to each of these tools as necessary.
-For more advanced operations, please read the respective documentation for each tool.</p>
-
-
-<h2 id="CreatingAProject">Creating an Android Project</h2>
-
-<p>To create an Android project, you must use the <code>android</code> tool. When you create
-a new project with <code>android</code>, it will generate a project directory
-with some default application files, stub files, configuration files and a build file.</p>
-
-
-<h3 id="CreatingANewProject">Creating a new Project</h3>
-
-<p>If you're starting a new project, use the <code>android create project</code>
-command to generate all the necessary files and folders.</p>
-
-<p>To create a new Android project, open a command-line,
-navigate to the <code>tools/</code> directory of your SDK and run:</p>
-<pre>
-android create project \
---target <em>&lt;target_ID&gt;</em> \
---name <em>&lt;your_project_name&gt;</em> \
---path <em>path/to/your/project</em> \
---activity <em>&lt;your_activity_name&gt;</em> \
---package <em>&lt;your_package_namespace&gt;</em>
-</pre>
-
-<ul>
-  <li><code>target</code> is the "build target" for your application. It corresponds
-  to an Android platform library (including any add-ons, such as Google APIs) that you would like to
-  build your project against. To see a list of available targets and their corresponding IDs, 
-  execute: <code>android list targets</code>.</li>
-  <li><code>name</code> is the name for your project. This is optional. If provided, this name will
-be used
-  for your .apk filename when you build your application.</li>
-  <li><code>path</code> is the location of your project directory. If the directory does not exist,
-  it will be created for you.</li>
-  <li><code>activity</code> is the name for your default {@link android.app.Activity} class. This
-class file
-  will be created for you inside 
- 
-<code><em>&lt;path_to_your_project&gt;</em>/src/<em>&lt;your_package_namespace_path&gt;</em>/</code>
-.
-  This will also be used for your .apk filename unless you provide a the <code>name</code>.</li>
-  <li><code>package</code> is the package namespace for your project, following the same rules as
-for
-  packages in the Java programming language.</li>
-</ul>
-
-<p>Here's an example:</p>
-<pre>
-android create project \
---target 1 \
---name MyAndroidApp \
---path ./MyAndroidAppProject \
---activity MyAndroidAppActivity \
---package com.example.myandroid
-</pre>
-
-<p>The tool generates the following files and directories:</p>
-
-<ul>
-  <li><code>AndroidManifest.xml</code> - The application manifest file, 
-  synced to the specified Activity class for the project.</li>
-  <li><code>build.xml</code> - Build file for Ant.</li>
-  <li><code>default.properties</code> - Properties for the build system. <em>Do not modify 
-  this file</em>.</li>
-  <li><code>build.properties</code> - Customizable properties for the build system. You can edit
-this
-  file to override default build settings used by Ant and provide a pointer to your keystore and key
-alias
-  so that the build tools can sign your application when built in release mode.</li>
-  <li><code>src<em>/your/package/namespace/ActivityName</em>.java</code> - The Activity class 
-  you specified during project creation.</li>
-  <li><code>bin/</code>  - Output directory for the build script.</li>
-  <li><code>gen/</code>  - Holds <code>Ant</code>-generated files, such as <code>R.java</code>.
-</li>
-  <li><code>libs/</code>  - Holds private libraries.</li>
-  <li><code>res/</code>  - Holds project resources.</li>
-  <li><code>src/</code>  - Holds source code.</li>
-  <li><code>tests/</code>  - Holds a duplicate of all-of-the-above, for testing purposes.</li>
-</ul>
-
-<p>Once you've created your project, you're ready to begin development.
-You can move your project folder wherever you want for development, but keep in mind
-that you must use the <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> 
-(adb) &mdash; located in the SDK <code>tools/</code> directory &mdash; to send your application 
-to the emulator (discussed later). So you need access between your project solution and 
-the <code>tools/</code> folder.</p>
-
-<p class="caution"><strong>Caution:</strong> You should refrain from moving the
-location of the SDK directory, because this will break the build scripts. (They
-will need to be manually updated to reflect the new SDK location before they will
-work again.)</p>
-
-
-<h3 id="UpdatingAProject">Updating a project</h3>
-
-<p>If you're upgrading a project from an older version of the Android SDK or want to create
-a new project from existing code, use the
-<code>android update project</code> command to update the project to the new development
-environment. You can also use this command to revise the build target of an existing project
-(with the <code>--target</code> option) and the project name (with the <code>--name</code> 
-option). The <code>android</code> tool will generate any files and 
-folders (listed in the previous section) that are either missing or need to be updated, 
-as needed for the Android project.</p>
-
-<p>To update an existing Android project, open a command-line
-and navigate to the <code>tools/</code> directory of your SDK. Now run:</p>
-<pre>
-android update project --name <em>&lt;project_name&gt;</em> --target <em>&lt;target_ID&gt;</em>
---path <em>&lt;path_to_your_project&gt;</em>
-</pre>
-
-<ul>
-  <li><code>target</code> is the "build target" for your application. It corresponds to 
-  an Android platform library (including any add-ons, such as Google APIs) that you would 
-  like to build your project against. To see a list of available targets and their corresponding
-IDs,
-  execute: <code>android list targets</code>.</li>
-  <li><code>path</code> is the location of your project directory.</li>
-  <li><code>name</code> is the name for the project. This is optional&mdash;if you're not 
-  changing the project name, you don't need this.</li>
-</ul>
-
-<p>Here's an example:</p>
-<pre>
-android update project --name MyApp --target 2 --path ./MyAppProject
-</pre>
-
-
-<h2 id="Signing">Preparing to Sign Your Application</h2>
-
-<p>As you begin developing Android applications, understand that all
-Android applications must be digitally signed before the system will install
-them on an emulator or device. There are two ways to do this:
-with a <em>debug key</em> (for immediate testing on an emulator or development device)
-or with a <em>private key</em> (for application distribution).</p>
-
-<p>The Android build tools help you get started by automatically signing your .apk
-files with a debug key at build time. This means
-that you can compile your application and install it on the emulator without
-having to generate your own private key. However, please note that if you intend
-to publish your application, you <strong>must</strong> sign the application with your
-own private key, rather than the debug key generated by the SDK tools. </p>
-
-<p>Please read <a href="{@docRoot}guide/publishing/app-signing.html">Signing Your
-Applications</a>, which provides a thorough guide to application signing on Android
-and what it means to you as an Android application developer.</p>
-
-
-
-<h2 id="Building">Building Your Application</h2>
-
-<p>There are two ways to build your application: one for testing/debugging your application
-&mdash; <em>debug mode</em> &mdash; and one for building your final package for release &mdash; 
-<em>release mode</em>. As described in the previous
-section, your application must be signed before it can be installed on an emulator
-or device.</p>
-
-<p>Whether you're building in debug mode or release mode, you
-need to use the Ant tool to compile and build your project. This will create the .apk file
-that is installed onto the emulator or device. When you build in debug mode, the .apk
-file is automatically signed by the SDK tools with a debug key, so it's instantly ready for
-installation
-(but only onto an emulator or attached development device).
-When you build in release mode, the .apk file is <em>unsigned</em>, so you must manually
-sign it with your own private key, using Keytool and Jarsigner.</p>
-
-<p>It's important that you read and understand 
-<a href="{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>, particularly
-once you're ready to release your application and share it with end-users. That document describes
-the procedure for generating a private key and then using it to sign your .apk file.
-If you're just getting started, however, 
-you can quickly run your applications on an emulator or your own development device by building in
-debug mode.</p>
-
-<p>If you don't have Ant, you can obtain it from the 
-<a href="http://ant.apache.org/">Apache Ant home page</a>. Install it and make
-sure it is in your executable PATH. Before calling Ant, you need to declare the JAVA_HOME 
-environment variable to specify the path to where the JDK is installed.</p>
-
-<p class="note"><strong>Note:</strong> When installing JDK on Windows, the default is to install 
-in the "Program Files" directory. This location will cause <code>ant</code> to fail, because of 
-the space. To fix the problem, you can specify the JAVA_HOME variable like this: 
-<code>set JAVA_HOME=c:\Progra~1\Java\&lt;jdkdir&gt;</code>. The easiest solution, however, is to
-install JDK in a non-space directory, for example: <code>c:\java\jdk1.6.0_02</code>.</p>
-
-
-<h3 id="DebugMode">Building in debug mode</h3>
-
-<p>For immediate application testing and debugging, you can build your application 
-in debug mode and immediately install it on an emulator. In debug mode, the build tools 
-automatically sign your application with a debug key and optimize the package with 
-{@code zipalign}. However, you can (and should) also test your
-application in release mode. Debug mode simply allows you to run your application without
-manually signing the application.</p>
-
-<p>To build in debug mode:</p>
-
-<ol>
-  <li>Open a command-line and navigate to the root of your project directory.</li>
-  <li>Use Ant to compile your project in debug mode:
-    <pre>ant debug</pre>
-    <p>This creates your debug .apk file inside the project <code>bin/</code>
-    directory, named <code><em>&lt;your_project_name&gt;</em>-debug.apk</code>. The file
-    is already signed with the debug key and has been aligned with {@code zipalign}.</p>
-  </li>
-</ol>
-
-<p>Each time you change a source file or resource, you must run Ant 
-again in order to package up the latest version of the application.</p>
-
-<p>To install and run your application on an emulator, see the following section
-about <a href="#Running">Running Your Application</a>.</p>
-
-
-<h3 id="ReleaseMode">Building in release mode</h3>
-
-<p>When you're ready to release and distribute your application to end-users, you must build
-your application in release mode. Once you have built in release mode, it's a good idea to perform 
-additional testing and debugging with the final .apk.</p>
-
-<p>Before you start building your application in release mode, be aware that you must sign
-the resulting application package with your private key, and should then align it using the
-{@code zipalign} tool. There are two approaches to building in release mode:
-build an unsigned package in release mode and then manually sign and align 
-the package, or allow the build script
-to sign and align the package for you.</p>
-
-<h4 id="ManualReleaseMode">Build unsigned</h4>
-
-<p>If you build your application <em>unsigned</em>, then you will need to
-manually sign and align the package.</p>
-
-<p>To build an <em>unsigned</em> .apk in release mode:</p>
-
-<ol>
-  <li>Open a command-line and navigate to the root of your project directory.</li>
-  <li>Use Ant to compile your project in release mode:
-    <pre>ant release</pre>
-  </li>
-</ol>
-
-<p>This creates your Android application .apk file inside the project <code>bin/</code>
-directory, named <code><em>&lt;your_project_name&gt;</em>-unsigned.apk</code>.</p>
-    
-<p class="note"><strong>Note:</strong> The .apk file is <em>unsigned</em> at this point 
-and can't be installed until signed with your private key.</p>
-
-<p>Once you have created the unsigned .apk, your next step is to sign the .apk
-with your private key and then align it with {@code zipalign}. To complete this procedure, 
-read <a href="{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>.</p>
-
-<p>When your .apk has been signed and aligned, it's ready to be distributed to end-users.</p>
-
-<h4 id="AutoReleaseMode">Build signed and aligned</h4>
-
-<p>If you would like, you can configure the Android build script to automatically
-sign and align your application package. To do so, you must provide the path to your keystore 
-and the name of your key alias in your project's {@code build.properties} file. With this
-information provided, the build script will prompt you for your keystore and alias password
-when you build in release mode and produce your final application package, which will be ready
-for distribution.</p>
-
-<p class="caution"><strong>Caution:</strong> Due to the way Ant handles input, the password that
-you enter during the build process <strong>will be visible</strong>. If you are
-concerned about your keystore and alias password being visible on screen, then you
-may prefer to perform the application signing manually, via Jarsigner (or a similar tool). To
-instead
-perform the signing procedure manually, <a href="#ManualReleaseMode">build unsigned</a> and then
-continue
-with <a href="{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a>.</p>
-
-<p>To specify your keystore and alias, open the project {@code build.properties} file (found in the
-root of the project directory) and add entries for {@code key.store} and {@code key.alias}. 
-For example:</p>
-
-<pre>
-key.store=path/to/my.keystore
-key.alias=mykeystore
-</pre>
-
-<p>Save your changes. Now you can build a <em>signed</em> .apk in release mode:</p>
-
-<ol>
-  <li>Open a command-line and navigate to the root of your project directory.</li>
-  <li>Use Ant to compile your project in release mode:
-    <pre>ant release</pre>
-  </li>
-  <li>When prompted, enter you keystore and alias passwords.
-    <p class="caution"><strong>Caution:</strong> As described above, 
-    your password will be visible on the screen.</p>
-  </li>
-</ol>
-
-<p>This creates your Android application .apk file inside the project <code>bin/</code>
-directory, named <code><em>&lt;your_project_name&gt;</em>-release.apk</code>.
-This .apk file has been signed with the private key specified in
-{@code build.properties} and aligned with {@code zipalign}. It's ready for 
-installation and distribution.</p>
-
-
-<h4>Once built and signed in release mode</h4>
-
-<p>Once you have signed your application with a private key, you can install it on an 
-emulator or device as discussed in the following section about 
-<a href="#Running">Running Your Application</a>.
-You can also try installing it onto a device from a web server.
-Simply upload the signed APK to a web site, then load the .apk URL in your Android web browser to 
-download the application and begin installation.
-(On your device, be sure you have enabled <em>Settings > Applications > Unknown sources</em>.)</p>
-
-
-<h2 id="AVD">Creating an AVD</h2>
-
-<p>An Android Virtual Device (AVD) is a device configuration for the emulator that
-allows you to model real world devices. In order to run an instance of the emulator, you must create
-an AVD.</p>
-
-<p>To create an AVD using the SDK tools:</p>
-
-<ol>
-  <li>Navigate to your SDK's <code>tools/</code> directory and execute the {@code android}
-tool with no arguments:
-    <pre>android</pre>
-    <p>This will launch the SDK and AVD Manager GUI.</p>
-  </li>
-  <li>In the <em>Virtual Devices</em> panel, you'll see a list of existing AVDs. Click
-<strong>New</strong>
-  to create a new AVD.</li>
-  <li>Fill in the details for the AVD.
-    <p>Give it a name, a platform target, an SD card size, and
-    a skin (HVGA is default).</p>
-    <p class="note"><strong>Note:</strong> Be sure to define
-    a target for your AVD that satisfies your application's build target (the AVD
-    platform target must have an API Level equal to or greater than the API Level that your
-application compiles against).</p>
-  </li>
-  <li>Click <strong>Create AVD</strong>.</li>
-</ol>
-
-<p>Your AVD is now ready and you can either close the AVD Manager, create more AVDs, or
-launch an emulator with the AVD by clicking <strong>Start</strong>.</p>
-
-<p>For more information about AVDs, read the
-<a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a>
-documentation.</p>
-
-
-<h2 id="Running">Running Your Application</h2>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>Use the Emulator to Test Different Configurations</h2>
-<p>Create multiple AVDs that each define a different device configuration with which your
-application is compatible, then launch each AVD into a new emulator from the SDK and AVD Manager.
-Set the target mode in your app's run configuration to manual, so that when you run your
-application, you can select from the available virtual devices.</p>
-</div>
-</div>
-
-<p>Running your application on a virtual or real device takes just a couple steps. Remember to
-first <a href="#Building">build your application</a>.</p>
-
-<h3 id="RunningOnEmulator">Running on the emulator</h3>
-
-<p>Before you can run your application on the Android Emulator,
-you must <a href="#AVD">create an AVD</a>.</p>
-
-<p>To run your application:</p>
-<ol>
-  <li><strong>Open the SDK and AVD Manager and launch a virtual device</strong></li>
-    <p>From your SDK's <code>tools/</code> directory, execute the {@code android} tool with no
-arguments:
-    <pre>android</pre>
-    <p>In the <em>Virtual Devices</em> view, select an AVD and click <strong>Start</strong>.</p>
-  </li>
-
-  <li><strong>Install your application</strong>
-    <p>From your SDK's <code>tools/</code> directory, install the {@code .apk} on the
-emulator:
-    <pre>adb install <em>&lt;path_to_your_bin&gt;</em>.apk</pre>
-    <p>Your APK file (signed with either a release or debug key) is in your project {@code bin/}
-directory after you <a href="#Building">build your application</a>.</p>
-    <p>If there is more than one emulator running, you must specify the emulator upon which to
-install the application, by its serial number, with the <code>-s</code> option. For example:</p>
-    <pre>adb -s emulator-5554 install <em>path/to/your/app</em>.apk</pre>
-    <p>To see a list of available device serial numbers, execute {@code adb devices}.</p>
-  </li>
-</ol>
-
-<p>If you don't see your application on the emulator. Try closing the emulator and launching the
-virtual device again from the SDK and AVD Manager. Sometimes when you install an Activity for the
-first time, it won't show up in the application launcher or be accessible by other 
-applications. This is because the package manager usually examines manifests 
-completely only on emulator startup.</p>
-
-<p>Be certain to create multiple AVDs upon which to test your application. You should have one AVD
-for each platform and screen type with which your application is compatible. For
-instance, if your application compiles against the Android 1.5 (API Level 3) platform, you should
-create an AVD for each platform equal to and greater than 1.5 and an AVD for each <a
-href="{@docRoot}guide/practices/screens_support.html">screen type</a> you support, then test
-your application on each one.</p>
-
-<p class="note"><strong>Tip:</strong> If you have <em>only one</em> emulator running,
-you can build your application and install it on the emulator in one simple step. 
-Navigate to the root of your project directory and use Ant to compile the project 
-with <em>install mode</em>:
-<code>ant install</code>. This will build your application, sign it with the debug key,
-and install it on the currently running emulator.</p>
-
-
-<h3 id="RunningOnDevice">Running on a device</h3>
-
-<p>Before you can run your application on a device, you must perform some basic setup for your
-device:</p>
-
-<ul>
-  <li>Declare your application as debuggable in your manifest</li>
-  <li>Enable USB Debugging on your device</li>
-  <li>Ensure that your development computer can detect your device when connected via USB</li>
-</ul>
-<p>Read <a href="{@docRoot}guide/developing/device.html#setting-up">Setting up a Device for
-Development</a> for more information.</p>
-
-<p>Once your device is set up and connected via USB, navigate to your
-SDK's <code>tools/</code> directory and install the <code>.apk</code> on the device:
-    <pre>adb -d install <em>path/to/your/app</em>.apk</pre>
-    <p>The {@code -d} flag specifies that you want to use the attached device (in case you also
-have an emulator running).</p>
-
-<p>For more information on the tools used above, please see the following documents:</p>
-<ul>
-  <li><a href="{@docRoot}guide/developing/tools/othertools.html#android">android Tool</a></li>
-  <li><a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a></li>
-  <li><a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> (ADB)</li>
-</ul>
-
-<h2 id="libraryProject">Working with Library Projects</h2>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>Library project example code</h2>
-
-<p>The SDK includes an example application called TicTacToeMain that shows how a
-dependent application can use code and resources from an Android Library
-project. The TicTacToeMain application uses code and resources from an example
-library project called TicTacToeLib. 
-
-<p style="margin-top:1em;">To download the sample applications and run them as
-projects in your environment, use the <em>Android SDK and AVD Manager</em> to
-download the "Samples for SDK API 8" component into your SDK. </p>
-
-<p style="margin-top:1em;">For more information and to browse the code of the
-samples, see the <a
-href="{@docRoot}resources/samples/TicTacToeMain/index.html">TicTacToeMain
-application</a>.</p>
-</div>
-</div>
-
-<p>An Android <em>library project</em> is a development project that holds
-shared Android source code and resources. Other Android application projects can
-reference the library project and, at build time, include its compiled sources
-in their <code>.apk</code> files. Multiple application projects can reference
-the same library project and any single application project can reference
-multiple library projects. </p>
-
-<p>If you have source code and resources that are common to multiple application
-projects, you can move them to a library project so that it is easier to
-maintain across applications and versions. Here are some common scenarios in
-which you could make use of library projects: </p>
-
-<ul>
-<li>If you are developing multiple related applications that use some of the
-same components, you could move the redundant components out of their respective
-application projects and create a single, reuseable set of the same components
-in a library project. </li>
-<li>If you are creating an application that exists in both free and paid
-versions, you could move the part of the application that is common to both versions
-into a library project. The two dependent projects, with their different package
-names, will reference the library project and provide only the difference
-between the two application versions.</li>
-</ul>
-
-<p>Structurally, a library project is similar to a standard Android application
-project. For example, it includes a manifest file at the project root, as well
-as <code>src/</code>, <code>res/</code> and similar directories. The project can
-contain the same types of source code and resources as a standard
-Android project, stored in the same way. For example, source code in the library
-project can access its own resources through its <code>R</code> class. </p>
-
-<p>However, a library project differs from an standard Android application
-project in that you cannot compile it directly to its own <code>.apk</code> or
-run it on the Android platform. Similarly, you cannot export the library project
-to a self-contained JAR file, as you would do for a true library. Instead, you
-must compile the library indirectly, by referencing the library from a dependent
-application's build path, then building that application. </p>
-
-<p>When you build an application that depends on a library project, the SDK
-tools compile the library and merge its sources with those in the main project,
-then use the result to generate the <code>.apk</code>. In cases where a resource
-ID is defined in both the application and the library, the tools ensure that the
-resource declared in the application gets priority and that the resource in the
-library project is not compiled into the application <code>.apk</code>. This
-gives your application the flexibility to either use or redefine any resource
-behaviors or values that are defined in any library.</p>
-
-<p>To organize your code further, your application can add references to
-multiple library projects, then specify the relative priority of the resources
-in each library. This lets you build up the resources actually used in your
-application in a cumulative manner. When two libraries referenced from an
-application define the same resource ID, the tools select the resource from the
-library with higher priority and discard the other. 
-
-<p>Once you've have added references, the tools let you set their relative
-priority by editing the application project's build properties. At build time,
-the tools merge the libraries with the application one at a time, starting from
-the lowest priority to the highest. </p>
-
-<p>Note that a library project cannot itself reference another library project
-and that, at build time, library projects are <em>not</em> merged with each
-other before being merged with the application. However, note that a library can
-import an external library (JAR) in the normal way.</p>
-
-<p>The sections below describe how to use ADT to set up and manage library your
-projects. Once you've set up your library projects and moved code into them, you
-can import library classes and resources to your application in the normal way.
-</p>
-
-
-<h3 id="libraryReqts">Development requirements</h3>
-
-<p>Android library projects are a build-time construct, so you can use them to
-build a final application <code>.apk</code> that targets any API level and is
-compiled against any version of the Android library. </p>
-
-<p>However, to use library projects, you need to update your development
-environment to use the latest tools and platforms, since older releases of the
-tools and platforms do not support building with library projects. Specifically,
-you need to download and install the versions listed below:</p>
-
-<p class="table-caption"><strong>Table 1.</strong> Minimum versions of SDK tools
-and plaforms on which you can develop library projects.</p>
-
-<table>
-<tr>
-<th>Component</th>
-<th>Minimum Version</th>
-</tr>
-<tr>
-<td>SDK Tools</td>
-<td>r6 (or higher)</td>
-</tr>
-<tr><td>Android 2.2 platform</td><td>r1 (or higher)</td></tr>
-<tr><td>Android 2.1 platform</td><td>r2 (or higher)</td></tr>
-<tr><td style="color:gray">Android 2.0.1 platform</td><td style="color:gray"><em>not supported</em></td></tr>
-<tr><td style="color:gray">Android 2.0 platform</td><td style="color:gray"><em>not supported</em></td></tr>
-<tr><td>Android 1.6 platform</td><td>r3 (or higher)</td></tr>
-<tr><td>Android 1.5 platform</td><td>r4 (or higher)</td></tr>
-<tr><td>ADT Plugin</td><td>0.9.7 (or higher)</td></tr>
-</table>
-
-<p>You can download the tools and platforms using the <em>Android SDK and AVD
-Manager</em>, as described in <a href="{@docRoot}sdk/adding-components.html">Adding SDK
-Components</a>.</p>
-
-
-<h3 id="librarySetup">Setting up a new library project</h3>
-
-<p>A library project is a standard Android project, so you can create a new one in the
-same way as you would a new application project. Specifically, you can use
-the <code>android</code> tool to generate a new library project with all of the
-necessary files and folders. </p>
-
-<h4>Creating a library project</h4>
-
-<p>To create a new library project, navigate to the <code>&lt;sdk&gt;/tools/</code> directory
-and use this command:</p>
-
-<pre class="no-pretty-print" style="color:black">
-android create lib-project --name <em>&lt;your_project_name&gt;</em> \
---target <em>&lt;target_ID&gt;</em> \
---path <em>path/to/your/project</em> \
---package <em>&lt;your_library_package_namespace&gt;</em>
-</pre>
-
-<p>The <code>create lib-project</code> command creates a standard project
-structure that includes preset property that indicates to the build system that
-the project is a library. It does this by adding this line to the project's
-<code>default.properties</code> file: </p>
-
-<pre class="no-pretty-print" style="color:black">android.library=true</pre>
-
-<p>Once the command completes, the library project is created and you can begin moving
-source code and resources into it, as described in the sections below.</p>
-
-<p>If you want to convert an existing application project to a library project,
-so that other applications can use it, you can do so by adding a the 
-<code>android.library=true</code> property to the application's 
-<code>default.properties</code> file. </p>
-
-<h4>Creating the manifest file</h4>
-
-<p>A library project's manifest file must declare all of the shared components
-that it includes, just as would a standard Android application. For more
-information, see the documentation for <a
-href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>.</p>
-
-<p>For example, the <a
-href="{@docRoot}resources/samples/TicTacToeLib/AndroidManifest.html">TicTacToeLib</a>
-example library project declares the Activity <code>GameActivity</code>: </p>
-
-<pre>&lt;manifest&gt;
-  ...
-  &lt;application&gt;
-    ...
-    &lt;activity android:name="GameActivity" /&gt;
-    ...
-  &lt;/application&gt;
-&lt;/manifest&gt;</pre>
-
-<h4>Updating a library project</h4>
-
-<p>If you want to update the build properties (build target, location) of the
-library project, use this command: </p>
-
-<pre>
-android update lib-project \
---target <em>&lt;target_ID&gt;</em> \
---path <em>path/to/your/project</em>
-</pre>
-
-
-<h3 id="libraryReference">Referencing a library project from an application</h3>
-
-<p>If you are developing an application and want to include the shared code or
-resources from a library project, you can do so easily by adding a reference to
-the library project in the application project's build properties.</p>
-
-<p>To add a reference to a library project, navigate to the <code>&lt;sdk&gt;/tools/</code> directory
-and use this command:</p>
-
-<pre>
-android update lib-project \
---target <em>&lt;target_ID&gt;</em> \
---path <em>path/to/your/project</em>
---library <em>path/to/library_projectA</em>
-</pre>
-
-<p>This command updates the application project's build properties to include a
-reference to the library project. Specifically, it adds an
-<code>android.library.reference.<em>n</em></code> property to the project's
-<code>default.properties</code> file. For example: </p>
-
-<pre class="no-pretty-print" style="color:black">
-android.library.reference.1=path/to/library_projectA
-</pre>
-
-<p>If you are adding references to multiple libraries, note that you can set
-their relative priority (and merge order) by manually editing the
-<code>default.properties</code> file and adjusting the each reference's
-<code>.<em>n</em></code> index as appropriate. For example, assume these
-references: </p>
-
-<pre class="no-pretty-print" style="color:black">
-android.library.reference.1=path/to/library_projectA
-android.library.reference.2=path/to/library_projectB
-android.library.reference.3=path/to/library_projectC
-</pre>
-
-<p>You can reorder the references to give highest priority to
-<code>library_projectC</code> in this way:</p>
-
-<pre class="no-pretty-print" style="color:black">
-android.library.reference.2=path/to/library_projectA
-android.library.reference.3=path/to/library_projectB
-android.library.reference.1=path/to/library_projectC
-</pre>
-
-<p>Note that the <code>.<em>n</em></code> index in the references
-must begin at "1" and increase uniformly without "holes". References
-appearing in the index after a hole are ignored. </p>
-
-<p>At build time, the libraries are merged with the application one at a time,
-starting from the lowest priority to the highest. Note that a library cannot
-itself reference another library and that, at build time, libraries are not
-merged with each other before being merged with the application.</p>
-
-
-<h4>Declaring library components in the the manifest file</h4>
-
-<p>In the manifest file of the application project, you must add declarations
-of all components that the application will use that are imported from a library
-project. For example, you must declare any <code>&lt;activity&gt;</code>,
-<code>&lt;service&gt;</code>, <code>&lt;receiver&gt;</code>,
-<code>&lt;provider&gt;</code>, and so on, as well as
-<code>&lt;permission&gt;</code>, <code>&lt;uses-library&gt;</code>, and similar
-elements.</p>
-
-<p>Declarations should reference the library components by their fully-qualified
-package names, where appropriate. </p>
-
-<p>For example, the 
-<a href="{@docRoot}resources/samples/TicTacToeMain/AndroidManifest.html">TicTacToeMain</a>
-example application declares the library Activity <code>GameActivity</code>
-like this: </p>
-
-<pre>&lt;manifest&gt;
-  ...
-  &lt;application&gt;
-    ...
-    &lt;activity android:name="com.example.android.tictactoe.library.GameActivity" /&gt;
-    ...
-  &lt;/application&gt;
-&lt;/manifest&gt;</pre>
-
-<p>For more information about the manifest file, see the documentation for <a
-href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>.</p>
-
-<h3 id="depAppBuild">Building a dependent application</h3>
-
-<p>To build an application project that depends on one or more library projects,
-you can use the standard Ant build commands and compile modes, as described in
-<a href="#Building">Building Your Application</a>, earlier in this document. The
-tools compile and merge all libraries referenced by the application as part
-of compiling the dependent application project. No additional commands or steps
-are necessary. </p>
-
-<h3 id="considerations">Development considerations</h3>
-
-<p>As you develop your library project and dependent applications, keep the 
-points listed below in mind.</p>
-
-<p><strong>Resource conflicts</strong></p>
-
-<p>Since the tools merge the resources of a library project with those of a
-dependent application project, a given resource ID might be defined in both
-projects. In this case, the tools select the resource from the application, or
-the library with highest priority, and discard the other resource. As you
-develop your applications, be aware that common resource IDs are likely to be
-defined in more than one project and will be merged, with the resource from the
-application or highest-priority library taking precedence.</p>
-
-<p><strong>Using prefixes to avoid resource conflicts</strong></p>
-
-<p>To avoid resource conflicts for common resource IDs, consider using a prefix
-or other consistent naming scheme that is unique to the project (or is  unique
-across all projects). </p>
-
-<p><strong>No export of library project to JAR</strong></p>
-
-<p>A library cannot be distributed as a binary file (such as a jar file). This
-is because the library project is compiled by the main project to use the
-correct resource IDs.</p>
-
-<p><strong>A library project can include a JAR library</strong></p>
-
-<p>You can develop a library project that itself includes a JAR library. When
-you build the dependent application project, the tools automatically locate and
-include the library in the application <code>.apk</code>. </p>
-
-<p><strong>A library project can depend on an external JAR library</strong></p>
-
-<p>You can develop a library project that depends on an external library (for
-example, the Maps external library). In this case, the dependent application
-must build against a target that includes the external library (for example, the
-Google APIs Add-On). Note also that both the library project and the dependent
-application must declare the external library their manifest files, in a <a
-href="{@docRoot}guide/topics/manifest/uses-library-element.html"><code>&lt;uses-library&gt;</code></a>
-element. </p>
-
-<p><strong>Library project cannot include raw assets</strong></p>
-
-<p>The tools do not support the use of raw asset files in a library project.
-Any asset resources used by an application must be stored in the 
-<code>assets/</code> directory of the application project
-itself.</p>
-
-<p><strong>Targeting different Android platform versions in library project and
-application project</strong></p>
-
-<p>A library is compiled as part of the dependent application project, so the
-API used in the library project must be compatible with the version of the
-Android library used to compile the application project. In general, the library
-project should use an <a href="{@docRoot}guide/appendix/api-levels.html">API level</a>
-that is the same as &mdash; or lower than &mdash; that used by the application.
-If the library project uses an API level that is higher than that of the
-application, the application project will fail to compile. It is perfectly
-acceptable to have a library that uses the Android 1.5 API (API level 3) and
-that is used in an Android 1.6 (API level 4) or Android 2.1 (API level 7)
-project, for instance.</p>
-
-<p><strong>No restriction on library package name</strong></p>
-
-<p>There is no requirement for the package name of a library to be the same as
-that of applications that use it.</p>
-
-<p><strong>Multiple R classes in gen/ folder of application project</strong></p>
-
-<p>When you build the dependent application project, the code of any libraries
-is compiled and merged to the application project. Each library has its own
-<code>R</code> class, named according to the library's package name. The
-<code>R</code> class generated from the resources of the main project and of the
-library is created in all the packages that are needed including the main
-project’s package and the libraries’ packages.</p>
-
-<p><strong>Testing a library project</strong></p>
-
-<p>There are two recommended ways of setting up testing on code and resources in
-a library project: </p>
-
-<ul>
-<li>You can set up a <a
-href="{@docRoot}guide/developing/testing/testing_otheride.html">test project</a>
-that instruments an application project that depends on the library project. You
-can then add tests to the project for library-specific features.</li>
-<li>You can set up a set up a standard application project that depends on the
-library and put the instrumentation in that project. This lets you create a
-self-contained project that contains both the tests/instrumentations and the
-code to test.</li>
-</ul>
-
-<p><strong>Library project storage location</strong></p>
-
-<p>There are no specific requirements on where you should store a library
-project, relative to a dependent application project, as long as the application
-project can reference the library project by a relative link. You can place the
-library project What is important is that the main project can reference the
-library project through a relative link.</p>
-
-<h2 id="AttachingADebugger">Attaching a Debugger to Your Application</h2>
-
-<p>This section describes how to display debug information on the screen (such
-    as CPU usage), as well as how to hook up your IDE to debug running applications
-    on the emulator. </p>
-
-<p>Attaching a debugger is automated using the Eclipse plugin,
-    but you can configure other IDEs to listen on a debugging port to receive debugging
-    information:</p>
-<ol>
-    <li><strong>Start the <a href="{@docRoot}guide/developing/tools/ddms.html">Dalvik Debug Monitor 
-      Server (DDMS)</a> tool, </strong> which
-        acts as a port forwarding service between your IDE and the emulator.</li>
-    <li><strong>Set 
-        optional debugging configurations on
-        your emulator</strong>, such as blocking application startup for an Activity
-        until a debugger is attached. Note that many of these debugging options
-        can be used without DDMS, such as displaying CPU usage or screen refresh
-        rate on the emulator.</li>
-    <li><strong>Configure your IDE to attach to port 8700 for debugging.</strong> Read
-        about <a href="{@docRoot}guide/developing/debug-tasks.html#ide-debug-port">
-        Configuring Your IDE to Attach to the Debugging Port</a>. </li>
-</ol>
diff --git a/docs/html/guide/developing/projects/index.jd b/docs/html/guide/developing/projects/index.jd
new file mode 100644
index 0000000..45fd5a1
--- /dev/null
+++ b/docs/html/guide/developing/projects/index.jd
@@ -0,0 +1,572 @@
+page.title=Creating and Managing Projects
+@jd:body
+
+ <div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li><a href="#ApplicationProjects">Android Projects</a></li>
+
+        <li><a href="#LibraryProjects">Library Projects</a>
+          <ol>
+            <li><a href="#libraryMigrating">Migrating library projects to ADT 0.9.8 or higher</a></li>
+          </ol>
+        </li>
+
+        <li><a href="#TestProjects">Test Projects</a></li>
+      </ol>
+    </div>
+  </div>
+
+  <p>Projects act as containers for storing things such as code and resource files. The SDK tools
+  expect your projects to follow a specific structure so it can compile and package your
+  application correctly, so it is highly recommended that you create them with Eclipse and ADT or
+  with the <code>android</code> tool on the command line. There are three types of projects, and
+  they all share the same general structure but differ in function:</p>
+
+  <dl>
+    <dt><strong>Android Projects</strong></dt>
+
+    <dd>An Android project is the container for your application's source code, resource files, and
+    files such as the Ant build and Android Manifest file. An application project is the main type
+    of project and the contents are eventually built into an <code>.apk</code> file that you install on a
+    device.</dd>
+
+    <dt><strong>Test Projects</strong></dt>
+
+    <dd>These projects contain code to test your application projects and are built into
+    applications that run on a device.</dd>
+
+    <dt><strong>Library Projects</strong></dt>
+
+    <dd>These projects contain shareable Android source code and resources that you can reference
+    in Android projects. This is useful when you have common code that you want to reuse. 
+    Library projects cannot be installed onto a device, however, they are
+    pulled into the <code>.apk</code> file at build time.</dd>
+  </dl>
+
+  <p>When you use the Android development tools to create a new project, the essential files and
+  folders will be created for you. There are only a handful of files and folders generated for you,
+  and some of them depend on whether you use the Eclipse plugin or the {@code android} tool to
+  generate your project. As your application grows in complexity, you might require new kinds of
+  resources, directories, and files.</p>
+
+  <h2 id="ApplicationProjects">Android Projects</h2>
+
+  <p>Android projects are the projects that eventually get built into an <code>.apk</code> file that you install
+  onto a device. They contain things such as application source code and resource files.
+  Some are generated for you by default, while others should be created if
+  required. The following directories and files comprise an Android project:</p>
+
+  <dl>
+    <dt><code>src/</code></dt>
+
+    <dd>Contains your stub Activity file, which is stored at
+    <code>src<em>/your/package/namespace/ActivityName</em>.java</code>. All other source code
+     files (such as <code>.java</code> or <code>.aidl</code> files) go here as well.</dd>
+
+    <dt><code>bin</code></dt>
+
+    <dd>Output directory of the build. This is where you can find the final <code>.apk</code> file and other
+    compiled resources.</dd>
+
+    <dt><code>jni</code></dt>
+
+    <dd>Contains native code sources developed using the Android NDK. For more information, see the
+    <a href="{@docRoot}sdk/ndk/index.html">Android NDK documentation</a>.</dd>
+
+    <dt><code>gen/</code></dt>
+
+    <dd>Contains the Java files generated by ADT, such as your <code>R.java</code> file and
+    interfaces created from AIDL files.</dd>
+
+    <dt><code>assets/</code></dt>
+
+    <dd>This is empty. You can use it to store raw asset files. Files that you save here are
+    compiled into an <code>.apk</code> file as-is, and the original filename is preserved. You can navigate this
+    directory in the same way as a typical file system using URIs and read files as a stream of
+    bytes using the the {@link android.content.res.AssetManager}. For example, this is a good
+    location for textures and game data.</dd>
+
+    <dt><code>res/</code></dt>
+
+    <dd>
+      Contains application resources, such as drawable files, layout files, and string values. See
+      <a href="{@docRoot}guide/topics/resources/index.html">Application Resources</a> for more
+      information.
+
+      <dl>
+        <dt><code>anim/</code></dt>
+
+        <dd>For XML files that are compiled into animation objects. See the <a href=
+        "{@docRoot}guide/topics/resources/animation-resource.html">Animation</a> resource
+        type.</dd>
+
+        <dt><code>color/</code></dt>
+
+        <dd>For XML files that describe colors. See the <a href=
+        "{@docRoot}guide/topics/resources/color-list-resource.html">Color Values</a> resource
+        type.</dd>
+
+        <dt><code>drawable/</code></dt>
+
+        <dd>For bitmap files (PNG, JPEG, or GIF), 9-Patch image files, and XML files that describe
+        Drawable shapes or a Drawable objects that contain multiple states (normal, pressed, or
+        focused). See the <a href=
+        "{@docRoot}guide/topics/resources/drawable-resource.html">Drawable</a> resource type.</dd>
+
+        <dt><code>layout/</code></dt>
+
+        <dd>XML files that are compiled into screen layouts (or part of a screen). See the <a href=
+        "{@docRoot}guide/topics/resources/layout-resource.html">Layout</a> resource type.</dd>
+
+        <dt><code>menu/</code></dt>
+
+        <dd>For XML files that define application menus. 
+        See the <a href="{@docRoot}guide/topics/resources/menu-resource.html">Menus</a>
+        resource type.</dd>
+
+        <dt><code>raw/</code></dt>
+
+        <dd>For arbitrary raw asset files. Saving asset files here instead of in the
+        <code>assets/</code> directory only differs in the way that you access them. These files
+        are processed by aapt and must be referenced from the application using a resource
+        identifier in the {@code R} class. For example, this is a good place for media, such as MP3
+        or Ogg files.</dd>
+
+        <dt><code>values/</code></dt>
+
+        <dd>For XML files that are compiled into many kinds of resource. Unlike other resources in
+        the <code>res/</code> directory, resources written to XML files in this folder are not
+        referenced by the file name. Instead, the XML element type controls how the resources is
+        defined within them are placed into the {@code R} class.</dd>
+
+        <dt><code>xml/</code></dt>
+
+        <dd>For miscellaneous XML files that configure application components. For example, an XML
+        file that defines a {@link android.preference.PreferenceScreen}, {@link
+        android.appwidget.AppWidgetProviderInfo}, or <a href=
+        "{@docRoot}reference/android/app/SearchManager.html#SearchabilityMetadata">Searchability
+        Metadata</a>. See <a href="{@docRoot}guide/topics/resources/index.html">Application Resources</a>
+        for more information about configuring these application components.</dd>
+      </dl>
+    </dd>
+
+    <dt><code>libs/</code></dt>
+
+    <dd>Contains private libraries.</dd>
+
+    <dt><code>AndroidManifest.xml</code></dt>
+
+    <dd>The control file that describes the nature of the application and each of its components.
+    For instance, it describes: certain qualities about the activities, services, intent receivers,
+    and content providers; what permissions are requested; what external libraries are needed; what
+    device features are required, what API Levels are supported or required; and others. See the
+    <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>
+    documentation for more information</dd>
+
+    <dt><code>build.properties</code></dt>
+
+    <dd>Customizable properties for the build system. You can edit this file to override default
+    build settings used by Ant and provide a pointer to your keystore and key alias so that the
+    build tools can sign your application when built in release mode. If you use Eclipse, this file
+    is not used.</dd>
+
+    <dt><code>build.xml</code></dt>
+
+    <dd>The Ant build file for your project. This is only applicable for projects that
+    you create on the command line.</dd>
+
+    <dt><code>default.properties</code></dt>
+
+    <dd>This file contains project settings, such as the build target. This files is integral to
+    the project, as such, it should be maintained in a Source Revision Control system. Do not edit
+    the file manually.</dd>
+  </dl>
+
+  <h2 id="LibraryProjects">Library Projects</h2>
+
+  <div class="sidebox-wrapper">
+    <div class="sidebox">
+      <h2>Library project example code</h2>
+
+      <p>The SDK includes an example application called <code>TicTacToeMain</code> that shows how a dependent
+      application can use code and resources from an Android Library project. The TicTacToeMain
+      application uses code and resources from an example library project called TicTacToeLib.</p>
+
+      <p>To download the sample applications and run them as projects in
+      your environment, use the <em>Android SDK and AVD Manager</em> to download the "Samples for
+      SDK API 8" component into your SDK.</p>
+
+      <p>For more information and to browse the code of the samples, see
+      the <a href="{@docRoot}resources/samples/TicTacToeMain/index.html">TicTacToeMain
+      application</a>.</p>
+    </div>
+  </div>
+
+    <p>An Android <em>library project</em> is a development project that holds shared Android
+    source code and resources. Other Android application projects can reference the library project
+    and, at build time, include its compiled sources in their <code>.apk</code> files. Multiple
+    application projects can reference the same library project and any single application project
+    can reference multiple library projects.</p>
+
+    <p>If you have source code and resources that are common to multiple Android projects, you
+    can move them to a library project so that it is easier to maintain across applications and
+    versions. Here are some common scenarios in which you could make use of library projects:</p>
+
+    <ul>
+      <li>If you are developing multiple related applications that use some of the same components,
+      you move the redundant components out of their respective application projects and create a
+      single, reuseable set of the same components in a library project.</li>
+
+      <li>If you are creating an application that exists in both free and paid versions. You move
+      the part of the application that is common to both versions into a library project. The two
+      dependent projects, with their different package names, will reference the library project
+      and provide only the difference between the two application versions.</li>
+    </ul>
+
+    <p>Structurally, a library project is similar to a standard Android application project. For
+    example, it includes a manifest file at the project root, as well as <code>src/</code>,
+    <code>res/</code> and similar directories. The project can contain the same types of source
+    code and resources as a standard Android project, stored in the same way. For example, source
+    code in the library project can access its own resources through its <code>R</code> class.</p>
+
+    <p>However, a library project differs from an standard Android application project in that you
+    cannot compile it directly to its own <code>.apk</code> and run it on an Android device.
+    Similarly, you cannot export the library project to a self-contained JAR file, as you would do
+    for a true library. Instead, you must compile the library indirectly, by referencing the
+    library in the dependent application and building that application.</p>
+
+    <p>When you build an application that depends on a library project, the SDK tools compile the
+    library and merge its sources with those in the main project, then use the result to generate
+    the <code>.apk</code>. In cases where a resource ID is defined in both the application and the
+    library, the tools ensure that the resource declared in the application gets priority and that
+    the resource in the library project is not compiled into the application <code>.apk</code>.
+    This gives your application the flexibility to either use or redefine any resource behaviors or
+    values that are defined in any library.</p>
+
+    <p>To organize your code further, your application can add references to multiple library
+    projects, then specify the relative priority of the resources in each library. This lets you
+    build up the resources actually used in your application in a cumulative manner. When two
+    libraries referenced from an application define the same resource ID, the tools select the
+    resource from the library with higher priority and discard the other.</p>
+
+    <p>Once you have added references to library projects to your Android project, 
+    you can set their relative priority. At build time, the
+    libraries are merged with the application one at a time, starting from the lowest priority to
+    the highest.</p>
+
+    <p>Note that a library project cannot itself reference another library project and that, at
+    build time, library projects are <em>not</em> merged with each other before being merged with
+    the application. However, note that a library can import an external library (JAR) in the
+    normal way.</p>
+
+  <h3 id="libraryReqts">Development requirements</h3>
+
+  <p>Android library projects are a build-time construct, so you can use them to build a final
+  application <code>.apk</code> that targets any API level and is compiled against any version of
+  the Android library.</p>
+
+  <p>However, to use library projects, you need to update your development environment to use the
+  latest tools and platforms, since older releases of the tools and platforms do not support
+  building with library projects. Specifically, you need to download and install the versions
+  listed below:</p>
+
+  <p class="table-caption"><strong>Table 1.</strong> Minimum versions of SDK tools and platforms on
+  which you can develop library projects.</p>
+
+  <table>
+    <tr>
+      <th>Component</th>
+
+      <th>Minimum Version</th>
+    </tr>
+
+    <tr>
+      <td>SDK Tools</td>
+
+      <td>r6 (or higher)</td>
+    </tr>
+
+    <tr>
+      <td>Android 2.2 platform</td>
+
+      <td>r1 (or higher)</td>
+    </tr>
+
+    <tr>
+      <td>Android 2.1 platform</td>
+
+      <td>r2 (or higher)</td>
+    </tr>
+
+    <tr>
+      <td style="color:gray">Android 2.0.1 platform</td>
+
+      <td style="color:gray"><em>not supported</em></td>
+    </tr>
+
+    <tr>
+      <td style="color:gray">Android 2.0 platform</td>
+
+      <td style="color:gray"><em>not supported</em></td>
+    </tr>
+
+    <tr>
+      <td>Android 1.6 platform</td>
+
+      <td>r3 (or higher)</td>
+    </tr>
+
+    <tr>
+      <td>Android 1.5 platform</td>
+
+      <td>r4 (or higher)</td>
+    </tr>
+
+    <tr>
+      <td>ADT Plugin</td>
+
+      <td>0.9.7 (or higher)</td>
+    </tr>
+  </table>
+
+  <p>You can download the tools and platforms using the <em>Android SDK and AVD Manager</em>, as
+  described in <a href="{@docRoot}sdk/adding-components.html">Adding SDK Components</a>.</p>
+
+  <h3 id="considerations">Development considerations</h3>
+
+  <p>As you develop your library project and dependent applications, keep the points listed below
+  in mind:</p>
+  
+  <ul>
+  <li><p><strong>Resource conflicts</strong></p>
+  <p>Since the tools merge the resources of a library project with those of a dependent application
+  project, a given resource ID might be defined in both projects. In this case, the tools select
+  the resource from the application, or the library with highest priority, and discard the other
+  resource. As you develop your applications, be aware that common resource IDs are likely to be
+  defined in more than one project and will be merged, with the resource from the application or
+  highest-priority library taking precedence.</p>
+  </li>
+  
+  <li><p><strong>Use prefixes to avoid resource conflicts</strong></p>
+
+  <p>To avoid resource conflicts for common resource IDs, consider using a prefix or other
+  consistent naming scheme that is unique to the project (or is unique across all projects).</p></li>
+  
+  <li><p><strong>You cannot export a library project to a JAR file</strong></p>
+
+  <p>A library cannot be distributed as a binary file (such as a jar file). This is because the
+  library project is compiled by the main project to use the correct resource IDs.</p></li>
+  <li><p><strong>One library project cannot reference another</strong></p>
+
+  <p>A library cannot depend on another library</p></li>
+  
+  <li><p><strong>A library project can include a JAR library</strong></p>
+
+  <p>You can develop a library project that itself includes a JAR library, however you need to
+  manually edit the dependent application project's build path and add a path to the JAR file.</p></li>
+  
+  <li><p><strong>A library project can depend on an external JAR library</strong></p>
+
+  <p>You can develop a library project that depends on an external library (for example, the Maps
+  external library). In this case, the dependent application must build against a target that
+  includes the external library (for example, the Google APIs Add-On). Note also that both the
+  library project and the dependent application must declare the external library in their manifest
+  files, in a <a href=
+  "{@docRoot}guide/topics/manifest/uses-library-element.html"><code>&lt;uses-library&gt;</code></a>
+  element.</p></li>
+  <li><p><strong>Library project cannot include AIDL files</strong></p>
+
+  <p>The tools do not support the use of AIDL files in a library project. Any AIDL files used by an
+  application must be stored in the application project itself.</p></li>
+  
+  <li> <p><strong>Library projects cannot include raw assets</strong></p>
+
+  <p>The tools do not support the use of raw asset files (saved in the <code>assets/</code> directory)
+  in a library project. Any asset resources
+  used by an application must be stored in the <code>assets/</code> directory of the application
+  project itself. However, resource files saved in the
+  <code>res/</code> directory are supported.</p></li>
+  
+  <li><p><strong>Platform version must be lower than or equal to the Android project</strong></p>
+
+  <p>A library is compiled as part of the dependent application project, so the API used in the
+  library project must be compatible with the version of the Android library used to compile the
+  application project. In general, the library project should use an <a href=
+  "{@docRoot}guide/appendix/api-levels.html">API level</a> that is the same as &mdash; or lower
+  than &mdash; that used by the application. If the library project uses an API level that is
+  higher than that of the application, the application project will not compile. It is
+  perfectly acceptable to have a library that uses the Android 1.5 API (API level 3) and that is
+  used in an Android 1.6 (API level 4) or Android 2.1 (API level 7) project, for instance.</p></li>
+  
+  <li> <p><strong>No restriction on library package names</strong></p>
+
+  <p>There is no requirement for the package name of a library to be the same as that of
+  applications that use it.</p></li>
+  
+  <li><p><strong>Each library project creates its own R class </strong></p>
+
+  <p>When you build the dependent application project, library projects are compiled and
+  merged with the application project. Each library has its own <code>R</code> class, named according
+  to the library's package name. The <code>R</code> class generated from main
+  project and the library project is created in all the packages that are needed including the main
+  project's package and the libraries' packages.</p></li>
+  
+  <li><p><strong>Library project storage location</strong></p>
+
+  <p>There are no specific requirements on where you should store a library project, relative to a
+  dependent application project, as long as the application project can reference the library
+  project by a relative link. What is important is that the main
+  project can reference the library project through a relative link.</p></li>
+  </ul>
+  
+  
+  
+  <h3 id="libraryMigrating">Migrating library projects to ADT 0.9.8 or higher</h3> 
+ 
+<p>This section provides information about how to migrate a library project
+created with ADT 0.9.7 to ADT 0.9.8 or higher. The migration is needed only if
+you are developing in Eclipse with ADT and assumes that you have also upgraded
+to SDK Tools r7 (or higher). </p> 
+ 
+<p>The way that ADT handles library projects has changed between
+ADT 0.9.7 and ADT 0.9.8. Specifically, in ADT 0.9.7, the <code>src/</code> 
+source folder of the library was linked into the dependent application project
+as a folder that had the same name as the library project. This worked because
+of two restrictions on the library projects:</p> 
+ 
+<ul> 
+<li>The library was only able to contain a single source folder (excluding the
+special <code>gen/</code> source folder), and</li> 
+<li>The source folder was required to have the name <code>src/</code> and be
+stored at the root of the project.</li> 
+</ul> 
+ 
+<p>In ADT 0.9.8, both of those restrictions were removed. A library project can
+have as many source folders as needed and each can have any name. Additionally,
+a library project can store source folders in any location of the project. For
+example, you could store sources in a <code>src/java/</code> directory. In order
+to support this, the name of the linked source folders in the main project are
+now called &lt;library-name&gt;_&lt;folder-name&gt; For
+example: <code>MyLibrary_src/</code> or <code>MyLibrary_src_java/</code>.</p> 
+ 
+<p>Additionally, the linking process now flags those folders in order for ADT to
+recognize that it created them. This will allow ADT to automatically migrate the
+project to new versions of ADT, should they contain changes to the handling of
+library projects. ADT 0.9.7 did not flag the linked source folders, so ADT 0.9.8
+cannot be sure whether the old linked folders can be removed safely. After
+upgrading ADT to 0.9.8, you will need to remove the old linked folders manually
+in a simple two-step process, as described below.</p> 
+ 
+<p>Before you begin, make sure to create a backup copy of your application or
+save the latest version to your code version control system. This ensures that
+you will be able to easily revert the migration changes in case there is a
+problem in your environment.</p> 
+ 
+<p>When you first upgrade to ADT 0.9.8, your main project will look as shown
+in figure 1, with two linked folders (in this example, <code>MyLibrary</code> and
+<code>MyLibrary_src</code> &mdash; both of which link to
+<code>MyLibrary/src</code>. Eclipse shows an error on one of them because they
+are duplicate links to a single class.</p> 
+ 
+<img src="/images/developing/lib-migration-0.png" alt=""> 
+<p class="img-caption"><strong>Figure 1.</strong> Library project migration error</p>
+<p>To fix the error, remove the linked folder that <em>does not</em> contain the
+<code>_src</code> suffix. </p> 
+ 
+<ol> 
+<li>Right click the folder that you want to remove (in this case, the
+<code>MyLibrary</code> folder) and choose <strong>Build Path</strong> &gt;
+<strong>Remove from Build Path</strong>, as shown in figure 2.</li> 
+ 
+<img src="/images/developing/lib-migration-1.png" style="height:600px"
+alt=""> 
+<p class="img-caption"><strong>Figure 2.</strong> Remove from Build Path menu item</p>
+ 
+<li>Next, when asked about unlinking the folder from the project, select
+<strong>Yes</strong>, as shown in figure 3.</li> 
+ 
+<img src="/images/developing/lib-migration-2.png" alt=""> 
+
+<p class="img-caption"><strong>Figure 3.</strong> Unlink folder confirmation window</p>
+</ol> 
+ 
+<p>This should resolve the error and migrate your library project to the new
+ADT environment. </p> 
+ 
+  
+
+  <h2 id="TestProjects">Test Projects</h2>
+
+  <p>Test projects contain Android applications that you write using the 
+  <a href="{@docRoot}guide/topics/testing/index.html">Testing and
+  Instrumentation framework</a>. The framework is an extension of the JUnit test framework and adds
+  access to Android system objects. The file structure of a test project is the same as an
+  Android project.</p>
+
+  <dl>
+    <dt><code>src/</code></dt>
+
+    <dd>Includes your test source files. Test projects do not require an Activity <code>.java</code>
+    file, but can include one.</dd>
+
+    <dt><code>gen/</code></dt>
+
+    <dd>This contains the Java files generated by ADT, such as your <code>R.java</code> file and
+    interfaces created from AIDL files.</dd>
+
+    <dt><code>assets/</code></dt>
+
+    <dd>This is empty. You can use it to store raw asset files.</dd>
+
+    <dt><code>res/</code></dt>
+
+    <dd>A folder for your application resources, such as drawable files, layout files, string
+    values, etc. See <a href="{@docRoot}guide/topics/resources/index.html">Application
+    Resources</a>.</dd>
+
+    <dt><code>AndroidManifest.xml</code></dt>
+
+    <dd>The Android Manifest for your project. See <a href=
+    "{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a>. Test
+    Projects have a special <a href=
+    "{@docRoot}guide/topics/manifest/instrumentation-element.html">
+    <code>&lt;instrumentation&gt;</code></a>
+    element that connects the test project with the application project.</dd>
+
+    <dt><code>build.properties</code></dt>
+
+    <dd>Customizable properties for the build system. You can edit this file to override default
+    build settings used by Ant and provide a pointer to your keystore and key alias so that the
+    build tools can sign your application when built in release mode.</dd>
+
+    <dt><code>build.xml</code></dt>
+
+    <dd>The Ant build file for your project.</dd>
+
+    <dt><code>default.properties</code></dt>
+
+    <dd>This file contains project settings, such as the build target. This files is integral to
+    the project, as such, it should be maintained in a Source Revision Control system. It should
+    never be edited manually &mdash; to edit project properties, right-click the project folder and
+    select "Properties".</dd>
+  </dl>For more information, see the <a href=
+  "{@docRoot}guide/developing/testing/index.html">Testing</a> section.
+
+
+  <h2>Testing a library project</h2>
+
+  <p>There are two recommended ways of setting up testing on code and resources in a library
+  project:</p>
+
+  <ul>
+    <li>You can set up a <a href="{@docRoot}guide/developing/testing/testing_otheride.html">test
+    project</a> that instruments an application project that depends on the library project. You
+    can then add tests to the project for library-specific features.</li>
+
+    <li>You can set up a set up a standard application project that depends on the library and put
+    the instrumentation in that project. This lets you create a self-contained project that
+    contains both the tests/instrumentations and the code to test.</li>
+  </ul>
\ No newline at end of file
diff --git a/docs/html/guide/developing/projects/projects-cmdline.jd b/docs/html/guide/developing/projects/projects-cmdline.jd
new file mode 100644
index 0000000..8b889ab
--- /dev/null
+++ b/docs/html/guide/developing/projects/projects-cmdline.jd
@@ -0,0 +1,285 @@
+page.title=Creating and Managing Projects on the Command Line
+@jd:body
+
+  <div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li><a href="#CreatingAProject">Creating an Android Project</a></li>
+
+        <li><a href="#UpdatingAProject">Updating a Project</a></li>
+
+        <li><a href="#SettingUpLibraryProject">Setting up a Library Project</a></li>
+
+        <li><a href="#ReferencingLibraryProject">Referencing a Library Project from an
+        Application</a></li>
+      </ol>
+
+      <h2>See also</h2>
+
+      <ol>
+        <li><a href=
+        "{@docRoot}guide/developing/testing/testing_otheride.html#CreateTestProjectCommand">Testing
+        in Other IDEs</a></li>
+      </ol>
+    </div>
+  </div>
+
+  <p>The <code>android</code> tool provides you with commands to create all three types of
+  projects. An Android project contains all of the files and resources that are needed to build a
+  project into an .apk file for installation. 
+  
+  <ul>
+    <li>An Android project contains all of the files and resources that are needed to build a project into
+  an .apk file for installation. You need to create an Android project for any application that you
+  want to eventually install on a device.</li>
+
+  <li>You can also designate an Android project as a library project, which allows it to be shared
+  with other projects that depend on it. Once an Android project is designated as a library
+  project, it cannot be installed onto a device.</li>
+
+  <li>Test projects extend JUnit test functionality to include Android specific functionality. For
+  more information on creating a test project, see <a href=
+  "{@docRoot}guide/developing/testing/testing_otheride.html">Testing in other IDEs</a>.</li>
+  </ul>
+
+
+  <h2 id="CreatingAProject">Creating an Android Project</h2>
+
+  <p>To create an Android project, you must use the <code>android</code> tool. When you create a
+  new project with <code>android</code>, it will generate a project directory with some default
+  application files, stub files, configuration files and a build file.</p>
+
+  <p>To create a new Android project, open a command-line, navigate to the <code>tools/</code>
+  directory of your SDK and run:</p>
+  <pre>
+android create project \
+--target &lt;target_ID&gt; \
+--name &lt;your_project_name&gt; \
+--path path/to/your/project \
+--activity &lt;your_activity_name&gt; \
+--package &lt;your_package_namespace&gt;
+</pre>
+
+  <ul>
+    <li><code>target</code> is the "build target" for your application. It corresponds to an
+    Android platform library (including any add-ons, such as Google APIs) that you would like to
+    build your project against. To see a list of available targets and their corresponding IDs,
+    execute: <code>android list targets</code>.</li>
+
+    <li><code>name</code> is the name for your project. This is optional. If provided, this name
+    will be used for your .apk filename when you build your application.</li>
+
+    <li><code>path</code> is the location of your project directory. If the directory does not
+    exist, it will be created for you.</li>
+
+    <li><code>activity</code> is the name for your default {@link android.app.Activity} class. This
+    class file will be created for you inside
+    <code><em>&lt;path_to_your_project&gt;</em>/src/<em>&lt;your_package_namespace_path&gt;</em>/</code>
+    . This will also be used for your .apk filename unless you provide a <code>name</code>.</li>
+
+    <li><code>package</code> is the package namespace for your project, following the same rules as
+    for packages in the Java programming language.</li>
+  </ul>
+
+  <p>Here's an example:</p>
+  <pre>
+android create project \
+--target 1 \
+--name MyAndroidApp \
+--path ./MyAndroidAppProject \
+--activity MyAndroidAppActivity \
+--package com.example.myandroid
+</pre>
+
+  <p>Once you've created your project, you're ready to begin development. You can move your project
+  folder wherever you want for development, but keep in mind that you must use the <a href=
+  "{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a> (adb) &mdash; located in the
+  SDK <code>platform-tools/</code> directory &mdash; to send your application to the emulator (discussed
+  later). So you need access between your project solution and the <code>platform-tools/</code> folder.</p>
+ 
+  <p class="note"><strong>Tip:</strong> Add the <code>platform-tools/</code> as well as the <code>tools/</code> directory
+  to your <code>PATH</code> environment variable.</p>
+  
+  <p class="caution"><strong>Caution:</strong> You should refrain from moving the location of the
+  SDK directory, because this will break the build scripts. (They will need to be manually updated
+  to reflect the new SDK location before they will work again.)</p>
+
+  <h2 id="UpdatingAProject">Updating a project</h2>
+
+  <p>If you're upgrading a project from an older version of the Android SDK or want to create a new
+  project from existing code, use the <code>android update project</code> command to update the
+  project to the new development environment. You can also use this command to revise the build
+  target of an existing project (with the <code>--target</code> option) and the project name (with
+  the <code>--name</code> option). The <code>android</code> tool will generate any files and
+  folders (listed in the previous section) that are either missing or need to be updated, as needed
+  for the Android project.</p>
+
+  <p>To update an existing Android project, open a command-line and navigate to the
+  <code>tools/</code> directory of your SDK. Now run:</p>
+  <pre>
+android update project --name &lt;project_name&gt; --target &lt;target_ID&gt;
+--path &lt;path_to_your_project&gt;
+</pre>
+
+  <ul>
+    <li><code>target</code> is the "build target" for your application. It corresponds to an
+    Android platform library (including any add-ons, such as Google APIs) that you would like to
+    build your project against. To see a list of available targets and their corresponding IDs,
+    execute: <code>android list targets</code>.</li>
+
+    <li><code>path</code> is the location of your project directory.</li>
+
+    <li><code>name</code> is the name for the project. This is optional&mdash;if you're not
+    changing the project name, you don't need this.</li>
+  </ul>
+
+  <p>Here's an example:</p>
+  <pre>
+android update project --name MyApp --target 2 --path ./MyAppProject
+</pre>
+
+  <h2 id="SettingUpLibraryProject">Setting up a library project</h2>
+
+  <p>A library project is a standard Android project, so you can create a new one in the same way
+  as you would a new application project. Specifically, you can use the <code>android</code> tool
+  to generate a new library project with all of the necessary files and folders.</p>
+
+  <p>To create a new library project, navigate to the <code>&lt;sdk&gt;/tools/</code> directory and
+  use this command:</p>
+  <pre class="no-pretty-print">
+android create lib-project --name &lt;your_project_name&gt; \
+--target &lt;target_ID&gt; \
+--path path/to/your/project \
+--package &lt;your_library_package_namespace&gt;
+</pre>
+
+  <p>The <code>create lib-project</code> command creates a standard project structure that includes
+  preset property that indicates to the build system that the project is a library. It does this by
+  adding this line to the project's <code>default.properties</code> file:</p>
+  <pre class="no-pretty-print">
+android.library=true
+</pre>
+
+  <p>Once the command completes, the library project is created and you can begin moving source
+  code and resources into it, as described in the sections below.</p>
+
+  <p>If you want to convert an existing application project to a library project, so that other
+  applications can use it, you can do so by adding a the <code>android.library=true</code> property
+  to the application's <code>default.properties</code> file.</p>
+
+  <h4>Creating the manifest file</h4>
+
+  <p>A library project's manifest file must declare all of the shared components that it includes,
+  just as would a standard Android application. For more information, see the documentation for
+  <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>.</p>
+
+  <p>For example, the <a href=
+  "{@docRoot}resources/samples/TicTacToeLib/AndroidManifest.html">TicTacToeLib</a> example library
+  project declares the Activity <code>GameActivity</code>:</p>
+  <pre>
+&lt;manifest&gt;
+  ...
+  &lt;application&gt;
+    ...
+    &lt;activity android:name="GameActivity" /&gt;
+    ...
+  &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+  <h4>Updating a library project</h4>
+
+  <p>If you want to update the build properties (build target, location) of the library project,
+  use this command:</p>
+  <pre>
+android update lib-project \
+--target <em>&lt;target_ID&gt;</em> \
+--path <em>path/to/your/project</em>
+</pre>
+
+  <h2 id="ReferencingLibraryProject">Referencing a Library Project</h2>
+
+  <p>If you are developing an application and want to include the shared code or resources from a
+  library project, you can do so easily by adding a reference to the library project in the
+  application project's build properties.</p>
+
+  <p>To add a reference to a library project, navigate to the <code>&lt;sdk&gt;/tools/</code>
+  directory and use this command:</p>
+  <pre>
+android update lib-project \
+--target <em>&lt;target_ID&gt;</em> \
+--path <em>path/to/your/project</em>
+--library <em>path/to/library_projectA</em>
+</pre>
+
+  <p>This command updates the application project's build properties to include a reference to the
+  library project. Specifically, it adds an <code>android.library.reference.<em>n</em></code>
+  property to the project's <code>default.properties</code> file. For example:</p>
+  <pre class="no-pretty-print">
+android.library.reference.1=path/to/library_projectA
+</pre>
+
+  <p>If you are adding references to multiple libraries, note that you can set their relative
+  priority (and merge order) by manually editing the <code>default.properties</code> file and
+  adjusting the each reference's <code>.<em>n</em></code> index as appropriate. For example, assume
+  these references:</p>
+  <pre class="no-pretty-print">
+android.library.reference.1=path/to/library_projectA
+android.library.reference.2=path/to/library_projectB
+android.library.reference.3=path/to/library_projectC
+</pre>
+
+  <p>You can reorder the references to give highest priority to <code>library_projectC</code> in
+  this way:</p>
+  <pre class="no-pretty-print">
+android.library.reference.2=path/to/library_projectA
+android.library.reference.3=path/to/library_projectB
+android.library.reference.1=path/to/library_projectC
+</pre>
+
+  <p>Note that the <code>.<em>n</em></code> index in the references must begin at "1" and increase
+  uniformly without "holes". References appearing in the index after a hole are ignored.</p>
+
+  <p>At build time, the libraries are merged with the application one at a time, starting from the
+  lowest priority to the highest. Note that a library cannot itself reference another library and
+  that, at build time, libraries are not merged with each other before being merged with the
+  application.</p>
+
+  <h3>Declaring library components in the the manifest file</h3>
+
+  <p>In the manifest file of the application project, you must add declarations of all components
+  that the application will use that are imported from a library project. For example, you must
+  declare any <code>&lt;activity&gt;</code>, <code>&lt;service&gt;</code>,
+  <code>&lt;receiver&gt;</code>, <code>&lt;provider&gt;</code>, and so on, as well as
+  <code>&lt;permission&gt;</code>, <code>&lt;uses-library&gt;</code>, and similar elements.</p>
+
+  <p>Declarations should reference the library components by their fully-qualified package names,
+  where appropriate.</p>
+
+  <p>For example, the <a href=
+  "{@docRoot}resources/samples/TicTacToeMain/AndroidManifest.html">TicTacToeMain</a> example
+  application declares the library Activity <code>GameActivity</code> like this:</p>
+  <pre>
+&lt;manifest&gt;
+  ...
+  &lt;application&gt;
+    ...
+    &lt;activity android:name="com.example.android.tictactoe.library.GameActivity" /&gt;
+    ...
+  &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+  <p>For more information about the manifest file, see the documentation for
+  <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>.</p>
+
+  <h3 id="depAppBuild">Building a dependent application</h3>
+
+  <p>To build an application project that depends on one or more library projects, you can use the
+  standard Ant build commands and compile modes, as described in <a href=
+  "{@docRoot}guide/developing/building/index.html">Building Your Application</a>, earlier in this
+  document. The tools compile and merge all libraries referenced by the application as part of
+  compiling the dependent application project. No additional commands or steps are necessary.</p>
+
diff --git a/docs/html/guide/developing/projects/projects-eclipse.jd b/docs/html/guide/developing/projects/projects-eclipse.jd
new file mode 100644
index 0000000..949e6f7
--- /dev/null
+++ b/docs/html/guide/developing/projects/projects-eclipse.jd
@@ -0,0 +1,235 @@
+page.title=Creating and Managing Projects in Eclipse
+@jd:body
+
+ <div id="qv-wrapper">
+    <div id="qv">
+      <h2>In this document</h2>
+
+      <ol>
+        <li><a href="#CreatingAProject">Creating an Android Project</a></li>
+
+        <li><a href="#SettingUpLibraryProject">Setting up a Library Project</a></li>
+
+        <li><a href="#ReferencingLibraryProject">Referencing a Library Project</a></li>
+      </ol>
+
+      <h2>See also</h2>
+
+      <ol>
+        <li><a href=
+        "{@docRoot}guide/developing/testing/testing_eclipse.html#CreateTestProjectEclipse">Testing
+        in Eclipse, with ADT</a></li>
+      </ol>
+    </div>
+  </div>
+
+  <p>Eclipse and the ADT plugin provide GUIs and wizards to create all three types of projects
+  (Android project, Library project, and Test project):
+  
+  <ul>
+    <li>An Android project contains all of the files and resources that are needed to build a project into
+  an .apk file for installation. You need to create an Android project for any application that you
+  want to eventually install on a device.</li>
+
+  <li>You can also designate an Android project as a library project, which allows it to be shared
+  with other projects that depend on it. Once an Android project is designated as a library
+  project, it cannot be installed onto a device.</li>
+
+  <li>Test projects extend JUnit test functionality to include Android specific functionality. For
+  more information on creating a test project, see <a href=
+  "{@docRoot}guide/developing/testing/testing_eclipse.html">Testing in Eclipse</a></li>
+  </ul>
+
+  <h2 id="CreatingAProject">Creating an Android Project</h2>
+
+  <p>The ADT plugin provides a <em>New Project Wizard</em> that you can use to quickly create a new Android
+  project (or a project from existing code). To create a new project:</p>
+
+  <ol>
+    <li>Select <strong>File</strong> &gt; <strong>New</strong> &gt; <strong>Project</strong>.</li>
+
+    <li>Select <strong>Android</strong> &gt; <strong>Android Project</strong>, and click
+    <strong>Next</strong>.</li>
+
+    <li>Select the contents for the project:
+
+      <ul>
+        <li>Enter a <em>Project Name</em>. This will be the name of the folder where your project
+        is created.</li>
+
+        <li>Under Contents, select <strong>Create new project in workspace</strong>. Select your
+        project workspace location.</li>
+
+        <li>Under Target, select an Android target to be used as the project's Build Target. The
+        Build Target specifies which Android platform you'd like your application built against.
+
+          <p>Select the lowest platform with which your application is compatible.</p>
+
+          <p class="note"><strong>Note:</strong> You can change your the Build Target for your
+          project at any time: Right-click the project in the Package Explorer, select
+          <strong>Properties</strong>, select <strong>Android</strong> and then check the desired
+          Project Target.</p>
+        </li>
+
+        <li>Under Properties, fill in all necessary fields.
+
+          <ul>
+            <li>Enter an <em>Application name</em>. This is the human-readable title for your
+            application &mdash; the name that will appear on the Android device.</li>
+
+            <li>Enter a <em>Package name</em>. This is the package namespace (following the same
+            rules as for packages in the Java programming language) where all your source code will
+            reside.</li>
+
+            <li>Select <em>Create Activity</em> (optional, of course, but common) and enter a name
+            for your main Activity class.</li>
+
+            <li>Enter a <em>Min SDK Version</em>. This is an integer that indicates the minimum API
+            Level required to properly run your application. Entering this here automatically sets
+            the <code>minSdkVersion</code> attribute in the <a href=
+            "{@docRoot}guide/topics/manifest/uses-sdk-element.html">&lt;uses-sdk&gt;</a> of your
+            Android Manifest file. If you're unsure of the appropriate <a href=
+            "{@docRoot}guide/appendix/api-levels.html">API Level</a> to use, copy the API Level
+            listed for the Build Target you selected in the Target tab.</li>
+          </ul>
+        </li>
+      </ul>
+    </li>
+
+    <li>Click <strong>Finish</strong>.</li>
+  </ol>
+
+  <p class="note"><strong>Tip:</strong> You can also start the New Project Wizard from the
+  <em>New</em> icon in the toolbar.</p>
+
+  <h2 id="SettingUpLibraryProject">Setting up a Library Project</h2>
+
+  <p>A library project is a standard Android project, so you can create a new one in the same way
+  as you would a new application project.</p>
+
+  <p>When you are creating the library project, you can select any application name, package, and
+  set other fields as needed, as shown in figure 1.</p>
+
+  <p>Next, set the project's properties to indicate that it is a library project:</p>
+
+  <ol>
+    <li>In the <strong>Package Explorer</strong>, right-click the library project and select
+    <strong>Properties</strong>.</li>
+
+    <li>In the <strong>Properties</strong> window, select the "Android" properties group at left
+    and locate the <strong>Library</strong> properties at right.</li>
+
+    <li>Select the "is Library" checkbox and click <strong>Apply</strong>.</li>
+
+    <li>Click <strong>OK</strong> to close the <em>Properties</em> window.</li>
+  </ol>
+
+  <p>The new project is now marked as a library project. You can begin moving source code and
+  resources into it, as described in the sections below.</p>
+
+  <p>You can also convert an existing application project into a library. To do so, simply open the
+  Properties for the project and select the "is Library" checkbox. Other application projects can
+  now reference the existing project as a library project.</p>
+  
+  <img src= "{@docRoot}images/developing/adt-props-isLib.png">
+
+  <p class="img-caption"><strong>Figure 1.</strong> Marking a project as an
+     Android library project.</p>
+
+  <h3>Creating the manifest file</h3>
+
+  <p>A library project's manifest file must declare all of the shared components that it includes,
+  just as would a standard Android application. For more information, see the documentation for
+  <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>.</p>
+
+  <p>For example, the <a href=
+  "{@docRoot}resources/samples/TicTacToeLib/AndroidManifest.html">TicTacToeLib</a> example library
+  project declares the Activity <code>GameActivity</code>:</p>
+  <pre>
+&lt;manifest&gt;
+  ...
+  &lt;application&gt;
+    ...
+    &lt;activity android:name="GameActivity" /&gt;
+    ...
+  &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+  <h2 id="ReferencingLibraryProject">Referencing a library project</h2>
+
+  <p>If you are developing an application and want to include the shared code or resources from a
+  library project, you can do so easily by adding a reference to the library project in the
+  application project's Properties.</p>
+
+  <p>To add a reference to a library project, follow these steps:</p>
+
+  <ol>
+    <li>In the <strong>Package Explorer</strong>, right-click the dependent project and select
+    <strong>Properties</strong>.</li>
+
+    <li>In the <strong>Properties</strong> window, select the "Android" properties group at left
+    and locate the <strong>Library</strong> properties at right.</li>
+
+    <li>Click <strong>Add</strong> to open the <strong>Project Selection</strong> dialog.</li>
+
+    <li>From the list of available library projects, select a project and click
+    <strong>OK</strong>.</li>
+
+    <li>When the dialog closes, click <strong>Apply</strong> in the <strong>Properties</strong>
+    window.</li>
+
+    <li>Click <strong>OK</strong> to close the <strong>Properties</strong> window.</li>
+  </ol>
+
+  <p>As soon as the Properties dialog closes, Eclipse rebuilds the project, including the contents
+  of the library project.</p>
+
+  <p>Figure 2 shows the Properties dialog that lets you add library references and move
+  them up and down in priority.</p><img src="{@docRoot}images/developing/adt-props-libRef.png">
+
+  <p class="img-caption"><strong>Figure 2.</strong> Adding a reference to a
+     library project in the properties of an application project.</p>
+
+  <p>If you are adding references to multiple libraries, note that you can set their relative
+  priority (and merge order) by selecting a library and using the <strong>Up</strong> and
+  <strong>Down</strong> controls. The tools merge the referenced libraries with your application
+  starting from lowest priority (bottom of the list) to highest (top of the list). If more than one
+  library defines the same resource ID, the tools select the resource from the library with higher
+  priority. The application itself has highest priority and its resources are always used in
+  preference to identical resource IDs defined in libraries.</p>
+
+  <h3>Declaring library components in the the manifest file</h3>
+
+  <p>In the manifest file of the application project, you must add declarations of all components
+  that the application will use that are imported from a library project. For example, you must
+  declare any <code>&lt;activity&gt;</code>, <code>&lt;service&gt;</code>,
+  <code>&lt;receiver&gt;</code>, <code>&lt;provider&gt;</code>, and so on, as well as
+  <code>&lt;permission&gt;</code>, <code>&lt;uses-library&gt;</code>, and similar elements.</p>
+
+  <p>Declarations should reference the library components by their fully-qualified package names,
+  where appropriate.</p>
+
+  <p>For example, the <a href=
+  "{@docRoot}resources/samples/TicTacToeMain/AndroidManifest.html">TicTacToeMain</a> example
+  application declares the library Activity <code>GameActivity</code> like this:</p>
+  <pre>
+&lt;manifest&gt;
+  ...
+  &lt;application&gt;
+    ...
+    &lt;activity android:name="com.example.android.tictactoe.library.GameActivity" /&gt;
+    ...
+  &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+  <p>For more information about the manifest file, see the documentation for <a href=
+  "{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>.</p>
+
+
+
+
+
+
+
diff --git a/docs/html/guide/developing/testing/index.jd b/docs/html/guide/developing/testing/index.jd
index 2164705..8ffaf58 100644
--- a/docs/html/guide/developing/testing/index.jd
+++ b/docs/html/guide/developing/testing/index.jd
@@ -1,4 +1,4 @@
-page.title=Testing Overview
+page.title=Testing
 @jd:body
 <p>
     Android includes powerful tools for setting up and running test applications.
diff --git a/docs/html/guide/developing/testing/testing_eclipse.jd b/docs/html/guide/developing/testing/testing_eclipse.jd
index 370c142..1b9c6b1 100644
--- a/docs/html/guide/developing/testing/testing_eclipse.jd
+++ b/docs/html/guide/developing/testing/testing_eclipse.jd
@@ -12,9 +12,10 @@
 </div>
 <p>
     This topic explains how create and run tests of Android applications in Eclipse with ADT.
-    Before you read this topic, you should read about how to create a Android application with the
+    Before you read this topic, you should read about how to create an Android application with the
     basic processes for creating and running applications with ADT, as described in
-    <a href="{@docRoot}guide/developing/eclipse-adt.html">Developing In Eclipse, with ADT</a>.
+    <a href="{@docRoot}guide/developing/projects/projects-eclipse.html">Creating and Managing Projects in Eclipse</a>
+    and <a href="guide/developing/building/building-eclipse.html">Building and Running Apps in Eclipse</a>.
     You may also want to read
     <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>,
     which provides an overview of the Android testing framework.
diff --git a/docs/html/guide/developing/testing/testing_otheride.jd b/docs/html/guide/developing/testing/testing_otheride.jd
index adb0efa..48fa032 100644
--- a/docs/html/guide/developing/testing/testing_otheride.jd
+++ b/docs/html/guide/developing/testing/testing_otheride.jd
@@ -133,7 +133,7 @@
     This creates a new test project with the appropriate directories and build files. The directory
     structure and build file contents are identical to those in a regular Android application
     project. They are described in detail in the topic
-    <a href="{@docRoot}guide/developing/other-ide.html">Developing In Other IDEs</a>.
+    <a href="{@docRoot}guide/developing/projects/index.html">Creating and Managing Projects</a>.
 </p>
 <p>
     The operation also creates an <code>AndroidManifest.xml</code> file with instrumentation
diff --git a/docs/html/guide/developing/tools/aapt.html b/docs/html/guide/developing/tools/aapt.html
new file mode 100644
index 0000000..e66a201
--- /dev/null
+++ b/docs/html/guide/developing/tools/aapt.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0;url=http://developer.android.com/guide/developing/building/index.html#detailed-build">
+<title>Redirecting...</title>
+</head>
+<body>
+<p>You should be redirected. Please <a
+href="http://developer.android.com/guide/developing/building/index.html#detailed-build">click here</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/guide/developing/tools/aapt.jd b/docs/html/guide/developing/tools/aapt.jd
deleted file mode 100644
index 40a209d..0000000
--- a/docs/html/guide/developing/tools/aapt.jd
+++ /dev/null
@@ -1,20 +0,0 @@
-page.title=Using aapt
-@jd:body
-
-<p><strong>aapt</strong> stands for Android Asset Packaging Tool and is included in the <code>tools/</code> directory of the SDK. This tool allows you to view, create, and update Zip-compatible archives (zip, jar, apk). It can also compile resources into binary assets.
-</p>
-<p>
-Though you probably won't often use <strong>aapt</strong> directly, build scripts and IDE plugins can utilize this tool to package the apk file that constitutes an Android application.
-</p>
-<p>
-For more usage details, open a terminal, go to the <code>tools/</code> directory, and run the command:
-</p>
-<ul>
-  <li><p>Linux or Mac OS X:</p>
-	<pre>./aapt</pre>
-  </li>
-  <li><p>Windows:</p>
-	<pre>aapt.exe</pre>
-  </li>
-</ul>
-
diff --git a/docs/html/guide/developing/tools/adb.jd b/docs/html/guide/developing/tools/adb.jd
index 04eed8e..bcdc2e6 100644
--- a/docs/html/guide/developing/tools/adb.jd
+++ b/docs/html/guide/developing/tools/adb.jd
@@ -79,6 +79,8 @@
   <li>A daemon, which runs as a background process on each emulator or device instance. </li>
 </ul>
 
+<p>You can find the {@code adb} tool in {@code &lt;sdk&gt;/platform-tools/}.</p>
+
 <p>When you start an adb client, the client first checks whether there is an adb server process already running. If there isn't, it starts the server process. When the server starts, it binds to local TCP port 5037 and listens for commands sent from adb clients&mdash;all adb clients use port 5037 to communicate with the adb server. </p>
 
 <p>The server then sets up connections to all running emulator/device instances. It locates emulator/device instances by scanning odd-numbered ports in the range 5555 to 5585, the range used by emulators/devices. Where the server finds an adb daemon, it sets up a connection to that port. Note that each emulator/device instance acquires a pair of sequential ports &mdash; an even-numbered port for console connections and an odd-numbered port for adb connections. For example: </p>
@@ -169,7 +171,7 @@
 
 <pre>adb install &lt;path_to_apk&gt;</pre>
 
-<p>For more information about how to create an .apk file that you can install on an emulator/device instance, see <a href="{@docRoot}guide/developing/tools/aapt.html">Android Asset Packaging Tool</a> (aapt). </p>
+<p>For more information about how to create an .apk file that you can install on an emulator/device instance, see <a href="{@docRoot}guide/developing/building/index.html">Building and Running Apps</a></p>
 
 <p>Note that, if you are using the Eclipse IDE and have the ADT plugin installed, you do not need to use adb (or aapt) directly to install your application on the emulator/device. Instead, the ADT plugin handles the packaging and installation of the application for you. </p>
 
@@ -463,7 +465,8 @@
 <tr>
 <td><code>dumpsys</code></td>
 <td>Dumps system data to the screen.</td>
-<td rowspan=4">The <a href="{@docRoot}guide/developing/tools/ddms.html">Dalvik Debug Monitor Service</a> (DDMS) tool offers integrated debug environment that you may find easier to use.</td>
+<td rowspan=4">The <a href="{@docRoot}guide/developing/debugging/ddms.html">Dalvik Debug Monitor Server</a> 
+(DDMS) tool offers integrated debug environment that you may find easier to use.</td>
 </tr>
 
 <tr>
diff --git a/docs/html/guide/developing/tools/android.jd b/docs/html/guide/developing/tools/android.jd
new file mode 100644
index 0000000..ebf95ce
--- /dev/null
+++ b/docs/html/guide/developing/tools/android.jd
@@ -0,0 +1,364 @@
+page.title=android
+@jd:body
+
+<p>{@code android} is an important development tool that lets you:</p>
+
+  <ul>
+    <li>Create, delete, and view Android Virtual Devices (AVDs). See <a href= 
+    "{@docRoot}guide/developing/devices/managing-avds-cmdline.html">
+    Creating and Managing AVDs on the Command Line</a>.</li>
+
+    <li>Create and update Android projects. See <a href= 
+    "{@docRoot}guide/developing/projects/projects-cmdline.html">Creating and Managing Projects on
+    the Command Line</a>.</li>
+
+    <li>Update your Android SDK with new platforms, add-ons, and documentation. See <a href= 
+    "{@docRoot}sdk/adding-components.html">Adding SDK Components</a>.</li>
+  </ul>If you are using Eclipse, the <code>android</code> tool's features are integrated
+  into ADT, so you should not need to use this tool directly.
+
+  <h2>Syntax</h2>
+  <pre>android [global options] action [action options]</pre>
+
+  <h3>Global Options</h3>
+
+  <dl>
+    <dt><code>-s</code></dt>
+
+    <dd>Silent mode: only errors are printed out</dd>
+
+    <dt><code>-h</code></dt>
+
+    <dd>Usage help</dd>
+
+    <dt><code>-v</code></dt>
+
+    <dd>Verbose mode: errors, warnings and informational messages are printed.</dd>
+  </dl>
+
+  <h3>AVD actions and options</h3>
+
+  <table>
+    <tr>
+      <th width="15%">Action</th>
+
+      <th width="20%">Option</th>
+
+      <th width="30%">Description</th>
+
+      <th>Comments</th>
+    </tr>
+
+    <tr>
+      <td rowspan="6"><code>create avd</code></td>
+
+      <td><code>-n &lt;name&gt;</code></td>
+
+      <td>The name for the AVD.</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-t &lt;targetID&gt;</code></td>
+
+      <td>Target ID of the system image to use with the new AVD. To obtain a list of available
+      targets, use <code>android list targets</code></td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-c &lt;path&gt;|&lt;size&gt;[K|M]</code></td>
+
+      <td>The path to the SD card image to use with this AVD or the size of a new SD card image to
+      create for this AVD. For example, <code>-c path/to/sdcard</code> or <code>-c
+      1000M</code>.</td>
+
+      <td></td>
+    </tr>
+
+    <tr>
+      <td><code>-f</code></td>
+
+      <td>Force creation of the AVD</td>
+
+      <td></td>
+    </tr>
+
+    <tr>
+      <td><code>-p &lt;path&gt;</code></td>
+
+      <td>Path to the location at which to create the directory for this AVD's files.</td>
+
+      <td></td>
+    </tr>
+
+    <tr>
+      <td><code>-s &lt;name&gt;|&lt;width&gt;-&lt;height&gt;</code></td>
+
+      <td>The skin to use for this AVD, identified by name or dimensions. The <code>android</code>
+      tool scans for a matching skin by name or dimension in the <code>skins/</code> directory of
+      the target referenced in the <code>-t &lt;targetID&gt;</code> argument. For example, <code>-s
+      HVGA-L</code></td>
+
+      <td></td>
+    </tr>
+
+    <tr>
+      <td><code>delete avd</code></td>
+
+      <td><code>-n &lt;name&gt;</code></td>
+
+      <td>The name of the AVD to delete</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td rowspan="3"><code>move avd</code></td>
+
+      <td><code>-n &lt;name&gt;</code></td>
+
+      <td>The name of the AVD to move</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-p &lt;path&gt;</code></td>
+
+      <td>Path to the location at which to create the directory for this AVD's files.</td>
+
+      <td></td>
+    </tr>
+
+    <tr>
+      <td><code>-r &lt;new-name&gt;</code></td>
+
+      <td>New name of the AVD if you want to rename it</td>
+
+      <td></td>
+    </tr>
+
+    <tr>
+      <td><code>update avd</code></td>
+
+      <td><code>-n &lt;name&gt;</code></td>
+
+      <td>The name of the AVD to move</td>
+
+      <td>Required</td>
+    </tr>
+  </table>
+
+  <h3>Project actions and options</h3>
+
+  <table>
+    <tr>
+      <th width="15%">Action</th>
+
+      <th width="20%">Option</th>
+
+      <th width="30%">Description</th>
+
+      <th>Comments</th>
+    </tr>
+
+    <tr>
+      <td rowspan="5"><code>create project</code></td>
+
+      <td><code>-n &lt;name&gt;</code></td>
+
+      <td>The name for the project</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-t &lt;targetID&gt;</code></td>
+
+      <td>Target ID of the system image to use with the new AVD. To obtain a list of available
+      targets, use <code>android list targets</code></td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-k &lt;path&gt;|&lt;size&gt;[K|M]</code></td>
+
+      <td>Package namespace</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-a</code></td>
+
+      <td>Name for the default Activity class</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-p &lt;path&gt;</code></td>
+
+      <td>Location of your project directory</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td rowspan="5"><code>update project</code></td>
+
+      <td><code>-n &lt;name&gt;</code></td>
+
+      <td>The name of the project to update</td>
+
+      <td></td>
+    </tr>
+
+    <tr>
+      <td><code>-p &lt;path&gt;</code></td>
+
+      <td>Location path of the project</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-l &lt;library path&gt;</code></td>
+
+      <td>Location path of an Android Library to add, relative to the main project</td>
+
+      <td></td>
+    </tr>
+
+    <tr>
+      <td><code>-s &lt;subprojects&gt;</code></td>
+
+      <td>Update any projects in subfolders such as test projects</td>
+
+      <td></td>
+    </tr>
+
+    <tr>
+      <td><code>-t &lt;targetID&gt;</code></td>
+
+      <td>Target id to set for the project</td>
+
+      <td></td>
+    </tr>
+
+    <tr>
+      <td rowspan="3"><code>create-test-project</code></td>
+
+      <td><code>-n &lt;name&gt;</code></td>
+
+      <td>The name of the project</td>
+
+      <td></td>
+    </tr>
+
+    <tr>
+      <td><code>-p &lt;path&gt;</code></td>
+
+      <td>Location path of the project</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-m &lt;main&gt;</code></td>
+
+      <td>The name of the project</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td rowspan="2"><code>update-test-project</code></td>
+
+      <td><code>-p &lt;path&gt;</code></td>
+
+      <td>Location path of the project to test, relative to the new project</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-m &lt;main&gt;</code></td>
+
+      <td>The main class of the project to test</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td rowspan="4"><code>create-lib-project</code></td>
+
+      <td><code>-k &lt;packageName&gt;</code></td>
+
+      <td>(Required) Package name of the library project</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-p &lt;path&gt;</code></td>
+
+      <td>Location path of the project</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-t &lt;targetID&gt;</code></td>
+
+      <td>Target ID of the library project</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-n &lt;name&gt;</code></td>
+
+      <td>The name of the project</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td rowspan="3"><code>update-lib-project</code></td>
+
+      <td><code>-p &lt;path&gt;</code></td>
+
+      <td>Location path of the project</td>
+
+      <td>Required</td>
+    </tr>
+
+    <tr>
+      <td><code>-l &lt;libraryPath&gt;</code></td>
+
+      <td>Location path of an Android Library to add, relative to the main project</td>
+
+      <td></td>
+    </tr>
+
+    <tr>
+      <td><code>-t &lt;name&gt;</code></td>
+
+      <td>Target ID of the library project</td>
+
+      <td></td>
+    </tr>
+  </table>
+
+  <h3>Update actions</h3>
+  <dl>
+  <dt><code>update adb</code></dt>
+  <dd>Updates adb to support the USB devices declared in the SDK add-ons.</dd>
+   
+  <dt><code>update sdk</code></dt>
+  <dd>Updates the SDK by suggesting new platforms to install if available.</dd>
diff --git a/docs/html/guide/developing/tools/avd.html b/docs/html/guide/developing/tools/avd.html
new file mode 100644
index 0000000..c8455db
--- /dev/null
+++ b/docs/html/guide/developing/tools/avd.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0;url=http://developer.android.com/guide/developing/devices/index.html">
+<title>Redirecting...</title>
+</head>
+<body>
+<p>You should be redirected. Please <a
+href="http://developer.android.com/guide/developing/devices/index.html">click here</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/guide/developing/tools/avd.jd b/docs/html/guide/developing/tools/avd.jd
deleted file mode 100644
index ca197cf..0000000
--- a/docs/html/guide/developing/tools/avd.jd
+++ /dev/null
@@ -1,447 +0,0 @@
-page.title=Android Virtual Devices
-@jd:body
-
-<div id="qv-wrapper">
-<div id="qv">
-
-  <h2>AVD quickview</h2>
-  <ul>
-    <li>You need to create an AVD to run any app in the Android emulator</li>
-    <li>Each AVD is a completely independent virtual device, with its own
-        hardware options, system image, and data storage.
-    <li>You create AVD configurations to model different device environments 
-        in the Android emulator.</li>
-    <li>You can launch a graphical Android AVD Manager either through Eclipse or
-through the <code>android</code> tool. The <code>android</code> tool also offers
-a command-line interface for creating and managing AVDs.</li> </ul>
-  <h2>In this document</h2>
-  <ol>
-    <li><a href="#creating">Creating an AVD</a>
-      <ol>
-        <li><a href="#hardwareopts">Setting hardware emulation options</a></li>
-        <li><a href="#location">Default location of the AVD files</a></li>
-      </ol>
-    </li>
-    <li><a href="#managing">Managing AVDs</a>
-      <ol>
-        <li><a href="#moving">Moving an AVD</a></li>
-        <li><a href="#updating">Updating an AVD</a></li>
-        <li><a href="#deleting">Deleting an AVD</a></li>
-      </ol>
-    </li>
-    <li><a href="#options">Command-line options</a></li>
-  </ol>
-  <h2>See Also</h2>
-  <ol>
-    <li><a href="{@docRoot}guide/developing/tools/emulator.html">Android 
-        Emulator</a></li>
-  </ol>
-</div>
-</div>
-
-<p>Android Virtual Devices (AVDs) are configurations of emulator options that let
-you better model an actual device.</p>
-
-<p>Each AVD is made up of: </p>
-
-<ul>
-<li>A hardware profile.&nbsp;&nbsp;You can set options to define the hardware
-features of the virtual device. For example, you can define whether the device
-has a camera, whether it uses a physical QWERTY keyboard or a dialing pad, how
-much memory it has, and so on. </li>
-<li>A mapping to a system image.&nbsp;&nbsp;You can define what version of the
-Android platform will run on the virtual device. You can choose a version of the
-standard Android platform or the system image packaged with an SDK add-on.</li>
-<li>Other options.&nbsp;&nbsp;You can specify the emulator skin you want to use
-with the AVD, which lets you control the screen dimensions, appearance, and so
-on. You can also specify the emulated SD card to use with the AVD.</li>
-<li>A dedicated storage area on your development machine, in which is stored the
-device's user data (installed applications, settings, and so on) and emulated SD
-card.</li>
-</ul>
-
-<p>You can create as many AVDs as you need, based on the types of devices you
-want to model and the Android platforms and external libraries you want to run
-your application on. </p>
-
-<p>In addition to the options in an AVD configuration, you can also
-specify emulator command-line options at launch or by using the emulator
-console to change behaviors or characteristics at run time. For a complete
-reference of emulator options, please see the <a
-href="{@docRoot}guide/developing/tools/emulator.html">Emulator</a>
-documentation. </p>
-
-<p>The easiest way to create an AVD is to use the graphical AVD Manager, which
-you can launch from Eclipse or from the command line using the
-<code>android</code> tool. The <code>android</code> tool is provided in the
-<code>tools/</code> directory of the Android SDK. When you run the
-<code>android</code> tool without options, it launches the graphical AVD
-Manager.</p>
-
-<p>For more information about how to work with AVDs from inside your development
-environment, see <a
-href="{@docRoot}guide/developing/eclipse-adt.html">Developing in Eclipse with
-ADT</a> or <a href="{@docRoot}guide/developing/other-ide.html">Developing in
-Other IDEs</a>, as appropriate for your environment.</p>
-
-<h2 id="creating">Creating an AVD</h2>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<p>The Android SDK does not include any preconfigured AVDs, so
-you need to create an AVD before you can run any application in the emulator
-(even the Hello World application).</p>
-</div>
-</div>
-<p>The easiest way to create an AVD is to use the graphical AVD Manager, but the
-<code>android</code> tool also offers a <a href="#options">command line option</a>.</p>
-<p>To create an AVD:</p>
-<ol>
-  <li>In Eclipse, choose <strong>Window &gt; Android SDK and AVD Manager</strong>. </li>
-  <p>Alternatively, you can launch the graphical AVD Manager by running the
-<code>android</code> tool with no options.</p>
-  <li>Select <strong>Virtual Devices</strong> in the left panel.</li>
-
-  <li>Click <strong>New</strong>. </li>
-
-<p>The <strong>Create New AVD</strong> dialog appears.</p> <a
-href="{@docRoot}images/developing/avd-dialog.png"><img
-src="{@docRoot}images/developing/avd-dialog.png" alt="AVD
-Dialog" /></a>
-
-  <li>Type the name of the AVD, such as "my_avd".</li>
-  <li>Choose a target. </li>
-<p>The target is the system image that you want to run on the emulator,
-from the set of platforms that are installed in your SDK environment. You can
-choose a version of the standard Android platform or an SDK add-on. For more
-information about how to add platforms to your SDK, see <a
-href="{@docRoot}sdk/adding-components.html">Adding SDK Components</a>. </p>
-  <li>Optionally specify any additional settings: </li>
-  <dl>
-  <dt><em>SD Card</em></dt> <dd>The path to the SD card image to use with this
-AVD, or the size of a new SD card image to create for this AVD.</dd> </dl>
-<dt><em>Skin</em></dt>
-    <dd>The skin to use for this AVD, identified by name or dimensions.</dd>
-<dt><em>Hardware</em></dt>
-    <dd>The hardware emulation options for the device. For a list of the options, see 
-<a href="#hardwareopts">Setting hardware emulation options</a>.</dd>
-  </dl>
-  <li>Click <strong>Create AVD</strong>.</li>
-</ol>
-
-<h3 id="hardwareopts">Setting hardware emulation options</h3>
-
-<p>When you create a new AVD that uses a standard Android system image ("Type:
-platform"), the AVD Manager
- lets you set hardware emulation
-options for your virtual device. 
-The table below lists the options available and the
-default values, as well as the names of properties that store the emulated
-hardware options in the AVD's configuration file (the <code>config.ini</code> file in the
-AVD's local directory). </p>
-
-<table>
-<tr>
-<th>Characteristic</th>
-<th>Description</th>
-<th>Property</th>
-</tr>
-
-<tr>
-<td>Device ram size</td>
-<td>The amount of physical RAM on the device, in megabytes. Default value is "96".
-<td>hw.ramSize</td>
-</tr>
-
-<tr>
-<td>Touch-screen support</td>
-<td>Whether there is a touch screen or not on the device. Default value is "yes".</td>
-<td>hw.touchScreen
-
-<tr>
-<td>Trackball support </td>
-<td>Whether there is a trackball on the device. Default value is "yes".</td>
-<td>hw.trackBall</td>
-</tr>
-
-<tr>
-
-<td>Keyboard support</td>
-<td>Whether the device has a QWERTY keyboard. Default value is "yes".</td>
-<td>hw.keyboard</td>
-</tr>
-
-<tr>
-<td>DPad support</td>
-<td>Whether the device has DPad keys. Default value is "yes".</td>
-<td>hw.dPad</td>
-</tr>
-
-<tr>
-<td>GSM modem support</td>
-<td>Whether there is a GSM modem in the device. Default value is "yes".</td>
-<td>hw.gsmModem</td>
-</tr>
-
-<tr>
-<td>Camera support</td>
-<td>Whether the device has a camera. Default value is "no".</td>
-<td>hw.camera</td>
-</tr>
-
-<tr>
-<td>Maximum horizontal camera pixels</td>
-<td>Default value is "640".</td>
-<td>hw.camera.maxHorizontalPixels</td>
-</tr>
-
-<tr>
-<td>Maximum vertical camera pixels</td>
-<td>Default value is "480".</td>
-<td>hw.camera.maxVerticalPixels</td>
-
-</tr>
-
-<tr>
-<td>GPS support</td>
-<td>Whether there is a GPS in the device. Default value is "yes".</td>
-<td>hw.gps</td>
-</tr>
-
-<tr>
-<td>Battery support</td>
-<td>Whether the device can run on a battery. Default value is "yes".</td>
-<td>hw.battery</td>
-
-</tr>
-
-<tr>
-<td>Accelerometer</td>
-<td>Whether there is an accelerometer in the device. Default value is "yes".</td>
-<td>hw.accelerometer</td>
-</tr>
-
-<tr>
-<td>Audio recording support</td>
-<td>Whether the device can record audio. Default value is "yes".</td>
-<td>hw.audioInput</td>
-
-</tr>
-
-<tr>
-<td>Audio playback support</td>
-<td>Whether the device can play audio. Default value is "yes".</td>
-<td>hw.audioOutput</td>
-</tr>
-
-<tr>
-<td>SD Card support</td>
-<td>Whether the device supports insertion/removal of virtual SD Cards. Default value is "yes".</td>
-<td>hw.sdCard</td>
-
-</tr>
-
-<tr>
-<td>Cache partition support</td>
-<td>Whether we use a /cache partition on the device. Default value is "yes".</td>
-<td>disk.cachePartition</td>
-</tr>
-
-<tr>
-<td>Cache partition size</td>
-<td>Default value is "66MB".</td>
-<td>disk.cachePartition.size </td>
-
-</tr>
-
-<tr>
-<td>Abstracted LCD density</td>
-<td>Sets the generalized density characteristic used by the AVD's screen. Most
-skins come with a value (which you can modify), but if a skin doesn't provide
-its own value, the default is 160. </td>
-<td>hw.lcd.density </td>
-</tr>
-
-<tr>
-<td>Max VM application heap size</td>
-<td>The maximum heap size a Dalvik application might allocate before being
-killed by the system. Value is in megabytes. Most skins come with a value (which
-you can modify), but if a skin doesn't provide its own value, the default is
-16.</td> 
-<td>vm.heapSize</td>
-</tr>
-
-</table>
-
-<h3 id="location">Default location of the AVD files</h3>
-
-<p>When you create an AVD, the AVD Manager creates a dedicated directory for it
-on your development computer. The directory contains the AVD configuration file,
-the user data image and SD card image (if available), and any other files
-associated with the device. Note that the directory does not contain a system
-image &mdash; instead, the AVD configuration file contains a mapping to the
-system image, which it loads when the AVD is launched. </p>
-
-<p>The AVD Manager also creates a <code>&lt;AVD name&gt;.ini</code> file for the
-AVD at the root of the <code>.android/avd</code> directory on your computer. The file
-specifies the location of the AVD directory and always remains at the root the
-.android directory.</p>
-
-<p>By default, the AVD Manager creates the AVD directory inside
-<code>~/.android/avd/</code> (on Linux/Mac), <code>C:\Documents and
-Settings\&lt;user&gt;\.android\</code> on Windows XP, and 
-<code>C:\Users\&lt;user&gt;\.android\</code> on Windows Vista. 
-If you want to use a custom location for the AVD directory, you 
-can do so by using the <code>-p &lt;path&gt;</code> option when 
-you create the AVD (command line tool only): </p>
-
-<pre>android create avd -n my_android1.5 -t 2 -p path/to/my/avd</pre>
-
-<p>If the <code>.android</code> directory is hosted on a network drive, we recommend using
-the <code>-p</code> option to place the AVD directory in another location. 
-The  AVD's <code>.ini</code> file remains in the <code>.android</code> directory on the network
-drive, regardless of the location of the AVD directory. </p>
-
-<h2 id="managing">Managing AVDs</h2>
-
-<p>The sections below provide more information about how to manage AVDs once you've created them. </p>
-
-<h3 id="moving">Moving an AVD</h3>
-
-<p>If you want to move or rename an AVD, you can do so using this command:</p>
-
-<pre>android move avd -n &lt;name&gt; [-&lt;option&gt; &lt;value&gt;] ...</pre>
-
-<p>The options for this command are listed in <a href="#options">Command-line
-options for AVDs</a> at the bottom of this page. </p>
-
-<h3 id="updating">Updating an AVD</h3>
-
-<p>
-If you rename or move the root directory of a platform (or add-on), an AVD configured to use that platform will no longer be able to load the system image properly. To fix the AVD, use the <strong>Repair...</strong> button in the AVD Manager. From the command line, you can also use the <code>android update avd</code> command to recompute the path to the system images.</p>
-
-<h3 id="deleting">Deleting an AVD</h3>
-
-<p>You can  delete an AVD in the AVD Manager by selecting the 
-AVD and clicking <strong>Delete</strong>.</p>
-
-<p>Alternatively, you can use the <code>android</code> tool to delete an AVD. Here is the command usage:</p>
-
-<pre>android delete avd -n &lt;name&gt; </pre>
-
-<p>When you issue the command, the <code>android</code> tool looks for an AVD matching the 
-specified name deletes the AVD's directory and files. </p>
-
-
-<h2 id="options">Command-line options</h2>
-
-<p>You can use the <code>android</code> tool to create and manage AVDs.</p>
-
-<p>The command line for creating an AVD has the following syntax:</p>
-
-<pre>
-android create avd -n &lt;name&gt; -t &lt;targetID&gt; [-&lt;option&gt; &lt;value&gt;] ... 
-</pre>
-
-<p>Here's an example that creates an AVD with the name "my_android2.2" and target ID "3":</p>
-
-<pre>
-android create avd -n my_android2.2 -t 3
-</pre>
-
-<p>The table below lists the command-line options you can use with the 
-<code>android</code> tool. </p>
-
-
-<table>
-<tr>
-  <th width="15%">Action</th>
-  <th width="20%">Option</th>
-  <th width="30%">Description</th>
-  <th>Comments</th>
-</tr>
-
-
-<tr>
-  <td><code>list&nbsp;avds</code></td>
-  <td>&nbsp;</td>
-  <td>List all known AVDs, with name, path, target, and skin. </td>
-  <td>&nbsp;</td>
-</tr>
-<tr>
-  <td rowspan="6"><code>create&nbsp;avd</code></td>
-  <td><code>-n &lt;name&gt; or <br></code></td>
-  <td>The name for the AVD.</td>
-  <td>Required</td>
-</tr>
-<tr>
-  <td><code>-t &lt;targetID&gt;</code></td>
-  <td>Target ID of the system image to use with the new AVD.</td>
-  <td>Required. To obtain a list of available targets, use <code>android list
-      targets</code>.</td>
-</tr>
-<tr>
-  <td><code>-c &lt;path&gt;</code> or <br>
-      <code>-c &lt;size&gt;[K|M]</code></td>
-  <td>The path to the SD card image to use with this AVD or the size of a new SD
-      card image to create for this AVD.</td>
-  <td>Examples: <code>-c path/to/sdcard</code> or <code>-c 1000M</code></td>
-</tr>
-<tr>
-  <td><code>-f</code></td>
-  <td>Force creation of the AVD</td>
-  <td>By default, if the name of the AVD being created matches that of an 
-      existing AVD, the <code>android</code> tool will not create the new AVD or overwrite 
-      the existing AVD. If you specify the <code>-f</code> option, however, the 
-      <code>android</code> tool will automatically overwrite any existing AVD that has the 
-      same name as the new AVD. The files and data of the existing AVD are 
-      deleted. </td>
-</tr>
-
-<tr>
-  <td><code>-p &lt;path&gt;</code></td>
-  <td>Path to the location at which to create the directory for this AVD's
-files.</td>
-  <td>&nbsp;</td>
-</tr>
-<tr>
-  <td><code>-s &lt;name&gt;</code> or <br>
-      <code>-s &lt;width&gt;-&lt;height&gt;</code> </td>
-  <td>The skin to use for this AVD, identified by name or dimensions.</td>
-  <td>The <code>android</code> tool scans for a matching skin by name or dimension in the
-<code>skins/</code> directory of the target referenced in the <code>-t
-&lt;targetID&gt;</code> argument. Example: <code>-s HVGA-L</code></td>
-</tr>
-<tr>
-  <td><code>delete&nbsp;avd</code></td>
-  <td><code>-n &lt;name&gt;</code></td>
-  <td>Delete the specified AVD.</td>
-  <td>Required</td>
-</tr>
-<tr>
-  <td rowspan="3"><code>move&nbsp;avd</code></td>
-  <td><code>-n &lt;name&gt;</code></td>
-  <td>The name of the AVD to move.</td>
-  <td>Required</td>
-</tr>
-<tr>
-  <td><code>-p &lt;path&gt;</code></td>
-  <td>The path to the new location for the AVD.</td>
-  <td>&nbsp;</td>
-</tr>
-<tr>
-  <td><code>-r &lt;new-name&gt;</code></td>
-  <td>Rename the AVD.</td>
-  <td>&nbsp;</td>
-</tr>
-<tr>
-  <td><code>update&nbsp;avds</code></td>
-  <td>&nbsp;</td>
-  <td>Recompute the paths to all system images.</td>
-  <td>&nbsp;</td>
-</tr>
-
-
-
-</table>
-
diff --git a/docs/html/guide/developing/tools/ddms.html b/docs/html/guide/developing/tools/ddms.html
new file mode 100644
index 0000000..052ccc9
--- /dev/null
+++ b/docs/html/guide/developing/tools/ddms.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0;url=http://developer.android.com/guide/developing/debugging/ddms.html">
+<title>Redirecting...</title>
+</head>
+<body>
+<p>You should be redirected. Please <a
+href="http://developer.android.com/guide/developing/debugging/ddms.html">click here</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/guide/developing/tools/ddms.jd b/docs/html/guide/developing/tools/ddms.jd
deleted file mode 100644
index f55940d..0000000
--- a/docs/html/guide/developing/tools/ddms.jd
+++ /dev/null
@@ -1,251 +0,0 @@
-page.title=Using the Dalvik Debug Monitor
-@jd:body
-
-<p>Android ships with a debugging tool called the Dalvik Debug Monitor Server (DDMS),
-    which provides port-forwarding services, screen capture on the device, thread
-    and heap information on the device, logcat, process, and radio state information,
-    incoming call and SMS spoofing, location data spoofing, and more. This page
-    provides a modest discussion of DDMS features; it is not an exhaustive exploration of
-    all the features and capabilities.</p>
-
-<p>DDMS ships in the <code>tools/</code> directory of the SDK.
-    Enter this directory from a terminal/console and type <code>ddms</code> (or <code>./ddms</code> 
-    on Mac/Linux) to run it. DDMS will work with both the emulator and a connected device. If both are
-    connected and running simultaneously, DDMS defaults to the emulator.</p>
-
-<h2 id="how-ddms-works">How DDMS works</h2>
-<p>DDMS acts as a middleman to connect the IDE to the applications running on
-the device. On Android, every application runs in its own process, 
-each of which hosts its own virtual machine (VM). And each process
-listens for a debugger on a different port.</p>
-
-<p>When it starts, DDMS connects to <a href="{@docRoot}guide/developing/tools/adb.html">adb</a> and 
-starts a device monitoring service between the two, which will notify DDMS when a device is
-connected or disconnected. When a device is connected, a VM monitoring service is created
-between adb and DDMS, which will notify DDMS when a VM on the device is started 
-or terminated. Once a VM is running, DDMS retrieves the the VM's process ID (pid), via adb,
-and opens a connection to the VM's debugger, through the adb daemon (adbd) on the device. 
-DDMS can now talk to the VM using a custom wire protocol.</p>
-
-<p>For each VM on the device, DDMS opens a port upon which it will listen for a debugger. For the first VM, DDMS listens for a debugger on port 8600, the next on 8601, and so on. When a debugger connects to one of these ports, all traffic is forwarded between the debugger and the associated VM. Debugging can then process like any remote debugging session.</p>
-
-<p>DDMS also opens another local port, the DDMS "base port" (8700, by default), upon which it also listens for a debugger. When a debugger connects to this base port, all traffic is forwarded to the VM currently selected in DDMS, so this is typically where you debugger should connect.</p>
-
-<p>For more information on port-forwarding with DDMS,
-read <a href="{@docRoot}guide/developing/debug-tasks.html#ide-debug-port">Configuring your IDE to attach
-to port 8700 for debugging</a>.</p>
-
-<p class="note"><strong>Tip:</strong>
-You can set a number of DDMS preferences in <strong>File</strong> > <strong>Preferences</strong>.
-Preferences are saved to &quot;$HOME/.ddmsrc&quot;. </p>
-
-<p class="warning"><strong>Known debugging issues with Dalvik</strong><br/>
-Debugging an application in the Dalvik VM should work the same as it does
-in other VMs. However, when single-stepping out of synchronized code, the "current line"
-cursor may jump to the last line in the method for one step.</p>
-
-
-<h2 id="left-pane">Left Pane</h2>
-<p>The left side of the Debug Monitor shows each emulator/device currently found, with a list of 
-    all the VMs currently running within each. 
-    VMs are identified by the package name of the application it hosts.</p>
-<p>Use this list to find and attach to the VM
-    running the activity(ies) that you want to debug. Next to each VM in the
-    list is a &quot;debugger pass-through&quot; port (in the right-most column). 
-    If you connect your debugger to one of the the ports listed, you
-    will be connected to the corresponding VM on the device. However, when using 
-    DDMS, you need only connect to port 8700, as DDMS forwards all traffic here to the 
-    currently selected VM. (Notice, as you select a VM in the list, the listed port includes 8700.)
-    This way, there's no need to reconfigure the debugger's port each time you switch between VMs.</p>
-<p>When an application running on the device calls {@link android.os.Debug#waitForDebugger()}
-    (or you select this option in the <a href="{@docRoot}guide/developing/debug-tasks.html#additionaldebugging">developer
-    options</a>), a red icon will be shown next to the client name, while it waits for the 
-    debugger to attach to the VM. When a debugger is connected, the icon will turn green. </p>
-<p>If you see a crossed-out bug icon, this means that the DDMS was unable to complete a 
-connection between the debugger and the VM because it was unable to open the VM's local port.
-If you see this for all VMs on the device, it is likely because you have another instance of
-DDMS running (this includes the Eclipse plugin).</p>
-<p>If you see a question mark in place of an application package, this means that, 
-once DDMS received the application pid from adb, it
-somehow failed to make a successful handshake with the VM process. Try restarting DDMS.</p>
-
-
-<h2 id="right-pane">Right pane</h2>
-<p>On the right side, the Debug Monitor provides tabs that display useful information 
-and some pretty cool tools.</p>
-
-<h3 id="info">Info</h3>
-<p>This view shows some general information about the selected VM, including the process
-    ID, package name, and VM version.</p>
-
-<h3 id="threads">Threads</h3>
-<p> The threads view has a list of threads running in the process of the target VM.
-     To reduce the amount
-    of data sent over the wire, the thread updates are only sent when explicitly
-    enabled by toggling the &quot;threads&quot; button
-    in the toolbar. This toggle is maintained per VM. This tab includes the following
-    information: </p>
-<ul>
-    <li> <strong>ID</strong> - a VM-assigned unique thread ID. In Dalvik, these are
-        odd numbers starting from 3. </li>
-    <li> <strong>Tid</strong> - the Linux thread ID. For the main thread in a process,
-        this will match the process ID. </li>
-    <li> <strong>Status</strong> - the VM thread status. Daemon threads are
-        shown with an asterisk (*). This will be one of the following:
-        <ul>
-                <li> <em>running</em> - executing application code </li>
-            <li> <em>sleeping</em> - called Thread.sleep() </li>
-            <li> <em>monitor</em> - waiting to acquire a monitor lock </li>
-            <li> <em>wait</em> - in Object.wait() </li>
-            <li> <em>native</em> - executing native code </li>
-            <li> <em>vmwait</em> - waiting on a VM resource </li>
-            <li> <em>zombie</em> - thread is in the process of dying </li>
-            <li> <em>init</em> - thread is initializing (you shouldn't see this) </li>
-            <li> <em>starting</em> - thread is about to start (you shouldn't see
-                this either) </li>
-        </ul>
-    </li>
-    <li> <strong>utime</strong> - cumulative time spent executing user code, in &quot;jiffies&quot; (usually
-        10ms). </li>
-    <li> <strong>stime</strong> - cumulative time spent executing system code, in &quot;jiffies&quot;  (usually
-        10ms). </li>
-    <li> <strong>Name</strong> - the name of the thread</li>
-</ul>
-<p> &quot;ID&quot; and &quot;Name&quot; are set when the thread is started. The remaining
-    fields are updated periodically (default is every 4 seconds). </p>
-
-<h3 id="vm-heap">VM Heap</h3>
-<p> Displays some heap stats, updated during garbage collection. If, when a VM is selected,
-the VM Heap view says that heap updates are not enabled, click the "Show heap updates" button, 
-located in the top-left toolbar. Back in the VM Heap view, click <strong>Cause GC</strong> 
-to perform garbage collection and update the heap stats.</p>
-
-
-<h3 id="allocation-tracker">Allocation Tracker</h3>
-<p>In this view, you can track the memory allocation of each virtual machine.
-With a VM selected in the left pane, click <strong>Start Tracking</strong>, then 
-<strong>Get Allocations</strong> to view all allocations since tracking started. 
-The table below will be filled with all the relevant
-data. Click it again to refresh the list.</p>
-
-
-<h3 id="emulator-control">Emulator Control</h3>
-<p>With these controls, you can simulate special device states and activities.
-Features include:</p>
-<ul>
-<li><strong>Telephony Status</strong> - change the state of the phone's Voice and Data plans
-    (home, roaming, searching, etc.), and simulate different kinds of network Speed and Latency
-    (GPRS, EDGE, UTMS, etc.).</li>
-<li><strong>Telephony Actions</strong> - perform simulated phone calls and SMS messages to the emulator.</li>
-<li><strong>Location Controls</strong> - send mock location data to the emulator so that you can perform
-  location-aware operations like GPS mapping.
-
-<p>To use the Location Controls, launch your application in the Android emulator and open DDMS. 
-Click the Emulator Controls tab and scroll down to Location Controls.
-From here, you can:</p>
-<ul class="listhead">
-    <li>Manually send individual longitude/latitude coordinates to the device.
-	<p>Click <strong>Manual</strong>, 
-	select the coordinate format, fill in the fields and click <strong>Send</strong>.
-	</p>
-    </li>
-    <li>Use a GPX file describing a route for playback to the device.
-	<p>Click <strong>GPX</strong> and load the file. Once loaded,
-	click the play button to playback the route for your location-aware application.</p>	
-	<p>When performing playback from GPX, you can adjust the speed of 
-	playback from the DDMS panel and control playback with the pause and skip buttons.
-	DDMS will parse both the waypoints (<code>&lt;wpt></code>, in the first table), 
-        and the tracks (<code>&lt;trk></code>,
-	in the second table, with support for multiple segments, <code>&lt;trkseg></code>, 
-        although they are simply
-	concatenated). Only the tracks can be played. Clicking a waypoint in the first list simply
-	sends its coordinate to the device, while selecting a track lets you play it.</p>
-    </li>
-    <li>Use a KML file describing individual placemarks for sequenced playback to the device.
-	<p>Click <strong>KML</strong> and load the file. Once loaded,
-	click the play button to send the coordinates to your location-aware application.</p>
-	<p>When using a KML file, it is parsed for a <code>&lt;coordinates&gt;</code>
-    	element. The value of which should be a single 
-    	set of longitude, latitude and altitude figures. For example:</p>
-	<pre>&lt;coordinates>-122.084143,37.421972,4&lt;/coordinates></pre>
-	<p>In your file, you may include multiple <code>&lt;Placemark></code> elements, each containing
-	a <code>&lt;coordinates></code> element. When you do so, the collection of placemarks will 
-	be added as tracks. DDMS will send one placemark per second to the device.</p>
-	<p>One way to generate a suitable KML file is to find a location in Google Earth.
-	Right-click the location entry that appears on the left and select "Save place as..." 
-	with the save format set to Kml.</p>
-<p class="note"><strong>Note:</strong> DDMS does not support routes created with the 
-<code>&lt;MultiGeometry>&lt;LineString>lat1, long1, lat2, long2, ....&lt;/LineString>&lt;/MultiGeometry></code> methods.
-	There is also currently no support for the <code>&lt;TimeStamp></code> node inside
-	the <code>&lt;Placemark></code>.
-	Future releases may support timed placement and routes within a single coordinate element.</p>
-    </li>
-  </ul>
-  <p>For <em>additional</em> methods of setting up mocks of location-based data, see the 
-  <a href="{@docRoot}guide/topics/location/index.html">Location</a> topic.</p>
-  </li>
-</ul>
-
-
-<!-- <h4>Event Log</h4> -->
-
-
-<h2 id="file-explorer">File Explorer</h2>
-<p>With the File Explorer, you can view the device file system and perform basic management, 
-like pushing and pulling files. This circumvents using the <a href="{@docRoot}guide/developing/tools/adb.html">adb</a>
-<code>push</code> and <code>pull</code> commands, with a GUI experience.</p>
-<p>With DDMS open, select <strong>Device</strong> > <strong>File Explorer...</strong> to open the
-File Explorer window. You can drag-and-drop into the device directories, but cannot drag <em>out</em> of them.
-To copy files from the device, select the file and click the <strong>Pull File from Device</strong>
-button in the toolbar. To delete files, use the <strong>Delete</strong> button in the toolbar.</p>
-<p>If you're interested in using an SD card image on the emulator, you're still required to use
-the <code>mksdcard</code> command to create an image, and then mount it during emulator bootup. 
-For example, from the <code>/tools</code> directory, execute:</p>
-<pre>
-<b>$</b> mksdcard 1024M ./img
-<b>$</b> emulator -sdcard ./img
-</pre>
-<p>Now, when the emulator is running, the DDMS File Explorer will be able to read and write to the 
-sdcard directory. However, your files may not appear automatically. For example, if you add an
-MP3 file to the sdcard, the media player won't see them until you restart the emulator. (When restarting
-the emulator from command line, be sure to mount the sdcard again.)</p>
-<p>For more information on creating an SD card image, see the 
-<a href="{@docRoot}guide/developing/tools/othertools.html#mksdcard">Other Tools</a> document.</p>
-
-<h2 id="screen-capture">Screen Capture</h2>
-<p>You can capture screen images on the device or emulator by selecting <strong>Device</strong>
-    &gt; <strong>Screen capture...</strong> in the menu bar, or press CTRL-S.
-	Be sure to select a device first.</p>
-
-<h2 id="exploring-processes">Exploring Processes</h2>
-<p>You can see the output of <code>ps -x</code> for a specific VM by selecting <strong>Device</strong>
-    &gt; <strong>Show process status</strong>... in the menu bar.</p>
-
-<h2 id="cause-a-gc-to-occur">Cause a GC to Occur</h2>
-<p>Cause garbage collection to occur in the selected application by pressing the trash can button on the toolbar. </p>
-
-<h2 id="running-dumpsys-and-dumpstate">Running Dumpsys and Dumpstate on the Device (logcat)<a name="logcat" id="logcat"></a> </h2>
-<ul>
-        <li>To run <strong>dumpsys</strong> (logcat) from Dalvik, select <strong>Device</strong> &gt; 
-            <strong>Run logcat...</strong> in the menu bar.</li>
-    <li>To run <strong>dumpstate</strong> from Dalvik, select <strong>Device</strong> &gt; <strong>Dump device
-        state...</strong> in the menu bar. </li>
-</ul>
-
-<h2 id="examine-radio-state">Examine Radio State</h2>
-<p>By default, radio state is not output during a standard logcat (it is a lot of
-    information). To see radio information, either click <strong>Device</strong> &gt; <strong>Dump radio
-    state...</strong> or run logcat as described in <a href="{@docRoot}guide/developing/debug-tasks.html#logradio">Logging
-    Radio Information</a>. </p>
-
-<h2 id="stop-a-vitrual-machine">Stop a Virtual Machine </h2>
-<p>You can stop a virtual machine by selecting <strong>Actions</strong> &gt; <strong>Halt
-VM</strong>. Pressing this button causes the VM to call <code>Runtime.halt(1)</code>.</p>
-
-<h2 id="known-issues" style="color:#FF0000">Known issues with DDMS </h2>
-<p>DDMS has the following known limitations:</p>
-<ul>
-    <li>If you connect and disconnect a debugger, ddms drops and reconnects the
-        client so the VM realizes that the debugger has gone away. This will be fixed
-        eventually. </li>
-</ul>
diff --git a/docs/html/guide/developing/tools/dmtracedump.jd b/docs/html/guide/developing/tools/dmtracedump.jd
new file mode 100644
index 0000000..492a049
--- /dev/null
+++ b/docs/html/guide/developing/tools/dmtracedump.jd
@@ -0,0 +1,64 @@
+page.title=dmtracedump
+@jd:body
+
+
+ <p><code>dmtracedump</code> is a tool that gives you an alternate way of generating
+  graphical call-stack diagrams from trace log files (instead of using Traceview).</p>
+  
+  <p>This document is a reference to the available command line options. For more information on generating trace
+  logs, see <a href="{@docRoot}guide/developing/debugging/debugging-tracing.html">Profiling with
+  Traceview and dmtracedump</a>.</p>
+
+  <p>The usage for <code>dmtracedump</code> is:</p>
+  <pre>
+dmtracedump [-ho] [-s sortable] [-d trace-base-name] [-g outfile] &lt;trace-base-name&gt;
+</pre>
+
+  <p>The tool then loads trace log data from <code>&lt;trace-base-name&gt;.data</code> and
+  &lt;trace-base-name&gt;.key. The table below lists the options for dmtracedump.</p>
+
+  <table>
+    <tr>
+      <th>Option</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <td><nobr><code>-d&nbsp;<em>&lt;trace-base-name&gt;</em></code></nobr></td>
+
+      <td>Diff with this trace name</td>
+    </tr>
+
+    <tr>
+      <td><code>-g&nbsp;<em>&lt;outfile&gt;</em></code></td>
+
+      <td>Generate output to &lt;outfile&gt;</td>
+    </tr>
+
+    <tr>
+      <td><code>-h</code></td>
+
+      <td>Turn on HTML output</td>
+    </tr>
+
+    <tr>
+      <td><code>-o</code></td>
+
+      <td>Dump the trace file instead of profiling</td>
+    </tr>
+
+    <tr>
+      <td><code>-d&nbsp;<em>&lt;trace-base-name&gt;</em></code></td>
+
+      <td>URL base to the location of the sortable javascript file</td>
+    </tr>
+
+    <tr>
+      <td><code>-t&nbsp;&lt;percent&gt;</code></td>
+
+      <td>Minimum threshold for including child nodes in the graph (child's inclusive time as a
+      percentage of parent inclusive time). If this option is not used, the default threshold is
+      20%.</td>
+    </tr>
+  </table>
\ No newline at end of file
diff --git a/docs/html/guide/developing/tools/draw9patch.jd b/docs/html/guide/developing/tools/draw9patch.jd
index 61da1e0..4d8043b 100644
--- a/docs/html/guide/developing/tools/draw9patch.jd
+++ b/docs/html/guide/developing/tools/draw9patch.jd
@@ -4,8 +4,9 @@
 <p>The Draw 9-patch tool allows you to easily create a 
    {@link android.graphics.NinePatch} graphic using a WYSIWYG editor.</p>
 <p>For an introduction to Nine-patch graphics and how they work, please read 
-the section on Nine-patch in the 
-<a href="{@docRoot}guide/topics/resources/available-resources.html#ninepatch">Nine-patch Images</a> topic.</p>
+the section about Nine-patch in the 
+<a href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">2D Graphics</a>
+document.</p>
 
 <img src="{@docRoot}images/draw9patch-norm.png" style="float:right" alt="" height="300" width="341"
 />
diff --git a/docs/html/guide/developing/tools/emulator.jd b/docs/html/guide/developing/tools/emulator.jd
index 2250979..9baf1a1 100644
--- a/docs/html/guide/developing/tools/emulator.jd
+++ b/docs/html/guide/developing/tools/emulator.jd
@@ -1,321 +1,29 @@
 page.title=Android Emulator
 @jd:body
-
-<div style="padding:1em;"><img src="/images/emulator-wvga800l.png" alt="Image of the Android Emulator" width="367" height="349" style="margin-left:2em;margin-top:-4em;float:right;"/></div>
-
-<p>The Android SDK includes a mobile device emulator -- a virtual mobile device 
-that runs on your computer. The emulator lets you prototype, develop, and test 
-Android applications without using a physical device. </p>
-
-<p>The Android emulator mimics all of the hardware and software features 
-of a typical mobile device, except that it can not receive or place actual phone 
-calls. It provides a variety of navigation and control keys, which you can "press" 
-using your mouse or keyboard to generate events for your application. It also 
-provides a screen in which your application is displayed, together with any other 
-Android applications running. </p>
-
-<p>To let you model and test your application more easily, the emulator supports
-Android Virtual Device (AVD) configurations. AVDs let you specify the Android
-platform that you want to run on the emulator, as well as the hardware options
-and emulator skin files tht you want to use. Once your application is running on
-the emulator, it can use the services of the Android platform to invoke other
-applications, access the network, play audio and video, store and retrieve data,
-notify the user, and render graphical transitions and themes. </p>
-
-<p>The emulator also includes a variety of debug capabilities, such as a console 
-from which you can log kernel output, simulate application interrupts (such as 
-arriving SMS messages or phone calls), and simulate latency effects and dropouts 
-on the data channel.</p>
-
-<table>
-<tr>
-<td colspan="2" style="border:0;"><strong>In this document:</strong></td>
-</tr>
-<tr>
-<td style="border:0;">
-
-<ol class="toc">
-<li><a href="#overview">Overview</a></li>
-<li><a href="#starting">Starting and Stopping the Emulator</a></li>
-<li><a href="#starting">Android Virtual Devices and the Emulator</a></li>
-<li><a href="#controlling">Controlling the Emulator</a></li>
-<li><a href="#startup-options">Emulator Startup Options</a></li>
-<li><a href="#diskimages">Working with Emulator Disk Images</a>
-	<ol class="toc">
-	<li><a href="#defaultimages">Default Images</a></li>
-	<li><a href="#runtimeimages">Runtime Images: User Data and SD Card</a></li>
-	<li><a href="#temporaryimages">Temporary Images</a></li>
-	</ol></li>
-<li><a href="#emulatornetworking">Emulator Networking</a>
-	<ol class="toc">
-	<li><a href="#networkaddresses">Network Address Space</a></li>
-	<li><a href="#networkinglimitations">Local Networking Limitations</a></li>
-	<li><a href="#redirections">Using Network Redirections</a></li>
-	<li><a href="#dns">Configuring the Emulator's DNS Settings</a></li>
-	<li><a href="#proxy">Using the Emulator with a Proxy</a></li>
-	<li><a href="#connecting">Interconnecting Emulator Instances</a></li>
-	<li><a href="#calling">Sending a Voice Call or SMS to Another Emulator Instance</a></li>
-	</ol></li>
-</ol>
-</td>
-
-<td style="border:0;">
-<ol class="toc">
-<li><a href="#console">Using the Emulator Console</a>
-	<ol class="toc">
-	<li><a href="#portredirection">Port Redirections</a></li>
-	<li><a href="#geo">Geo Location Provider Emulation</a></li>
-	<li><a href="#events">Sending Events</a></li>
-	<li><a href="#power">Emulating Device Power Characteristics</a></li>
-	<li><a href="#netstatus">Network Status</a></li>
-	<li><a href="#netdelay">Network Delay Emulation</a></li>
-	<li><a href="#netspeed">Network Speed Emulation</a></li>
-	<li><a href="#telephony">Telephony Emulation</a></li>
-	<li><a href="#sms">SMS Emulation</a></li>
-	<li><a href="#vm">VM State</a></li>
-	<li><a href="#window">Emulator Window</a></li>
-	<li><a href="#terminating">Terminating an Emulator Instance</a></li>
-	</ol></li>
-<li><a href="#skins">Using Emulator Skins</a></li>
-<li><a href="#multipleinstances">Running Multiple Instances of the Emulator</a></li>
-<li><a href="#apps">Installing Applications on the Emulator</a></li>
-<li><a href="#sdcard">SD Card Emulation</a>
-	<ol class="toc">
-	<li><a href="#creatinga">Creating an SD card image using the android tool</li>
-	<li><a href="#creatingm">Creating an SD card image using mksdcard</a></li>
-	<li><a href="#copying">Copying Files to a Disk Image</a></li>
-	<li><a href="#loading">Loading the Disk Image at Emulator Startup</a></li>
-	</ol></li>
-<li><a href="#troubleshooting">Troubleshooting Emulator Problems</a></li>
-<li><a href="#limitations">Emulator Limitations</a></li>
-</ol>
-</td>
-
-</table>
-
-<a name="overview"></a>
-
-<h2>Overview</h2>
-
-<p>The Android emulator is a QEMU-based application that provides a virtual ARM
-mobile device on which you can run your Android applications. It runs a full
-Android system stack, down to the kernel level, that includes a set of
-preinstalled applications (such as the dialer) that you can access from your
-applications. You can choose what version of the Android system you want to 
-run in the emulator by configuring AVDs, and you can also customize the 
-mobile device skin and key mappings. When launching the emulator and at runtime,
-you can use a variety of commands and options to control the its behaviors. 
-</p>
-
-<p>The Android system image distributed in the SDK contains ARM machine code for
-the Android Linux kernel, the native libraries, the Dalvik VM, and the various
-Android package files (such as for for the Android framework and preinstalled
-applications). The emulator's QEMU layers provide dynamic binary translation of
-the ARM machine code to the OS and processor architecture of your development
-machine. </p>
-
-<p>Adding custom capabilities to the underlying QEMU services, the Android
-emulator supports many hardware features likely to be found on mobile devices,
-including: </p>
-
-<ul>
-  <li>An ARMv5 CPU and the corresponding memory-management unit (MMU)</li>
-  <li>A 16-bit LCD display</li>
-  <li>One or more keyboards (a Qwerty-based keyboard and associated Dpad/Phone
-buttons)</li>
-  <li>A sound chip with output and input capabilities</li>
-  <li>Flash memory partitions (emulated through disk image files on the
-development machine)</li>
-  <li>A GSM modem, including a simulated SIM Card</li>
-</li>
-</ul>
-
-<p>The sections below provide more information about the emulator and how to use
-it for developing Android applications.</p>
-
-<a name="starting"></a>
-
-<h2>Starting and Stopping the Emulator</h2>
-
-<p>During development and testing of your application, you install and run your
-application in the Android emulator. You can launch the emulator as a standalone
-application, from a command line, or you can use it as part of your Eclipse
-development environment. In either case, you specify the AVD configuration to 
-load and any startup options you want to use, as described in this document.
-</p>
-
-<p>You can run your application on a single instance of the emulator or,
-depending on your needs, you can start multiple emulator instances and run your
-application in more than one emulated device. You can use the emulator's
-built-in commands to simulate GSM phone calling or SMS between emulator
-instances, and you can set up network redirections that allow emulators to send
-data to one another. For more information, see <a href="#telephony">Telephony
-Emulation</a>, <a href="#sms">SMS Emulation</a>, and 
-<a href="#emulatornetworking">Emulator Networking</a></p>
-
-<p>To start an instance of the emulator from the command line, change to the
-<code>tools/</code> folder of the SDK. Enter <code>emulator</code> command
-like this: </p>
-
-<pre>emulator -avd &lt;avd_name&gt;</pre> 
-
-<p>This initializes the emulator and loads an AVD configuration (see the next
-section for more information about AVDs). You will see the emulator window
-appear on your screen. </p>
-
-<p>If you are working in Eclipse, the ADT plugin for Eclipse installs your
-application and starts the emulator automatically, when you run or debug 
-the application. You can specify emulator startup options in the Run/Debug 
-dialog, in the Target tab. When the emulator is running, you can issue 
-console commands as described later in this document.</p>
-
-<p>If you are not working in Eclipse, see <a href="#apps">Installing Applications
-on the Emulator</a> for information about how to install your application.</p>
-
-<p>To stop an emulator instance, just close the emulator's window.</p>
-
-<a name="controlling"></a>
-
-<a name="avds"></a>
-
-<h2>Android Virtual Devices and the Emulator</h2>
-
-<p>To use the emulator, you first must create one or more AVD configurations. In each
-configuration, you specify an Android platform to run in the emulator and the set of hardware 
-options and emulator skin you want to use. Then, when you launch the emulator, you specify
-the AVD configuration that you want to load. </p>
-
-<p>To specify the AVD you want to load when starting the emulator, you use the 
-<code>-avd</code> argument, as shown in the previous section. </p>
-
-<p>Each AVD functions as an independent device, with its own private storage for 
-user data, SD card, and so on. When you launch the emulator with an AVD configuration, 
-it automatically loads the user data and SD card data from the AVD directory. By default,
-the emulator stores the user data, SD card data, and cache in the AVD directory.</p>
-
-<p>To create and manage AVDs you use the android tool, a command-line utility
-included in the SDK. For complete information about how to set up AVDs, see <a
-href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a>.</p>
-
-<h2>Controlling the Emulator</h2>
-
-<p>You can use emulator <a href="#startup-options">startup options</a> and <a
-href="#console">console commands</a> to control the behaviors and
-characteristics of the emulated environment itself.
-</p>
+<p>
+<p>The Android SDK includes a mobile device emulator &mdash; a virtual mobile device 
+that runs on your computer. The emulator lets you develop and test
+Android applications without using a physical device.</p>
 
 <p>When the emulator is running, you can interact with the emulated mobile
 device just as you would an actual mobile device, except that you use your mouse
-pointer to &quot;touch&quot; the touchscreen and your keyboard keys to
-&quot;press&quot; the simulated device keys. </p>
+pointer to &quot;touch&quot; the touchscreen and can use some keyboard keys to
+invoke certain keys on the device. </p>
 
-<p>The table below summarizes the mappings between the emulator keys and and 
-the keys of your keyboard. </p>
+<p>This document is a reference to the available command line options and the keyboard mapping to device keys. 
+For a complete guide to using the Android Emulator, see 
+<a href="{@docRoot}guide/developing/devices/emulator.html">Using the Android Emulator</a>.
 
-<table  border="0" style="clear:left;">
-  <tr>
-    <th>Emulated Device Key </th>
-    <th>Keyboard Key </th>
-  </tr>
-  <tr>
-    <td>Home</td>
-    <td>HOME</td>
-  </tr>
-  <tr>
-    <td>Menu (left softkey)</td>
-    <td>F2 <em>or</em> Page-up button</td>
-  </tr>
-  <tr>
-    <td>Star (right softkey)</td>
-    <td>Shift-F2 <em>or </em>Page Down</td>
-  </tr>
-  <tr>
-    <td>Back</td>
-    <td>ESC</td>
-  </tr>
-  <tr>
-    <td>Call/dial button </td>
-    <td>F3</td>
-  </tr>
-  <tr>
-    <td>Hangup/end call button</td>
-    <td>F4</td>
-  </tr>
-  <tr>
-    <td>Search</td>
-    <td>F5 </td>
-  </tr>
-  <tr>
-    <td>Power button</td>
-    <td>F7 </td>
-  </tr>
-  <tr>
-    <td>Audio volume up button</td>
-    <td>KEYPAD_PLUS, Ctrl-5</td>
-  </tr>
 
-  <tr>
-    <td>Audio volume down button</td>
-    <td>KEYPAD_MINUS, Ctrl-F6</td>
-  </tr>
-  <tr>
-    <td>Camera button</td>
-    <td>Ctrl-KEYPAD_5, Ctrl-F3</td>
-  </tr>
-  <tr>
-    <td>Switch to previous layout orientation (for example, portrait, landscape)</td>
-    <td>KEYPAD_7, Ctrl-F11</td>
-  </tr>
-  <tr>
-    <td>Switch to next layout orientation (for example, portrait, landscape)</td>
-    <td>KEYPAD_9, Ctrl-F12</td>
-  </tr>
-  <tr>
-    <td>Toggle cell networking on/off</td>
-    <td>F8</td>
-  </tr>
-  <tr>
-    <td>Toggle code profiling</td>
-    <td>F9 (only with <code>-trace</code> startup option)</td>
-  </tr>
-  <tr>
-    <td>Toggle fullscreen mode</td>
-    <td>Alt-Enter</td>
-  </tr>
-  <tr>
-    <td>Toggle trackball mode</td>
-    <td>F6</td>
-  </tr>
-  <tr>
-    <td>Enter trackball mode temporarily (while key is pressed)</td>
-    <td>Delete</td>
-  </tr>
-  <tr>
-    <td>DPad left/up/right/down</td>
-    <td>KEYPAD_4/8/6/2</td>
-  </tr>
-  <tr>
-    <td>DPad center click</td>
-    <td>KEYPAD_5</td>
-  </tr>
-  <tr>
-    <td>Onion alpha increase/decrease</td>
-    <td>KEYPAD_MULTIPLY(*) / KEYPAD_DIVIDE(/)</td>
-  </tr>
-</table>
+<h2 id="startup-options">Emulator Startup Options</h2>
 
-<p>Note that, to use keypad keys, you must first disable NumLock on your development computer. </p>
-
-<a name="startup-options"></a>
-
-<h2> Emulator Startup Options</h2>
 <p>The emulator supports a variety of options that you can specify 
 when launching the emulator, to control its appearance or behavior. 
 Here's the command-line usage for launching the emulator with options: </p>
 
 <pre>emulator -avd &lt;avd_name&gt; [-&lt;option&gt; [&lt;value&gt;]] ... [-&lt;qemu args&gt;]</pre>
 
-<p>The table below summarizes the available options.</p>
+<p class="table-caption"><strong>Table 1.</strong>Emulator startup options</p>
 
 <table>
 <tr>
@@ -377,8 +85,8 @@
   <td><strong>Required</strong>. Specifies the AVD to load for this emulator
       instance.</td>
   <td>You must create an AVD configuration before launching the emulator. For
-      information, see <a href="{@docRoot}guide/developing/tools/avd.html">Android
-      Virtual Devices</a>.</td>
+      information, see <a href="{@docRoot}guide/developing/devices/managing-avds.html#createavd">
+      Creating and Managing AVDs with AVD Manager</a>.</td>
 <tr>
   <td rowspan="7">Disk Images</td>
   <td><code>-cache&nbsp;&lt;filepath&gt;</code></td>
@@ -731,7 +439,8 @@
 results, since the density with which to render the skin may not be defined.
 AVDs let you associate each skin with a default density and override the default
 as needed. For more information, see <a
-href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a>.
+href="{@docRoot}guide/developing/devices/managing-avds.html#createavd">
+Creating and Managing Virtual Devices with AVD Manager</a>.
 </td>
 </tr>
 <tr>
@@ -740,1032 +449,100 @@
   <td>See comments for <code>-skin</code>, above.</td></tr>
 </table>
 
-<a name="diskimages"></a>
-
-<h2>Working with Emulator Disk Images</h2>
-
-<p>The emulator uses mountable disk images stored on your development machine to
-simulate flash (or similar) partitions on an actual device. For example, it uses
-disk image containing an emulator-specific kernel, the Android system, a
-ramdisk image, and writeable images for user data and simulated SD card.</p>
-
-<p>To run properly, the emulator requires access to a specific set of disk image
-files. By default, the Emulator always looks for the disk images in the 
-private storage area of the AVD in use. If no images exist there when 
-the Emulator is launched, it creates the images in the AVD directory based on 
-default versions stored in the SDK. </p>
-
-<p class="note"><strong>Note:</strong> The default storage location for 
-AVDs is in <code>~/.android/avd</code> on OS X and Linux, <code>C:\Documents and 
-Settings\&lt;user&gt;\.android\</code> on Windows XP, and 
-<code>C:\Users\&lt;user&gt;\.android\</code>
-on Windows Vista.</p>
-
-<p>To let you use alternate or custom versions of the image files, the emulator
-provides startup options that override the default locations and filenames of
-the image files. When you use the options, the emulator searches for the image
-file under the image name or location that you specify; if it can not locate the
-image, it reverts to using the default names and location.</p>
-
-<p>The emulator uses three types of image files: default image files, runtime
-image files, and temporary image files. The sections below describe how to
-override the location/name of each type of file. </p>
-
-<a name="defaultimages"></a>
-<h3>Default Images</h3>
-
-<p>When the emulator launches but does not find an existing user data image in
-the active AVD's storage area, it creates a new one from a default version
-included in the SDK. The default user data image is read-only. The image 
-files are read-only.</p>
-
-<p>The emulator provides the <code>-system &lt;dir&gt;</code> startup option to
-let you override the location under which the emulator looks for the default
-user data image. </p>
-
-<p>The emulator also provides a startup option that lets you override the name
-of the default user data image, as described in the table below. When you use the 
-option, the emulator looks in the default directory, or in a custom location
-(if you specified <code>-system &lt;dir&gt;</code>). </p>
-
-
-<table>
-<tr>
-  <th width="10%" >Name</th>
-    <th width="30%" >Description</th>
-    <th width="40%" >Comments</th>
-</tr>
-
-<!--
-<tr>
-  <td><code>kernel-qemu.img</code></td>
-  <td>The emulator-specific Linux kernel image</td>
-  <td>Override using <code>-kernel &lt;file&gt;</code></td>
-</tr>
-
-<tr>
-  <td><code>ramdisk.img</code></td>
-  <td>The ramdisk image used to boot the system.</td>
-  <td>Override using <code>-ramdisk &lt;file&gt;</code></td>
-</tr>
-
-<tr>
-  <td><code>system.img</code></td>
-  <td>The <em>initial</em> Android system image.</td>
-  <td>Override using <code>-image &lt;file&gt;</code></td>
-</tr>
--->
-<tr>
-  <td><code>userdata.img</code></td>
-  <td>The <em>initial</em> user-data disk image</td>
-  <td>Override using <code>-initdata &lt;file&gt;</code>. Also see
-<code>-data &lt;file&gt;</code>, below.</td>
-</tr>
-
-</table>
-
-<a name="runtimeimages"></a>
-<h3>Runtime Images: User Data and SD Card</h3>
-
-<p>At runtime, the emulator reads and writes data on two disk images: a
-user-data image and (optionally) an SD card image. This emulates the user-data
-partition and removable storage media on actual device. </p>
-
-<p>The emulator provides a default user-data disk image. At startup, the emulator 
-creates the default image as a copy of the system user-data image (user-data.img), 
-described above. The emulator stores the new image with the files of the active AVD.</p>
-
-<!--
-<p>The emulator provides a startup option, <code>-datadir &lt;dir&gt;</code>, 
-that you can use to override the location under which the emulator looks for the runtime
-image files. </p>
--->
-
-<p>The emulator provides startup options to let you override the actual names and storage 
-locations of the runtime images to load, as described in the table below. When you use one 
-of these options, the emulator looks for the specified file(s) in the current working directory,
-in the AVD directory, or in a custom location (if you specified a path with the filename). </p>
-
-<table>
-<tr>
-  <th width="10%" >Name</th>
-    <th width="30%" >Description</th>
-    <th width="40%" >Comments</th>
-</tr>
-<tr>
-  <td><code>userdata-qemu.img</code></td>
-  <td>An image to which the emulator writes runtime user-data for a unique user.</td>
-  <td>Override using <code>-data &lt;filepath&gt;</code>, where <code>&lt;filepath&gt;</code> is the
-path the image, relative to the current working directory. If you supply a filename only, 
-the emulator looks for the file in the current working directory. If the file at <code>&lt;filepath&gt;</code> does
-not exist, the emulator creates an image from the default userdata.img, stores it under the name you
-specified, and persists user data to it at shutdown. </td>
-</tr>
-
-<tr>
-  <td><code>sdcard.img</code></td>
-  <td>An image representing an SD card inserted into the emulated device.</td>
-  <td>Override using <code>-sdcard &lt;filepath&gt;</code>, where <code>&lt;filepath&gt;</code> is the
-path the image, relative to the current working directory. If you supply a filename only, 
-the emulator looks for the file in the current working directory. </td>
-</tr>
-
-</table>
-
-<h4>User-Data Image</h4>
-
-<p>Each emulator instance uses a writeable user-data image to store user- and
-session-specific data. For example, it uses the image to store a unique user's
-installed application data, settings, databases, and files. </p>
-
-<p>At startup, the emulator attempts to load a user-data image stored during 
-a previous session. It looks for the file in the current working directory, 
-in the AVD directory as described above, and at the custom location/name 
-that you specified at startup. </p>
-
-<ul>
-<li>If it finds a user-data image, it mounts the image and makes it available 
-to the system for reading/writing of user data. </li>
-<li>If it does not find one, it creates an image by copying the system user-data
-image (userdata.img), described above. At device power-off, the system persists
-the user data to the image, so that it will be available in the next session. 
-Note that the emulator stores the new disk image at the location/name that you
-specify in <code>-data</code> startup option.</li>
-</ul>
-
-<p class="note"><strong>Note:</strong> Because of the AVD configurations used in the emulator,
-each emulator instance now gets its own dedicated storage. There is no need 
-to use the <code>-d</code> option to specify an instance-specific storage area.</p>
-
-<h4>SD Card</h4>
-
-<P>Optionally, you can create a writeable disk image that the emulator can use
-to simulate removeable storage in an actual device. For information about how to create an 
-emulated SD card and load it in the emulator, see <a href="#sdcard">SD Card Emulation</a></p>
-
-<p>You can also use the android tool to automatically create an SD Card image
-for you, when creating an AVD. For more information, see <a 
-href="{@docRoot}guide/developing/tools/avd.html#options">Command-line options for AVDs</a>.
-
-<a name="temporaryimages"></a>
-<h3>Temporary Images</h3>
-
-<p>The emulator creates two writeable images at startup that it deletes at
-device power-off. The images are: </p>
-
-<ul>
-  <li>A writable copy of the Android system image</li>
-  <li>The <code>/cache</code> partition image</li>
-</ul>
-
-<p>The emulator does not permit renaming the temporary system image or
-persisting it at device power-off. </p>
-
-<p>The <code>/cache</code> partition image is initially empty, and is used by
-the browser to cache downloaded web pages and images. The emulator provides an 
-<code>-cache &lt;file&gt;</code>, which specifies the name of the file at which 
-to persist the <code>/cache</code> image at device power-off. If <code>&lt;file&gt;
-</code> does not exist, the emulator creates it as an empty file. </p>
-
-<p>You can also disable the use of the cache partition by specifying the
-<code>-nocache</code> option at startup. </p>
-
-
-<a name="emulatornetworking"></a>
-<h2>Emulator Networking</h2>
-
-<p>The emulator provides versatile networking capabilities that you can use to
-set up complex modeling and testing environments for your application. The
-sections below introduce the emulator's network architecture and capabilities.
-</p>
-
-<a name="networkaddresses"></a>
-<h3>Network Address Space</h3>
-
-<p>Each instance of the emulator runs behind a virtual router/firewall service
-that isolates it from your development machine's network interfaces and settings
-and from the internet. An emulated device can not see your development machine
-or other emulator instances on the network. Instead, it sees only that it is
-connected through Ethernet to a router/firewall.</p>
-
-<p>The virtual router for each instance manages the 10.0.2/24 network address
-space &mdash; all addresses managed by the router are in the form of
-10.0.2.&lt;xx&gt;, where &lt;xx&gt; is a number. Addresses within this space are
-pre-allocated by the emulator/router as follows:</p>
-
-<table>
+<h2>Emulator Keyboard Mapping</h2>
+<p>The table below summarizes the mappings between the emulator keys and and 
+the keys of your keyboard. </p>
+<p class="table-caption"><strong>Table 2.</strong> Emulator keyboard mapping</p>
+<table  border="0" style="clear:left;">
   <tr>
-    <th>Network Address</th>
-    <th>Description</th>
+    <th>Emulated Device Key </th>
+    <th>Keyboard Key </th>
   </tr>
   <tr>
-    <td>10.0.2.1</td>
-    <td>Router/gateway address </td>
+    <td>Home</td>
+    <td>HOME</td>
   </tr>
   <tr>
-    <td>10.0.2.2</td>
-    <td>Special alias to your host loopback interface (i.e., 127.0.0.1 on your
-development machine)</td>
+    <td>Menu (left softkey)</td>
+    <td>F2 <em>or</em> Page-up button</td>
   </tr>
   <tr>
-    <td>10.0.2.3</td>
-    <td>First DNS server</td>
+    <td>Star (right softkey)</td>
+    <td>Shift-F2 <em>or </em>Page Down</td>
   </tr>
   <tr>
-    <td>10.0.2.4 / 10.0.2.5 / 10.0.2.6</td>
-    <td>Optional second, third and fourth DNS server (if any) </td>
+    <td>Back</td>
+    <td>ESC</td>
   </tr>
   <tr>
-    <td>10.0.2.15</td>
-    <td>The emulated device's own network/ethernet interface</td>
+    <td>Call/dial button </td>
+    <td>F3</td>
   </tr>
   <tr>
-    <td>127.0.0.1</td>
-    <td>The emulated device's own loopback interface </td>
+    <td>Hangup/end call button</td>
+    <td>F4</td>
+  </tr>
+  <tr>
+    <td>Search</td>
+    <td>F5 </td>
+  </tr>
+  <tr>
+    <td>Power button</td>
+    <td>F7 </td>
+  </tr>
+  <tr>
+    <td>Audio volume up button</td>
+    <td>KEYPAD_PLUS, Ctrl-5</td>
+  </tr>
+
+  <tr>
+    <td>Audio volume down button</td>
+    <td>KEYPAD_MINUS, Ctrl-F6</td>
+  </tr>
+  <tr>
+    <td>Camera button</td>
+    <td>Ctrl-KEYPAD_5, Ctrl-F3</td>
+  </tr>
+  <tr>
+    <td>Switch to previous layout orientation (for example, portrait, landscape)</td>
+    <td>KEYPAD_7, Ctrl-F11</td>
+  </tr>
+  <tr>
+    <td>Switch to next layout orientation (for example, portrait, landscape)</td>
+    <td>KEYPAD_9, Ctrl-F12</td>
+  </tr>
+  <tr>
+    <td>Toggle cell networking on/off</td>
+    <td>F8</td>
+  </tr>
+  <tr>
+    <td>Toggle code profiling</td>
+    <td>F9 (only with <code>-trace</code> startup option)</td>
+  </tr>
+  <tr>
+    <td>Toggle fullscreen mode</td>
+    <td>Alt-Enter</td>
+  </tr>
+  <tr>
+    <td>Toggle trackball mode</td>
+    <td>F6</td>
+  </tr>
+  <tr>
+    <td>Enter trackball mode temporarily (while key is pressed)</td>
+    <td>Delete</td>
+  </tr>
+  <tr>
+    <td>DPad left/up/right/down</td>
+    <td>KEYPAD_4/8/6/2</td>
+  </tr>
+  <tr>
+    <td>DPad center click</td>
+    <td>KEYPAD_5</td>
+  </tr>
+  <tr>
+    <td>Onion alpha increase/decrease</td>
+    <td>KEYPAD_MULTIPLY(*) / KEYPAD_DIVIDE(/)</td>
   </tr>
 </table>
 
-<p>Note that the same address assignments are used by all running emulator
-instances. That means that if you have two instances running concurrently on
-your machine, each will have its own router and, behind that, each will have an
-IP address of 10.0.2.15. The instances are isolated by a router and can
-<em>not</em> see each other on the same network. For information about how to
-let emulator instances communicate over TCP/UDP, see <a
-href="#connecting">Connecting Emulator Instances</a>.</p>
-
-<p>Also note that the address 127.0.0.1 on your development machine corresponds
-to the emulator's own loopback interface. If you want to access services running
-on your development machine's loopback interface (a.k.a. 127.0.0.1 on your
-machine), you should use the special address 10.0.2.2 instead.</p>
-
-<p>Finally, note that each emulated device's pre-allocated addresses are
-specific to the Android emulator and will probably be very different on real
-devices (which are also very likely to be NAT-ed, i.e., behind a
-router/firewall)</p>
-
-<a name="networkinglimitations"></a>
-<h3>Local Networking Limitations</h3>
-
-<p>Each emulator instance runs behind a virtual router, but unlike an actual
-device connected to a physical router, the emulated device doesn't have access
-to a physical network. Instead it runs as part of a normal application on your
-development machine. This means that it is subject to the same networking
-limitations as other applications on your machine:</p>
-
-<ul>
-  <li>Communication with the emulated device may be blocked by a firewall
-program running on your machine.</li>
-  <li>Communication with the emulated device may be blocked by another
-(physical) firewall/router to which your machine is connected.</li>
-</ul>
-
-<p>The emulator's virtual router should be able to handle all outbound TCP and
-UDP connections/messages on behalf of the emulated device, provided your
-development machine's network environment allows it to do so. There are no
-built-in limitations on port numbers or ranges except the one imposed by your
-host operating system and network.</p>
-
-<p>Depending on the environment, the emulator may not be able to support other
-protocols (such as ICMP, used for "ping") might not be supported. Currently, the
-emulator does not support IGMP or multicast. </p>
-
-<a name="redirections"></a>
-<h3>Using Network Redirections</h3>
-
-<p>To communicate with an emulator instance behind its virtual router, you need
-to set up network redirections on the virtual router. Clients can then connect
-to a specified guest port on the router, while the router directs traffic
-to/from that port to the emulated device's host port. </p>
-
-<p>To set up the network redirections, you create a mapping of host and guest
-ports/addresses on the the emulator instance. There are two ways to set up
-network redirections: using emulator console commands and using the ADB tool, as
-described below. </p>
-
-<a name="consoleredir"></a>
-<h4>Setting up Redirections through the Emulator Console</h4>
-
-<p>Each emulator instance provides a control console the you can connect to, to
-issue commands that are specific to that instance. You can use the
-<code>redir</code> console command to set up redirections as needed for an
-emulator instance. </p>
-
-<p>First, determine the console port number for the target emulator instance.
-For example, the console port number for the first emulator instance launched is
-5554. Next, connect to the console of the target emulator instance, specifying
-its console port number, as follows: </p>
-
-<pre><code>telnet localhost 5554</code></pre>
-
-<p>Once connected, use the <code>redir</code> command to work with redirections.
-To add a redirection, use:</a>. </p>
-
-<pre><code>add&nbsp;&lt;protocol&gt;:&lt;host-port&gt;:&lt;guest-port&gt;</code>
-</pre>
-
-<p>where <code>&lt;protocol&gt;</code> is either <code>tcp</code> or <code>udp</code>, 
-and <code>&lt;host-port&gt;</code> and <code>&lt;guest-port&gt;</code> sets the 
-mapping between your own machine and the emulated system, respectively. </p>
-
-<p>For example, the following command sets up a redirection that will handle all
-incoming TCP connections to your host (development) machine on 127.0.0.1:5000
-and will pass them through to the emulated system's 10.0.2.15:6000.:</p>
-
-<pre>redir add tcp:5000:6000</pre>
-
-<p>To delete a redirection, you can use the <code>redir del</code> command. To
-list all redirections for a specific instance, you can use <code>redir
-list</code>. For more information about these and other console commands, see 
-<a href="#console">Using the Emulator Console</a>. </p>
-
-<p>Note that port numbers are restricted by your local environment. this typically
-means that you cannot use host port numbers under 1024 without special
-administrator privileges.  Also, you won't be able to set up a redirection for a
-host port that is already in use by another process on your machine. In that
-case, <code>redir</code> generates an error message to that effect. </p>
-
-<a name="adbredir"></a>
-<h4>Setting Up Redirections through ADB</h4>
-
-<p>The Android Debug Bridge (ADB) tool provides port forwarding, an alternate
-way for you to set up network redirections. For more information, see <a
-href="{@docRoot}guide/developing/tools/adb.html#forwardports">Forwarding Ports</a> in the ADB
-documentation.</p>
-
-<p>Note that ADB does not currently offer any way to remove a redirection,
-except by killing the ADB server.</p>
-
-<a name="dns"></a>
-<h3>Configuring the Emulator's DNS Settings</h3>
-
-<p>At startup, the emulator reads the list of DNS servers that your system is
-currently using. It then stores the IP addresses of up to four servers on this
-list and sets up aliases to them on the emulated addresses 10.0.2.3, 10.0.2.4,
-10.0.2.5 and 10.0.2.6 as needed.  </p>
-
-<p>On Linux and OS X, the emulator obtains the DNS server addresses by parsing 
-the file <code>/etc/resolv.conf</code>. On Windows, the emulator obtains the 
-addresses by calling the <code>GetNetworkParams()</code> API. Note that this 
-usually means that the emulator ignores the content of your "hosts" file 
-(<code>/etc/hosts</code> on Linux/OS X, <code>%WINDOWS%/system32/HOSTS</code>
- on Windows).</P>
-
-<p>When starting the emulator at the command line, you can also use the
-<code>-dns-server &lt;serverList&gt;</code> option to manually specify the
-addresses of DNS servers to use, where &lt;serverList&gt; is a comma-separated
-list of server names or IP addresses. You might find this option useful if you
-encounter DNS resolution problems in the emulated network (for example, an
-"Unknown Host error" message that appears when using the web browser).</p>
-
-<a name="proxy"></a>
-<h3>Using the Emulator with a Proxy</h3>
-
-<p>If your emulator must access the Internet through a proxy server, you can use
-the <code>-http-proxy &lt;proxy&gt;</code> option when starting the emulator, to
-set up the appropriate redirection. In this case, you specify proxy information
-in <code>&lt;proxy&gt;</code> in one of these formats:</p>
-
-<pre>http://&lt;machineName&gt;:&lt;port&gt;</pre>
-
-<p>or</p>
-
-<pre>http://&lt;username&gt;:&lt;password&gt;@&lt;machineName&gt;:&lt;port&gt;</pre>
-
-<p>The <code>-http-proxy</code> option forces the emulator to use the specified
-HTTP/HTTPS proxy for all outgoing TCP connections. Redirection for UDP is not
-currently supported.</p>
-
-<p>Alternatively, you can define the environment variable
-<code>http_proxy</code> to the value you want to use for
-<code>&lt;proxy&gt;</code>. In this case, you do not need to specify a value for
-<code>&lt;proxy&gt;</code> in the <code>-http-proxy</code> command &mdash; the
-emulator checks the value of the <code>http_proxy</code> environment variable at
-startup and uses its value automatically, if defined. </p>
-
-<p>You can use the <code>-debug-proxy</code> option to diagnose proxy
-connection problems.</p>
-
-<a name="connecting"></a>
-<h3>Interconnecting Emulator Instances</h3>
-
-<p>To allow one emulator instance to communicate with another, you must set up
-the necessary network redirections as illustrated below. </p>
-
-<p>Assume that your environment is</p>
-
-<ul>
-  <li>A is you development machine</li>
-  <li>B is your first emulator instance, running on A</li>
-  <li>C is your second emulator instance, running on A too</li>
-</ul>
-
-<p>and you want to run a server on B, to which C will connect, here is how you
-could set it up: </p>
-
-<ol>
-  <li>Set up the server on B, listening to
-<code>10.0.2.15:&lt;serverPort&gt;</code></li>
-  <li>On B's console, set up a redirection from
-<code>A:localhost:&lt;localPort&gt;</code> to <code>
-B:10.0.2.15:&lt;serverPort&gt;</code></li>
-  <li>On C, have the client connect to 10.0.2.2:&lt;localPort&gt;</code></li>
-</ol>
-
-<p>For example, if you wanted to run an HTTP server, you can select
-<code>&lt;serverPort&gt;</code> as 80 and <code>&lt;localPort&gt;</code> as
-8080:</p>
-
-<ul>
-  <li>B listens on 10.0.2.15:80</li>
-  <li>On B's console, issue <code>redir add tcp:8080:80</code></li>
-  <li>C connects to 10.0.2.2:8080</li>
-</ul>
-
-<a name="calling"></a>
-<h3>Sending a Voice Call or SMS to Another Emulator Instance</h3>
-
-<p>The emulator automatically forwards simulated voice calls and SMS messages from one instance to another. To send a voice call or SMS, you use the dialer application and SMS application (if available) installed on one emulator </p>
-
-<p>To initiate a simulated voice call to another emulator instance:</p>
-<ol>
-<li>Launch the dialer application on the originating emulator instance.</li>
-<li>As the number to dial, enter the console port number of the instance you'd like to call. You can determine
-  the console port number of the target instance by checking its window title, where the
-  console port number is reported as "Android Emulator (&lt;port&gt;). </li>
-<li>Press "Dial". A new inbound call appears in the target emulator instance. </li>
-</ol>
-
-<p>To send an SMS message to another emulator instance, launch the SMS application (if available). Specify the console port number of the target emulator instance as as the SMS address, enter the message text, and send the message. The message is delivered to the target emulator instance. </p>
-
-<p>You can also connect to an emulator instance's console to simulate an incoming voice call or SMS. For more information, see <a href="#telephony">Telephony Emulation</a> and <a href="#sms">SMS Emulation</a>.
-
-<a name="console"></a>
-
-<h2>Using the Emulator Console</h2>
-
-<p>Each running emulator instance includes a console facility that lets you dynamically query and control the simulated device environment. For example, you can use the console to dynamically manage port redirections and network characteristics and simulate telephony events. To access the console and enter commands, you use telnet to connect to the console's port number. </p>
-<p>To connect to the console of any running emulator instance at any time, use this command: </p>
-
-<pre>telnet localhost &lt;console-port&gt;</pre>
-
-<p>An emulator instance occupies a pair of adjacent ports: a console port and an adb port. The port numbers differ by 1, with the adb port having the higher port number. The console of the first emulator instance running on a given machine uses console port 5554 and adb port 5555. Subsequent instances use port numbers increasing by two &mdash; for example, 5556/5557, 5558/5559, and so on. Up to 16 concurrent emulator instances can run a console facility. </p>
-
-<p>To connect to the emulator console, you must specify a valid console port. If multiple emulator instances are running, you need to determine the console port of the emulator instance you want to connect to. You can find the instance's console port listed in the title of the instance window. For example, here's the window title for an instance whose console port is 5554:</p>
-
-<p><code>Android Emulator (5554)</code></p>
-
-<p>Alternatively, you can use the <code>adb devices</code> command, which prints a list of running emulator instances and their console port numbers. For more information, see <a href="{@docRoot}guide/developing/tools/adb.html#devicestatus">Querying for Emulator/Device Instances</a> in the adb documentation.</p>
-
-<p class="note">Note: The emulator listens for connections on ports 5554-5587 and accepts connections only from localhost.</p>
-
-<p>Once you are connected to the console, you can then enter <code>help [command]</code> to see a list of console commands and learn about specific commands. </p>
-
-<p>To exit the console session, use <code>quit</code> or <code>exit</code>.</p>
-
-<p>The sections below describe the major functional areas of the console.</p>
-
-<a name="portredirection"></a>
-
-<h3>Port Redirection</h3>
-<p>You can use the console to add and remove port redirections while the emulator is running. After connecting to the console, you can manage port redirections in this way:</p>
-<pre>redir &lt;list|add|del&gt; </pre>
-
-<p>The <code>redir</code> command supports the subcommands listed in the table below. </p>
-
-<table>
-<tr>
-  <th width="25%" >Subcommand
-  <th width="30%" >Description</th>
-  <th width="35%">Comments</th>
-</tr>
-  
-  <tr>
-    <td><code>list</code></td>
-    <td>List the current port redirections.</td>
-  <td>&nbsp;</td>
-  </tr>
-
-  
-<tr>
- <td><code>add&nbsp;&lt;protocol&gt;:&lt;host-port&gt;:&lt;guest-port&gt;</code></td>
-  <td>Add a new port redirection.</td>
-<td><li>&lt;protocol&gt; must be either &quot;tcp&quot; or &quot;udp&quot;</li>
-<li>&lt;host-port&gt; is the port number to open on the host</li>
-<li>&lt;guest-port&gt; is the port number to route data to on the emulator/device</li></td>
-</tr>
-<tr>
-  <td><code>del &lt;protocol&gt;:&lt;host-port&gt;</code></td>
-  <td>Delete a port redirection.</td>
-<td>See above for meanings of &lt;protocol&gt; and &lt;host-port&gt;.</td>
-</tr>
-</table>
-
-<a name="geo"></a>
-<h3>Geo Location Provider Emulation</h3>
-
-<p>The console provides commands to let you set the geo position used by an emulator emulated device. You can use the <code>geo</code> command to send a simple GPS fix to the emulator, without needing to use NMEA 1083 formatting. The usage for the command is: </p>
-
-<pre>geo &lt;fix|nmea&gt;</pre>
-
-<p>The <code>geo</code> command supports the subcommands listed in the table below. </p>
-
-<table>
-<tr>
-  <th width="25%" >Subcommand
-  <th width="30%" >Description</th>
-  <th width="35%">Comments</th>
-</tr>
-  
-  <tr>
-    <td><code>fix &lt;longitude&gt; &lt;latitude&gt; [&lt;altitude&gt;]</code></td>
-    <td>Send a simple GPS fix to the emulator instance.</td>
-  <td>Specify longitude and latitude in decimal degrees. Specify altitude in meters.</td>
-  </tr>
-<tr>
-  <td><code>nmea &lt;sentence&gt;</code></td>
-  <td>Send an NMEA 0183 sentence to the emulated device, as if it were sent from an emulated GPS modem.</td>
-<td><code>&lt;sentence&gt;</code> must begin with '$GP'. Only '$GPGGA' and '$GPRCM' sentences are currently supported.</td>
-</tr>
-</table>
-
-<p>You can issue the <code>geo</code> command to fix the GPS location as soon as an emulator instance is running. The emulator creates a mock location provider that sends it to GPS-aware applications as soon as they start and register location listeners. Any application can query the location manager to obtain the current GPS fix for the emulated device by calling:
-
-<pre>LocationManager.getLastKnownLocation("gps")</pre>
-
-<p>For more information about the Location Manager, see {@link android.location.LocationManager} and its methods.</p>
-
-<a name="events"></a>
-<h3>Hardware Events Emulation</h3>
-
-<p>You can use the <code>event</code> command to send various events to the emulator.The usage for the command is: </p>
-
-<pre>event &lt;send|types|codes|text&gt;</pre>
-
-<p>The <code>event</code> command supports the subcommands listed in the table below. </p>
-
-<table>
-<tr>
-  <th width="25	%" >Subcommand
-  <th width="30%" >Description</th>
-  <th width="35%">Comments</th>
-</tr>
-  
-  <tr>
-    <td><code>send &lt;type&gt;:&lt;code&gt;:&lt;value&gt; [...]</code></td>
-    <td>Send one or more events to the Android kernel. </td>
-  <td>You can use text names or integers for <code>&lt;type&gt;</code> and <code>&lt;value&gt;</code>.</td>
-  </tr>
-<tr>
-  <td><code>types</code></td>
-  <td>List all <code>&lt;type&gt;</code> string aliases supported by the <code>event</code> subcommands.</td>
-<td>&nbsp;</td>
-</tr>
-<tr>
-  <td><code>codes &lt;type&gt;</code></td>
-  <td>List all <code>&lt;codes&gt;</code> string aliases supported by the <code>event</code> 
-   subcommands for the specified <code>&lt;type&gt;</code>.</td>
-<td>&nbsp;</td>
-</tr>
-<tr>
-  <td><code>event text &lt;message&gt;</code></td>
-  <td>Simulate keypresses to send the specified string of characters as a message,</td>
-<td>The message must be a UTF-8 string. Unicode posts will be reverse-mapped according to the current device keyboard. Unsupported characters will be discarded silently.</td>
-</tr>
-</table>
-
-<a name="power"></a>
-<h3>Device Power Characteristics</h3>
-
-<p>You can use the <code>power</code> command to control the simulated power state of the emulator instance.The usage for the command is: </p>
-
-<pre>power &lt;display|ac|status|present|health|capacity&gt;</pre>
-
-<p>The <code>event</code> command supports the subcommands listed in the table below. </p>
-
-<table>
-<tr>
-  <th width="25	%" >Subcommand
-  <th width="30%" >Description</th>
-  <th width="35%">Comments</th>
-</tr>
-  
-  <tr>
-    <td><code>display</code></td>
-    <td>Display battery and charger state.</td>
-  <td>&nbsp;</td>
-  </tr>
-<tr>
-  <td><code>ac &lt;on|off&gt;</code></td>
-  <td>Set AC charging state to on or off. </td>
-<td>&nbsp;</td>
-</tr>
-<tr>
-  <td><code>status &lt;unknown|charging|discharging|not-charging|full&gt;</code></td>
-  <td>Change battery status as specified.</td>
-<td>&nbsp;</td>
-</tr>
-
-<tr>
-  <td><code>present &lt;true|false&gt;</code></td>
-  <td>Set battery presence state.</td>
-<td>&nbsp;</td>
-</tr>
-<tr>
-  <td><code>health &lt;unknown|good|overheat|dead|overvoltage|failure&gt;</code></td>
-  <td>Set battery health state.</td>
-<td>&nbsp;</td>
-</tr>
-<tr>
-  <td><code>power health &lt;percent&gt;</code></td>
-  <td>Set remaining battery capacity state (0-100).</td>
-<td>&nbsp;</td>
-</tr>
-</table>
-
-<a name="netstatus"></a>
-<h3>Network Status</h3>
-
-<p>You can use the console to check the network status and current delay and speed characteristics. To do so, connect to the console and use the <code>netstatus</code> command. Here's an example of the command and its output. </p>
-
-<pre>network status
-</pre>
-
-<a name="netdelay"></a>
-<h3>Network Delay Emulation</h3>
-
-<p>The emulator lets you simulate various network latency levels, so that you can test your application in an environment more typical of the actual conditions in which it will run. You can set a latency level or range at emulator startup or you can use the console to change the latency dynamically, while the application is running in the emulator. </p>
-<p>To set latency at emulator startup, use the  <code>-netdelay</code> emulator option with a supported <code>&lt;delay&gt;</code> value, as listed in the table below. Here are some examples:</p>
-<pre>emulator -netdelay gprs
-emulator -netdelay 40 100</pre>
-
-<p>To make dynamic changes to  network delay while the emulator is running, connect to the console and use the <code>netdelay</code> command with a supported <code>&lt;delay&gt;</code> value from the table below.  </p>
-
-<pre>network delay gprs</pre>
-
-<p>The format of network <delay> is one of the following (numbers are milliseconds):</p>
-
-<table style="clear:right;width:100%;">
-<tr>
-  <th width="30%" >Value</td>
-  <th width="35%" >Description</th><th width="35%">Comments</th></tr>
-  
-  <tr><td><code>gprs</code></td><td>GPRS</td>
-  <td>(min 150, max 550)</td>
-  </tr>
-
-<tr><td><code>edge</code></td><td>EDGE/EGPRS</td>
-<td>(min 80, max 400)</td>
-</tr>
-<tr><td><code>umts</code></td><td>UMTS/3G</td>
-<td>(min 35, max 200)</td>
-</tr>
-<tr><td><code>none</code></td><td>No latency</td><td>(min 0, max 0)</td></tr>
-<tr><td><code>&lt;num&gt;</code></td>
-<td>Emulate an exact latency  (milliseconds).</td>
-<td>&nbsp;</td></tr>
-<tr><td><code>&lt;min&gt;:&lt;max&gt;</code></td>
-<td>Emulate an specified latency range (min, max milliseconds).</td>
-<td>&nbsp;</td></tr>
-</table>
-
-<a name="netspeed"></a>
-<h3>Network Speed Emulation</h3>
-
-<p>The emulator also lets you simulate various network transfer rates. You can set a transfer rate or range at emulator startup or you can use the console to change the rate dynamically, while the application is running in the emulator. </p>
-<p>To set the network speed at emulator startup, use the  <code>-netspeed</code> emulator option with a supported <code>&lt;speed&gt;</code> value, as listed in the table below. Here are some examples:</p>
-<pre>emulator -netspeed gsm
-emulator -netspeed 14.4 80</pre>
-
-<p>To make dynamic changes to  network speed while the emulator is running, connect to the console and use the <code>netspeed</code> command with a supported <code>&lt;speed&gt;</code> value from the table below.  </p>
-
-<pre>network speed 14.4 80</pre>
-
-<p>The format of network <code>&lt;speed&gt;</code> is one of the following (numbers are
-kilobits/sec):</p>
-<table style="clear:right;width:100%;">
-<tbody>
-<tr>
-  <th width="30%">Value</td>
-  <th width="35%">Description</th><th width="35%">Comments</th></tr>
-  
-  <tr>
-  <td><code>gsm</code></td>
-  <td>GSM/CSD</td><td>(Up: 14.4, down: 14.4)</td></tr>
-<tr>
-  <td><code>hscsd</code></td>
-  <td>HSCSD</td><td>(Up: 14.4, down: 43.2)</td></tr>
-<tr>
-  <td><code>gprs</code></td>
-  <td>GPRS</td><td>(Up: 40.0, down: 80.0)</td></tr>
-<tr>
-  <td><code>edge</code></td>
-  <td>EDGE/EGPRS</td>
-  <td>(Up: 118.4, down: 236.8)</td>
-</tr>
-<tr>
-  <td><code>umts</code></td>
-  <td>UMTS/3G</td><td>(Up: 128.0, down: 1920.0)</td></tr>
-<tr>
-  <td><code>hsdpa</code></td>
-  <td>HSDPA</td><td>(Up: 348.0, down: 14400.0)</td></tr>
-<tr>
-  <td><code>full</code></td>
-  <td>no limit</td><td>(Up: 0.0, down: 0.0)</td></tr>
-<tr>
-  <td><code>&lt;num&gt;</code></td>
-  <td>Set an exact rate used for both upload and download.</td><td></td></tr>
-<tr>
-  <td><code>&lt;up&gt;:&lt;down&gt;</code></td>
-  <td>Set exact rates for upload and download separately.</td><td></td></tr>
-</table>
-
-
-<a name="telephony"></a>
-
-<h3>Telephony Emulation</h3>
-
-<p>The Android emulator includes its own GSM emulated modem that lets you simulate telephony functions in the emulator. For example, you can simulate inbound phone calls and establish/terminate data connections. The Android system handles simulated calls exactly as it would actual calls. The emulator does not support call audio in this release. </p>
-<p>You can use the console to access the emulator's telephony functions. After connecting to the console, you can use</p>
-<pre>gsm &lt;call|accept|busy|cancel|data|hold|list|voice|status&gt; </pre>
-<p>to invoke telephony functions. </p>
-<p>The <code>gsm</code> command supports the subcommands listed in the table below. </p>
-<table>
-  <tr>
-    <th >Subcommand </th>
-    <th width="25%">Description</th>
-    <th>Comments</th>
-  </tr>
-  <tr>
-    <td><code>call &lt;phonenumber&gt;</code></td>
-    <td>Simulate an inbound phone call from &lt;phonenumber&gt;.</td>
-    <td>&nbsp;</td>
-  </tr>
-  <tr>
-    <td><code>accept &lt;phonenumber&gt;</code></td>
-    <td>Accept an inbound call from &lt;phonenumber&gt; and change the call's state "active".</td>
-    <td>You can change a call's state to "active" only if its current state is "waiting" or "held".</td>
-  </tr>
-  <tr>
-    <td><code>busy &lt;phonenumber&gt;</code></td>
-    <td>Close an outbound call to &lt;phonenumber&gt; and change the call's state to "busy".</td>
-    <td>You can change a call's state to "busy" only if its current state is "waiting".</td>
-  </tr>
-  <tr>
-    <td><code>cancel &lt;phonenumber&gt;</code></td>
-    <td>Terminate an inbound or outbound phone call to/from &lt;phonenumber&gt;.</td>
-    <td>&nbsp;</td>
-  </tr>
-  <tr>
-    <td><code>data &lt;state&gt;</code></td>
-    <td>Change the state of the GPRS data connection to &lt;state&gt;.</td>
-    <td>Supported &lt;state&gt; values are:<br />
-          <li><code>unregistered</code> -- No network available</li>
-          <li><code>home</code> -- On local network, non-roaming</li>
-          <li><code>roaming</code> -- On roaming network</li>
-          <li><code>searching</code> -- Searching networks</li>
-          <li><code>denied</code> -- Emergency calls only</li>
-          <li><code>off</code> -- Same as 'unregistered'</li>
-      <li><code>on</code> -- same as 'home'</li>    </td>
-  </tr>
-  <tr>
-    <td><code>hold</code></td>
-    <td>Change the state of a call to "held". </td>
-    <td>You can change a call's state to "held" only if its current state is	 "active" or "waiting". </td>
-  </tr>
-  <tr>
-    <td><code>list</code></td>
-    <td>List all inbound and outbound calls and their states.</td>
-    <td>&nbsp;</td>
-  </tr>
-  <tr>
-    <td><code>voice &lt;state&gt;</code></td>
-    <td>Change the state of the GPRS voice connection to &lt;state&gt;.</td>
-    <td>Supported &lt;state&gt; values are:<br />
-    <li><code>unregistered</code> -- No network available</li>
-    <li><code>home</code> -- On local network, non-roaming</li>
-    <li><code>roaming</code> -- On roaming network</li>
-    <li><code>searching</code> -- Searching networks</li>
-    <li><code>denied</code> -- Emergency calls only</li>
-    <li><code>off</code> -- Same as 'unregistered'</li>
-    <li><code>on</code> -- Same as 'home'</li></td>
-  </tr>
-
-  <tr>
-    <td><code>status</code></td>
-    <td>Report the current GSM voice/data state.</td>
-    <td>Values are those described for the <code>voice</code> and <code>data</code> commands.</td>
-  </tr>
-</table>
-
-<a name="sms"></a>
-
-<h3>SMS Emulation</h3>
-
-<p>The Android emulator console lets you generate an SMS message and direct it to an emulator instance. Once you connect to an emulator instance, you can generate an emulated incoming SMS using this command:</p>
-
-<pre>sms send &lt;senderPhoneNumber&gt; &lt;textmessage&gt;</pre>
-
-<p>where <code>&lt;senderPhoneNumber&gt;</code> contains an arbitrary numeric string. </p>
-
-<p>The console forwards the SMS message to the Android framework, which passes it through to an application that handles that message type. </p>
-
-<a name="vm"></a>
-
-<h3>VM State</h3>
-
-<p>You can use the <code>vm</code> command to control the VM on an emulator instance.The usage for the command is: </p>
-
-<pre>vm &lt;start|stop|status&gt;</pre>
-
-<p>The <code>vm</code> command supports the subcommands listed in the table below. </p>
-
-<table>
-<tr>
-  <th width="25%" >Subcommand
-  <th width="30%" >Description</th>
-  <th width="35%">Comments</th>
-</tr>
-<tr>
-    <td><code>start</code></td>
-    <td>Start the VM on the instance. </td>
-  <td>&nbsp;</td>
-</tr>
-<tr>
-    <td><code>stop</code></td>
-    <td>Stop the VM on the instance. </td>
-  <td>&nbsp;</td>
-</tr>
-<tr>
-    <td><code>start</code></td>
-    <td>Display the current status of the VM (running or stopped). </td>
-  <td>&nbsp;</td>
-</tr>
-</table>
-
-
-<a name="window"></a>
-
-<h3>Emulator Window</h3>
-
-<p>You can use the <code>window</code> command to manage the emulator window. The usage for the command is: </p>
-
-<pre>window &lt;scale&gt;</pre>
-
-<p>The <code>vm</code> command supports the subcommands listed in the table below. </p>
-
-<table>
-<tr>
-  <th width="25%" >Subcommand
-  <th width="30%" >Description</th>
-  <th width="35%">Comments</th>
-</tr>
-<tr>
-    <td><code>scale &lt;scale&gt;</code></td>
-    <td>Scale the emulator window.</td>
-  <td>&lt;scale&gt; must be a number between 0.1 and 3 that describes the desired scaling factor. You can 
-  also specify scale as a DPI value if you add the suffix "dpi" to the scale value. A value of "auto" 
-  tells the emulator to select the best window size.</td>
-</tr>
-</table>
-
-
-<a name="terminating"></a>
-
-<h3>Terminating an Emulator Instance</h3>
-
-<p>You can terminate an emulator instance through the console, using the <code>kill</code> command.</p>
-
-
-<a name="skins"></a>
-
-<h2>Using Emulator Skins</h2>
-
-<p>The Android SDK includes several Emulator skins that you can use to control the resolution and density of the emulated device's screen. To select a specific skin for running the emulator, create an AVD that uses that skin. Please do not use deprecated emulator options such as <code>-skin</code> to control the skin used by an emulator instance. For more information about AVDs, see <a
-href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a>.  </p>
-
-
-<a name="multipleinstances"></a>
-
-<h2>Running Multiple Emulator Instances</h2>
-
-<p>Through the AVDs configurations used by the emulator, you can run multiple
-instances of the emulator concurrently, each with its own AVD configuration and
-storage area for user data, SD card, and so on. You no longer need to use the
-<code>-d</code> option when launching the emulator, to point to an
-instance-specific storage area. </p>
-
-<a name="apps"></a>
-
-<h2>Installing Applications on the Emulator</h2>
-
-<p>If you don't have access to Eclipse or the ADT Plugin, you can install 
-your application on the emulator <a href="{@docRoot}guide/developing/tools/adb.html#move">using 
-the adb utility</a>. Before installing the application, you need to package it 
-in a .apk file using the <a href="{@docRoot}guide/developing/tools/aapt.html">Android Asset Packaging Tool</a>. 
-Once the application is installed, you can start the emulator from the command 
-line, as described in this document, using any startup options necessary. 
-When the emulator is running, you can also connect to the emulator instance's 
-console to issue commands as needed.</p>
-
-<p>As you update your code, you periodically package and install it on the emulator. 
-The emulator preserves the application and its state data across restarts, 
-in a user-data disk partition. To ensure that the application runs properly 
-as you update it, you may need to delete the emulator's user-data partition. 
-To do so, start the emulator with the <code>-wipe-data</code> option. 
-For more information about the user-data partition and other emulator storage, 
-see <a href="#diskimages">Working with Emulator Disk Images</a>.</p>
-
-<a name="sdcard"></a>
-<a name="creating"></a>
-
-<h2>SD Card Emulation</h2>
-
-<p>You can create a disk image and then load it to the emulator at startup, to
-simulate the presence of a user's SD card in the device. To do this, you can use
-the android tool to create a new SD card image with a new AVD, or you can use
-the mksdcard utility included in the SDK. </p>
-
-<p>The sections below describe how to create an SD card disk image, how to copy
-files to it, and how to load it in the emulator at startup. </p>
-
-<p>Note that you can only load disk image at emulator startup. Similarly, you
-can not remove a simulated SD card from a running emulator. However, you can
-browse, send files to, and copy/remove files from a simulated SD card either
-with adb or the emulator. </p>
-
-<p>The emulator supports emulated SDHC cards, so you can create an SD card image
-of any size up to 128 gigabytes.</p>
-
-<h3 id="creatinga">Creating an SD card image using the android tool</h3>
-
-<p>The easiest way to create a new SD card is to use the android tool. When
-creating an AVD, you simply specify the <code>-c</code> option, like this: </p>
-
-<pre>android create avd -n &lt;avd_name&gt; -t &lt;targetID&gt; -c &lt;size&gt;[K|M]</pre>
-
-<p>You can also use the <code>-c</code> option to specify a path to an SD card
-image to use in the new AVD. For more information, see <a
-href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a>.
-</p>
-
-<h3 id="creatingm">Creating an SD card image using mksdcard</h3>
-
-<p>You can use the mksdcard tool, included in the SDK, to create a FAT32 disk
-image that you can load in the emulator at startup. You can access mksdcard in
-the tools/ directory of the SDK and create a disk image like this: </p>
-
-<pre>mksdcard &lt;size&gt; &lt;file&gt;</pre>
-	
-<p>For example:</p>
-
-<pre>mksdcard 1024M sdcard1.iso</pre>
-
-<p>For more information, see <a href="{@docRoot}guide/developing/tools/othertools.html">Other Tools</a>. </p>
-
-<a name="copying"></a>
-<h3>Copying Files to a Disk Image</h3>
-
-<p>Once you have created the disk image, you can copy files to it prior to
-loading it in the emulator. To copy files, you can mount the image as a loop
-device and then copy the files to it, or you can use a utility such as mtools to
-copy the files directly to the image. The mtools package is available for Linux,
-Mac, and Windows.</p>
-
-<a name="loading"></a>
-<a name="step3" id="step3"></a>
-
-<h3>Loading the Disk Image at Emulator Startup</h3>
-
-<p>By default, the emulator loads the SD card image that is stored with the active
-AVD (see the <code>-avd</code> startup option).</p>
-
-<p>Alternatively, you ca start the emulator with the
-<code>-sdcard</code> flag and specify the name and path of your image (relative
-to the current working directory): </p>
-
-<pre>emulator -sdcard &lt;filepath&gt;</pre>
-
-<a name="troubleshooting"></a>
-
-<h2>Troubleshooting Emulator Problems</h2>
-
-<p>The adb utility sees the emulator as an actual physical device. For this reason, you might have to use the -d flag with some common adb commands, such as <code>install</code>. The -d flag lets you specify which of several connected devices to use as the target of a command. If you don't specify -d, the emulator will target the first device in its list. For more information about adb, see <a href="{@docRoot}guide/developing/tools/adb.html">Android Debug Bridge</a>.</p>
-
-<p>For emulators running on Mac OS X, if you see an error &quot;Warning: No DNS servers found&quot; when starting the emulator, check to see whether you have an <code>/etc/resolv.conf</code> file. If not, please run the following line in a command window:</p>
-    <pre>ln -s /private/var/run/resolv.conf /etc/resolv.conf</pre>
-
-<p>See <a href="{@docRoot}resources/faq/index.html">Frequently Asked Questions</a> for more troubleshooting information. </p>
-
-<a name="limitations"></a>
-    <h2>Emulator Limitations</h2>
-    <p>In this release, the  limitations of the emulator include: </p>
-    <ul>
-      <li>No support for placing or receiving actual phone calls. You can simulate phone calls (placed and received) through the emulator console, however. </li>
-      <li>No support for USB connections</li>
-      <li>No support for camera/video capture (input).</li>
-      <li>No support for device-attached headphones</li>
-      <li>No support for determining connected state</li>
-      <li>No support for determining battery charge level and AC charging state</li>
-      <li>No support for determining SD card insert/eject</li>
-      <li>No support for Bluetooth</li>
-    </ul>
+<p>Note that, to use keypad keys, you must first disable NumLock on your development computer. </p>
diff --git a/docs/html/guide/developing/tools/hierarchy-viewer.jd b/docs/html/guide/developing/tools/hierarchy-viewer.jd
index 431008c..ce660fc 100644
--- a/docs/html/guide/developing/tools/hierarchy-viewer.jd
+++ b/docs/html/guide/developing/tools/hierarchy-viewer.jd
@@ -1,98 +1,16 @@
 page.title=Hierarchy Viewer
 @jd:body
 
-<p>The Hierarchy Viewer application allows you to debug and optimize your user 
+<p>Hierarchy Viewer allows you to debug and optimize your user 
 interface. It provides a visual representation of the layout's View hierarchy 
 (the Layout View) and a magnified inspector of the display (the Pixel Perfect View). 
 </p>
 
-<p>To get the Hierarchy Viewer started:</p>
-<ol>
-  <li>Connect your device or launch an emulator.</li>
-  <li>From a terminal, launch <code>hierarchyviewer</code> from your SDK 
-    <code>/tools</code> directory.
-    </li>
-  <li>In the window that opens, you'll see a list of <strong>Devices</strong>. When a device is
-    selected, a list of currently active <strong>Windows</strong> is displayed 
-    on the right. The <em>&lt;Focused Window></em> is the window currently in 
-    the foreground, and also the default window loaded if you do not select another.
-    </li> 
-  <li>Select the window that you'd like to inspect and click 
-    <strong>Load View Hierarchy</strong>. The Layout View will be loaded. 
-    You can then load the Pixel Perfect View by clicking the second 
-    icon at the bottom-left of the window.
-    </li>
+<p>To start Hierarchy Viewer, enter the following command from the SDK <code>tools/</code> directory:</p>
+  <pre>hierarchyviewer</pre>
 </ol>
 
-<p>If you've navigated to a different window on the device, press <strong>Refresh Windows</strong>
-to refresh the list of available windows on the right.</p>
-
-<h2>Layout View</h2>
-<p>The Layout View offers a look at the View layout and properties. It has three views:</p>
-<ul>
-  <li>Tree View: a hierarchy diagram of the Views, on the left.</li>
-  <li>Properties View: a list of the selected View's properties, on the top-right.</li>
-  <li>Wire-frame View: a wire-frame drawing of the layout, on the bottom-right.</li>
-</ul>
-<br/>
-<img src="{@docRoot}images/hierarchyviewer-layout.png" alt="" height="509" width="700" />
-
-<p>Select a node in the Tree View to display the properties of that element in 
-the Properties View. When a node is selected, the Wire-frame View 
-also indicates the bounds of the element with a red rectangle.
-Double click a node in the tree (or select it, and click <strong>Display 
-View</strong>) to open a new window with a rendering of that element.</p>
-
-<p>The Layout View includes a couple other helpful features for debugging your layout: 
-<strong>Invalidate</strong> and <strong>Request Layout</strong>. These buttons execute the
-respective View calls, {@link android.view.View#invalidate()} and {@link android.view.View#requestLayout()},
-on the View element currently selected in the tree. Calling these methods on any View can
-be very useful when simultaneously running a debugger on your application.</p>
-
-<p>The Tree View can be resized by adjusting the zoom slider, below
-the diagram. The number of View elements in the window is also given here. You 
-should look for ways to minimize the number of Views. The fewer View elements there
-are in a window, the faster it will perform.</p>
-
-<p>If you interact with the device and change the focused View, the diagram will not automatically refresh.
-You must reload the Layout View by clicking <strong>Load View Hierarchy</strong>.
-
-
-<h2>Pixel Perfect View</h2>
-<p>The Pixel Perfect View provides a magnified look at the current device window. It has three views:</p>
-<ul>
-  <li>Explorer View: shows the View hierarchy as a list, on the left.</li>
-  <li>Normal View: a normal view of the device window, in the middle.</li>
-  <li>Loupe View: a magnified, pixel-grid view of the device window, on the right.</li>
-</ul>
-<br/>
-<img src="{@docRoot}images/hierarchyviewer-pixelperfect.png" alt="" height="509" width="700" />
-
-<p>Click on an element in the Explorer View and a "layout box" will be drawn in the
-Normal View to indicate the layout position of that element. The layout box uses multiple rectangles, to indicate the normal bounds, the padding and the margin (as needed). The purple or green rectangle indicates 
-the normal bounds of the element (the height and width). The inner white or black rectangle indicates 
-the content bounds, when padding is present. A  black or white rectangle outside the normal purple/green
-rectangle indicates any present margins. 
-(There are two colors for each rectangle, in order to provide the best contrast
-based on the colors currently in the background.)</p> 
-
-<p>A very handy feature for designing your UI is the ability to overlay an image in the Normal and Loupe
-Views. For example, you might have a mock-up image of how you'd like to layout your interface. 
-By selecting <strong>Load...</strong> from the controls in the Normal View, you can choose the
-image from your computer and it will be placed atop the preview. Your chosen image will anchor at the bottom left corner of the screen. You can then adjust the opacity of the overlay and begin fine-tuning your layout to match the mock-up.</p>
-
-<p>The Normal View and Loupe View refresh at regular intervals (5 seconds by default), but the 
-Explorer View does not. If you navigate away and focus on a different View, then you should refresh the 
-Explorer's hierarchy by clicking <strong>Load View Hierarchy</strong>. This is even true 
-when you're working in a window that holds multiple Views that are not always visible. If you do not,
-although the previews will refresh, clicking a View in the Explorer will not provide the proper layout box
-in the Normal View, because the hierarchy believes you are still focused on the prior View.</p>
-
-<p>Optional controls include:</p>
-<ul>
-  <li><strong>Overlay</strong>: Load an overlay image onto the view and adjust its opacity.</li>
-  <li><strong>Refresh Rate</strong>: Adjust how often the Normal and Loupe View refresh their display.</li>
-  <li><strong>Zoom</strong>: Adjust the zoom level of the Loupe View.</li>
-</ul>
-
+<p>For more information on how to use Hierarchy Viewer, see 
+<a href="{@docRoot}guide/developing/debugging/debugging-ui.html">Debugging and Profiling UIs</a>
+</p>
 
diff --git a/docs/html/guide/developing/tools/hprof-conv.jd b/docs/html/guide/developing/tools/hprof-conv.jd
new file mode 100644
index 0000000..27000b4
--- /dev/null
+++ b/docs/html/guide/developing/tools/hprof-conv.jd
@@ -0,0 +1,14 @@
+page.title=HPROF Converter
+@jd:body
+
+<p>
+The <code>hprof-conv</code> tool converts the HPROF file that is
+generated by the Android SDK tools to a standard format so you
+can view the file in a profiling tool of your choice. </p>
+
+<pre> hprof-conv &lt;infile&gt; &lt;outfile&gt;</pre>
+
+<p>
+You can use "-" for <code>&lt;infile&gt;</code> or <code>&lt;outfile&gt;</code>
+to specify stdin or stdout.
+</p>
diff --git a/docs/html/guide/developing/tools/index.jd b/docs/html/guide/developing/tools/index.jd
index 899c0dc..c603780 100644
--- a/docs/html/guide/developing/tools/index.jd
+++ b/docs/html/guide/developing/tools/index.jd
@@ -1,4 +1,4 @@
-page.title=Tools Overview
+page.title=Tools
 @jd:body
 
 <img src="{@docRoot}assets/images/android_wrench.png" alt="" align="right">
@@ -10,98 +10,75 @@
 applications on the emulator. </p>
 
  <dl>
-  <dt><a href="adt.html">Android Development Tools Plugin</a> (for the Eclipse IDE)</dt>
-          <dd>The ADT plugin adds powerful extensions to the Eclipse integrated environment,
-          making creating and debugging your Android applications easier and faster. If you
-          use Eclipse, the ADT plugin gives you an incredible boost in developing Android
-          applications.</dd>
+  <dt><a href="adb.html">Android Debug Bridge</a></dt>
+    <dd>A versatile tool lets you manage the state of an emulator instance
+    or Android-powered device.</dd>    
+
+   <dt><a href="android.html">android</a></dt>
+     <dd>Lets you manage AVDs, projects, and the installed components of the SDK.
+     </dd>
+
+  <dt><a href="bmgr.html">bmgr</a></dt>
+
+    <dd>Lets you interact with the Backup Manager on Android devices
+    supporting API Level 8 or greater. It provides commands to invoke backup and restore operations
+    so that you don't need to repeatedly wipe data or take similar intrusive steps in order to test
+    your application's backup agent. These commands are accessed via the adb shell.
+    </dd>
+
+  <dt><a href="dmtracedump.html">dmtracedump</a></dt>
+
+    <dd>Generates graphical call-stack diagrams from trace log files.
+    The tool uses the Graphviz Dot utility to create the graphical output, so you need to install
+    Graphviz before running <code>dmtracedump</code>. For more information on using <code>dmtracedump</code>, see
+    <a href="{@docRoot}guide/developing/debugging/debugging-tracing.html#dmtracedump">Profiling with
+    Traceview and dmtracedump</a>
+    </dd>
+
+    <dt><a href="draw9patch.html">Draw 9-patch</a></dt>
+	    <dd>Allows you to easily create a {@link android.graphics.NinePatch} graphic using a WYSIWYG editor.
+	    It also previews stretched versions of the image, and highlights the area in which content is allowed.
+	    </dd>
+
   <dt><a href="emulator.html">Android Emulator</a></dt>
     <dd>A QEMU-based device-emulation tool that you can use to design,
     debug, and test your applications in an actual Android run-time environment. </dd>
 
-  <dt><a href="avd.html">Android Virtual Devices (AVDs)</a></dt>
-    <dd>Virtual device configurations that you create, to model device
-        characteristics in the Android Emulator. In each configuration, you can
-        specify the Android platform to run, the hardware options, and the
-        emulator skin to use. Each AVD functions as an independent device with
-        it's own storage for user data, SD card, and so on. </dd>
+  <dt><a href="hprof-conv.html">hprof-conv</a></dt>
 
- <dt><a href="hierarchy-viewer.html">Hierarchy Viewer</a></dt>
-    <dd>The Hierarchy Viewer tool allows you to debug and optimize your user interface.
-        It provides a visual representation of your layout's hierarchy of Views and a magnified inspector
-        of the current display with a pixel grid, so you can get your layout just right.
+    <dd>Converts the HPROF file that is generated by the Android SDK tools to a
+    standard format so you can view the file in a profiling tool of your choice.</dd>
+
+  <dt><a href="layoutopt.html">layoutopt</a></dt>
+    <dd>Lets you quickly analyze your application's layouts in order to
+    optimize them for efficiency.
     </dd>
 
- <dt><a href="layoutopt.html">layoutopt</a></dt>
-    <dd>This tool lets you quickly analyze your application's layouts for
-efficiency.
-    </dd>
+  <dt><a href="mksdcard.html">logcat</a></dt>
+      <dd>Lets you read system log messages that are output on an Android device or emulator.</dd>
 
-      <dt><a href="draw9patch.html">Draw 9-patch</a></dt>
-        <dd>The Draw 9-patch tool allows you to easily create a
-        {@link android.graphics.NinePatch} graphic using a WYSIWYG editor. It also previews stretched
-         versions of the image, and highlights the area in which content is allowed.
-        </dd>
+  <dt><a href="mksdcard.html">mksdcard</a></dt>
+      <dd>Helps you create a disk image that you can use with the emulator, 
+      to simulate the presence of an external storage card (such as an SD card).</dd>
 
-  <dt><a href="ddms.html" >Dalvik Debug Monitor
-      Service</a> (ddms)</dt>
-        <dd>Integrated with Dalvik, the Android platform's custom VM, this tool
-        lets you manage processes on an emulator or device and assists in debugging.
-        You can use it to kill processes, select a specific process to debug,
-        generate trace data, view heap and thread information, take screenshots
-        of the emulator or device, and more. </dd>
-
-  <dt><a href="adb.html" >Android Debug Bridge</a> (adb)</dt>
-                  <dd>The adb tool lets you install your application's .apk files on an
-                  emulator or device and access the emulator or device from a command line.
-                  You can also use it to link a standard debugger to application code running
-                  on an Android emulator or device.</dd>
-
-  <dt><a href="aapt.html">Android Asset
-          Packaging Tool</a> (aapt)</dt>
-                  <dd>The aapt tool lets you create .apk files containing the binaries and
-                  resources of Android applications.</dd>
-
-  <dt><a href="aidl.html" >Android Interface
-  Description Language</a> (aidl)</dt>
-            <dd>Lets you generate code for an interprocess interface, such as what
-            a service might use.</dd>
-
-  <dt><a href="adb.html#sqlite">sqlite3</a></dt>
-      <dd>Included as a convenience, this tool lets you access the SQLite data
-      files created and used by Android applications.</dd>
-
-  <dt><a href="traceview.html" >Traceview</a></dt>
-            <dd> This tool produces graphical analysis views of trace log data that you
-            can generate from your Android application. </dd>
-
-  <dt><a href="othertools.html#mksdcard">mksdcard</a></dt>
-            <dd>Helps you create a disk image that you can use with the emulator,
-                      to simulate the presence of an external storage card (such as an SD card).</dd>
-
-  <dt><a href="othertools.html#dx">dx</a></dt>
-                  <dd>The dx tool rewrites .class bytecode into Android bytecode
-                                          (stored in .dex files.)</dd>
-
-  <dt><a href="monkey.html">UI/Application
-  Exerciser Monkey</a></dt>
-      <dd>The Monkey is a program that runs on your emulator or device and generates pseudo-random
-      streams of user events such as clicks, touches, or gestures, as well as a number of system-
-      level events.  You can use the Monkey to stress-test applications that you are developing,
-      in a random yet repeatable manner.</dd>
+  <dt><a href="monkey.html">Monkey</a></dt>
+      <dd>Runs on your emulator or device and generates pseudo-random
+      streams of user events such as clicks, touches, or gestures, as well as a number of system-level events.
+      You can use the Monkey to stress-test applications that you are developing, in a random yet repeatable manner.</dd>
 
   <dt><a href="monkeyrunner_concepts.html">monkeyrunner</a></dt>
-  <dd>
-    The monkeyrunner tool provides an API for writing Python programs that control an Android device
-    or emulator from outside of Android code.
-  </dd>
-  <dt><a  href="othertools.html#android">android</a></dt>
-            <dd>A script that lets you manage AVDs and generate <a
-                        href="http://ant.apache.org/" title="Ant">Ant</a> build files that
-                        you can use to compile your Android applications. </dd>
+      <dd>Provides an API for writing programs that control an Android device
+      or emulator from outside of Android code.</dd>
 
-  <dt><a  href="zipalign.html">zipalign</a></dt>
-            <dd>An important .apk optimization tool. This tool ensures that all uncompressed data starts
+  <dt><a href="proguard.html">ProGuard</a></dt>
+      <dd>Shrinks, optimizes, and obfuscates your code by removing unused code and renaming classes,
+      fields, and methods with semantically obscure names.</dd>
+
+  <dt><a href="sqlite3.html">sqlite3</a></dt>
+      <dd>Lets you access the SQLite data files created and used by Android applications.</dd>
+
+  <dt><a href="zipalign.html">zipalign</a></dt>
+            <dd>Optimizes <code>.apk</code> files by ensuring that all uncompressed data starts
             with a particular alignment relative to the start of the file. This should always be used
             to align .apk files after they have been signed.</dd>
 </dl>
diff --git a/docs/html/guide/developing/tools/layoutopt.jd b/docs/html/guide/developing/tools/layoutopt.jd
index f7c3d77..fdbf777 100644
--- a/docs/html/guide/developing/tools/layoutopt.jd
+++ b/docs/html/guide/developing/tools/layoutopt.jd
@@ -2,61 +2,20 @@
 @jd:body
 
 <p><code>layoutopt</code> is a command-line tool that helps you optimize the
-layouts and layout hierarchies of your applications. You can run it against your
-layout files or resource directories to quickly check for inefficiencies or
-other types of problems that could be affecting the performance of your
-application. </p>
+layouts and layout hierarchies of your applications.<p>
 
-<p>To run the tool, open a terminal and launch <code>layoutopt
-&lt;resources&gt;</code> from your SDK <code>tools/</code> directory. In the
-command, supply a list of uncompiled resource xml files or directories that you
-want to analyze. </p>
-
-<p>When run, the tool loads the specified XML files and analyzes their layout
-structures and hierarchies according to a set of predefined rules. If it detects
-issues, it outputs information about the issues, giving filename, line numbers,
-description of issue, and for some types of issues a suggested resolution. </p>
-
-<p>Here's an example of the output:</p>
-
-<pre>$ layoutopt samples/
-samples/compound.xml
-   7:23 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
-   11:21 This LinearLayout layout or its FrameLayout parent is useless
-samples/simple.xml
-   7:7 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
-samples/too_deep.xml
-   -1:-1 This layout has too many nested layouts: 13 levels, it should have &lt= 10!
-   20:81 This LinearLayout layout or its LinearLayout parent is useless
-   24:79 This LinearLayout layout or its LinearLayout parent is useless
-   28:77 This LinearLayout layout or its LinearLayout parent is useless
-   32:75 This LinearLayout layout or its LinearLayout parent is useless
-   36:73 This LinearLayout layout or its LinearLayout parent is useless
-   40:71 This LinearLayout layout or its LinearLayout parent is useless
-   44:69 This LinearLayout layout or its LinearLayout parent is useless
-   48:67 This LinearLayout layout or its LinearLayout parent is useless
-   52:65 This LinearLayout layout or its LinearLayout parent is useless
-   56:63 This LinearLayout layout or its LinearLayout parent is useless
-samples/too_many.xml
-   7:413 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
-   -1:-1 This layout has too many views: 81 views, it should have &lt= 80!
-samples/useless.xml
-   7:19 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
-   11:17 This LinearLayout layout or its FrameLayout parent is useless</pre>
-
-<p>The <code>layoutopt</code> tool is available in SDK Tools, Revision 3 or
-later. If you do not have SDK Tools r3 or later installed in your SDK, you can
-download it from the Android SDK repository site using the Android SDK and AVD
-Manager. For information, see <a
-href="{@docRoot}sdk/adding-components.html">Adding SDK Components</a>.</p>
+<p>This document is a reference to the available command line options. For more information and sample
+output of the tool, see <a href="{@docRoot}guide/developing/debugging/debugging-ui.html#layoutopt.html">
+Optimizing layouts with layoutopt</a>.</p>
 
 <h3>Usage</h3>
 
 <p>To run <code>layoutopt</code> against a given list of layout resources:</p>
 
-<pre>layoutopt &lt;list of xml files or directories></pre>
+<pre>layoutopt &lt;file_or_directory&gt; ...</pre>
 
 <p>For example:</p>
 
 <pre>$ layoutopt res/layout-land</pre>
 <pre>$ layoutopt res/layout/main.xml res/layout-land/main.xml</pre>
+
diff --git a/docs/html/guide/developing/tools/logcat.jd b/docs/html/guide/developing/tools/logcat.jd
new file mode 100644
index 0000000..1577604
--- /dev/null
+++ b/docs/html/guide/developing/tools/logcat.jd
@@ -0,0 +1,104 @@
+page.title=logcat
+@jd:body
+<div></div>
+
+  <p>The Android logging system provides a mechanism for collecting and viewing system debug
+  output. Logs from various applications and portions of the system are collected in a series of
+  circular buffers, which then can be viewed and filtered by the <code>logcat</code> command. You can use 
+  <code>logcat</code> from an ADB shell to view the log messages.</p>
+
+  <p>This document is a reference to the available command line options. For more information on <code>logcat</code>, see
+  <a href="{@docRoot}guide/developing/debugging/debugging-log.html">Reading and Writing Log Messages</a>. For more
+  information on accessing <code>logcat</code> from DDMS, instead of the command line, see the documentation for the
+  <a href="{@docRoot}guide/developing/debugging/ddms.html">Dalvik Debug Monitor Server</a>.
+  </p>
+
+  <h3>Syntax</h3>
+  <pre>
+[adb] logcat [&lt;option&gt;] ... [&lt;filter-spec&gt;] ...
+</pre>
+
+  <p>You can run <code>logcat</code> as an adb command or directly in a shell prompt
+  of your emulator or connected device. To view log output using adb, navigate to your SDK
+  <code>platform-tools/</code> directory and execute:/p>
+  <pre>
+$ adb logcat
+</pre>
+
+  <p>You can create a shell connection to a device and execute:</p>
+  <pre>
+$ adb shell
+# logcat
+</pre>
+
+  <h3>Options</h3>
+  <p>The following table describes the command line options of <code>logcat</code>.</p>
+  
+  <table>
+    <tr>
+      <th>Option</th>
+
+      <th>Description</th>
+    </tr>
+
+    <tr>
+      <td><code>-b&nbsp;&lt;buffer&gt;</code></td>
+
+      <td>Loads an alternate log buffer for viewing, such as <code>event</code> or
+      <code>radio</code>. The <code>main</code> buffer is used by default. See <a href= 
+      "#alternativebuffers">Viewing Alternative Log Buffers</a>.</td>
+    </tr>
+
+    <tr>
+      <td><code>-c</code></td>
+
+      <td>Clears (flushes) the entire log and exits.</td>
+    </tr>
+
+    <tr>
+      <td><code>-d</code></td>
+
+      <td>Dumps the log to the screen and exits.</td>
+    </tr>
+
+    <tr>
+      <td><code>-f&nbsp;&lt;filename&gt;</code></td>
+
+      <td>Writes log message output to <code>&lt;filename&gt;</code>. The default is
+      <code>stdout</code>.</td>
+    </tr>
+
+    <tr>
+      <td><code>-g</code></td>
+
+      <td>Prints the size of the specified log buffer and exits.</td>
+    </tr>
+
+    <tr>
+      <td><code>-n&nbsp;&lt;count&gt;</code></td>
+
+      <td>Sets the maximum number of rotated logs to <code>&lt;count&gt;</code>. The default value
+      is 4. Requires the <code>-r</code> option.</td>
+    </tr>
+
+    <tr>
+      <td><code>-r&nbsp;&lt;kbytes&gt;</code></td>
+
+      <td>Rotates the log file every <code>&lt;kbytes&gt;</code> of output. The default value is
+      16. Requires the <code>-f</code> option.</td>
+    </tr>
+
+    <tr>
+      <td><code>-s</code></td>
+
+      <td>Sets the default filter spec to silent.</td>
+    </tr>
+
+    <tr>
+      <td><code>-v&nbsp;&lt;format&gt;</code></td>
+
+      <td>Sets the output format for log messages. The default is <code>brief</code> format. For a
+      list of supported formats, see <a href="#outputformat">Controlling Log Output
+      Format</a>.</td>
+    </tr>
+  </table>
diff --git a/docs/html/guide/developing/tools/mksdcard.jd b/docs/html/guide/developing/tools/mksdcard.jd
new file mode 100644
index 0000000..f70d6b7
--- /dev/null
+++ b/docs/html/guide/developing/tools/mksdcard.jd
@@ -0,0 +1,53 @@
+page.title=mksdcard
+@jd:body
+
+ <p>The <code>mksdcard</code> tool lets you quickly create a FAT32 disk image that you can load in the
+  emulator, to simulate the presence of an SD card in the device. Because you can specify an SD
+  card while creating an AVD in the AVD Manager, you usually use that feature to create an SD card.
+  This tool creates an SD card that is not bundled with an AVD, so it is useful for situations
+  where you need to share a virtual SD card between multiple emulators.</p>
+
+  <h3>Usage</h3>
+  <pre>
+mksdcard -l &lt;label&gt; &lt;size&gt; &lt;file&gt;
+</pre>
+
+  <h3>Options</h3>
+  The following table describes the command-line options of <code>mksdcard</code>
+  <table>
+    <tr>
+      <th>Option</th>
+      
+      <th>Description</th>
+    </tr>
+    
+    <tr>
+      <td><code>-l</code></td>
+
+      <td>A volume label for the disk image to create.</td>
+    </tr>
+
+    <tr>
+      <td><code>size</code></td>
+
+      <td>An integer that specifies the size (in bytes) of disk image to create. You can also
+      specify size in kilobytes or megabytes, by appending a "K" or "M" to &lt;size&gt;. For
+      example, <code>1048576K</code>, <code>1024M</code>.</td>
+    </tr>
+
+    <tr>
+      <td><code>file</code></td>
+
+      <td>The path/filename of the disk image to create.</td>
+    </tr>
+  </table>
+
+  <p>Once you have created the disk image file, you can load it in the emulator at startup using
+  the emulator's <code>-sdcard</code> option. For more information, see <a href= 
+  "{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a>.</p>
+  
+  <p>The usage for the <code>-sdcard</code> option is as follows:</p>
+  <pre>emulator -sdcard &lt;file&gt;</pre>
+
+<h3>Example</h3>
+mksdcard -l mySdCard 1024M mySdCardFile.img
\ No newline at end of file
diff --git a/docs/html/guide/developing/tools/monkey.jd b/docs/html/guide/developing/tools/monkey.jd
index 9a2ab6f..6c05934 100644
--- a/docs/html/guide/developing/tools/monkey.jd
+++ b/docs/html/guide/developing/tools/monkey.jd
@@ -185,7 +185,7 @@
 <td>If set, this option will generate profiling reports immediately before and after
 the Monkey event sequence.
 This will generate large (~5Mb) files in data/misc, so use with care.  See 
-<a href="{@docRoot}guide/developing/tools/traceview.html" title="traceview">Traceview</a> for more information
+<a href="{@docRoot}guide/developing/debugging/debugging-tracing.html" title="traceview">Traceview</a> for more information
 on trace files.</td>
 </tr>
 
diff --git a/docs/html/guide/developing/tools/othertools.html b/docs/html/guide/developing/tools/othertools.html
new file mode 100644
index 0000000..a074f33
--- /dev/null
+++ b/docs/html/guide/developing/tools/othertools.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0;url=http://developer.android.com/guide/developing/tools/index.html">
+<title>Redirecting...</title>
+</head>
+<body>
+<p>You should be redirected. Please <a
+href="http://developer.android.com/guide/developing/tools/index.html">click here</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/guide/developing/tools/othertools.jd b/docs/html/guide/developing/tools/othertools.jd
deleted file mode 100644
index 00f0b8d6..0000000
--- a/docs/html/guide/developing/tools/othertools.jd
+++ /dev/null
@@ -1,95 +0,0 @@
-page.title=Other Tools
-@jd:body
-
-<p>The sections below describe other tools that you can use when building 
-Android applications. </p>
-
-<p>All of the tools are included in the Android SDK and are accessible from the 
-<code>&lt;sdk&gt;/tools/</code> directory.</p>
-
-<h2>Contents</h2>
-
-<dl>
-    <dt><a href="#android">android</a></dd>
-    <dt><a href="#mksdcard">mksdcard</a></dt>
-    <dt><a href="#dx">dx</a></dt>
-</dl>
-
-<a name="activitycreator"></a>
-<h2 id="android">android</h2>
-
-<p>{@code android} is an important development tool that lets you:</p>
-
-<ul>
-  <li>Create, delete, and view Android Virtual Devices (AVDs). See 
-  <a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a>.</li>
-  <li>Create and update Android projects. See
-  <a href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>.</li>
-  <li>Update your Android SDK with new platforms, add-ons, and documentation. See
-  <a href="{@docRoot}sdk/adding-components.html">Adding SDK Components</a>.</li>
-</ul>
-
-<p>If you develop in Eclipse with the ADT plugin, you can perform
-these tasks directly from the IDE. To create
-Android projects and AVDs from Eclipse, see <a href="{@docRoot}guide/developing/eclipse-adt.html">Developing
-In Eclipse</a>. To update your SDK from Eclipse, see
-<a href="{@docRoot}sdk/adding-components.html">Adding SDK Components</a>. 
-</p>
-
-
-<a name="mksdcard"></a>
-
-<h2>mksdcard</h2>
-
-<p>The mksdcard tool lets you quickly create a FAT32 disk image that you can 
-load in the emulator, to simulate the presence of an SD card in the device. 
-Here is the usage for mksdcard:</p>
-
-<pre>mksdcard [-l label] &lt;size&gt;[K|M] &lt;file&gt;</pre>
-
-<p>The table below lists the available options/arguments</p>
-
-<table>
-<tr>
-	<th>Argument</th>
-	<th>Description</th>
-</tr>
-
-<tr>
-	<td><code>-l</code></td>
-	<td>A volume label for the disk image to create. </td>
-</tr>
-
-<tr>
-	<td><code>size</code></td>
-	<td>An integer that specifies the size (in bytes) of disk image to create. 
-You can also specify size in kilobytes or megabytes, by appending a "K" or "M" to 
-&lt;size&gt;. For example, <code>1048576K</code>, <code>1024M</code>.</td>
-</tr>
-
-<tr>
-	<td><code>file</code></td>
-	<td>The path/filename of the disk image to create. </td>
-</tr>
-
-</table>
-
-<p>Once you have created the disk image file, you can load it in the emulator at 
-startup using the emulator's -sdcard option. For more information, see 
-<a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a>.</p>
-
-<pre>emulator -sdcard &lt;file&gt;</pre>
-
-<a name="dx"></a>
-
-<h2>dx</h2>
-
-<p>The dx tool lets you generate Android bytecode from .class files. The tool 
-converts target files and/or directories to Dalvik executable format (.dex) files, 
-so that they can run in the Android environment. It can also dump the class files 
-in a human-readable format and run a target unit test. You can get the usage and 
-options for this tool by using <code>dx --help</code>.</p>
-
-
-
-
diff --git a/docs/html/guide/developing/tools/sqlite3.jd b/docs/html/guide/developing/tools/sqlite3.jd
new file mode 100644
index 0000000..71e614f
--- /dev/null
+++ b/docs/html/guide/developing/tools/sqlite3.jd
@@ -0,0 +1,57 @@
+page.title=sqlite3
+@jd:body
+
+ <p>From a remote shell to your device or from your host machine, you can use the <a href= 
+  "http://www.sqlite.org/sqlite.html">sqlite3</a> command-line program to manage SQLite databases
+  created by Android applications. The <code>sqlite3</code> tool includes many useful commands,
+  such as <code>.dump</code> to print out the contents of a table and <code>.schema</code> to print
+  the SQL CREATE statement for an existing table. The tool also gives you the ability to execute
+  SQLite commands on the fly.</p>
+
+  <p>To use <code>sqlite3</code> from a remote shell:</p>
+
+  <ol>
+    <li>Enter a remote shell by entering the following command:
+      <pre>adb [-d|-e|-s {&lt;serialNumber&gt;}] shell</pre>
+    </li>
+
+    <li>From a remote shell, start the <code>sqlite3</code> tool by entering the following command:
+      <pre>sqlite3</pre>
+
+      <p>You can also optionally specify a full path to a database that you want to explore.
+      Emulator/device instances store SQLite3 databases in the directory 
+      <code>/data/data/&lt;package_name&gt;/databases/</code>.</p>
+    </li>
+
+    <li>Once you invoke <code>sqlite3</code>, you can issue <code>sqlite3</code> commands in the
+    shell. To exit and return to the adb remote shell, enter <code>exit</code> or press
+    <code>CTRL+D</code>.</li>
+  </ol>
+  
+  
+      <p>Here's an example:</p>
+      <pre>$ adb -s emulator-5554 shell
+# sqlite3 /data/data/com.example.google.rss.rssexample/databases/rssitems.db
+SQLite version 3.3.12
+Enter ".help" for instructions
+<em>.... enter commands, then quit...</em>
+# sqlite&gt; .exit 
+</pre>
+
+  <p>To use <code>sqlite3</code> locally, instead of within a shell, 
+  pull the database file from the device and start {@code sqlite3}:</p>
+
+  <ol>
+    <li>Copy a database file from your device to your host machine:
+      <pre>
+adb pull &lt;database-file-on-device&gt;
+</pre>
+    </li>
+
+    <li>Start the sqlite3 tool from the <code>/tools</code> directory, specifying the database
+    file:
+      <pre>
+sqlite3 &lt;database-file-on-host&gt;
+</pre>
+    </li>
+  </ol>
\ No newline at end of file
diff --git a/docs/html/guide/developing/tools/traceview.jd b/docs/html/guide/developing/tools/traceview.jd
index 95ae823..422fe00 100644
--- a/docs/html/guide/developing/tools/traceview.jd
+++ b/docs/html/guide/developing/tools/traceview.jd
@@ -1,319 +1,14 @@
-page.title=Traceview: A Graphical Log Viewer
+page.title=Traceview
 @jd:body
 
-<div id="qv-wrapper">
-<div id="qv">
+<p>Traceview is a graphical viewer for execution logs saved by your application. 
+Traceview can help you debug your application and profile its performance.</p>
 
-  <h2>In this document</h2>
-<ol>
-    <li><a href="#creatingtracefiles">Creating Trace Files</a></li>
-    <li><a href="#copyingfiles">Copying Trace Files to a Host Machine</a></li>
-    <li><a href="#runningtraceview">Viewing Trace Files in Traceview</a>
-            <ol>
-		<li><a href="#timelinepanel">Timeline Panel</a></li>
-        	<li><a href="#profilepanel">Profile Panel</a></li>
-	    </ol></li>
-    <li><a href="#format">Traceview File Format</a>
-            <ol>
-		<li><a href="#datafileformat">Data File Format</a></li>
-        	<li><a href="#keyfileformat">Key File Format</a></li>
-	    </ol></li>
-    <li><a href="#knownissues">Traceview Known Issues</a></li>
-    <li><a href="#dmtracedump">Using dmtracedump</a></li>
+<p>To start Traceview, enter the following command from the SDK <code>tools/</code> directory:</p>
+  <pre>traceview</pre>
 </ol>
-</div>
-</div>
 
-<p>Traceview is a graphical viewer for execution logs
-saved by your application. Traceview can help you debug your application and 
-profile its performance. The sections below describe how to use the program. </p>
-
-<a name="creatingtracefiles"></a>
-
-<h2>Creating Trace Files</h2>
-
-<p>To use Traceview, you need to generate log files containing the trace information you want to analyze. To do that, you  include the {@link android.os.Debug}
-  class in your code and call its methods to start and stop logging of trace information
-  to disk. When your application quits, you can then use Traceview to examine the log files
-  for useful run-time information such
-  as method calls and run times. </p>
-<p>To create the trace files, include the {@link android.os.Debug} class and call one
-  of the {@link android.os.Debug#startMethodTracing() startMethodTracing()} methods. 
-  In the call, you specify a base name for the trace files that the system generates. 
-  To stop tracing, call {@link android.os.Debug#stopMethodTracing() stopMethodTracing()}.
-  These methods start and stop method tracing across the entire virtual machine. For 
-  example, you could call startMethodTracing() in your activity's onCreate()
-  method, and call stopMethodTracing() in that activity's onDestroy() method.</p>
-
-<pre>
-    // start tracing to "/sdcard/calc.trace"
-    Debug.startMethodTracing("calc");
-    // ...
-    // stop tracing
-    Debug.stopMethodTracing();
-</pre>
-
-<p>When your application calls startMethodTracing(), the system creates a
-file called <code>&lt;trace-base-name>.trace</code>.  This contains the
-binary method trace data and a mapping table with thread and method names.</p>
-
-<p>The system then begins buffering the generated trace data, until your application calls 
-	stopMethodTracing(), at which time it writes the buffered data to the
-	output file.
-	If the system reaches the maximum buffer size before stopMethodTracing() 
-	is called, the system stops tracing and sends a notification
-	to the console. </p>
-
-<p>Interpreted code will run more slowly when profiling is enabled.  Don't
-try to generate absolute timings from the profiler results (i.e. "function
-X takes 2.5 seconds to run").  The times are only
-useful in relation to other profile output, so you can see if changes
-have made the code faster or slower. </p>
-
-<p>When using the Android emulator, you must create an SD card image upon which
-the trace files will be written. For example, from the <code>/tools</code> directory, you 
-can create an SD card image named "imgcd" and mount it when launching the emulator like so:</p>
-<pre>
-<b>$</b> mksdcard 1024M ./imgcd
-<b>$</b> emulator -sdcard ./imgcd
-</pre>
-<p>For more information, read about the 
-<a href="{@docRoot}guide/developing/tools/othertools.html#mksdcard">mksdcard tool</a>.</p>
-	
-<p>The format of the trace files is described <a href="#format">later 
-   in this document</a>. </p>
-
-<a name="copyingfiles"></a>
-
-<h2>Copying Trace Files to a Host Machine</h2>
-<p>After your application has run and the system has created your trace files <code>&lt;trace-base-name>.trace</code>
-    on a device or emulator, you must copy those files to your development computer.   You can use <code>adb pull</code> to copy
-    the files. Here's an example that shows how to copy an example file,
-    calc.trace, from the default location on the emulator to the /tmp directory on
-the emulator host machine:</p>
-<pre>adb pull /sdcard/calc.trace /tmp</pre>
-
-
-<a name="runningtraceview"></a>
-
-<h2>Viewing Trace Files in Traceview</h2>
-<p>To run traceview and view the trace files, enter <code>traceview &lt;trace-base-name></code>.
-    For example, to run Traceview on the example files copied in the previous section,
-    you would use: </p>
-    <pre>traceview /tmp/calc</pre>
-
-	<p>Traceview loads the log files and displays their data in a window that has two panels:</p>
-	<ul>
-		<li>A <a href="#timelinepanel">timeline panel</a> -- describes when each thread
-	    and method started and stopped</li>
-    	<li>A <a href="#timelinepanel">profile panel</a> -- provides a summary of what happened inside a method</li>
-	</ul>
-	<p>The sections below provide addition information about the traceview output panes. </p>
-
-<a name="timelinepanel"></a>
-
-<h3>Timeline Panel  </h3>
-<p>The image below shows a close up of the timeline panel. Each thread&rsquo;s
-    execution is shown in its own row, with time increasing to the right. Each method
-    is shown in another color (colors are reused in a round-robin fashion starting
-    with the methods that have the most inclusive time). The thin lines underneath
-    the first row show the extent (entry to exit) of all the calls to the selected
-    method. The method in this case is LoadListener.nativeFinished() and it was
-    selected in the profile view. </p>
-<p><img src="/images/traceview_timeline.png" alt="Traceview timeline panel" width="893" height="284"></p>
-<a name="profilepanel"></a>
-<h3>Profile Panel</h3>
-<p>The image below shows the profile pane. The profile pane shows a
-    summary of all the time spent in a method. The table shows
-    both the inclusive and exclusive times (as well as the percentage of the total
-    time). Exclusive time is the time spent in the method. Inclusive time is the
-    time spent in the method plus the time spent in any called functions. We refer
-    to  calling methods as &quot;parents&quot; and called methods as &quot;children.&quot;
-    When a method is selected (by clicking on it), it expands to show the parents
-    and children. Parents are shown with a purple background and children
-    with a yellow background. The last column in the table shows the number of calls
-    to this method plus the number of recursive calls. The last column shows the
-    number of calls out of the total number of calls made to that method. In this
-    view, we can see that there were 14 calls to LoadListener.nativeFinished(); looking
-    at the timeline panel shows that one of those calls took an unusually
-    long time.</p>
-<p><img src="/images/traceview_profile.png" alt="Traceview profile panel." width="892" height="630"></p>
-
-<a name="format"></a>
-<h2>Traceview File Format</h2>
-<p>Tracing creates two distinct pieces of output: a <em>data</em> file,
-    which holds the trace data, and a <em>key</em> file, which
-    provides a mapping from binary identifiers to thread and method names.
-	The files are concatenated when tracing completes, into a
-	single <em>.trace</em> file. </p>
-
-<p class="note"><strong>Note:</strong> The previous version of Traceview did not concatenate 
-these files for you. If you have old key and data files that you'd still like to trace, you 
-can concatenate them yourself with <code>cat mytrace.key mytrace.data > mytrace.trace</code>.</p>
-
-<a name="datafileformat"></a>
-
-<h3>Data File Format</h3>
-<p>The data file is binary, structured as
-    follows (all values are stored in little-endian order):</p>
-<pre>* File format:
-* header
-* record 0
-* record 1
-* ...
-*
-* Header format:
-* u4 magic 0x574f4c53 ('SLOW')
-* u2 version
-* u2 offset to data
-* u8 start date/time in usec
-*
-* Record format:
-* u1 thread ID
-* u4 method ID | method action
-* u4 time delta since start, in usec
-</pre>
-<p>The application is expected to parse all of the header fields, then seek
-    to &quot;offset to data&quot; from the start of the file. From there it just
-    reads
-    9-byte records until EOF is reached.</p>
-<p><em>u8 start date/time in usec</em> is the output from gettimeofday().
-    It's mainly there so that you can tell if the output was generated yesterday
-    or three months ago.</p>
-<p><em>method action</em> sits in the two least-significant bits of the
-    <em>method</em> word. The currently defined meanings are:    </p>
-<ul>
-    <li>0 - method entry </li>
-    <li>1 - method exit </li>
-    <li>2 - method &quot;exited&quot; when unrolled by exception handling </li>
-    <li>3 - (reserved)</li>
-</ul>
-<p>An unsigned 32-bit integer can hold about 70 minutes of time in microseconds.
+<p>For more information on how to use Traceview, see 
+<a href="{@docRoot}guide/developing/debugging/debugging-tracing.html">Profiling with Traceview and dmtracedump</a>
 </p>
 
-<a name="keyfileformat"></a>
-	
-<h3>Key File Format</h3>
-<p>The key file is a plain text file divided into three sections. Each
-    section starts with a keyword that begins with '*'. If you see a '*' at the start
-    of a line, you have found the start of a new section.</p>
-<p>An example file might look like this:</p>
-<pre>*version
-1
-clock=global
-*threads
-1 main
-6 JDWP Handler
-5 Async GC
-4 Reference Handler
-3 Finalizer
-2 Signal Handler
-*methods
-0x080f23f8 java/io/PrintStream write ([BII)V
-0x080f25d4 java/io/PrintStream print (Ljava/lang/String;)V
-0x080f27f4 java/io/PrintStream println (Ljava/lang/String;)V
-0x080da620 java/lang/RuntimeException	&lt;init&gt;	()V
-[...]
-0x080f630c android/os/Debug startMethodTracing ()V
-0x080f6350 android/os/Debug startMethodTracing (Ljava/lang/String;Ljava/lang/String;I)V
-*end</pre>
-<dl>
-    <dt><em>version section</em></dt>
-    <dd>The first line is the file version number, currently
-        1.
-        The second line, <code>clock=global</code>, indicates that we use a common
-        clock across all threads. A future version may use per-thread CPU time counters
-        that are independent for every thread.</dd>
-    <dt><em>threads section</em></dt>
-    <dd>One line per thread. Each line consists of two parts: the thread ID, followed
-        by a tab, followed by the thread name. There are few restrictions on what
-        a valid thread name is, so include everything to the end of the line.</dd>
-    <dt><em>methods section </em></dt>
-    <dd>One line per method entry or exit. A line consists of four pieces,
-        separated by tab marks: <em>method-ID</em> [TAB] <em>class-name</em> [TAB] 
-        <em>method-name</em> [TAB] 
-        <em>signature</em> . Only
-        the methods that were actually entered or exited are included in the list.
-        Note that all three identifiers are required to uniquely identify a
-        method.</dd>
-</dl>
-<p>Neither the threads nor methods sections are sorted.</p>
-
-<a name="knownissues"></a>
-<h2>Traceview Known Issues</h2>
-<dl>
-	<dt>Threads</dt>
-	<dd>Traceview logging does not handle threads well, resulting in these two problems:
-<ol>
-  <li> If a thread exits during profiling, the thread name is not emitted; </li>
-    <li>The VM reuses thread IDs. If a thread stops and another starts, they
-        may get the same ID. </li>
-</ol>
-</dd>
-
-<a name="dmtracedump"></a>
-
-<h2>Using dmtracedump</h2>
-
-<p>The Android SDK includes dmtracedump, a tool that gives you an alternate way 
-	of generating graphical call-stack diagrams from trace log files. The tool 
-	uses the Graphviz Dot utility to create the graphical output, so you need to 
-	install Graphviz before running dmtracedump.</p>
-	
-<p>The dmtracedump tool generates the call stack data as a tree diagram, with each call 
-	represented as a node. It shows call flow (from parent node to child nodes) using 
-	arrows. The diagram below shows an example of dmtracedump output.</p>
-	
-<img src="{@docRoot}images/tracedump.png" width="485" height="401" style="margin-top:1em;"/>
-
-<p style="margin-top:1em;">For each node, dmtracedump shows <code>&lt;ref> <em>callname</em> (&lt;inc-ms>,
-	&lt;exc-ms>,&lt;numcalls>)</code>, where</p>
-
-<ul>
-		<li><code>&lt;ref></code> -- Call reference number, as used in trace logs</li>
-		<li><code>&lt;inc-ms></code> -- Inclusive elapsed time (milliseconds spent in method, including all child methods)</li>
-		<li><code>&lt;exc-ms></code> -- Exclusive elapsed time (milliseconds spent in method, not including any child methods)</li>
-		<li><code>&lt;numcalls></code> -- Number of calls</li>
-</ul>
-
-<p>The usage for dmtracedump is: </p>
-
-<pre>dmtracedump [-ho] [-s sortable] [-d trace-base-name] [-g outfile] &lt;trace-base-name></pre>
-
-<p>The tool then loads trace log data from &lt;trace-base-name>.data and &lt;trace-base-name>.key. 
-	The table below lists the options for dmtracedump.</p>
-
-<table>
-<tr>
-  <th>Option</td>
-  <th>Description</th>
-</tr>
-  
-  <tr>
-	<td><code>-d&nbsp;&lt;trace-base-name> </code></td>
-	<td>Diff with this trace name</td>
-  </tr>
-  <tr>
-	<td><code>-g&nbsp;&lt;outfile> </code></td>
-	<td>Generate output to &lt;outfile></td>
-  </tr>
-  <tr>
-	<td><code>-h </code></td>
-	<td>Turn on HTML output</td>
-  </tr>
-  <tr>
-	<td><code>-o </code></td>
-	<td>Dump the trace file instead of profiling</td>
-  </tr>
-  <tr>
-	<td><code>-d&nbsp;&lt;trace-base-name> </code></td>
-	<td>URL base to the location of the sortable javascript file</td>
-  </tr>
-  <tr>
-	<td><code>-t&nbsp;&lt;percent> </code></td>
-	<td>Minimum threshold for including child nodes in the graph (child's inclusive 
-		time as a percentage of parent inclusive time). If this option is not used, 
-		the default threshold is 20%. </td>
-  </tr>
-
-</table>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index e91d362..746597f 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -262,7 +262,7 @@
       </li>
       <li><a href="<?cs var:toroot?>guide/topics/admin/device-admin.html">
             <span class="en">Device Administration</span>
-         </a> <span class="new">new!</span>
+         </a>
       </li>
       <li class="toggle-list">
            <div>
@@ -274,27 +274,22 @@
               <li>
                 <a href="<?cs var:toroot?>guide/topics/testing/testing_android.html">
                 <span class="en">Testing Fundamentals</span></a>
-                <span class="new">new!</span>
               </li>
               <li>
                 <a href="<?cs var:toroot?>guide/topics/testing/activity_testing.html">
                 <span class="en">Activity Testing</span></a>
-                <span class="new">new!</span>
               </li>
               <li>
                 <a href="<?cs var:toroot?>guide/topics/testing/contentprovider_testing.html">
                 <span class="en">Content Provider Testing</span></a>
-                <span class="new">new!</span>
               </li>
               <li>
                 <a href="<?cs var:toroot?>guide/topics/testing/service_testing.html">
                 <span class="en">Service Testing</span></a>
-                <span class="new">new!</span>
               </li>
               <li>
                 <a href="<?cs var:toroot ?>guide/topics/testing/what_to_test.html">
                 <span class="en">What To Test</span></a>
-                <span class="new">new!</span>
               </li>
 
            </ul>
@@ -315,32 +310,120 @@
     <ul>
   <!--<li><a href="">Developing for Android</a></li>
       signing, upgrading, selecting a package name, select device profile, touch, trackball, dpad available, etc. -->
-      <li><a href="<?cs var:toroot ?>guide/developing/eclipse-adt.html">
-            <span class="en">In Eclipse, with ADT</span>
-            <span class="de" style="display:none">In Eclipse, mit ADT</span>
-            <span class="es" style="display:none">En Eclipse, con ADT</span>
-            <span class="fr" style="display:none">Sous Eclipse, à l'aide du plugin ADT</span>
-            <span class="it" style="display:none">In Eclipse, con ADT</span>
-            <span class="ja" style="display:none">Eclipse 内で ADT を使用</span>
-            <span class="zh-CN" style="display:none">利用 ADT 在 Eclipse 中开发</span>
-            <span class="zh-TW" style="display:none">在加裝 ADT 工具的 Eclipse 環境中</span>
+      <li>
+        <a href="<?cs var:toroot ?>guide/developing/index.html">
+        <span class="en">Overview</span></a>
+      </li>
+
+      <li class="toggle-list">
+        <div>
+           <a href="<?cs var:toroot ?>guide/developing/devices/index.html">
+        	     <span class="en">Creating and Managing Virtual Devices</span>
+         	 </a>
+        </div>
+        <ul>
+          <li>
+            <a href="<?cs var:toroot ?>guide/developing/devices/managing-avds.html">
+              <span class="en">With AVD Manager</span>
+         	 </a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>guide/developing/devices/managing-avds-cmdline.html">
+              <span class="en">On the Command Line</span>
+         	 </a>
+          </li>
+          <li>
+           <a href="<?cs var:toroot ?>guide/developing/devices/emulator.html">
+        	     <span class="en">Using the Android Emulator</span>
+         	 </a>
+          </li>
+        </ul>
+      </li>
+      <li>
+        <a href="<?cs var:toroot ?>guide/developing/device.html">
+          <span class="en">Connecting Hardware Devices</span>
+        </a>
+      </li>
+      
+      <li class="toggle-list">
+        <div>
+          <a href="<?cs var:toroot ?>guide/developing/projects/index.html">
+            <span class="en">Creating and Managing Projects</span>
+          </a>
+        </div>
+        <ul>
+          <li>
+            <a href="<?cs var:toroot ?>guide/developing/projects/projects-eclipse.html">
+              <span class="en">In Eclipse with ADT</span>
+            </a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>guide/developing/projects/projects-cmdline.html">
+        	    <span class="en">On the Command Line</span>
+            </a>
+          </li>
+        </ul>
+      </li>
+
+      <li class="toggle-list">
+        <div>
+          <a href="<?cs var:toroot ?>guide/developing/building/index.html">
+            <span class="en">Building and Running Apps</span>
+          </a>
+        </div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>guide/developing/building/building-eclipse.html">
+          <span class="en">In Eclipse with ADT</span>
           </a></li>
-      <li><a href="<?cs var:toroot ?>guide/developing/other-ide.html">
-            <span class="en">In Other IDEs</span>
-            <span class="de" style="display:none">In anderen IDEs</span>
-            <span class="es" style="display:none">En otros entornos</span>
-            <span class="fr" style="display:none">Sous d'autres environnements</span>
-            <span class="it" style="display:none">In altri IDE</span>
-            <span class="ja" style="display:none">その他の統合開発環境</span>
-            <span class="zh-CN" style="display:none">在其他 IDE 中开发</span>
-            <span class="zh-TW" style="display:none">在其他開發環境中</span>
-          </a></li>
-      <li><a href="<?cs var:toroot ?>guide/developing/device.html">
-            <span class="en">On a Device</span>
-          </a></li>
-      <li><a href="<?cs var:toroot ?>guide/developing/debug-tasks.html">
-            <span class="en">Debugging Tasks</span>
-          </a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/building/building-cmdline.html"><span class="en">On the Command Line</span></a></li>
+        </ul>
+      </li>
+
+      <li class="toggle-list">
+        <div>
+          <a href="<?cs var:toroot ?>guide/developing/debugging/index.html">
+            <span class="en">Debugging</span>
+          </a>
+        </div>
+        <ul>
+          <li>
+            <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-projects.html">
+         	    <span class="en">In Eclipse with ADT</span>
+            </a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-projects-cmdline.html">
+         	    <span class="en">In Other IDEs</span>
+            </a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>guide/developing/debugging/ddms.html">
+              <span class="en">Using DDMS</span>
+            </a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-log.html">
+         	    <span class="en">Reading and Writing Log Messages</span>
+            </a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-ui.html">
+         	    <span class="en">Debugging and Profiling UIs</span>
+          	</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-tracing.html">
+         	    <span class="en">Profiling with Traceview and dmtracedump</span>
+          	</a>
+          </li>
+          <li>
+            <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-devtools.html">
+         	    <span class="en">Using the Dev Tools App</span>
+          	</a>
+          </li>
+        </ul>
+      </li>
+
       <li class="toggle-list">
            <div>
                 <a href="<?cs var:toroot ?>guide/developing/testing/index.html">
@@ -350,71 +433,59 @@
            <ul>
               <li>
                 <a href="<?cs var:toroot ?>guide/developing/testing/testing_eclipse.html">
-                  <span class="en">Testing in Eclipse, with ADT</span>
+                  <span class="en">In Eclipse with ADT</span>
                 </a>
               </li>
 
               <li>
                 <a href="<?cs var:toroot ?>guide/developing/testing/testing_otheride.html">
-                  <span class="en">Testing in Other IDEs</span>
+                  <span class="en">In Other IDEs</span>
                 </a>
               </li>
            </ul>
          </li>
-      <li class="toggle-list">
+
+         <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/developing/tools/index.html">
             <span class="en">Tools</span>
           </a></div>
         <ul>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/aapt.html">aapt</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/adb.html">adb</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/othertools.html#android">android</a></li>
-      <!--<li><a href="<?cs var:toroot ?>guide/developing/tools/adt.html">ADT Plugin</a></li>-->
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/aidl.html">aidl</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/avd.html">AVDs</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/bmgr.html">bmgr</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/ddms.html">ddms</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/othertools.html#dx">dx</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/draw9patch.html">Draw 9-Patch</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/emulator.html">Emulator</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/hierarchy-viewer.html">Hierarchy Viewer</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/layoutopt.html">layoutopt</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/othertools.html#mksdcard">mksdcard</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/monkey.html">Monkey</a></li>
-              <li class="toggle-list">
-                 <div>
-                     <a href="<?cs var:toroot?>guide/developing/tools/monkeyrunner_concepts.html">
-                     <span class="en">monkeyrunner</span>
-                  </a>
-                      <span class="new">new!</span>
-                  </div>
-                  <ul>
-                      <li>
-                          <a href="<?cs var:toroot?>guide/developing/tools/MonkeyDevice.html">
-                                <span class="en">MonkeyDevice</span>
-                        </a>
-                        <span class="new">new!</span>
-                    </li>
-                    <li>
-                        <a href="<?cs var:toroot?>guide/developing/tools/MonkeyImage.html">
-                            <span class="en">MonkeyImage</span>
-                        </a>
-                        <span class="new">new!</span>
-                    </li>
-                    <li>
-                        <a href="<?cs var:toroot?>guide/developing/tools/MonkeyRunner.html">
-                            <span class="en">MonkeyRunner</span>
-                        </a>
-                        <span class="new">new!</span>
-                    </li>
-                  </ul>
-              </li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/proguard.html">Proguard</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/adb.html#sqlite">sqlite3</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/traceview.html" >Traceview</a></li>
-              <li><a href="<?cs var:toroot ?>guide/developing/tools/zipalign.html" >zipalign</a></li>
-          </ul>
-        </li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/adb.html">adb</a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/android.html">android</a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/aidl.html">aidl</a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/bmgr.html">bmgr</a>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/dmtracedump.html">dmtracedump</a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/draw9patch.html" >Draw 9-Patch</a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/emulator.html">Emulator</a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/hierarchy-viewer.html">Hierarchy Viewer</a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/hprof-conv.html">hprof-conv</a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/layoutopt.html">layoutopt</a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/logcat.html">logcat</a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/mksdcard.html">mksdcard</a></li>
+
+          <li><a href="/guide/developing/tools/monkey.html">Monkey</a></li>
+          <li class="toggle-list">
+            <div><a href="/guide/developing/tools/monkeyrunner_concepts.html">
+              <span class="en">monkeyrunner</span>
+            </a></div>
+            <ul>
+              <li><a href="/guide/developing/tools/MonkeyDevice.html">
+                <span class="en">MonkeyDevice</span>
+                </a></li>
+              <li><a href="/guide/developing/tools/MonkeyImage.html">
+                <span class="en">MonkeyImage</span>
+                </a></li>
+              <li><a href="/guide/developing/tools/MonkeyRunner.html">
+                <span class="en">MonkeyRunner</span>
+                </a></li>
+            </ul>
+          </li>
+          <li><a href="/guide/developing/tools/proguard.html">ProGuard</a></li>
+          <li><a href="/guide/developing/tools/adb.html#sqlite">sqlite3</a></li>
+          <li><a href="/guide/developing/tools/traceview.html">Traceview</a></li>
+          <li><a href="<?cs var:toroot ?>guide/developing/tools/zipalign.html">zipalign</a></li>
+        </ul>
+      </li>
     </ul>
   </li>
 
@@ -451,7 +522,7 @@
           </a></li>
       <li><a href="<?cs var:toroot ?>guide/publishing/licensing.html">
             <span class="en">Licensing Your Applications</span>
-          </a> <span class="new">new!</span></li>
+          </a></li>
       <li><a href="<?cs var:toroot ?>guide/publishing/preparing.html">
             <span class="en">Preparing to Publish</span>
             <span class="de" style="display:none">Vorbereitung auf die Veröffentlichung</span>
@@ -546,19 +617,19 @@
     <ul>
       <li><a href="<?cs var:toroot ?>guide/webapps/index.html">
             <span class="en">Web Apps Overview</span>
-          </a> <span class="new">new!</span><!-- 11/1/10 --></li>
+          </a></li>
       <li><a href="<?cs var:toroot ?>guide/webapps/targeting.html">
             <span class="en">Targeting Screens from Web Apps</span>
-          </a> <span class="new">new!</span><!-- 11/1/10 --></li>
+          </a></li>
       <li><a href="<?cs var:toroot ?>guide/webapps/webview.html">
             <span class="en">Building Web Apps in WebView</span>
-          </a> <span class="new">new!</span><!-- 11/1/10 --></li>
+          </a></li>
       <li><a href="<?cs var:toroot ?>guide/webapps/debugging.html">
             <span class="en">Debugging Web Apps</span>
-          </a> <span class="new">new!</span><!-- 11/1/10 --></li>
+          </a></li>
       <li><a href="<?cs var:toroot ?>guide/webapps/best-practices.html">
             <span class="en">Best Practices for Web Apps</span>
-          </a> <span class="new">new!</span><!-- 11/1/10 --></li>
+          </a></li>
     </ul>
   </li>
 
diff --git a/docs/html/guide/practices/design/performance.jd b/docs/html/guide/practices/design/performance.jd
index f5588ac..97b31cf 100644
--- a/docs/html/guide/practices/design/performance.jd
+++ b/docs/html/guide/practices/design/performance.jd
@@ -425,7 +425,7 @@
 to run your own microbenchmarks.</p>
 
 <p>You may also find
-<a href="{@docRoot}guide/developing/tools/traceview.html">Traceview</a> useful
+<a href="{@docRoot}guide/developing/debugging/debugging-tracing.html">Traceview</a> useful
 for profiling, but it's important to realize that it currently disables the JIT,
 which may cause it to misattribute time to code that the JIT may be able to win
 back. It's especially important after making changes suggested by Traceview
diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index 5738bd6..520bd28 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -38,7 +38,7 @@
     <li><a
 href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">
 Providing Alternative Resources</a></li>
-    <li><a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a></li>
+    <li><a href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</a></li>
   </ol>
 
 </div>
@@ -1205,7 +1205,7 @@
 Manager or the <code>android</code> tool to create AVDs that use the various
 emulator skins and you can also set up custom AVDs to test densities other than
 the defaults. For general information about working with AVDs, see
-<a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual
+<a href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual
 Devices</a>.</p>
 
 <p>The Android SDK provides a set of default emulator skins that you can use for
diff --git a/docs/html/guide/publishing/app-signing.jd b/docs/html/guide/publishing/app-signing.jd
index c7e1c79..93077a0 100644
--- a/docs/html/guide/publishing/app-signing.jd
+++ b/docs/html/guide/publishing/app-signing.jd
@@ -240,8 +240,8 @@
 compile your app, the build script generates a keystore/key and signs the .apk for you. 
 The script then also aligns the .apk with the <code>zipalign</code> tool.
 No other action on your part is needed. Read 
-<a href="{@docRoot}guide/developing/other-ide.html#DebugMode">Developing In Other IDEs: Building
-in debug mode</a> for more information.</p>
+<a href="{@docRoot}guide/developing/building/building-cmdline.html#DebugMode">Building and Running Apps
+on the Command Line</a> for more information.</p>
 
 
 <h3 id="debugexpiry">Expiry of the Debug Certificate</h3>
@@ -259,7 +259,7 @@
 <p>In Eclipse/ADT, you will see a similar error in the Android console.</p>
 
 <p>To fix this problem, simply delete the <code>debug.keystore</code> file. 
-The default storage location for AVDs is in <code>~/.android/avd</code> on OS X and Linux, 
+The default storage location for AVDs is in <code>~/.android/</code> on OS X and Linux, 
 in <code>C:\Documents and Settings\<user>\.android\</code> on Windows XP, and in
 <code>C:\Users\<user>\.android\</code> on Windows Vista.</p>
 
@@ -441,8 +441,8 @@
 <code><em>&lt;your_project_name></em>-release.apk</code>. With these steps
 automated for you, you're able to skip the manual procedures below (steps 3 and 4).
 To learn how to specify your keystore and alias in the {@code build.properties} file,
-see <a href="{@docRoot}guide/developing/other-ide.html#ReleaseMode">Developing In Other
-IDEs: Building in release mode</a>.</p>
+see <a href="{@docRoot}guide/developing/building/building-cmdline.html#ReleaseMode">
+Building and Running Apps on the Command Line</a>.</p>
 
 
 
diff --git a/docs/html/guide/publishing/licensing.jd b/docs/html/guide/publishing/licensing.jd
index 40439f0..e099413 100644
--- a/docs/html/guide/publishing/licensing.jd
+++ b/docs/html/guide/publishing/licensing.jd
@@ -518,7 +518,7 @@
 </ol>
 
 <p>If you are not familiar with AVDs or how to use them, see <a
-href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a>.</p>
+href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</a>.</p>
 
 <h4 id="project-update">Updating your project configuration</h4>
 
@@ -628,12 +628,9 @@
 share its code and resources across multiple applications. </p>
 
 <p style="margin-top:.5em;">If you aren't familiar with library projects or how
-to use them, read more in <a
-href="{@docRoot}guide/developing/eclipse-adt.html#libraryProject">Developing in
-Eclipse with ADT</a> or <a
-href="{@docRoot}guide/developing/other-ide.html#libraryProject">Developing in
-Other IDEs</a>, as appropriate for your environment.</p>
-
+to use them, see <a href="{@docRoot}guide/developing/projects/index.html#LibraryProjects">
+Creating and Managing Projects</a>.
+</p>
 </div>
 </div>
 
@@ -669,9 +666,8 @@
 no further configuration is needed. </p>
 
 <p>For more information about how to create an application project or work with
-library projects in Eclipse, see <a
-href="{@docRoot}guide/developing/eclipse-adt.html#CreatingAProject">Developing
-in Eclipse with ADT</a>.</p>
+library projects in Eclipse, see <a href="{@docRoot}guide/developing/projects/projects-eclipse.html">
+Creating and Managing Projects in Eclipse</a></p>.
 
 <h4>Copying the LVL sources to your application</h4>
 
@@ -701,9 +697,9 @@
 <p>Next, open the application's project properties window, as shown below.
 Select the "Android" properties group and click <strong>Add</strong>, then
 choose the LVL library project (com_android_vending_licensing) and click
-<strong>OK</strong>. For more information, see
-<a href="{@docRoot}guide/developing/eclipse-adt.html#libraryProject">Developing
-in Eclipse with ADT</a></p>
+<strong>OK</strong>. For more information, see 
+<a href="{@docRoot}developing/projects/projects-eclipse.html#SettingUpLibraryProject">
+Creating and Managing Projects in Eclipse</a></p>.
 
 <div style="margin-bottom:2em;">
 
@@ -730,11 +726,9 @@
 --library <em>path/to/my/library_project</em>
 </pre>
 
-<p>For more information about working with library projects, see <a
-href="{@docRoot}guide/developing/eclipse-adt.html#libraryProject">Developing
-in Eclipse with ADT</a> or <a
-href="{@docRoot}guide/developing/other-ide.html#libraryProject">Developing in
-Other IDEs</a>, as appropriate for your environment.</p>
+<p>For more information about working with library projects, 
+see <a href="{@docRoot}developing/projects/projects-cmdline.html#SettingUpLibraryProject">
+Creating and Managing Projects on the Command Line</a></p>.
 
 
 <h2 id="app-integration">Integrating the LVL with Your Application</h2>
diff --git a/docs/html/guide/topics/advanced/aidl.jd b/docs/html/guide/topics/advanced/aidl.jd
new file mode 100644
index 0000000..fef46ec
--- /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/fragments/index.jd b/docs/html/guide/topics/fragments/index.jd
index 766146e..d07daf4 100644
--- a/docs/html/guide/topics/fragments/index.jd
+++ b/docs/html/guide/topics/fragments/index.jd
@@ -277,13 +277,13 @@
 which to place the fragment.</p>
   <p>To make any fragment transactions in your activity (such as add, remove, or replace a
 fragment), you must use APIs from {@link android.app.FragmentTransaction}. You can get an instance
-of {@link android.app.FragmentTransaction} from your {@link android.app.Activity} using {@link
-android.app.Activity#openFragmentTransaction()}. You can then add a fragment using the {@link
+of {@link android.app.FragmentTransaction} from your {@link android.app.FragmentManager} using {@link
+android.app.FragmentManager#openTransaction()}. You can then add a fragment using the {@link
 android.app.FragmentTransaction#add add()} method, specifying the fragment to add and the view in
 which to insert it. For example:</p>
 <pre>
 MyFragment fragment = new MyFragment();
-openFragmentTransaction().add(R.id.fragment_container, fragment).commit();
+getFragmentManager().openTransaction().add(R.id.fragment_container, fragment).commit();
 </pre>
   <p>The first argument passed to {@link android.app.FragmentTransaction#add add()}
 is the {@link android.view.ViewGroup} in which the fragment should be placed, specified by
@@ -372,8 +372,8 @@
 operations on a fragment as the user interacts with the activity, alowing for more rich user
 experiences without changing activities. In order to perform these operations, you must use {@link
 android.app.FragmentTransaction} to perform fragment "transactions." You can acquire {@link
-android.app.FragmentTransaction} from your activity with {@link
-android.app.Activity#openFragmentTransaction}.</p>
+android.app.FragmentTransaction} from your FragmentManager with {@link
+android.app.FragmentManager#openTransaction}.</p>
 
 <p>Common transactions you can perform with fragments include:</p>
 
@@ -397,7 +397,7 @@
 <pre>
 // Create new fragment
 Fragment newFragment = new MyFragment();
-FragmentTransaction ft = openFragmentTransaction();
+FragmentTransaction ft = getFragmentManager().openTransaction();
 // Replace and add to back stack
 ft.replace(R.id.myfragment, newFragment);
 ft.addToBackStack(null);
@@ -519,7 +519,7 @@
 
 <p>Likewise, your activity can call public methods in the fragment when you have a reference to the
 {@link android.app.Fragment}. You can acquire a reference to the fragment with {@link
-android.app.Activity#findFragmentById findFragmentById()} and cast it to your implementation of
+android.app.FragmentManager#findFragmentById findFragmentById()} and cast it to your implementation of
 {@link android.app.Fragment}. For example:</p>
 
 <pre>
diff --git a/docs/html/guide/topics/fundamentals.jd b/docs/html/guide/topics/fundamentals.jd
index fffc1cd..1658fa6 100644
--- a/docs/html/guide/topics/fundamentals.jd
+++ b/docs/html/guide/topics/fundamentals.jd
@@ -52,10 +52,9 @@
 <p>
 Android applications are written in the Java programming language. 
 The compiled Java code &mdash; along with any data and resource 
-files required by the application &mdash; is bundled by the 
-<a href="{@docRoot}guide/developing/tools/aapt.html"><code>aapt</code> 
-tool</a> into an <i>Android package</i>, an archive file 
-marked by an {@code .apk} suffix.  This file is the vehicle 
+files required by the application &mdash; is bundled into an 
+<i>Android package</i>, an archive file 
+marked by an {@code .apk} suffix. This file is the vehicle 
 for distributing the application and installing it on mobile devices; 
 it's the file users download to their devices.  All the code in a 
 single {@code .apk} file is considered to be one <i>application</i>.
@@ -425,7 +424,7 @@
 <code><a href="{@docRoot}guide/topics/manifest/provider-element.html">&lt;provider&gt;</a></code>
 elements for content providers.  Activities, services, and content providers 
 that are not declared in the manifest are not visible to the system and are 
-consequently never run.  However, broadcast receivers can either be 
+consequently never run. However, broadcast receivers can either be 
 declared in the manifest, or they can be created dynamically in code 
 (as {@link android.content.BroadcastReceiver} objects) 
 and registered with the system by calling 
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 0000000..e5d626c
--- /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 0000000..df1eace
--- /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/guide/topics/graphics/2d-graphics.jd b/docs/html/guide/topics/graphics/2d-graphics.jd
index acb6f9f..05f4023 100644
--- a/docs/html/guide/topics/graphics/2d-graphics.jd
+++ b/docs/html/guide/topics/graphics/2d-graphics.jd
@@ -14,9 +14,9 @@
           <li><a href="#drawables-from-xml">Creating from resource XML</a></li>
         </ol>
       </li>
-      <li><a href="#shape-drawable">ShapeDrawable</a></li>
+      <li><a href="#shape-drawable">Shape Drawable</a></li>
    <!--   <li><a href="#state-list">StateListDrawable</a></li> -->
-      <li><a href="#nine-patch">NinePatchDrawable</a></li>
+      <li><a href="#nine-patch">Nine-patch</a></li>
       <li><a href="#tween-animation">Tween Animation</a></li>
       <li><a href="#frame-animation">Frame Animation</a></li>
     </ol>
@@ -61,7 +61,7 @@
 
 <p class="note"><strong>Note:</strong> Image resources placed in <code>res/drawable/</code> may be 
 automatically optimized with lossless image compression by the 
-<a href="{@docRoot}guide/developing/tools/aapt.html">aapt</a> tool. For example, a true-color PNG that does
+<code>aapt</code> tool during the build process. For example, a true-color PNG that does
 not require more than 256 colors may be converted to an 8-bit PNG with a color palette. This 
 will result in an image of equal quality but which requires less memory. So be aware that the
 image binaries placed in this directory can change during the build. If you plan on reading
@@ -165,7 +165,7 @@
 
 
 
-<h2 id="shape-drawable">ShapeDrawable</h2>
+<h2 id="shape-drawable">Shape Drawable</h2>
 
 <p>When you want to dynamically draw some two-dimensional graphics, a {@link android.graphics.drawable.ShapeDrawable}
 object will probably suit your needs. With a ShapeDrawable, you can programmatically draw
@@ -234,6 +234,11 @@
 Some properties you might want to adjust include
 alpha transparency, color filter, dither, opacity and color.</p>
 
+<p>You can also define primitive drawable shapes using XML. For more information, see the
+section about Shape Drawables in the <a
+href="{@docRoot}guide/topics/resources/drawable-resource.html#Shape">Drawable Resources</a>
+document.</p>
+
 <!-- TODO
 <h2 id="state-list">StateListDrawable</h2>
 
@@ -245,7 +250,7 @@
 of the object it's attached to.
 -->
 
-<h2 id="nine-patch">NinePatchDrawable</h2>
+<h2 id="nine-patch">Nine-patch</h2>
 
 <p>A {@link android.graphics.drawable.NinePatchDrawable} graphic is a stretchable bitmap image, which Android
 will automatically resize to accommodate the contents of the View in which you have placed it as the background. 
@@ -424,8 +429,8 @@
 <code>{@link android.view.View#setAnimation(android.view.animation.Animation) View.setAnimation()}</code>.
 </p>
 
-<p>For more information on the XML syntax, available tags and attributes, see the discussion on animation 
-in the <a href="{@docRoot}guide/topics/resources/available-resources.html#animation">Available Resources</a>.</p>
+<p>For more information on the XML syntax, available tags and attributes, see <a
+href="{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
 
 <p class="note"><strong>Note:</strong> Regardless of how your animation may move or resize, the bounds of the 
 View that holds your animation will not automatically adjust to accommodate it. Even so, the animation will still
@@ -489,4 +494,6 @@
 <code>{@link android.app.Activity#onWindowFocusChanged(boolean) onWindowFocusChanged()}</code> method in 
 your Activity, which will get called when Android brings your window into focus.</p> 
 
+<p>For more information on the XML syntax, available tags and attributes, see <a
+href="{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
 
diff --git a/docs/html/guide/topics/location/obtaining-user-location.jd b/docs/html/guide/topics/location/obtaining-user-location.jd
index bc782d2..3b450f0 100644
--- a/docs/html/guide/topics/location/obtaining-user-location.jd
+++ b/docs/html/guide/topics/location/obtaining-user-location.jd
@@ -421,8 +421,8 @@
     <li>Use a KML file describing individual place marks for sequenced playback to the device.</li>
 </ul>
 
-<p>For more information on using DDMS to spoof location data, see the
-<a href="{@docRoot}guide/developing/tools/ddms.html#emulator-control">Using DDMS guide</a>.
+<p>For more information on using DDMS to spoof location data, see
+<a href="{@docRoot}guide/developing/debugging/ddms.html">Using DDMS</a>.
 
 
 <h3 id="MockGeo">Using the "geo" command in the emulator console</h3>
@@ -451,4 +451,4 @@
 </ol>
 
 <p>For information about how to connect to the emulator console, see
-<a href="{@docRoot}guide/developing/tools/emulator.html#console">Using the Emulator Console</a>.</p>
+<a href="{@docRoot}guide/developing/devices/emulator.html#console">Using the Emulator Console</a>.</p>
diff --git a/docs/html/guide/topics/media/index.jd b/docs/html/guide/topics/media/index.jd
index 8e18754..e355212 100644
--- a/docs/html/guide/topics/media/index.jd
+++ b/docs/html/guide/topics/media/index.jd
@@ -115,9 +115,8 @@
 <p>{@link android.media.MediaPlayer#stop() stop()} and 
 {@link android.media.MediaPlayer#pause() pause()} work the same as discussed
 above.</p>
-  <p class="note"><strong>Note:</strong> It is possible that <code>mp</code> could be
-  null, so good code should <code>null</code> check after the <code>new</code>.
-  Also, <code>IllegalArgumentException</code> and <code>IOException</code> either
+  <p class="note"><strong>Note:</strong>
+  <code>IllegalArgumentException</code> and <code>IOException</code> either
   need to be caught or passed on when using <code>setDataSource()</code>, since
   the file you are referencing may not exist.</p>
 <p class="note"><strong>Note:</strong>
diff --git a/docs/html/guide/topics/resources/drawable-resource.jd b/docs/html/guide/topics/resources/drawable-resource.jd
index 129462e..cee8fc3 100644
--- a/docs/html/guide/topics/resources/drawable-resource.jd
+++ b/docs/html/guide/topics/resources/drawable-resource.jd
@@ -74,7 +74,7 @@
 alias resource ID in XML.</p>
 
 <p class="note"><strong>Note:</strong> Bitmap files may be automatically optimized with lossless
-image compression by the <a href="{@docRoot}guide/developing/tools/aapt.html">aapt</a> tool. For
+image compression by the <code>aapt</code> tool during the build process. For
 example, a true-color PNG that does not require more than 256 colors may be converted to an 8-bit
 PNG with a color palette. This will result in an image of equal quality but which requires less
 memory. So be aware that the image binaries placed in this directory can change during the build. If
@@ -474,7 +474,7 @@
         android:right="<em>dimension</em>"
         android:bottom="<em>dimension</em>"
         android:left="<em>dimension</em>" /&gt;
-&lt;/selector>
+&lt;/layer-list>
 </pre>
 </dd>
 
@@ -906,7 +906,7 @@
         android:right="<em>dimension</em>"
         android:bottom="<em>dimension</em>"
         android:left="<em>dimension</em>" /&gt;
-&lt;/selector>
+&lt;/transition>
 </pre>
 </dd>
 
@@ -926,8 +926,8 @@
       </dl>
     </dd>
   <dt id="transition-item-element"><code>&lt;item&gt;</code></dt>
-    <dd>Defines a drawable to place in the layer drawable, in a position defined by its attributes.
-Must be a child of a <code>&lt;selector&gt;</code> element. Accepts child {@code &lt;bitmap&gt;}
+    <dd>Defines a drawable to use as part of the drawable transition.
+Must be a child of a <code>&lt;transition&gt;</code> element. Accepts child {@code &lt;bitmap&gt;}
 elements.
       <p class="caps">attributes:</p>
       <dl class="atn-list">
@@ -963,7 +963,7 @@
 &lt;transition xmlns:android="http://schemas.android.com/apk/res/android"&gt;
     &lt;item android:drawable="@drawable/on" /&gt;
     &lt;item android:drawable="@drawable/off" /&gt;
-&lt;/layer-list&gt;
+&lt;/transition&gt;
 </pre>
 
 <p>This layout XML applies the drawable to a View:</p>
@@ -1226,11 +1226,11 @@
 <dd>XML file saved at <code>res/drawable/clip.xml</code>:
 <pre>
 &lt;?xml version="1.0" encoding="utf-8"?>
-&lt;shape xmlns:android="http://schemas.android.com/apk/res/android"
+&lt;clip xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/android"
     android:clipOrientation="horizontal"
     android:gravity="left" /&gt;
-&lt;/shape>
+&lt;/clip>
 </pre>
     <p>The following layout XML applies the clip drawable to a View:</p>
 <pre>
diff --git a/docs/html/guide/topics/testing/testing_android.jd b/docs/html/guide/topics/testing/testing_android.jd
index d4b0dcc..6f3048c 100755
--- a/docs/html/guide/topics/testing/testing_android.jd
+++ b/docs/html/guide/topics/testing/testing_android.jd
@@ -625,9 +625,8 @@
 </p>
 <p>
     When possible, you should run these tests on an actual device. If this is not possible, you can
-    use the <a href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a> with
-    <a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a> configured for
-    the hardware, screens, and versions you want to test.
+    use the <a href="{@docRoot}guide/developing/devices/emulator.html">Android Emulator</a> with
+    Android Virtual Devices configured for the hardware, screens, and versions you want to test.
 </p>
 <h2 id="NextSteps">Next Steps</h2>
 <p>
diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd
index 843414a..c348767 100644
--- a/docs/html/guide/topics/ui/declaring-layout.jd
+++ b/docs/html/guide/topics/ui/declaring-layout.jd
@@ -47,11 +47,11 @@
   Plugin for Eclipse</a> offers a layout preview of your XML &mdash; 
   with the XML file opened, select the <strong>Layout</strong> tab.</li>
   <li>You should also try the 
-  <a href="{@docRoot}guide/developing/tools/hierarchy-viewer.html">Hierarchy Viewer</a> tool, 
+  <a href="{@docRoot}guide/developing/debugging/debugging-ui.html#hierarchyViewer">Hierarchy Viewer</a> tool, 
   for debugging layouts &mdash; it reveals layout property values, 
   draws wireframes with padding/margin indicators, and full rendered views while 
   you debug on the emulator or device.</li>
-  <li>The <a href="{@docRoot}guide/developing/tools/layoutopt.html">layoutopt</a> tool lets
+  <li>The <a href="{@docRoot}guide/developing/debugging/debugging-ui.html#layoutopt">layoutopt</a> tool lets
   you quickly analyze your layouts and hierarchies for inefficiencies or other problems.</li>
 </div>
 </div>
diff --git a/docs/html/guide/tutorials/hello-world.jd b/docs/html/guide/tutorials/hello-world.jd
index 6e315b2..11e6497 100644
--- a/docs/html/guide/tutorials/hello-world.jd
+++ b/docs/html/guide/tutorials/hello-world.jd
@@ -23,9 +23,11 @@
 great plugin that handles your project creation and management to greatly speed-up your
 development cycles.</p>
 
-<p>If you're not using Eclipse, that's okay. Familiarize yourself with 
-<a href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>.
-You can then return to this tutorial and ignore anything about Eclipse.</p>
+<p>If you are not using Eclipse, the tools provided by the Android SDK are accessible
+on the command line, so you can choose your IDE or text editor.
+For more information about developing with the Android SDK tools, see
+the <a href="{@docRoot}guide/developing/index.html">Overview</a>
+section for developing on Android.</p>
 
 <p>Before you start, you should already have the very latest SDK installed, and if you're using
 Eclipse, you should have installed the ADT plugin as well. If you have not installed these, see 
@@ -562,5 +564,6 @@
   <p>This creates the required folders and files for the project at the location 
   defined by the <em>path</em>.</p>
   
-  <p>For more information on how to use the SDK tools to create and build projects, please read 
-<a href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>.</p>
+  <p>For more information on how to use the SDK tools to create and build projects on the command line, read
+<a href="{@docRoot}guide/developing/projects/index.html">Creating and Managing Projects on the Command Line</a> and
+<a href="{@docRoot}guide/developing/building/building-cmdline.html">Building and Running Apps on the Command Line</a>.</p>
diff --git a/docs/html/guide/tutorials/notepad/notepad-extra-credit.jd b/docs/html/guide/tutorials/notepad/notepad-extra-credit.jd
index 0d59b56..34f7063 100644
--- a/docs/html/guide/tutorials/notepad/notepad-extra-credit.jd
+++ b/docs/html/guide/tutorials/notepad/notepad-extra-credit.jd
@@ -65,6 +65,6 @@
 
 <p>The Android Eclipse plugin not only offers excellent debugging support for
 your application development, but also superb profiling support. You can also
-try using <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview</a> to profile your application. If your application is running too slow, this can help you 
+try using <a href="{@docRoot}guide/developing/debugging/debugging-tracing.html">Traceview</a> to profile your application. If your application is running too slow, this can help you 
 find the bottlenecks and fix them.</p>
 
diff --git a/docs/html/guide/webapps/debugging.jd b/docs/html/guide/webapps/debugging.jd
index ee4b723..c0dce48 100644
--- a/docs/html/guide/webapps/debugging.jd
+++ b/docs/html/guide/webapps/debugging.jd
@@ -18,7 +18,7 @@
 
 <h2>See also</h2>
 <ol>
-  <li><a href="{@docRoot}guide/developing/debug-tasks.html">Debugging Tasks</a></li>
+  <li><a href="{@docRoot}guide/developing/debugging/index.html">Debugging</a></li>
 </ol>
 
 </div>
@@ -46,8 +46,8 @@
 <strong>Device > Run logcat</strong>. When using the <a href="{@docRoot}sdk/eclipse-adt.html">ADT
 plugin for Eclipse</a>, you can also view logcat messages by opening the Logcat view, available from
 <strong>Window > Show View > Other > Android > Logcat</strong>.</p>
-  <p>See <a href="{@docRoot}guide/developing/debug-tasks.html">Debugging
-Tasks</a> for more information about logcat.</p>
+  <p>See <a href="{@docRoot}guide/developing/debugging/debugging-log.html">Debugging</a>
+  for more information about <codelogcat</code>.</p>
 </div>
 </div>
 
diff --git a/docs/html/images/avd-manager.png b/docs/html/images/avd-manager.png
new file mode 100644
index 0000000..69ce972
--- /dev/null
+++ b/docs/html/images/avd-manager.png
Binary files differ
diff --git a/docs/html/images/build-simplified.png b/docs/html/images/build-simplified.png
new file mode 100644
index 0000000..73e3452
--- /dev/null
+++ b/docs/html/images/build-simplified.png
Binary files differ
diff --git a/docs/html/images/build.png b/docs/html/images/build.png
new file mode 100644
index 0000000..bf4cf4e
--- /dev/null
+++ b/docs/html/images/build.png
Binary files differ
diff --git a/docs/html/images/debug-ddms.png b/docs/html/images/debug-ddms.png
new file mode 100644
index 0000000..d92fb3c
--- /dev/null
+++ b/docs/html/images/debug-ddms.png
Binary files differ
diff --git a/docs/html/images/debugging.png b/docs/html/images/debugging.png
new file mode 100644
index 0000000..fd6a41a
--- /dev/null
+++ b/docs/html/images/debugging.png
Binary files differ
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 0000000..46d2df5
--- /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 0748db2..f9602f8 100644
--- a/docs/html/images/service_lifecycle.png
+++ b/docs/html/images/service_lifecycle.png
Binary files differ
diff --git a/docs/html/resources/articles/backward-compatibility.jd b/docs/html/resources/articles/backward-compatibility.jd
index 4b1a34c..ad64dfc 100644
--- a/docs/html/resources/articles/backward-compatibility.jd
+++ b/docs/html/resources/articles/backward-compatibility.jd
@@ -245,6 +245,6 @@
 to do this easily by creating "Android Virtual Devices" with different API
 levels. Once you create the AVDs, you can test your application with old and new
 versions of the system, perhaps running them side-by-side to see the
-differences. More information about emulator AVDs can be found <a
-href="{@docRoot}guide/developing/tools/avd.html">in the AVD documentation</a> and
+differences. More information about emulator AVDs can be found in <a
+href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</a> and
 from <code>emulator -help-virtual-device</code>.</p>
\ No newline at end of file
diff --git a/docs/html/resources/articles/contacts.jd b/docs/html/resources/articles/contacts.jd
index bdf84e6..c837dc3 100644
--- a/docs/html/resources/articles/contacts.jd
+++ b/docs/html/resources/articles/contacts.jd
@@ -107,7 +107,7 @@
 <p>When a raw contact is added or modified, the system looks for matching
 (overlapping) raw contacts with which to aggregate it. It may not find any
 matching raw contacts, in which case it will create an aggregate contact that
-contains just the original raw contact. If it finds a single match,it creates a
+contains just the original raw contact. If it finds a single match, it creates a
 new contact that contains the two raw contacts. And it may even find multiple
 similar raw contacts, in which case it chooses the closest match. </p>
 
diff --git a/docs/html/resources/articles/layout-tricks-merge.jd b/docs/html/resources/articles/layout-tricks-merge.jd
index 00e0479..95409e4 100644
--- a/docs/html/resources/articles/layout-tricks-merge.jd
+++ b/docs/html/resources/articles/layout-tricks-merge.jd
@@ -44,7 +44,7 @@
 <div style="text-align: center;"><img src="images/merge1.jpg" alt="A FrameLayout is used to overlay a title on top of an image"></div>
 
 <p>Things get more interesting when you inspect the result with <a
-href="{@docRoot}guide/developing/tools/hierarchy-viewer.html">HierarchyViewer</a>. 
+href="{@docRoot}guide/developing/debugging/debugging-ui.html#hierarchyViewer">HierarchyViewer</a>. 
 If you look closely at the resulting tree, you will notice that the
 <code>FrameLayout</code> defined in our XML file (highlighted in blue below) is
 the sole child of another <code>FrameLayout</code>:</p>
diff --git a/docs/html/resources/dashboard/platform-versions.jd b/docs/html/resources/dashboard/platform-versions.jd
index 7416764..21d1ffb 100644
--- a/docs/html/resources/dashboard/platform-versions.jd
+++ b/docs/html/resources/dashboard/platform-versions.jd
@@ -52,8 +52,7 @@
 <div class="dashboard-panel">
 
 <img alt="" height="250" width="460"
-src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:6.3,10.6,0.1,39.6,43.4&chl
-=Android%201.5|Android%201.6|Other*|Android%202.1|Android%202.2&chco=c4df9b,6fad0c" />
+src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:4.7,7.9,35.2,51.8,0.4&chl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3&chco=c4df9b,6fad0c" />
 
 <table>
 <tr>
@@ -61,15 +60,17 @@
   <th>API Level</th>
   <th>Distribution</th>
 </tr>
-<tr><td>Android 1.5</td><td>3</td><td>6.3%</td></tr>
-<tr><td>Android 1.6</td><td>4</td><td>10.6%</td></tr>
-<tr><td>Android 2.1</td><td>7</td><td>39.6%</td></tr>
-<tr><td>Android 2.2</td><td>8</td><td>43.4%</td></tr>
+<tr><td>Android 1.5</td><td>3</td><td>4.7%</td></tr> 
+<tr><td>Android 1.6</td><td>4</td><td>7.9%</td></tr> 
+<tr><td>Android 2.1</td><td>7</td><td>35.2%</td></tr> 
+<tr><td>Android 2.2</td><td>8</td><td>51.8%</td></tr> 
+<tr><td>Android 2.3</td><td>9</td><td>0.4%</td></tr> 
 </table>
 
-<p><em>Data collected during two weeks ending on December 1, 2010</em></p>
+<p><em>Data collected during two weeks ending on January 4, 2011</em></p>
+<!--
 <p style="font-size:.9em">* <em>Other: 0.1% of devices running obsolete versions</em></p>
-
+-->
 </div><!-- end dashboard-panel -->
 
 
@@ -95,17 +96,9 @@
 <div class="dashboard-panel">
 
 <img alt="" height="250" width="660" style="padding:5px;background:#fff"
-src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,y,r&chxr=0,0,12|1,0,100|2,0,100&
-chxl=0:|2010/06/01|06/15|07/01|07/15|08/01|08/15|09/01|09/15|10/01|10/15|11/01|11/15|2010/12/01|1:|0
-%25|25%25|50%25|75%25|100%25|2:|0%25|25%25|50%25|75%25|100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&
-chxtc=0,5&chd=t:100.3,100.8,99.7,99.8,99.8,99.7,99.8,99.9,99.9,99.9,99.9,99.9,99.9|72.7,76.1,78.4,80
-.9,84.3,86.5,87.9,89.2,90.2,91.1,92.0,92.7,93.6|45.9,51.0,54.9,58.8,64.0,68.1,70.3,72.1,73.8,75.3,77
-.0,79.0,83.0|0.8,1.2,1.8,3.3,4.3,11.3,27.8,32.1,33.4,34.5,36.2,38.3,43.4&chm=tAndroid%201.5,7caa36,0
-,0,15,,t::-5|b,c3df9b,0,1,0|tAndroid%201.6,5b831d,1,0,15,,t::-5|b,aadb5e,1,2,0|tAndroid%202.1,38540b
-,2,0,15,,t::-5|b,91da1e,2,3,0|tAndroid%202.2,131d02,3,5,15,,t::-5|B,6fad0c,3,4,0&chg=7,25&chdl=
-Android%201.5|Android%201.6|Android%202.1|Android%202.2&chco=add274,94d134,73ad18,507d08" />
+src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,x,y,r&chxr=0,0,12|1,0,12|2,0,100|3,0,100&chxl=0%3A%7C07/01%7C07/15%7C08/01%7C08/15%7C09/01%7C09/15%7C10/01%7C10/15%7C11/01%7C11/15%7C12/01%7C12/15%7C01/01%7C1%3A%7C2010%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C2011%7C2%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C3%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:99.7,99.8,99.8,99.7,99.8,99.9,99.9,99.9,100.0,99.9,99.8,99.7,99.6|78.4,80.9,84.3,86.5,87.9,89.2,90.2,91.1,92.0,92.7,93.4,94.1,94.8|54.9,58.8,64.0,68.1,70.3,72.1,73.8,75.3,77.4,79.6,82.2,84.4,86.8|1.8,3.3,4.3,11.3,27.8,32.1,33.4,34.5,37.1,40.5,44.3,47.7,51.4&chm=tAndroid 1.5,7caa36,0,0,15,,t::-5|b,c3df9b,0,1,0|tAndroid 1.6,5b831d,1,0,15,,t::-5|b,aadb5e,1,2,0|tAndroid 2.1,38540b,2,0,15,,t::-5|b,91da1e,2,3,0|tAndroid 2.2,131d02,3,3,15,,t::-5|B,6fad0c,3,4,0&chg=7,25&chdl=Android 1.5|Android 1.6|Android 2.1|Android 2.2&chco=add274,94d134,73ad18,507d08" />
 
-<p><em>Last historical dataset collected during two weeks ending on December 1, 2010</em></p>
+<p><em>Last historical dataset collected during two weeks ending on January 4, 2011</em></p>
 
 
 </div><!-- end dashboard-panel -->
diff --git a/docs/html/resources/faq/commontasks.jd b/docs/html/resources/faq/commontasks.jd
index 9c32e9c..807df08 100644
--- a/docs/html/resources/faq/commontasks.jd
+++ b/docs/html/resources/faq/commontasks.jd
@@ -97,7 +97,7 @@
         the device, are described below.
         The list of files you'll need for your application are described in <a href="#filelist">List
         of Files for an Android Application</a>. </li>
-    <li><strong><a href="{@docRoot}guide/developing/other-ide.html#buildingwithant">Build and install your
+    <li><strong><a href="{@docRoot}guide/developing/building/building-cmdline.html">Build and install your
                 package</a>.</strong> The Android SDK has some nice tools for generating
                 projects and debugging code. </li>
 </ol>
@@ -655,7 +655,7 @@
         and <code>STRIKE</code> (strikethrough).
         So, for example, in res/values/strings.xml you could declare this:<br />
         <code>&lt;resource&gt;<br />
-        &nbsp;&nbsp;&nbsp;&nbsp;&lt;string&gt;id=&quot;@+id/styled_welcome_message&quot;&gt;We
+        &nbsp;&nbsp;&nbsp;&nbsp;&lt;string&nbsp;id=&quot;@+id/styled_welcome_message&quot;&gt;We
         are &lt;b&gt;&lt;i&gt;so&lt;/i&gt;&lt;/b&gt; glad to see you.&lt;/string&gt;<br />
         &lt;/resources&gt;</code></li>
     <li>To style text on the fly, or to add highlighting or more complex styling,
diff --git a/docs/html/resources/faq/troubleshooting.jd b/docs/html/resources/faq/troubleshooting.jd
index f3252b0..05a7ddab 100644
--- a/docs/html/resources/faq/troubleshooting.jd
+++ b/docs/html/resources/faq/troubleshooting.jd
@@ -5,7 +5,8 @@
 
 
 <p>Here are some tips and tricks for common Android errors. Don't forget to use the
-    ddms logcat capability to get a deeper view when errors occur. See <a href="{@docRoot}guide/developing/debug-tasks.html">Debugging</a> for more debugging tips. </p>
+    ddms logcat capability to get a deeper view when errors occur. 
+    See the <a href="{@docRoot}guide/developing/debugging/index.html">Debugging</a> documentation for more information.</p>
 <ul>
     <li><a href="#installeclipsecomponents">ADT Installation Error: "requires plug-in org.eclipse.wst.sse.ui".</a></li>
     <li><a href="#nodevice">ADB reports &quot;no device&quot; when an emulator is running</a></li>
@@ -282,9 +283,10 @@
 
 <p>If you get an error message such as "Could not load /sdcard/gestures. 
 Make sure you have a mounted SD card," be sure that your target AVD has an 
-SD card. To create an AVD that has an SD card, use the
-<a href="{@docRoot}guide/developing/tools/avd.html#options"><code>-c</code> 
-option</a> in the <code>android create avd</code> command.</p> 
+SD card. To create an AVD that has an SD card, specify one when creating
+an AVD with the AVD manager. See 
+<a href="{@docRoot}guide/developing/devices/managing-avds.html#createavd">
+Creating and Managing AVDs with AVD Manager</a> for more information.</p>
 
 <h2 id="signingcalendar">I can't compile my app because the build tools generated an expired debug certificate</h2>
 
diff --git a/docs/html/resources/resources_toc.cs b/docs/html/resources/resources_toc.cs
index 1c1ece9..a2580a6 100644
--- a/docs/html/resources/resources_toc.cs
+++ b/docs/html/resources/resources_toc.cs
@@ -87,8 +87,7 @@
 ?>
 
   <li>
-   <h2><span class="en">More</span>
-    </h2>
+   <h2><span class="en">More</span></h2>
     <ul>
       <li><a href="<?cs var:toroot ?>resources/faq/commontasks.html">
             <span class="en">Common Tasks </span>
diff --git a/docs/html/resources/samples/index.jd b/docs/html/resources/samples/index.jd
index cbe6ca3..beecd67 100644
--- a/docs/html/resources/samples/index.jd
+++ b/docs/html/resources/samples/index.jd
@@ -18,6 +18,13 @@
 -->
 <dl>
 
+ <dt><a href="AccelerometerPlay/index.html">Accelerometer Play</a></dt>
+  <dd>An example that demonstrates how to use accelerometer readings
+  in an application.</dd>
+  
+ <dt><a href="AccessibilityService/index.html">Accessibility Service</a></dt>
+  <dd>An example that demonstrates the use of accessibility APIs.</dd>
+
  <dt><a href="ApiDemos/index.html">API Demos</a></dt>
   <dd>A variety of small applications that demonstrate an extensive collection of
   framework topics.</dd>
diff --git a/docs/html/resources/tutorials/testing/activity_test.jd b/docs/html/resources/tutorials/testing/activity_test.jd
index ec878d2..afb9e3c 100644
--- a/docs/html/resources/tutorials/testing/activity_test.jd
+++ b/docs/html/resources/tutorials/testing/activity_test.jd
@@ -239,7 +239,8 @@
 <p>
   In this tutorial, you will use the Android emulator to run applications. The emulator needs
   an Android Virtual Device (AVD) with an API level equal to or higher than the one you set for the projects in the previous step.
-  To find out how to check this and create the right AVD if necessary, see <a href="{@docRoot}guide/developing/eclipse-adt.html#AVD">Creating an AVD</a>.
+  To find out how to check this and create the right AVD if necessary, 
+  see <a href="{@docRoot}guide/developing/devices/managing-avds.html">Creating an AVD</a>.
 </p>
 <p>
     As a test of the AVD and emulator, run the SpinnerActivity application in Eclipse with ADT. When it starts,
@@ -1237,7 +1238,7 @@
    also use this tool to run the test application from the command line.
   </li>
   <li>
-    <a href="{@docRoot}guide/developing/tools/othertools.html#android">android</a> - Manages projects and test projects. This tool also manages AVDs and Android platforms.
+    <a href="{@docRoot}guide/developing/tools/android.html">android</a> - Manages projects and test projects. This tool also manages AVDs and Android platforms.
   </li>
 </ul>
   <p>
diff --git a/docs/html/resources/tutorials/views/hello-mapview.jd b/docs/html/resources/tutorials/views/hello-mapview.jd
index a3fa548..836d22c 100644
--- a/docs/html/resources/tutorials/views/hello-mapview.jd
+++ b/docs/html/resources/tutorials/views/hello-mapview.jd
@@ -17,13 +17,13 @@
 
 <p>After installing the Google APIs add-on in your SDK, set your project properties to use the build
 target called "Google APIs by Google Inc.". See the instructions for setting a build
-target in <a href="{@docRoot}guide/developing/eclipse-adt.html">Developing in
-Eclipse with ADT</a> or <a
-href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>,
-as appropriate for your environment. </p>
+target in <a href="{@docRoot}guide/developing/projects/projects-eclipse.html#CreatingAProject">
+Creating and Managing Projects in Eclipse</a> or <a
+href="{@docRoot}guide/developing/projects/projects-cmdline.html#CreatingAProject">
+Creating and Managing Projects on the Command Line</a>, as appropriate for your environment.</p>
 
 <p>You will also need to set up a new AVD that uses the same Google APIs deployment target. See <a
-href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a> for
+href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</a> for
 more information.</p>
 
 <p>For reference material, see the <a
@@ -127,7 +127,7 @@
 </pre>
 </li>
 <li>That's all there is to it. Run the application. (Remember, you must have an <a
-href="{@docRoot}guide/developing/tools/avd.html">AVD</a> configured to use the Google APIs
+href="{@docRoot}guide/developing/devices/index.html">AVD</a> configured to use the Google APIs
 target, or be using a development device that includes the Maps library.)</li>
 </ol>
 
@@ -223,7 +223,7 @@
   OverlayItem item = mOverlays.get(index);
   AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
   dialog.setTitle(item.getTitle());
-  dialog.setMessage(item.getSnippet())
+  dialog.setMessage(item.getSnippet());
   dialog.show();
   return true;
 }
diff --git a/docs/html/sdk/RELEASENOTES.jd b/docs/html/sdk/RELEASENOTES.jd
index a94eba7..bf091e9 100644
--- a/docs/html/sdk/RELEASENOTES.jd
+++ b/docs/html/sdk/RELEASENOTES.jd
@@ -64,7 +64,7 @@
 skins. </li>
     <li>Android SDK and AVD Manager, a graphical UI to let you manage your
 SDK and AVD environments more easily. The tool lets you create and manage 
-your <a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual
+your <a href="{@docRoot}guide/developing/devices/managing-avds.html">Android Virtual
 Devices</a> and download new SDK packages (such as platform versions and 
 add-ons) into your environment.</li>
     <li>Improved support for test packages in New Project Wizard</li>
@@ -222,7 +222,7 @@
 density for each skin, to create any combination of resolution/density (WVGA
 with medium density, for instance).  To do so, use the <code>android</code> tool
 command line to create a new AVD that uses a custom hardware configuration. See
-<a href="{@docRoot}guide/developing/tools/avd.html#createavd">Creating an
+<a href="{@docRoot}guide/developing/devices/managing-avds.html#createavd">Creating an
 AVD</a> for more information.</p>
 
 <h3>Other Notes and Resolved Issues</h3>
@@ -330,7 +330,7 @@
 Android 1.5). The tools are updated to let you deploy your application
 on any platform in the SDK, which helps you ensure forward-compatibility and, 
 if applicable, backward-compatibility.</li>
-    <li>Introduces <a href="{@docRoot}guide/developing/tools/avd.html">Android
+    <li>Introduces <a href="{@docRoot}guide/developing/devices/managing-avds.html">Android
 Virtual Devices</a> &mdash; (AVD) configurations of options that you
 run in the emulator to better model actual devices. Each AVD gets its
 own dedicated storage area, making it much easier to work with multiple emulators 
@@ -407,7 +407,7 @@
 available to use.</p>
 
 <p>For more information about AVDs, see <a
-href="{@docRoot}guide/developing/tools/avd.html">Android Virtual Devices</a>
+href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</a>
 
 <h3>Other Notes</h3>
 
@@ -585,8 +585,7 @@
 <p>The USB driver files are located in the
 <code>&lt;SDK&gt;/usb_driver</code> directory. For details and
 installation instructions, see <a
-href="{@docRoot}guide/developing/device.html#setting-up">Setting Up a
-Device for Development</a>.</p>
+href="{@docRoot}guide/developing/device.html#setting-up">Connecting Hardware Devices</a>.</p>
 </p>
 
 <h3>Resolved Issues, Changes</h3>
diff --git a/docs/html/sdk/android-2.3-highlights.jd b/docs/html/sdk/android-2.3-highlights.jd
index 1a603af..d8614d3 100644
--- a/docs/html/sdk/android-2.3-highlights.jd
+++ b/docs/html/sdk/android-2.3-highlights.jd
@@ -40,18 +40,18 @@
 
 <div class="video">
 <object width="278" height="180">
-<param name="movie" value="http://www.youtube.com/v/yAZYSVr2Bhc&hl=en&fs=1&"></param>
+<param name="movie" value="http://www.youtube.com/v/Jx3pdWBlZ34?hl=en&fs=1"></param>
 <param name="allowFullScreen" value="true"></param><param name="allowscriptaccess"
 value="always"></param>
-<embed src="http://www.youtube.com/v/yAZYSVr2Bhc&hl=en&fs=1&" type="application/x-shockwave-flash"
+<embed src="http://www.youtube.com/v/Jx3pdWBlZ34?hl=en&fs=1" type="application/x-shockwave-flash"
 allowscriptaccess="always" allowfullscreen="true" width="278" height="180"></embed>
 </object>
 </div>
 
 <p>The Android 2.3 platform introduces many new and exciting features for
-users and developers. This document provides a glimpse at some of the new user features
+users and developers. This document provides a glimpse at some of the new features
 and technologies in Android 2.3. For detailed information about the new developer APIs, see the <a
-href="android-2.3.html#api">Android 2.3 version notes</a>.</p>
+href="android-2.3.html">Android 2.3 version notes</a>.</p>
 
 <ul>
   <li><a href="#UserFeatures">New User Features</a></li>
@@ -251,7 +251,8 @@
 to recognize complex user gestures and motions, such as tilt, spin, thrust, and
 slice.  </p>
 
-<p style="margin-top:1.25em;margin-bottom:.75em;"><strong>Low-latency native
+
+<p style="margin-top:1.25em;margin-bottom:.75em;"><strong>Open API for native
 audio</strong></p>
 
 <p>The platform provides a software implementation of <a
@@ -405,7 +406,7 @@
 <ul>
 <li>Dalvik VM:
 <ul>
-<li>Concurrent Garbage Collector (target sub-3ms pauses)</li>
+<li>Concurrent garbage collector (target sub-3ms pauses)</li>
 <li>Adds further JIT (code-generation) optimizations</li>
 <li>Improved code verification</li>
 <li>StrictMode debugging, for identifying performance and memory issues</li>
@@ -438,5 +439,5 @@
 </ul>
 
 <p>For more information about the new developer APIs, see the <a
-href="android-2.3.html#api">Android 2.3 version notes</a> and the <a
+href="android-2.3.html">Android 2.3 version notes</a> and the <a
 href="{@docRoot}sdk/api_diff/9/changes.html">API Differences Report</a>.</p>
diff --git a/docs/html/sdk/android-2.3.jd b/docs/html/sdk/android-2.3.jd
index a0b7c99..734d97b 100644
--- a/docs/html/sdk/android-2.3.jd
+++ b/docs/html/sdk/android-2.3.jd
@@ -225,7 +225,7 @@
 android:name="android.hardware.sensor.gyroscope"
 android:required="true"&gt;</code> to the application manifest.</p>
 
-<p>For API details, see {@link android.hardware.Sensor}</p>
+<p>For API details, see {@link android.hardware.Sensor}.</p>
 
 
 <h3 id="cameras">Multiple cameras support</h3>
@@ -238,14 +238,13 @@
 <ul>
 <li>New {@link android.hardware.Camera.CameraInfo} class stores a camera's
 positional characteristics (orientation, front-facing or back-facing).</li>
-<li>New {@link android.hardware.Camera#getNumberOfCameras()}, {@link
-android.hardware.Camera#getCameraInfo(int,CameraInfo) getCameraInfo()}, and
-{@link android.hardware.Camera#getNumberOfCameras()} methods in the {@link
+<li>New {@link android.hardware.Camera#getNumberOfCameras()} and {@link
+android.hardware.Camera#getCameraInfo(int,CameraInfo) getCameraInfo()} methods in the {@link
 android.hardware.Camera} class let applications query for the cameras available
 and open the camera that they need.</li>
-<li>New {@link android.media.CamcorderProfile get(int,int) method lets
-applications retrieve a CamcorderProfile for a specific camera. </li>
-<li>New {@link android media.CameraProfile#getJpegEncodingQualityParameter(int, int)
+<li>New {@link android.media.CamcorderProfile#get get()} method lets
+applications retrieve a {@link android.media.CamcorderProfile} for a specific camera. </li>
+<li>New {@link android.media.CameraProfile#getJpegEncodingQualityParameter(int, int)
 getJpegEncodingQualityParameter()} lets applications obtain the still-image
 capture quality level for a specific camera.</li>
 </ul>
@@ -390,19 +389,19 @@
 touch filtering is appropriate to ensure the security of user actions such as
 granting a permission request, making a purchase, or clicking on an
 advertisement. For details, see the <a
-href="{@docRoot}reference/android/view/View.html#security">View class
+href="{@docRoot}reference/android/view/View.html#Security">View class
 documentation</a>.</li>
 <li>New <code>filterTouchesWhenObscured</code> attribute for view elements,
 which declares whether to filter touches when the view's window is obscured by
 another visible window. When set to <code>"true"</code>, the view will not
 receive touches whenever a toast, dialog or other window appears above the
 view's window. Refer to <a
-href="{@docRoot}reference/android/view/View.html#security">View security
+href="{@docRoot}reference/android/view/View.html#Security">View security
 documentation</a> for details.</li>
 </ul>
 
 <p class="note">To look at sample code for touch filtering, see
-<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/SecureView.html">SurfaceView.java</a>
+<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/SecureView.html">SecureView.java</a>
 in the ApiDemos sample application.</p>
 </li>
 
@@ -691,7 +690,7 @@
 <li><code>"reverseLandscape"</code> &mdash; The Activity would like to have the
 screen in landscape orientation, turned in the opposite direction from normal
 landscape.</li>
-<li><code>"reversePortait"</code> &mdash; The Activity would like to have the
+<li><code>"reversePortrait"</code> &mdash; The Activity would like to have the
 screen in portrait orientation, turned in the opposite direction from normal
 portrait.</li>
 <li><code>"sensorLandscape"</code> &mdash; The Activity would like to have the
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index 0144eb4..d0fa727 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -152,9 +152,9 @@
   "export signed/unsigned application package", ADT does <em>not</em> insert it.
   If you manually set <code>debuggable="true"</code> in the manifest file, then release builds will
   actually create a debug build (it does not remove it if you placed it there).</p></li>
-  <li>Automatic <a href="{@docRoot}guide/developing/tools/proguard.html">Proguard</a> support in
-release builds. For it to work, you need to have a <code>proguard.config</code>
-  property in the <code>default.properties</code> file that points to a proguard config file.</li>
+  <li>Automatic <a href="{@docRoot}guide/developing/tools/proguard.html">ProGuard</a> support in
+  release builds. For it to work, you need to have a <code>proguard.config</code>
+  property in the <code>default.properties</code> file that points to a ProGuard config file.</li>
   <li>Completely rewritten Visual Layout Editor. (This is still a work in progress.) Now includes:
     <ul>
       <li>Full drag and drop from palette to layout for all Layout classes.</li>
@@ -225,7 +225,7 @@
 with no name restriction. They can even be in subfolder such as
 <code>src/java</code>. If you are already working with library projects created
 in ADT 0.9.7, see <a
-href="{@docRoot}guide/developing/eclipse-adt.html#libraryMigrating">Migrating
+href="{@docRoot}guide/developing/projects/index.html#libraryMigrating">Migrating
 library projects to ADT 0.9.8</a> for important information about moving
 to the new ADT environment.</li>
 <li>Adds support for library projects that depend on other library
@@ -263,8 +263,7 @@
 library project from other Android projects and, at build time, the tools
 compile the shared code and resources as part of the dependent applications.
 More information about this feature is available in the <a
-href="{@docRoot}guide/developing/eclipse-adt.html#libraryProject">Developing
-in Eclipse with ADT</a> document. </p>
+href="{@docRoot}guide/developing/projects/index.html#LibraryProjects">Creating and Managing Projects</a> document. </p>
 <p>If you are not developing in Eclipse, <a
 href="tools-notes.html">SDK Tools r6</a> provides the equivalent library
 project support through the Ant build system.</p>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 4153951..4113463 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -2,20 +2,20 @@
 sdk.redirect=0
 
 sdk.win_installer=installer_r08-windows.exe
-sdk.win_installer_bytes=TODO
-sdk.win_installer_checksum=TODO
+sdk.win_installer_bytes=32746192
+sdk.win_installer_checksum=04ce87b10a8361a1f63cf2238bbc1ee3
 
 sdk.win_download=android-sdk_r08-windows.zip
-sdk.win_bytes=TODO
-sdk.win_checksum=TODO
+sdk.win_bytes=32696391
+sdk.win_checksum=3e0b08ade5bfa9624bce9ddc164a48cb
 
-sdk.mac_download=android-sdk_r08-mac_x86.zip
-sdk.mac_bytes=TODO
-sdk.mac_checksum=TODO
+sdk.mac_download=android-sdk_r08-mac_86.zip
+sdk.mac_bytes=28797617
+sdk.mac_checksum=d2e392c4e4680cbf2dfd6dbf82b662c7
 
-sdk.linux_download=android-sdk_r08-linux_x86.tgz
-sdk.linux_bytes=TODO
-sdk.linux_checksum=TODO
+sdk.linux_download=android-sdk_r08-linux_86.tgz
+sdk.linux_bytes=26817291
+sdk.linux_checksum=3b626645b223d137d27beefbda0c94bc
 
 @jd:body
 
diff --git a/docs/html/sdk/installing.jd b/docs/html/sdk/installing.jd
index 488382e..e8d97e7 100644
--- a/docs/html/sdk/installing.jd
+++ b/docs/html/sdk/installing.jd
@@ -148,8 +148,9 @@
 
 <p>If you prefer to work in a different IDE, you do not need to
 install Eclipse or ADT, instead, you can directly use the SDK tools to build and
-debug your application. The developer guide has more information about <a
-href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>.</p>
+debug your application. The <a href="{@docRoot}guide/developing/index.html">Overview</a>
+section of the developer guide outlines the major steps that you need to complete 
+when developing in Eclipse or other IDEs.</p>
 
 
 
@@ -446,7 +447,7 @@
 </tr>
 <td colspan="3"><code>tools/</code></td>
 <td>Contains the set of development and profiling tools that are platform-independent, such
-as the emulator, the AVD and SDK Manager, adb, ddms, hierarchyviewer and more. The tools in
+as the emulator, the AVD and SDK Manager, ddms, hierarchyviewer and more. The tools in
 this directory may be updated at any time (from the <em>Android SDK Tools</em> component),
 independent of platform releases, whereas the tools in {@code platform-tools/} may be updated based
 on the latest platform release.</td>
@@ -547,9 +548,9 @@
   <li>Get an overview of the <a
   href="{@docRoot}guide/developing/tools/index.html">development
   tools</a> that are available to you</li>
-  <li>Read how to develop <a
-  href="{@docRoot}guide/developing/eclipse-adt.html">in Eclipse/ADT</a> or
-  <a href="{@docRoot}guide/developing/other-ide.html">in other IDEs</a>
+  <li>Read the <a
+  href="{@docRoot}guide/developing/index.html">Overview</a> 
+  for how to develop an Android application.
   </li>
   <li>Read <a href="{@docRoot}guide/developing/device.html">Developing on a Device</a> to set up an
 Android-powered device to run and test your application.</li>
diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd
index 19f4d02..8b27f37 100644
--- a/docs/html/sdk/ndk/index.jd
+++ b/docs/html/sdk/ndk/index.jd
@@ -1,16 +1,16 @@
 ndk=true
 
-ndk.win_download=android-ndk-r4b-windows.zip
-ndk.win_bytes=45792835
-ndk.win_checksum=e397145e155a639be53ee4b6db8ad511
+ndk.win_download=android-ndk-r5-windows.zip
+ndk.win_bytes=62217450
+ndk.win_checksum=59cbb02d91d74e9c5c7278d94c989e80
 
-ndk.mac_download=android-ndk-r4b-darwin-x86.zip
-ndk.mac_bytes=50586041
-ndk.mac_checksum=41dbd54335fb828ee408eab17103a1b0
+ndk.mac_download=android-ndk-r5-darwin-x86.tar.bz2
+ndk.mac_bytes=50210863
+ndk.mac_checksum=9dee8e4cb529a5619e9b8d1707478c32
 
-ndk.linux_download=android-ndk-r4b-linux-x86.zip
-ndk.linux_bytes=49464776
-ndk.linux_checksum=2deabcb125c219b34140975b710f00ec
+ndk.linux_download=android-ndk-r5-linux-x86.tar.bz2
+ndk.linux_bytes=44362746
+ndk.linux_checksum=49d5c35ec02bafc074842542c58b7eb3
 
 page.title=Android NDK
 @jd:body
@@ -64,7 +64,7 @@
          onclick="return toggleDiv(this)"><img src="{@docRoot}assets/images/triangle-opened.png"
          class="toggle-img"
          height="9px"
-         width="9px" /> Android NDK, Revision 5</a> <em>(November 2010)</em>
+         width="9px" /> Android NDK, Revision 5</a> <em>(December 2010)</em>
 
     <div class="toggleme">
       <p>This release of the NDK includes many new APIs, most of which are introduced to
diff --git a/docs/html/sdk/ndk/overview.jd b/docs/html/sdk/ndk/overview.jd
index 56b9201..2562a25 100644
--- a/docs/html/sdk/ndk/overview.jd
+++ b/docs/html/sdk/ndk/overview.jd
@@ -275,16 +275,19 @@
     <li>If you are developing in Eclipse with ADT, use the New Project Wizard to create a new
     Android project for each sample, using the "Import from Existing Source" option and importing
     the source from <code>&lt;ndk&gt;/apps/&lt;app_name&gt;/project/</code>. Then, set up an AVD,
-    if necessary, and build/run the application in the emulator. For more information about
-    creating a new Android project in Eclipse, see <a href=
-    "{@docRoot}guide/developing/eclipse-adt.html">Developing in Eclipse</a>.</li>
+    if necessary, and build/run the application in the emulator.</li>
 
     <li>If you are developing with Ant, use the <code>android</code> tool to create the build file
     for each of the sample projects at <code>&lt;ndk&gt;/apps/&lt;app_name&gt;/project/</code>.
     Then set up an AVD, if necessary, build your project in the usual way, and run it in the
-    emulator. For more information, see <a href=
-    "{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>.</li>
+    emulator.</li>    
+    
   </ul>
+  
+  <p>For more information about developing with the Android SDK tools and what
+  you need to do to create, build, and run your applications, see
+  the <a href="{@docRoot}guide/developing/index.html">Overview</a>
+  section for developing on Android.</p>
 
   <h4 id="hello-jni">Exploring the hello-jni Sample</h4>
 
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 9c7ad89..9e1ff9c 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -98,7 +98,7 @@
     <ul>
       <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r8</a> <span class="new">new!</span></li>
       <li><a href="<?cs var:toroot ?>sdk/win-usb.html">USB Driver for
-      Windows, r3</a>
+      Windows, r4</a> <span class="new">new!</span>
       </li>
     </ul>
   </li>
diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd
index f8d7071..fb8636e 100644
--- a/docs/html/sdk/tools-notes.jd
+++ b/docs/html/sdk/tools-notes.jd
@@ -183,9 +183,8 @@
 library project from other Android projects and, at build time, the tools
 compile the shared code and resources as part of the dependent applications.
 More information about this feature is available in the <a
-href="{@docRoot}guide/developing/other-ide.html#libraryProject">Developing 
-in Other IDEs</a> document.</p>
-<p>If you are developing in Eclipse, <a href="eclipse-adt.html">ADT 0.9.7</a>
+href="{@docRoot}guide/developing/projects/index.html#LibraryProjects">Creating and Managing Projects</a> document.</p>
+<p>If you are developing in Eclipse, <a href="eclipse-adt.html">ADT</a>
 provides the equivalent library project support.</p>
 </dd>
 </dl>
diff --git a/docs/html/sdk/win-usb.jd b/docs/html/sdk/win-usb.jd
index bb0dde6..1f74ffe 100644
--- a/docs/html/sdk/win-usb.jd
+++ b/docs/html/sdk/win-usb.jd
@@ -82,7 +82,21 @@
 
 <div class="toggleable opened">
   <a href="#" onclick="return toggleDiv(this)">
-        <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />
+        <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px"
+width="9px" />
+USB Driver for Windows, Revision 4</a> <em>(December 2010)</em>
+  <div class="toggleme">
+
+<dl>
+<dt><p>Adds support for the Nexus S.</p></dt>
+</dl>
+ </div>
+</div>
+
+<div class="toggleable closed">
+  <a href="#" onclick="return toggleDiv(this)">
+        <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px"
+width="9px" />
 USB Driver for Windows, Revision 3</a> <em>(January 2010)</em>
   <div class="toggleme">
 
@@ -126,10 +140,11 @@
 Android-powered
 devices:</p>
   <ul>
-    <li>T-Mobile G1* / ADP1</li>
-    <li>T-Mobile myTouch 3G* / Google Ion</li>
+    <li>ADP1 / T-Mobile G1*</li>
+    <li>ADP2 / Google Ion / T-Mobile myTouch 3G*</li>
     <li>Verizon Droid*</li>
     <li>Nexus One</li>
+    <li>Nexus S</li>
   </ul>
   <p>* <em>Or similar hardware on other carriers</em></p>
   <p>Any additional devices will require Windows drivers provided by
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 9a6f787..ef7d274 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -87,7 +87,7 @@
 }
 
 status_t DrmManager::loadPlugIns() {
-    String8 pluginDirPath("/system/lib/drm/plugins/native");
+    String8 pluginDirPath("/system/lib/drm");
     return loadPlugIns(pluginDirPath);
 }
 
@@ -117,7 +117,11 @@
 status_t DrmManager::setDrmServiceListener(
             int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
     Mutex::Autolock _l(mLock);
-    mServiceListeners.add(uniqueId, drmServiceListener);
+    if (NULL != drmServiceListener.get()) {
+        mServiceListeners.add(uniqueId, drmServiceListener);
+    } else {
+        mServiceListeners.removeItem(uniqueId);
+    }
     return DRM_NO_ERROR;
 }
 
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index 2f54b33..6caf678 100644
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -738,26 +738,34 @@
      */
     private String convertUriToPath(Uri uri) {
         String path = null;
-        String scheme = uri.getScheme();
-        if (null == scheme || scheme.equals("") || scheme.equals(ContentResolver.SCHEME_FILE)) {
-            path = uri.getPath();
-        } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) {
-            String[] projection = new String[] {MediaStore.MediaColumns.DATA};
-            Cursor cursor = null;
-            try {
-                cursor = mContext.getContentResolver().query(uri, projection, null, null, null);
-            } catch (SQLiteException e) {
-                throw new IllegalArgumentException("Given Uri is not formatted in a way " +
-                        "so that it can be found in media store.");
+        if (null != uri) {
+            String scheme = uri.getScheme();
+            if (null == scheme || scheme.equals("") ||
+                    scheme.equals(ContentResolver.SCHEME_FILE)) {
+                path = uri.getPath();
+            } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) {
+                String[] projection = new String[] {MediaStore.MediaColumns.DATA};
+                Cursor cursor = null;
+                try {
+                    cursor = mContext.getContentResolver().query(uri, projection, null,
+                            null, null);
+                    if (null == cursor || 0 == cursor.getCount() || !cursor.moveToFirst()) {
+                        throw new IllegalArgumentException("Given Uri could not be found" +
+                                " in media store");
+                    }
+                    int pathIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
+                    path = cursor.getString(pathIndex);
+                } catch (SQLiteException e) {
+                    throw new IllegalArgumentException("Given Uri is not formatted in a way " +
+                            "so that it can be found in media store.");
+                } finally {
+                    if (null != cursor) {
+                        cursor.close();
+                    }
+                }
+            } else {
+                throw new IllegalArgumentException("Given Uri scheme is not supported");
             }
-            if (null == cursor || 0 == cursor.getCount() || !cursor.moveToFirst()) {
-                throw new IllegalArgumentException("Given Uri could not be found in media store");
-            }
-            int pathIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
-            path = cursor.getString(pathIndex);
-            cursor.close();
-        } else {
-            throw new IllegalArgumentException("Given Uri scheme is not supported");
         }
         return path;
     }
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
index 578e135..7b51822 100644
--- a/drm/libdrmframework/DrmManagerClient.cpp
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -31,6 +31,7 @@
 DrmManagerClient::~DrmManagerClient() {
     DrmManagerClientImpl::remove(mUniqueId);
     mDrmManagerClientImpl->removeClient(mUniqueId);
+    mDrmManagerClientImpl->setOnInfoListener(mUniqueId, NULL);
     delete mDrmManagerClientImpl; mDrmManagerClientImpl = NULL;
 }
 
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index f39131d..d20de92 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -81,7 +81,8 @@
             int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener) {
     Mutex::Autolock _l(mLock);
     mOnInfoListener = infoListener;
-    return getDrmManagerService()->setDrmServiceListener(uniqueId, this);
+    return getDrmManagerService()->setDrmServiceListener(uniqueId,
+            (NULL != infoListener.get()) ? this : NULL);
 }
 
 status_t DrmManagerClientImpl::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
diff --git a/drm/libdrmframework/plugins/common/Android.mk b/drm/libdrmframework/plugins/common/Android.mk
new file mode 100644
index 0000000..9ee7961
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/Android.mk
@@ -0,0 +1,16 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+include $(call all-subdir-makefiles)
diff --git a/drm/libdrmframework/plugins/common/util/Android.mk b/drm/libdrmframework/plugins/common/util/Android.mk
new file mode 100644
index 0000000..15dda80
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/util/Android.mk
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    src/MimeTypeUtil.cpp
+
+LOCAL_MODULE := libdrmutility
+
+LOCAL_SHARED_LIBRARIES :=  \
+    libutils \
+    libdl \
+    libdvm \
+    libandroid_runtime \
+    libnativehelper \
+    liblog
+
+
+base := frameworks/base
+
+LOCAL_C_INCLUDES += \
+    $(JNI_H_INCLUDE) \
+    $(base)/include \
+    $(base)/include/drm \
+    $(base)/include/drm/plugins \
+    $(LOCAL_PATH)/include
+
+
+ifneq ($(TARGET_BUILD_VARIANT),user)
+LOCAL_C_INCLUDES += \
+    $(LOCAL_PATH)/tools
+
+endif
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/drm/libdrmframework/plugins/common/util/include/MimeTypeUtil.h b/drm/libdrmframework/plugins/common/util/include/MimeTypeUtil.h
new file mode 100644
index 0000000..4d12a61
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/util/include/MimeTypeUtil.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MIMETYPEUTIL_H__
+#define __MIMETYPEUTIL_H__
+
+#include <utils/String8.h>
+
+namespace android {
+
+class MimeTypeUtil {
+
+public:
+
+    MimeTypeUtil() {}
+
+    virtual ~MimeTypeUtil() {}
+
+/**
+ * May convert the mimetype if there is a well known
+ * replacement mimetype otherwise the original mimetype
+ * is returned.
+ *
+ * @param mimeType - mimetype in lower case to convert.
+ *
+ * @return mimetype or null.
+ */
+static String8 convertMimeType(String8& mimeType);
+
+};
+};
+
+#endif /* __MIMETYPEUTIL_H__ */
diff --git a/drm/libdrmframework/plugins/common/util/include/SessionMap.h b/drm/libdrmframework/plugins/common/util/include/SessionMap.h
new file mode 100644
index 0000000..3dff58c
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/util/include/SessionMap.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SESSIONMAP_H__
+#define __SESSIONMAP_H__
+
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+/**
+ * A wrapper template class for handling DRM Engine sessions.
+ */
+template <typename NODE>
+class SessionMap {
+
+public:
+    KeyedVector<int, NODE> map;
+
+    SessionMap() {}
+
+    virtual ~SessionMap() {
+        destroyMap();
+    }
+
+/**
+ * Adds a new value in the session map table. It expects memory to be allocated already
+ * for the session object
+ *
+ * @param key - key or Session ID
+ * @param value - session object to add
+ *
+ * @return boolean result of adding value. returns false if key is already exist.
+ */
+bool addValue(int key, NODE value) {
+    bool result = false;
+
+    if (!isCreated(key)) {
+        map.add(key, value);
+        result = true;
+    }
+
+    return result;
+}
+
+
+/**
+ * returns the session object by the key
+ *
+ * @param key - key or Session ID
+ *
+ * @return session object as per the key
+ */
+NODE getValue(int key) {
+    NODE value = NULL;
+
+    if (isCreated(key)) {
+        value = (NODE) map.valueFor(key);
+    }
+
+    return value;
+}
+
+/**
+ * returns the number of objects in the session map table
+ *
+ * @return count of number of session objects.
+ */
+int getSize() {
+    return map.size();
+}
+
+/**
+ * returns the session object by the index in the session map table
+ *
+ * @param index - index of the value required
+ *
+ * @return session object as per the index
+ */
+NODE getValueAt(unsigned int index) {
+    NODE value = NULL;
+
+    if (map.size() > index) {
+      value = map.valueAt(index);
+    }
+
+    return value;
+}
+
+/**
+ * deletes the object from session map. It also frees up memory for the session object.
+ *
+ * @param key - key of the value to be deleted
+ *
+ */
+void removeValue(int key) {
+    deleteValue(getValue(key));
+    map.removeItem(key);
+}
+
+/**
+ * decides if session is already created.
+ *
+ * @param key - key of the value for the session
+ *
+ * @return boolean result of whether session is created
+ */
+bool isCreated(int key) {
+    return (0 <= map.indexOfKey(key));
+}
+
+/**
+ * empty the entire session table. It releases all the memory for session objects.
+ */
+void destroyMap() {
+    int size = map.size();
+    int i = 0;
+
+    for (i = 0; i < size; i++) {
+        deleteValue(map.valueAt(i));
+    }
+
+    map.clear();
+}
+
+/**
+ * free up the memory for the session object.
+ * Make sure if any reference to the session object anywhere, otherwise it will be a
+ * dangle pointer after this call.
+ *
+ * @param value - session object to free
+ *
+ */
+void deleteValue(NODE value) {
+    delete value;
+}
+
+};
+
+};
+
+#endif /* __SESSIONMAP_H__ */
diff --git a/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
new file mode 100644
index 0000000..4ee903e
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <MimeTypeUtil.h>
+#include <utils/Log.h>
+
+namespace android {
+
+#undef LOG_TAG
+#define LOG_TAG "MimeTypeUtil"
+
+enum {
+    MIMETYPE_AUDIO       = 0,
+    MIMETYPE_APPLICATION = 1,
+    MIMETYPE_IMAGE       = 2,
+    MIMETYPE_VIDEO       = 3,
+    MIMETYPE_LAST        = -1,
+};
+
+struct MimeGroup{
+    int         type;     // Audio, video,.. use the enum values
+    const char* pGroup;   // "audio/", "video/",.. should contain the last "/"
+    int         size;     // Number of bytes. e.g. "audio/" = 6 bytes
+};
+
+struct MimeTypeList{
+    int         type;
+    const char* pMimeExt;  // Everything after the '/' e.g. audio/x-mpeg -> "x-mpeg"
+    int         size;      // Number of bytes. e.g. "x-mpeg" = 6 bytes
+    const char* pMimeType; // Mimetype that should be returned
+};
+
+
+// Known mimetypes by android
+static const char mime_type_audio_mpeg[]  = "audio/mpeg";
+static const char mime_type_audio_3gpp[]  = "audio/3gpp";
+static const char mime_type_audio_amr[]   = "audio/amr-wb";
+static const char mime_type_audio_aac[]   = "audio/mp4a-latm";
+static const char mime_type_audio_wav[]   = "audio/wav";
+
+static const char mime_type_video_mpeg4[] = "video/mpeg4";
+static const char mime_type_video_3gpp[]  = "video/3gpp";
+
+// Known mimetype groups
+static const char mime_group_audio[]       = "audio/";
+static const char mime_group_application[] = "application/";
+static const char mime_group_image[]       = "image/";
+static const char mime_group_video[]       = "video/";
+
+static struct MimeGroup mimeGroup[] = {
+    {MIMETYPE_AUDIO,       mime_group_audio,        sizeof(mime_group_audio)-1},
+    {MIMETYPE_APPLICATION, mime_group_application,  sizeof(mime_group_application)-1},
+    {MIMETYPE_IMAGE,       mime_group_image,        sizeof(mime_group_image)-1},
+    {MIMETYPE_VIDEO,       mime_group_video,        sizeof(mime_group_video)-1},
+    {MIMETYPE_LAST,        NULL,                    0} // Must be last entry
+};
+
+// List of all mimetypes that should be converted.
+static struct MimeTypeList mimeTypeList[] = {
+    // Mp3 mime types
+    {MIMETYPE_AUDIO, "mp3",          sizeof("mp3")-1,         mime_type_audio_mpeg},
+    {MIMETYPE_AUDIO, "x-mpeg",       sizeof("x-mpeg")-1,      mime_type_audio_mpeg},
+    {MIMETYPE_AUDIO, "x-mp3",        sizeof("x-mp3")-1,       mime_type_audio_mpeg},
+    {MIMETYPE_AUDIO, "mpg",          sizeof("mpg")-1,         mime_type_audio_mpeg},
+    {MIMETYPE_AUDIO, "mpg3",         sizeof("mpg")-1,         mime_type_audio_mpeg},
+    {MIMETYPE_AUDIO, "x-mpg",        sizeof("x-mpg")-1,       mime_type_audio_mpeg},
+    {MIMETYPE_AUDIO, "x-mpegaudio",  sizeof("x-mpegaudio")-1, mime_type_audio_mpeg},
+
+    // 3gpp audio mime types
+    {MIMETYPE_AUDIO, "3gp",          sizeof("3gp")-1,         mime_type_audio_3gpp},
+
+    // Amr audio mime types
+    {MIMETYPE_AUDIO, "amr",          sizeof("amr")-1,         mime_type_audio_amr},
+
+    // Aac audio mime types
+    {MIMETYPE_AUDIO, "aac",          sizeof("aac")-1,         mime_type_audio_aac},
+
+    // Wav audio mime types
+    {MIMETYPE_AUDIO, "x-wav",        sizeof("x-wav")-1,       mime_type_audio_wav},
+
+    // Mpeg4 video mime types
+    {MIMETYPE_VIDEO, "mpg4",         sizeof("mpg4")-1,        mime_type_video_mpeg4},
+    {MIMETYPE_VIDEO, "mp4v-es",      sizeof("mp4v-es")-1,     mime_type_video_mpeg4},
+
+    // 3gpp video mime types
+    {MIMETYPE_VIDEO, "3gp",          sizeof("3gp")-1,         mime_type_video_3gpp},
+
+    // Must be last entry
+    {MIMETYPE_LAST,  NULL,           0,                       NULL}
+};
+
+/**
+ * May convert the mimetype if there is a well known
+ * replacement mimetype otherwise the original mimetype
+ * is returned.
+ *
+ * @param mimeType - mimetype in lower case to convert.
+ *
+ * @return mimetype or null.
+ */
+String8 MimeTypeUtil::convertMimeType(String8& mimeType) {
+    String8 result = mimeType;
+    const char* pTmp;
+    const char* pMimeType;
+    struct MimeGroup* pGroup;
+    struct MimeTypeList* pMimeItem;
+    int len;
+
+    pMimeType = mimeType.string();
+    if (NULL != pMimeType) {
+        /* Check which group the mimetype is */
+        pGroup = mimeGroup;
+
+        while (MIMETYPE_LAST != pGroup->type) {
+            if (0 == strncmp(pMimeType, pGroup->pGroup, pGroup->size)) {
+                break;
+            }
+            pGroup++;
+        }
+
+        /* Go through the mimetype list. Only check items of the correct group */
+        if (MIMETYPE_LAST != pGroup->type) {
+            pMimeItem = mimeTypeList;
+            len = strlen (pMimeType+pGroup->size);
+
+            while (MIMETYPE_LAST != pMimeItem->type) {
+                if ((len == pMimeItem->size) &&
+                    (0 == strcmp(pMimeType+pGroup->size, pMimeItem->pMimeExt))) {
+                    result = String8(pMimeItem->pMimeType);
+                    break;
+                }
+                pMimeItem++;
+            }
+        }
+        LOGI("convertMimeType got mimetype %s, converted into mimetype %s",
+             pMimeType, result.string());
+    }
+
+    return result;
+}
+};
diff --git a/drm/libdrmframework/plugins/forward-lock/Android.mk b/drm/libdrmframework/plugins/forward-lock/Android.mk
new file mode 100644
index 0000000..9ee7961
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/Android.mk
@@ -0,0 +1,16 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+include $(call all-subdir-makefiles)
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
new file mode 100644
index 0000000..d4a6f18
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
@@ -0,0 +1,67 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+base := frameworks/base
+
+# Determine whether the DRM framework uses 64-bit data types for file offsets and do the same.
+ifneq ($(shell grep -c 'off64_t offset' $(base)/drm/libdrmframework/plugins/common/include/IDrmEngine.h), 0)
+LOCAL_CFLAGS += -DUSE_64BIT_DRM_API
+endif
+
+LOCAL_SRC_FILES:= \
+    src/FwdLockEngine.cpp
+
+LOCAL_MODULE := libfwdlockengine
+
+LOCAL_SHARED_LIBRARIES := \
+    libicui18n \
+    libicuuc \
+    libutils \
+    libdl \
+    libandroid_runtime \
+    libnativehelper \
+    libcrypto \
+    libssl \
+    libdrmframework
+
+LOCAL_STATIC_LIBRARIES := \
+    libdrmutility \
+    libdrmframeworkcommon \
+    libfwdlock-common \
+    libfwdlock-converter \
+    libfwdlock-decoder
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_C_INCLUDES += \
+    $(JNI_H_INCLUDE) \
+    $(base)/include/drm \
+    $(base)/drm/libdrmframework/plugins/common/include \
+    $(base)/drm/libdrmframework/plugins/common/util/include \
+    $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/common \
+    $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/converter \
+    $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/decoder \
+    $(LOCAL_PATH)/include \
+    external/openssl/include
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/drm/plugins/native
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h
new file mode 100644
index 0000000..34804cf
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __FWDLOCKENGINE_H__
+#define __FWDLOCKENGINE_H__
+
+#include <DrmEngineBase.h>
+#include <DrmConstraints.h>
+#include <DrmRights.h>
+#include <DrmInfo.h>
+#include <DrmInfoStatus.h>
+#include <DrmConvertedStatus.h>
+#include <DrmInfoRequest.h>
+#include <DrmSupportInfo.h>
+#include <DrmInfoEvent.h>
+
+#include "SessionMap.h"
+#include "FwdLockConv.h"
+
+namespace android {
+
+/**
+ * Forward Lock Engine class.
+ */
+class FwdLockEngine : public android::DrmEngineBase {
+
+public:
+    FwdLockEngine();
+    virtual ~FwdLockEngine();
+
+protected:
+/**
+ * Get constraint information associated with input content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the protected content
+ * @param action Actions defined such as,
+ *     Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ *     key-value pairs of constraint are embedded in it
+ * @note
+ *     In case of error, return NULL
+ */
+DrmConstraints* onGetConstraints(int uniqueId, const String8* path, int action);
+
+/**
+ * Get metadata information associated with input content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the protected content
+ * @return DrmMetadata
+ *      For Forward Lock engine, it returns an empty object
+ * @note
+ *     In case of error, returns NULL
+ */
+DrmMetadata* onGetMetadata(int uniqueId, const String8* path);
+
+/**
+ * Initialize plug-in.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @return status_t
+ *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onInitialize(int uniqueId);
+
+/**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param infoListener Listener
+ * @return status_t
+ *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener);
+
+/**
+ * Terminate the plug-in and release resources bound to it.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @return status_t
+ *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onTerminate(int uniqueId);
+
+/**
+ * Get whether the given content can be handled by this plugin or not.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path to the protected object
+ * @return bool
+ *      Returns true if this plugin can handle , false in case of not able to handle
+ */
+bool onCanHandle(int uniqueId, const String8& path);
+
+/**
+ * Processes the given DRM information as appropriate for its type.
+ * Not used for Forward Lock Engine.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param drmInfo Information that needs to be processed
+ * @return DrmInfoStatus
+ *      instance as a result of processing given input
+ */
+DrmInfoStatus* onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+/**
+ * Save DRM rights to specified rights path
+ * and make association with content path.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param drmRights DrmRights to be saved
+ * @param rightsPath File path where rights to be saved
+ * @param contentPath File path where content was saved
+ * @return status_t
+ *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onSaveRights(int uniqueId,
+                      const DrmRights& drmRights,
+                      const String8& rightsPath,
+                      const String8& contentPath);
+
+/**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ *      instance as a result of processing given input
+ */
+DrmInfo* onAcquireDrmInfo(int uniqueId,
+                          const DrmInfoRequest* drmInfoRequest);
+
+/**
+ * Retrieves the mime type embedded inside the original content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the protected content
+ * @return String8
+ *       Returns mime-type of the original content, such as "video/mpeg"
+ */
+String8 onGetOriginalMimeType(int uniqueId, const String8& path);
+
+/**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the content or null.
+ * @param mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ *     such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+int onGetDrmObjectType(int uniqueId,
+                       const String8& path,
+                       const String8& mimeType);
+
+/**
+ * Check whether the given content has valid rights or not.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the protected content
+ * @param action Action to perform (Action::DEFAULT, Action::PLAY, etc)
+ * @return the status of the rights for the protected content,
+ *     such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+int onCheckRightsStatus(int uniqueId,
+                        const String8& path,
+                        int action);
+
+/**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights are reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param reserve True if the rights should be reserved.
+ * @return status_t
+ *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onConsumeRights(int uniqueId,
+                         DecryptHandle* decryptHandle,
+                         int action,
+                         bool reserve);
+
+/**
+ * Informs the DRM Engine about the playback actions performed on the DRM files.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param position Position in the file (in milliseconds) where the start occurs.
+ *     Only valid together with Playback::START.
+ * @return status_t
+ *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+#ifdef USE_64BIT_DRM_API
+status_t onSetPlaybackStatus(int uniqueId,
+                             DecryptHandle* decryptHandle,
+                             int playbackStatus,
+                             int64_t position);
+#else
+status_t onSetPlaybackStatus(int uniqueId,
+                             DecryptHandle* decryptHandle,
+                             int playbackStatus,
+                             int position);
+#endif
+
+/**
+ *  Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the protected content
+ * @param action Action to validate (Action::PLAY, Action::TRANSFER, etc)
+ * @param description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+bool onValidateAction(int uniqueId,
+                      const String8& path,
+                      int action,
+                      const ActionDescription& description);
+
+/**
+ * Removes the rights associated with the given protected content.
+ * Not used for Forward Lock Engine.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the protected content
+ * @return status_t
+ *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onRemoveRights(int uniqueId, const String8& path);
+
+/**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset but does nothing for
+ * Forward Lock Engine.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @return status_t
+ *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onRemoveAllRights(int uniqueId);
+
+/**
+ * Starts the Forward Lock file conversion session.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API. The convertId is used as the conversion session key
+ * and must not be the same for different convert sessions.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param convertId Handle for the convert session
+ * @return status_t
+ *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onOpenConvertSession(int uniqueId, int convertId);
+
+/**
+ * Accepts and converts the input data which is part of DRM file.
+ * The resultant converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there is a new block
+ * of data received by the application.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param convertId Handle for the convert session
+ * @param inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ *       the output converted data and offset. In this case the
+ *      application will ignore the offset information.
+ */
+DrmConvertedStatus* onConvertData(int uniqueId,
+                                  int convertId,
+                                  const DrmBuffer* inputData);
+
+/**
+ * Closes the convert session in case of data supply completed or error occurred.
+ * Upon successful conversion of the complete data, it returns signature calculated over
+ * the entire data used over a conversion session. This signature must be copied to the offset
+ * mentioned in the DrmConvertedStatus. Signature is used for data integrity protection.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ *      the header and body signature data. It also informs
+ *      the application about the file offset at which this
+ *      signature data should be written.
+ */
+DrmConvertedStatus* onCloseConvertSession(int uniqueId, int convertId);
+
+/**
+ * Returns the information about the Drm Engine capabilities which includes
+ * supported MimeTypes and file suffixes.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @return DrmSupportInfo
+ *      instance which holds the capabilities of a plug-in
+ */
+DrmSupportInfo* onGetSupportInfo(int uniqueId);
+
+/**
+ * Open the decrypt session to decrypt the given protected content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the current decryption session
+ * @param fd File descriptor of the protected content to be decrypted
+ * @param offset Start position of the content
+ * @param length The length of the protected content
+ * @return
+ *     DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+#ifdef USE_64BIT_DRM_API
+status_t onOpenDecryptSession(int uniqueId,
+                              DecryptHandle* decryptHandle,
+                              int fd, off64_t offset, off64_t length);
+#else
+status_t onOpenDecryptSession(int uniqueId,
+                              DecryptHandle* decryptHandle,
+                              int fd, int offset, int length);
+#endif
+
+/**
+ * Open the decrypt session to decrypt the given protected content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the current decryption session
+ * @param uri Path of the protected content to be decrypted
+ * @return
+ *     DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+status_t onOpenDecryptSession(int uniqueId,
+                              DecryptHandle* decryptHandle,
+                              const char* uri);
+
+/**
+ * Close the decrypt session for the given handle.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @return status_t
+ *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onCloseDecryptSession(int uniqueId,
+                               DecryptHandle* decryptHandle);
+
+/**
+ * Initialize decryption for the given unit of the protected content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param headerInfo Information for initializing decryption of this decrypUnit
+ * @return
+ *     DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+status_t onInitializeDecryptUnit(int uniqueId,
+                                 DecryptHandle* decryptHandle,
+                                 int decryptUnitId,
+                                 const DrmBuffer* headerInfo);
+
+/**
+ * Decrypt the protected content buffers for the given unit.
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param encBuffer Encrypted data block
+ * @param decBuffer Decrypted data block
+ * @return status_t
+ *     Returns the error code for this API
+ *     DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ *     DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ *     DRM_ERROR_DECRYPT for failure.
+ */
+status_t onDecrypt(int uniqueId,
+                   DecryptHandle* decryptHandle,
+                   int decryptUnitId,
+                   const DrmBuffer* encBuffer,
+                   DrmBuffer** decBuffer);
+
+/**
+ * Decrypt the protected content buffers for the given unit.
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptId Handle for the decryption session
+ * @param decryptUnitId ID Specifies decryption unit, such as track ID
+ * @param encBuffer Encrypted data block
+ * @param decBuffer Decrypted data block
+ * @param IV Optional buffer
+ * @return status_t
+ *     Returns the error code for this API
+ *     DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ *     DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ *     DRM_ERROR_DECRYPT for failure.
+ */
+status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle,
+                   int decryptUnitId, const DrmBuffer* encBuffer,
+                   DrmBuffer** decBuffer, DrmBuffer* IV);
+
+/**
+ * Finalize decryption for the given unit of the protected content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param decryptUnitId ID Specifies decryption unit, such as track ID
+ * @return
+ *     DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+status_t onFinalizeDecryptUnit(int uniqueId,
+                               DecryptHandle* decryptHandle,
+                               int decryptUnitId);
+
+/**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param buffer Reference to the buffer that should receive the read data.
+ * @param numBytes Number of bytes to read.
+ *
+ * @return Number of bytes read.
+ * @retval -1 Failure.
+ */
+ssize_t onRead(int uniqueId,
+               DecryptHandle* decryptHandle,
+               void* pBuffer,
+               int numBytes);
+
+/**
+ * Updates the file position within an open DRM file.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param offset Offset with which to update the file position.
+ * @param whence One of SEEK_SET, SEEK_CUR, and SEEK_END.
+ *           These constants are defined in unistd.h.
+ *
+ * @return New file position.
+ * @retval ((off_t)-1) Failure.
+ */
+#ifdef USE_64BIT_DRM_API
+off64_t onLseek(int uniqueId,
+                DecryptHandle* decryptHandle,
+                off64_t offset,
+                int whence);
+#else
+off_t onLseek(int uniqueId,
+              DecryptHandle* decryptHandle,
+              off_t offset,
+              int whence);
+#endif
+
+/**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param buffer Reference to the buffer that should receive the read data.
+ * @param numBytes Number of bytes to read.
+ * @param offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+#ifdef USE_64BIT_DRM_API
+ssize_t onPread(int uniqueId,
+                DecryptHandle* decryptHandle,
+                void* buffer,
+                ssize_t numBytes,
+                off64_t offset);
+#else
+ssize_t onPread(int uniqueId,
+                DecryptHandle* decryptHandle,
+                void* buffer,
+                ssize_t numBytes,
+                off_t offset);
+#endif
+
+private:
+
+/**
+ * Session Class for Forward Lock Conversion. An object of this class is created
+ * for every conversion.
+ */
+class ConvertSession {
+    public :
+        int uniqueId;
+        FwdLockConv_Output_t output;
+
+        ConvertSession() {
+            uniqueId = 0;
+            memset(&output, 0, sizeof(FwdLockConv_Output_t));
+        }
+
+        virtual ~ConvertSession() {}
+};
+
+/**
+ * Session Class for Forward Lock decoder. An object of this class is created
+ * for every decoding session.
+ */
+class DecodeSession {
+    public :
+        int fileDesc;
+        off_t offset;
+
+        DecodeSession() {
+            fileDesc = -1;
+            offset = 0;
+        }
+
+        DecodeSession(int fd) {
+            fileDesc = fd;
+            offset = 0;
+        }
+
+        virtual ~DecodeSession() {}
+};
+
+/**
+ * Session Map Tables for Conversion and Decoding of forward lock files.
+ */
+SessionMap<ConvertSession*> convertSessionMap;
+SessionMap<DecodeSession*> decodeSessionMap;
+
+/**
+ * Converts the error code from Forward Lock Converter to DrmConvertStatus error code.
+ *
+ * @param Forward Lock Converter error code
+ *
+ * @return Status code from DrmConvertStatus.
+ */
+static int getConvertedStatus(FwdLockConv_Status_t status);
+};
+
+};
+
+#endif /* __FWDLOCKENGINE_H__ */
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngineConst.h b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngineConst.h
new file mode 100644
index 0000000..da95d60
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngineConst.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __FWDLOCKENGINECONST_H__
+#define __FWDLOCKENGINECONST_H__
+
+namespace android {
+
+/**
+ * Constants for forward Lock Engine used for exposing engine's capabilities.
+ */
+#define FWDLOCK_EXTENSION_FL           ("FL")
+#define FWDLOCK_DOTEXTENSION_FL        (".fl")
+#define FWDLOCK_MIMETYPE_FL            ("application/x-android-drm-fl")
+
+#define FWDLOCK_EXTENSION_DM           ("DM")
+#define FWDLOCK_DOTEXTENSION_DM        (".dm")
+#define FWDLOCK_MIMETYPE_DM            ("application/vnd.oma.drm.message")
+
+#define FWDLOCK_DESCRIPTION            ("OMA V1 Forward Lock")
+
+};
+
+#endif /* __FWDLOCKENGINECONST_H__ */
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
new file mode 100644
index 0000000..d430f72
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SessionMap.h"
+#include "FwdLockEngine.h"
+#include <utils/Log.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "drm_framework_common.h"
+#include <fcntl.h>
+#include <limits.h>
+#include <DrmRights.h>
+#include <DrmConstraints.h>
+#include <DrmMetadata.h>
+#include <DrmInfo.h>
+#include <DrmInfoStatus.h>
+#include <DrmInfoRequest.h>
+#include <DrmSupportInfo.h>
+#include <DrmConvertedStatus.h>
+#include <utils/String8.h>
+#include "FwdLockConv.h"
+#include "FwdLockFile.h"
+#include "FwdLockGlue.h"
+#include "FwdLockEngineConst.h"
+#include "MimeTypeUtil.h"
+
+#undef LOG_TAG
+#define LOG_TAG "FwdLockEngine"
+
+using namespace android;
+// This extern "C" is mandatory to be managed by TPlugInManager
+extern "C" IDrmEngine* create() {
+    return new FwdLockEngine();
+}
+
+// This extern "C" is mandatory to be managed by TPlugInManager
+extern "C" void destroy(IDrmEngine* plugIn) {
+    delete plugIn;
+}
+
+FwdLockEngine::FwdLockEngine() {
+    LOGD("FwdLockEngine Construction");
+}
+
+FwdLockEngine::~FwdLockEngine() {
+    LOGD("FwdLockEngine Destruction");
+
+    convertSessionMap.destroyMap();
+    decodeSessionMap.destroyMap();
+}
+
+int FwdLockEngine::getConvertedStatus(FwdLockConv_Status_t status) {
+    int retStatus = DrmConvertedStatus::STATUS_ERROR;
+
+    switch(status) {
+        case FwdLockConv_Status_OK:
+            retStatus = DrmConvertedStatus::STATUS_OK;
+            break;
+        case FwdLockConv_Status_SyntaxError:
+        case FwdLockConv_Status_InvalidArgument:
+        case FwdLockConv_Status_UnsupportedFileFormat:
+        case FwdLockConv_Status_UnsupportedContentTransferEncoding:
+            LOGD("FwdLockEngine getConvertedStatus: file conversion Error %d. " \
+                  "Returning STATUS_INPUTDATA_ERROR", status);
+            retStatus = DrmConvertedStatus::STATUS_INPUTDATA_ERROR;
+            break;
+        default:
+            LOGD("FwdLockEngine getConvertedStatus: file conversion Error %d. " \
+                  "Returning STATUS_ERROR", status);
+            retStatus = DrmConvertedStatus::STATUS_ERROR;
+            break;
+    }
+
+    return retStatus;
+}
+
+DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) {
+    DrmConstraints* drmConstraints = NULL;
+
+    LOGD("FwdLockEngine::onGetConstraints");
+
+    if (NULL != path &&
+        (RightsStatus::RIGHTS_VALID == onCheckRightsStatus(uniqueId, *path, action))) {
+        // Return the empty constraints to show no error condition.
+        drmConstraints = new DrmConstraints();
+    }
+
+    return drmConstraints;
+}
+
+DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) {
+    DrmMetadata* drmMetadata = NULL;
+
+    LOGD("FwdLockEngine::onGetMetadata");
+
+    if (NULL != path) {
+        // Returns empty metadata to show no error condition.
+        drmMetadata = new DrmMetadata();
+    }
+
+    return drmMetadata;
+}
+
+android::status_t FwdLockEngine::onInitialize(int uniqueId) {
+    LOGD("FwdLockEngine::onInitialize");
+
+
+    if (FwdLockGlue_InitializeKeyEncryption()) {
+        LOGD("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
+    } else {
+        LOGD("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:"
+             "errno = %d", errno);
+    }
+
+    return DRM_NO_ERROR;
+}
+
+android::status_t
+FwdLockEngine::onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
+    // Not used
+    LOGD("FwdLockEngine::onSetOnInfoListener");
+
+    return DRM_NO_ERROR;
+}
+
+android::status_t FwdLockEngine::onTerminate(int uniqueId) {
+    LOGD("FwdLockEngine::onTerminate");
+
+    return DRM_NO_ERROR;
+}
+
+DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) {
+    DrmSupportInfo* pSupportInfo = new DrmSupportInfo();
+
+    LOGD("FwdLockEngine::onGetSupportInfo");
+
+    // fill all Forward Lock mimetypes and extensions
+    if (NULL != pSupportInfo) {
+        pSupportInfo->addMimeType(String8(FWDLOCK_MIMETYPE_FL));
+        pSupportInfo->addFileSuffix(String8(FWDLOCK_DOTEXTENSION_FL));
+        pSupportInfo->addMimeType(String8(FWDLOCK_MIMETYPE_DM));
+        pSupportInfo->addFileSuffix(String8(FWDLOCK_DOTEXTENSION_DM));
+
+        pSupportInfo->setDescription(String8(FWDLOCK_DESCRIPTION));
+    }
+
+    return pSupportInfo;
+}
+
+bool FwdLockEngine::onCanHandle(int uniqueId, const String8& path) {
+    bool result = false;
+
+    String8 extString = path.getPathExtension();
+
+    extString.toLower();
+
+    if ((extString == String8(FWDLOCK_DOTEXTENSION_FL)) ||
+        (extString == String8(FWDLOCK_DOTEXTENSION_DM))) {
+        result = true;
+    }
+    return result;
+}
+
+DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+    DrmInfoStatus *drmInfoStatus = NULL;
+
+    // Nothing to process
+
+    drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8(""));
+
+    LOGD("FwdLockEngine::onProcessDrmInfo");
+
+    return drmInfoStatus;
+}
+
+status_t FwdLockEngine::onSaveRights(
+            int uniqueId,
+            const DrmRights& drmRights,
+            const String8& rightsPath,
+            const String8& contentPath) {
+    // No rights to save. Return
+    LOGD("FwdLockEngine::onSaveRights");
+    return DRM_ERROR_UNKNOWN;
+}
+
+DrmInfo* FwdLockEngine::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+    DrmInfo* drmInfo = NULL;
+
+    // Nothing to be done for Forward Lock file
+    LOGD("FwdLockEngine::onAcquireDrmInfo");
+
+    return drmInfo;
+}
+
+int FwdLockEngine::onCheckRightsStatus(int uniqueId,
+                                       const String8& path,
+                                       int action) {
+    int result = RightsStatus::RIGHTS_INVALID;
+
+    LOGD("FwdLockEngine::onCheckRightsStatus");
+
+    // Only Transfer action is not allowed for forward Lock files.
+    if (onCanHandle(uniqueId, path)) {
+        switch(action) {
+            case Action::DEFAULT:
+            case Action::PLAY:
+            case Action::RINGTONE:
+            case Action::OUTPUT:
+            case Action::PREVIEW:
+            case Action::EXECUTE:
+            case Action::DISPLAY:
+                result = RightsStatus::RIGHTS_VALID;
+                break;
+
+            case Action::TRANSFER:
+            default:
+                result = RightsStatus::RIGHTS_INVALID;
+                break;
+        }
+    }
+
+    return result;
+}
+
+status_t FwdLockEngine::onConsumeRights(int uniqueId,
+                                        DecryptHandle* decryptHandle,
+                                        int action,
+                                        bool reserve) {
+    // No rights consumption
+    LOGD("FwdLockEngine::onConsumeRights");
+    return DRM_NO_ERROR;
+}
+
+bool FwdLockEngine::onValidateAction(int uniqueId,
+                                     const String8& path,
+                                     int action,
+                                     const ActionDescription& description) {
+    LOGD("FwdLockEngine::onValidateAction");
+
+    // For the forwardlock engine checkRights and ValidateAction are the same.
+    return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID);
+}
+
+String8 FwdLockEngine::onGetOriginalMimeType(int uniqueId, const String8& path) {
+    LOGD("FwdLockEngine::onGetOriginalMimeType");
+    String8 mimeString = String8("");
+    int fileDesc = FwdLockFile_open(path.string());
+
+    if (-1 < fileDesc) {
+        const char* pMimeType = FwdLockFile_GetContentType(fileDesc);
+
+        if (NULL != pMimeType) {
+            String8 contentType = String8(pMimeType);
+            contentType.toLower();
+            mimeString = MimeTypeUtil::convertMimeType(contentType);
+        }
+
+        FwdLockFile_close(fileDesc);
+    }
+
+    return mimeString;
+}
+
+int FwdLockEngine::onGetDrmObjectType(int uniqueId,
+                                      const String8& path,
+                                      const String8& mimeType) {
+    String8 mimeStr = String8(mimeType);
+
+    LOGD("FwdLockEngine::onGetDrmObjectType");
+
+    mimeStr.toLower();
+
+    /* Checks whether
+    * 1. path and mime type both are not empty strings (meaning unavailable) else content is unknown
+    * 2. if one of them is empty string and if other is known then its a DRM Content Object.
+    * 3. if both of them are available, then both may be of known type
+    *    (regardless of the relation between them to make it compatible with other DRM Engines)
+    */
+    if (((0 == path.length()) || onCanHandle(uniqueId, path)) &&
+        ((0 == mimeType.length()) || ((mimeStr == String8(FWDLOCK_MIMETYPE_FL)) ||
+        (mimeStr == String8(FWDLOCK_MIMETYPE_DM)))) && (mimeType != path) ) {
+            return DrmObjectType::CONTENT;
+    }
+
+    return DrmObjectType::UNKNOWN;
+}
+
+status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
+    // No Rights to remove
+    LOGD("FwdLockEngine::onRemoveRights");
+    return DRM_NO_ERROR;
+}
+
+status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
+    // No rights to remove
+    LOGD("FwdLockEngine::onRemoveAllRights");
+    return DRM_NO_ERROR;
+}
+
+#ifdef USE_64BIT_DRM_API
+status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
+                                            int playbackStatus, int64_t position) {
+#else
+status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
+                                            int playbackStatus, int position) {
+#endif
+    // Not used
+    LOGD("FwdLockEngine::onSetPlaybackStatus");
+    return DRM_NO_ERROR;
+}
+
+status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
+                                         int convertId) {
+    status_t result = DRM_ERROR_UNKNOWN;
+    LOGD("FwdLockEngine::onOpenConvertSession");
+    if (!convertSessionMap.isCreated(convertId)) {
+        ConvertSession *newSession = new ConvertSession();
+        if (FwdLockConv_Status_OK ==
+            FwdLockConv_OpenSession(&(newSession->uniqueId), &(newSession->output))) {
+            convertSessionMap.addValue(convertId, newSession);
+            result = DRM_NO_ERROR;
+        } else {
+            LOGD("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed.");
+            delete newSession;
+        }
+    }
+    return result;
+}
+
+DrmConvertedStatus* FwdLockEngine::onConvertData(int uniqueId,
+                                                 int convertId,
+                                                 const DrmBuffer* inputData) {
+    FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
+    DrmBuffer *convResult = new DrmBuffer(NULL, 0);
+    int offset = -1;
+
+    if (NULL != inputData && convertSessionMap.isCreated(convertId)) {
+        ConvertSession *convSession = convertSessionMap.getValue(convertId);
+
+        if (NULL != convSession) {
+            retStatus = FwdLockConv_ConvertData(convSession->uniqueId,
+                                                inputData->data,
+                                                inputData->length,
+                                                &(convSession->output));
+
+            if (FwdLockConv_Status_OK == retStatus) {
+                // return bytes from conversion if available
+                if (convSession->output.fromConvertData.numBytes > 0) {
+                    convResult->data = new char[convSession->output.fromConvertData.numBytes];
+
+                    if (NULL != convResult->data) {
+                        convResult->length = convSession->output.fromConvertData.numBytes;
+                        memcpy(convResult->data,
+                               (char *)convSession->output.fromConvertData.pBuffer,
+                               convResult->length);
+                    }
+                }
+            } else {
+                offset = convSession->output.fromConvertData.errorPos;
+            }
+        }
+    }
+    return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
+}
+
+DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int uniqueId,
+                                                         int convertId) {
+    FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
+    DrmBuffer *convResult = new DrmBuffer(NULL, 0);
+    int offset = -1;
+
+    LOGD("FwdLockEngine::onCloseConvertSession");
+
+    if (convertSessionMap.isCreated(convertId)) {
+        ConvertSession *convSession = convertSessionMap.getValue(convertId);
+
+        if (NULL != convSession) {
+            retStatus = FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output));
+
+            if (FwdLockConv_Status_OK == retStatus) {
+                offset = convSession->output.fromCloseSession.fileOffset;
+                convResult->data = new char[FWD_LOCK_SIGNATURES_SIZE];
+
+                if (NULL != convResult->data) {
+                      convResult->length = FWD_LOCK_SIGNATURES_SIZE;
+                      memcpy(convResult->data,
+                             (char *)convSession->output.fromCloseSession.signatures,
+                             convResult->length);
+                }
+            }
+        }
+        convertSessionMap.removeValue(convertId);
+    }
+    return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
+}
+
+#ifdef USE_64BIT_DRM_API
+status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
+                                             DecryptHandle* decryptHandle,
+                                             int fd,
+                                             off64_t offset,
+                                             off64_t length) {
+#else
+status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
+                                             DecryptHandle* decryptHandle,
+                                             int fd,
+                                             int offset,
+                                             int length) {
+#endif
+    status_t result = DRM_ERROR_CANNOT_HANDLE;
+    int fileDesc = -1;
+
+    LOGD("FwdLockEngine::onOpenDecryptSession");
+
+    if ((-1 < fd) &&
+        (NULL != decryptHandle) &&
+        (!decodeSessionMap.isCreated(decryptHandle->decryptId))) {
+        fileDesc = dup(fd);
+    } else {
+        LOGD("FwdLockEngine::onOpenDecryptSession parameter error");
+        return result;
+    }
+
+    if (-1 < fileDesc &&
+        -1 < ::lseek(fileDesc, offset, SEEK_SET) &&
+        -1 < FwdLockFile_attach(fileDesc)) {
+        // check for file integrity. This must be done to protect the content mangling.
+        int retVal = FwdLockFile_CheckHeaderIntegrity(fileDesc);
+        DecodeSession* decodeSession = new DecodeSession(fileDesc);
+
+        if (retVal && NULL != decodeSession) {
+            decodeSessionMap.addValue(decryptHandle->decryptId, decodeSession);
+            const char *pmime= FwdLockFile_GetContentType(fileDesc);
+            String8 contentType = String8(pmime == NULL ? "" : pmime);
+            contentType.toLower();
+            decryptHandle->mimeType = MimeTypeUtil::convertMimeType(contentType);
+            decryptHandle->decryptApiType = DecryptApiType::CONTAINER_BASED;
+            decryptHandle->status = RightsStatus::RIGHTS_VALID;
+            decryptHandle->decryptInfo = NULL;
+            result = DRM_NO_ERROR;
+        } else {
+            LOGD("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
+            FwdLockFile_detach(fileDesc);
+            ::close(fileDesc);
+            delete decodeSession;
+        }
+    }
+
+    LOGD("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
+
+    return result;
+}
+
+status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
+                                             DecryptHandle* decryptHandle,
+                                             const char* uri) {
+    status_t result = DRM_ERROR_CANNOT_HANDLE;
+    const char fileTag [] = "file://";
+
+    if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) {
+        String8 uriTag = String8(uri);
+        uriTag.toLower();
+
+        if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) {
+            const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/');
+            if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) {
+                int fd = open(filePath, O_RDONLY);
+
+                if (-1 < fd) {
+                    // offset is always 0 and length is not used. so any positive size.
+                    result = onOpenDecryptSession(uniqueId, decryptHandle, fd, 0, 1);
+
+                    // fd is duplicated already if success. closing the file
+                    close(fd);
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
+                                              DecryptHandle* decryptHandle) {
+    status_t result = DRM_ERROR_UNKNOWN;
+    LOGD("FwdLockEngine::onCloseDecryptSession");
+
+    if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
+        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
+        if (NULL != session && session->fileDesc > -1) {
+            FwdLockFile_detach(session->fileDesc);
+            ::close(session->fileDesc);
+            decodeSessionMap.removeValue(decryptHandle->decryptId);
+            result = DRM_NO_ERROR;
+        }
+    }
+
+    LOGD("FwdLockEngine::onCloseDecryptSession Exit");
+    return result;
+}
+
+status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId,
+                                                DecryptHandle* decryptHandle,
+                                                int decryptUnitId,
+                                                const DrmBuffer* headerInfo) {
+    LOGD("FwdLockEngine::onInitializeDecryptUnit");
+    return DRM_ERROR_UNKNOWN;
+}
+
+status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+    LOGD("FwdLockEngine::onDecrypt");
+    return DRM_ERROR_UNKNOWN;
+}
+
+status_t FwdLockEngine::onDecrypt(int uniqueId,
+                                  DecryptHandle* decryptHandle,
+                                  int decryptUnitId,
+                                  const DrmBuffer* encBuffer,
+                                  DrmBuffer** decBuffer) {
+    LOGD("FwdLockEngine::onDecrypt");
+    return DRM_ERROR_UNKNOWN;
+}
+
+status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
+                                              DecryptHandle* decryptHandle,
+                                              int decryptUnitId) {
+    LOGD("FwdLockEngine::onFinalizeDecryptUnit");
+    return DRM_ERROR_UNKNOWN;
+}
+
+ssize_t FwdLockEngine::onRead(int uniqueId,
+                              DecryptHandle* decryptHandle,
+                              void* buffer,
+                              int numBytes) {
+    ssize_t size = -1;
+
+    if (NULL != decryptHandle &&
+       decodeSessionMap.isCreated(decryptHandle->decryptId) &&
+        NULL != buffer &&
+        numBytes > -1) {
+        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
+        if (NULL != session && session->fileDesc > -1) {
+            size = FwdLockFile_read(session->fileDesc, buffer, numBytes);
+
+            if (0 > size) {
+                session->offset = ((off_t)-1);
+            } else {
+                session->offset += size;
+            }
+        }
+    }
+
+    return size;
+}
+
+#ifdef USE_64BIT_DRM_API
+off64_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
+                               off64_t offset, int whence) {
+#else
+off_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
+                             off_t offset, int whence) {
+#endif
+    off_t offval = -1;
+
+    if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
+        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
+        if (NULL != session && session->fileDesc > -1) {
+            offval = FwdLockFile_lseek(session->fileDesc, offset, whence);
+            session->offset = offval;
+        }
+    }
+
+    return offval;
+}
+
+#ifdef USE_64BIT_DRM_API
+ssize_t FwdLockEngine::onPread(int uniqueId,
+                               DecryptHandle* decryptHandle,
+                               void* buffer,
+                               ssize_t numBytes,
+                               off64_t offset) {
+#else
+ssize_t FwdLockEngine::onPread(int uniqueId,
+                               DecryptHandle* decryptHandle,
+                               void* buffer,
+                               ssize_t numBytes,
+                               off_t offset) {
+#endif
+    ssize_t bytesRead = -1;
+
+    DecodeSession* decoderSession = NULL;
+
+    if ((NULL != decryptHandle) &&
+        (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) &&
+        (NULL != buffer) &&
+        (numBytes > -1) &&
+        (offset > -1)) {
+        if (offset != decoderSession->offset) {
+            decoderSession->offset = onLseek(uniqueId, decryptHandle, offset, SEEK_SET);
+        }
+
+        if (((off_t)-1) != decoderSession->offset) {
+            bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes);
+            if (bytesRead < 0) {
+                LOGD("FwdLockEngine::onPread error reading");
+            }
+        }
+    } else {
+        LOGD("FwdLockEngine::onPread decryptId not found");
+    }
+
+    return bytesRead;
+}
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/Android.mk
new file mode 100644
index 0000000..9ee7961
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/Android.mk
@@ -0,0 +1,16 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+include $(call all-subdir-makefiles)
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
new file mode 100644
index 0000000..6c5d3cf
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
@@ -0,0 +1,32 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    FwdLockGlue.c
+
+LOCAL_C_INCLUDES := \
+    external/openssl/include
+
+LOCAL_SHARED_LIBRARIES := libcrypto
+
+LOCAL_MODULE := libfwdlock-common
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.c b/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.c
new file mode 100644
index 0000000..92bda8ff
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <openssl/aes.h>
+
+#include "FwdLockGlue.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define KEY_SIZE 16
+#define KEY_SIZE_IN_BITS (KEY_SIZE * 8)
+
+static int isInitialized = FALSE;
+
+static const char strKeyFilename[] = "/data/drm/fwdlock/kek.dat";
+
+static AES_KEY encryptionRoundKeys;
+static AES_KEY decryptionRoundKeys;
+
+/**
+ * Creates all directories along the fully qualified path of the given file.
+ *
+ * @param[in] path A reference to the fully qualified path of a file.
+ * @param[in] mode The access mode to use for the directories being created.
+ *
+ * @return A Boolean value indicating whether the operation was successful.
+ */
+static int FwdLockGlue_CreateDirectories(const char *path, mode_t mode) {
+    int result = TRUE;
+    size_t partialPathLength = strlen(path);
+    char *partialPath = malloc(partialPathLength + 1);
+    if (partialPath == NULL) {
+        result = FALSE;
+    } else {
+        size_t i;
+        for (i = 0; i < partialPathLength; ++i) {
+            if (path[i] == '/' && i > 0) {
+                partialPath[i] = '\0';
+                if (mkdir(partialPath, mode) != 0 && errno != EEXIST) {
+                    result = FALSE;
+                    break;
+                }
+            }
+            partialPath[i] = path[i];
+        }
+        free(partialPath);
+    }
+    return result;
+}
+
+/**
+ * Initializes the round keys used for encryption and decryption of session keys. First creates a
+ * device-unique key-encryption key if none exists yet.
+ */
+static void FwdLockGlue_InitializeRoundKeys() {
+    unsigned char keyEncryptionKey[KEY_SIZE];
+    int fileDesc = open(strKeyFilename, O_RDONLY);
+    if (fileDesc >= 0) {
+        if (read(fileDesc, keyEncryptionKey, KEY_SIZE) == KEY_SIZE) {
+            isInitialized = TRUE;
+        }
+        (void)close(fileDesc);
+    } else if (errno == ENOENT &&
+               FwdLockGlue_GetRandomNumber(keyEncryptionKey, KEY_SIZE) &&
+               FwdLockGlue_CreateDirectories(strKeyFilename, S_IRWXU)) {
+        fileDesc = open(strKeyFilename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR);
+        if (fileDesc >= 0) {
+            if (write(fileDesc, keyEncryptionKey, KEY_SIZE) == KEY_SIZE) {
+                isInitialized = TRUE;
+            }
+            (void)close(fileDesc);
+        }
+    }
+    if (isInitialized) {
+        if (AES_set_encrypt_key(keyEncryptionKey, KEY_SIZE_IN_BITS, &encryptionRoundKeys) != 0 ||
+            AES_set_decrypt_key(keyEncryptionKey, KEY_SIZE_IN_BITS, &decryptionRoundKeys) != 0) {
+            isInitialized = FALSE;
+        }
+    }
+    memset(keyEncryptionKey, 0, KEY_SIZE); // Zero out key data.
+}
+
+/**
+ * Validates the padding of a decrypted key.
+ *
+ * @param[in] pData A reference to the buffer containing the decrypted key and padding.
+ * @param[in] decryptedKeyLength The length in bytes of the decrypted key.
+ *
+ * @return A Boolean value indicating whether the padding was valid.
+ */
+static int FwdLockGlue_ValidatePadding(const unsigned char *pData, size_t decryptedKeyLength) {
+    size_t i;
+    size_t padding = AES_BLOCK_SIZE - (decryptedKeyLength % AES_BLOCK_SIZE);
+    pData += decryptedKeyLength;
+    for (i = 0; i < padding; ++i) {
+        if ((size_t)*pData != padding) {
+            return FALSE;
+        }
+        ++pData;
+    }
+    return TRUE;
+}
+
+int FwdLockGlue_GetRandomNumber(void *pBuffer, size_t numBytes) {
+    // Generate 'cryptographically secure' random bytes by reading them from "/dev/urandom" (the
+    // non-blocking version of "/dev/random").
+    ssize_t numBytesRead = 0;
+    int fileDesc = open("/dev/urandom", O_RDONLY);
+    if (fileDesc >= 0) {
+        numBytesRead = read(fileDesc, pBuffer, numBytes);
+        (void)close(fileDesc);
+    }
+    return numBytesRead >= 0 && (size_t)numBytesRead == numBytes;
+}
+
+int FwdLockGlue_InitializeKeyEncryption() {
+    static pthread_once_t once = PTHREAD_ONCE_INIT;
+    pthread_once(&once, FwdLockGlue_InitializeRoundKeys);
+    return isInitialized;
+}
+
+size_t FwdLockGlue_GetEncryptedKeyLength(size_t plaintextKeyLength) {
+    return ((plaintextKeyLength / AES_BLOCK_SIZE) + 2) * AES_BLOCK_SIZE;
+}
+
+int FwdLockGlue_EncryptKey(const void *pPlaintextKey,
+                           size_t plaintextKeyLength,
+                           void *pEncryptedKey,
+                           size_t encryptedKeyLength) {
+    int result = FALSE;
+    assert(encryptedKeyLength == FwdLockGlue_GetEncryptedKeyLength(plaintextKeyLength));
+    if (FwdLockGlue_InitializeKeyEncryption()) {
+        unsigned char initVector[AES_BLOCK_SIZE];
+        if (FwdLockGlue_GetRandomNumber(initVector, AES_BLOCK_SIZE)) {
+            size_t padding = AES_BLOCK_SIZE - (plaintextKeyLength % AES_BLOCK_SIZE);
+            size_t dataLength = encryptedKeyLength - AES_BLOCK_SIZE;
+            memcpy(pEncryptedKey, pPlaintextKey, plaintextKeyLength);
+            memset((unsigned char *)pEncryptedKey + plaintextKeyLength, (int)padding, padding);
+            memcpy((unsigned char *)pEncryptedKey + dataLength, initVector, AES_BLOCK_SIZE);
+            AES_cbc_encrypt(pEncryptedKey, pEncryptedKey, dataLength, &encryptionRoundKeys,
+                            initVector, AES_ENCRYPT);
+            result = TRUE;
+        }
+    }
+    return result;
+}
+
+int FwdLockGlue_DecryptKey(const void *pEncryptedKey,
+                           size_t encryptedKeyLength,
+                           void *pDecryptedKey,
+                           size_t decryptedKeyLength) {
+    int result = FALSE;
+    assert(encryptedKeyLength == FwdLockGlue_GetEncryptedKeyLength(decryptedKeyLength));
+    if (FwdLockGlue_InitializeKeyEncryption()) {
+        size_t dataLength = encryptedKeyLength - AES_BLOCK_SIZE;
+        unsigned char *pData = malloc(dataLength);
+        if (pData != NULL) {
+            unsigned char initVector[AES_BLOCK_SIZE];
+            memcpy(pData, pEncryptedKey, dataLength);
+            memcpy(initVector, (const unsigned char *)pEncryptedKey + dataLength, AES_BLOCK_SIZE);
+            AES_cbc_encrypt(pData, pData, dataLength, &decryptionRoundKeys, initVector,
+                            AES_DECRYPT);
+            memcpy(pDecryptedKey, pData, decryptedKeyLength);
+            result = FwdLockGlue_ValidatePadding(pData, decryptedKeyLength);
+            free(pData);
+        }
+    }
+    return result;
+}
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.h b/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.h
new file mode 100644
index 0000000..f36f6ea
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __FWDLOCKGLUE_H__
+#define __FWDLOCKGLUE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Generates the specified number of cryptographically secure random bytes.
+ *
+ * @param[out] pBuffer A reference to the buffer that should receive the random data.
+ * @param[in] numBytes The number of random bytes to generate.
+ *
+ * @return A Boolean value indicating whether the operation was successful.
+ */
+int FwdLockGlue_GetRandomNumber(void *pBuffer, size_t numBytes);
+
+/**
+ * Performs initialization of the key-encryption key. Should be called once during startup to
+ * facilitate encryption and decryption of session keys.
+ *
+ * @return A Boolean value indicating whether the operation was successful.
+ */
+int FwdLockGlue_InitializeKeyEncryption();
+
+/**
+ * Returns the length of the encrypted key, given the length of the plaintext key.
+ *
+ * @param[in] plaintextKeyLength The length in bytes of the plaintext key.
+ *
+ * @return The length in bytes of the encrypted key.
+ */
+size_t FwdLockGlue_GetEncryptedKeyLength(size_t plaintextKeyLength);
+
+/**
+ * Encrypts the given session key using a key-encryption key unique to this device.
+ *
+ * @param[in] pPlaintextKey A reference to the buffer containing the plaintext key.
+ * @param[in] plaintextKeyLength The length in bytes of the plaintext key.
+ * @param[out] pEncryptedKey A reference to the buffer containing the encrypted key.
+ * @param[in] encryptedKeyLength The length in bytes of the encrypted key.
+ *
+ * @return A Boolean value indicating whether the operation was successful.
+ */
+int FwdLockGlue_EncryptKey(const void *pPlaintextKey,
+                           size_t plaintextKeyLength,
+                           void *pEncryptedKey,
+                           size_t encryptedKeyLength);
+
+/**
+ * Decrypts the given session key using a key-encryption key unique to this device.
+ *
+ * @param[in] pEncryptedKey A reference to the buffer containing the encrypted key.
+ * @param[in] encryptedKeyLength The length in bytes of the encrypted key.
+ * @param[out] pDecryptedKey A reference to the buffer containing the decrypted key.
+ * @param[in] decryptedKeyLength The length in bytes of the decrypted key.
+ *
+ * @return A Boolean value indicating whether the operation was successful.
+ */
+int FwdLockGlue_DecryptKey(const void *pEncryptedKey,
+                           size_t encryptedKeyLength,
+                           void *pDecryptedKey,
+                           size_t decryptedKeyLength);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __FWDLOCKGLUE_H__
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
new file mode 100644
index 0000000..00bb788
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    FwdLockConv.c
+
+LOCAL_C_INCLUDES := \
+    frameworks/base/drm/libdrmframework/plugins/forward-lock/internal-format/common \
+    external/openssl/include
+
+LOCAL_SHARED_LIBRARIES := libcrypto
+
+LOCAL_WHOLE_STATIC_LIBRARIES := libfwdlock-common
+
+LOCAL_STATIC_LIBRARIES := libfwdlock-common
+
+LOCAL_MODULE := libfwdlock-converter
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
new file mode 100644
index 0000000..14ea9e9
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
@@ -0,0 +1,1339 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <openssl/aes.h>
+#include <openssl/hmac.h>
+
+#include "FwdLockConv.h"
+#include "FwdLockGlue.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define INVALID_OFFSET ((off64_t)-1)
+
+#define MAX_NUM_SESSIONS 32
+
+#define OUTPUT_BUFFER_SIZE_INCREMENT 1024
+#define READ_BUFFER_SIZE 1024
+
+#define MAX_BOUNDARY_LENGTH 70
+#define MAX_DELIMITER_LENGTH (MAX_BOUNDARY_LENGTH + 4)
+
+#define STRING_LENGTH_INCREMENT 25
+
+#define KEY_SIZE AES_BLOCK_SIZE
+#define KEY_SIZE_IN_BITS (KEY_SIZE * 8)
+
+#define SHA1_HASH_SIZE 20
+
+#define FWD_LOCK_VERSION 0
+#define FWD_LOCK_SUBFORMAT 0
+#define USAGE_RESTRICTION_FLAGS 0
+#define CONTENT_TYPE_LENGTH_POS 7
+#define TOP_HEADER_SIZE 8
+
+/**
+ * Data type for the parser states of the converter.
+ */
+typedef enum FwdLockConv_ParserState {
+    FwdLockConv_ParserState_WantsOpenDelimiter,
+    FwdLockConv_ParserState_WantsMimeHeaders,
+    FwdLockConv_ParserState_WantsBinaryEncodedData,
+    FwdLockConv_ParserState_WantsBase64EncodedData,
+    FwdLockConv_ParserState_Done
+} FwdLockConv_ParserState_t;
+
+/**
+ * Data type for the scanner states of the converter.
+ */
+typedef enum FwdLockConv_ScannerState {
+    FwdLockConv_ScannerState_WantsFirstDash,
+    FwdLockConv_ScannerState_WantsSecondDash,
+    FwdLockConv_ScannerState_WantsCR,
+    FwdLockConv_ScannerState_WantsLF,
+    FwdLockConv_ScannerState_WantsBoundary,
+    FwdLockConv_ScannerState_WantsBoundaryEnd,
+    FwdLockConv_ScannerState_WantsMimeHeaderNameStart,
+    FwdLockConv_ScannerState_WantsMimeHeaderName,
+    FwdLockConv_ScannerState_WantsMimeHeaderNameEnd,
+    FwdLockConv_ScannerState_WantsContentTypeStart,
+    FwdLockConv_ScannerState_WantsContentType,
+    FwdLockConv_ScannerState_WantsContentTransferEncodingStart,
+    FwdLockConv_ScannerState_Wants_A_OR_I,
+    FwdLockConv_ScannerState_Wants_N,
+    FwdLockConv_ScannerState_Wants_A,
+    FwdLockConv_ScannerState_Wants_R,
+    FwdLockConv_ScannerState_Wants_Y,
+    FwdLockConv_ScannerState_Wants_S,
+    FwdLockConv_ScannerState_Wants_E,
+    FwdLockConv_ScannerState_Wants_6,
+    FwdLockConv_ScannerState_Wants_4,
+    FwdLockConv_ScannerState_Wants_B,
+    FwdLockConv_ScannerState_Wants_I,
+    FwdLockConv_ScannerState_Wants_T,
+    FwdLockConv_ScannerState_WantsContentTransferEncodingEnd,
+    FwdLockConv_ScannerState_WantsMimeHeaderValueEnd,
+    FwdLockConv_ScannerState_WantsMimeHeadersEnd,
+    FwdLockConv_ScannerState_WantsByte1,
+    FwdLockConv_ScannerState_WantsByte1_AfterCRLF,
+    FwdLockConv_ScannerState_WantsByte2,
+    FwdLockConv_ScannerState_WantsByte3,
+    FwdLockConv_ScannerState_WantsByte4,
+    FwdLockConv_ScannerState_WantsPadding,
+    FwdLockConv_ScannerState_WantsWhitespace,
+    FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF,
+    FwdLockConv_ScannerState_WantsDelimiter
+} FwdLockConv_ScannerState_t;
+
+/**
+ * Data type for the content transfer encoding.
+ */
+typedef enum FwdLockConv_ContentTransferEncoding {
+    FwdLockConv_ContentTransferEncoding_Undefined,
+    FwdLockConv_ContentTransferEncoding_Binary,
+    FwdLockConv_ContentTransferEncoding_Base64
+} FwdLockConv_ContentTransferEncoding_t;
+
+/**
+ * Data type for a dynamically growing string.
+ */
+typedef struct FwdLockConv_String {
+    char *ptr;
+    size_t length;
+    size_t maxLength;
+    size_t lengthIncrement;
+} FwdLockConv_String_t;
+
+/**
+ * Data type for the per-file state information needed by the converter.
+ */
+typedef struct FwdLockConv_Session {
+    FwdLockConv_ParserState_t parserState;
+    FwdLockConv_ScannerState_t scannerState;
+    FwdLockConv_ScannerState_t savedScannerState;
+    off64_t numCharsConsumed;
+    char delimiter[MAX_DELIMITER_LENGTH];
+    size_t delimiterLength;
+    size_t delimiterMatchPos;
+    FwdLockConv_String_t mimeHeaderName;
+    FwdLockConv_String_t contentType;
+    FwdLockConv_ContentTransferEncoding_t contentTransferEncoding;
+    unsigned char sessionKey[KEY_SIZE];
+    void *pEncryptedSessionKey;
+    size_t encryptedSessionKeyLength;
+    AES_KEY encryptionRoundKeys;
+    HMAC_CTX signingContext;
+    unsigned char topHeader[TOP_HEADER_SIZE];
+    unsigned char counter[AES_BLOCK_SIZE];
+    unsigned char keyStream[AES_BLOCK_SIZE];
+    int keyStreamIndex;
+    unsigned char ch;
+    size_t outputBufferSize;
+    size_t dataOffset;
+    size_t numDataBytes;
+} FwdLockConv_Session_t;
+
+static FwdLockConv_Session_t *sessionPtrs[MAX_NUM_SESSIONS] = { NULL };
+
+static pthread_mutex_t sessionAcquisitionMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static const FwdLockConv_String_t nullString = { NULL, 0, 0, STRING_LENGTH_INCREMENT };
+
+static const unsigned char topHeaderTemplate[] =
+    { 'F', 'W', 'L', 'K', FWD_LOCK_VERSION, FWD_LOCK_SUBFORMAT, USAGE_RESTRICTION_FLAGS };
+
+static const char strContent[] = "content-";
+static const char strType[] = "type";
+static const char strTransferEncoding[] = "transfer-encoding";
+static const char strTextPlain[] = "text/plain";
+static const char strApplicationVndOmaDrmRightsXml[] = "application/vnd.oma.drm.rights+xml";
+static const char strApplicationVndOmaDrmContent[] = "application/vnd.oma.drm.content";
+
+static const size_t strlenContent = sizeof strContent - 1;
+static const size_t strlenTextPlain = sizeof strTextPlain - 1;
+
+static const signed char base64Values[] = {
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
+    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+};
+
+/**
+ * Acquires an unused converter session.
+ *
+ * @return A session ID.
+ */
+static int FwdLockConv_AcquireSession() {
+    int sessionId = -1;
+    int i;
+    pthread_mutex_lock(&sessionAcquisitionMutex);
+    for (i = 0; i < MAX_NUM_SESSIONS; ++i) {
+        if (sessionPtrs[i] == NULL) {
+            sessionPtrs[i] = malloc(sizeof *sessionPtrs[i]);
+            if (sessionPtrs[i] != NULL) {
+                sessionId = i;
+            }
+            break;
+        }
+    }
+    pthread_mutex_unlock(&sessionAcquisitionMutex);
+    return sessionId;
+}
+
+/**
+ * Checks whether a session ID is in range and currently in use.
+ *
+ * @param[in] sessionID A session ID.
+ *
+ * @return A Boolean value indicating whether the session ID is in range and currently in use.
+ */
+static int FwdLockConv_IsValidSession(int sessionId) {
+    return 0 <= sessionId && sessionId < MAX_NUM_SESSIONS && sessionPtrs[sessionId] != NULL;
+}
+
+/**
+ * Releases a converter session.
+ *
+ * @param[in] sessionID A session ID.
+ */
+static void FwdLockConv_ReleaseSession(int sessionId) {
+    pthread_mutex_lock(&sessionAcquisitionMutex);
+    assert(FwdLockConv_IsValidSession(sessionId));
+    memset(sessionPtrs[sessionId], 0, sizeof *sessionPtrs[sessionId]); // Zero out key data.
+    free(sessionPtrs[sessionId]);
+    sessionPtrs[sessionId] = NULL;
+    pthread_mutex_unlock(&sessionAcquisitionMutex);
+}
+
+/**
+ * Derives cryptographically independent keys for encryption and signing from the session key.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ *
+ * @return A status code.
+ */
+static int FwdLockConv_DeriveKeys(FwdLockConv_Session_t *pSession) {
+    FwdLockConv_Status_t status;
+    struct FwdLockConv_DeriveKeys_Data {
+        AES_KEY sessionRoundKeys;
+        unsigned char value[KEY_SIZE];
+        unsigned char key[KEY_SIZE];
+    } *pData = malloc(sizeof *pData);
+    if (pData == NULL) {
+        status = FwdLockConv_Status_OutOfMemory;
+    } else {
+        if (AES_set_encrypt_key(pSession->sessionKey, KEY_SIZE_IN_BITS,
+                                &pData->sessionRoundKeys) != 0) {
+            status = FwdLockConv_Status_ProgramError;
+        } else {
+            // Encrypt the 16-byte value {0, 0, ..., 0} to produce the encryption key.
+            memset(pData->value, 0, KEY_SIZE);
+            AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys);
+            if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS,
+                                    &pSession->encryptionRoundKeys) != 0) {
+                status = FwdLockConv_Status_ProgramError;
+            } else {
+                // Encrypt the 16-byte value {1, 0, ..., 0} to produce the signing key.
+                ++pData->value[0];
+                AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys);
+                HMAC_CTX_init(&pSession->signingContext);
+                HMAC_Init_ex(&pSession->signingContext, pData->key, KEY_SIZE, EVP_sha1(), NULL);
+                status = FwdLockConv_Status_OK;
+            }
+        }
+        memset(pData, 0, sizeof pData); // Zero out key data.
+        free(pData);
+    }
+    return status;
+}
+
+/**
+ * Checks whether a given character is valid in a boundary. Note that the boundary may contain
+ * leading and internal spaces.
+ *
+ * @param[in] ch The character to check.
+ *
+ * @return A Boolean value indicating whether the given character is valid in a boundary.
+ */
+static int FwdLockConv_IsBoundaryChar(int ch) {
+    return isalnum(ch) || ch == '\'' ||
+            ch == '(' || ch == ')' || ch == '+' || ch == '_' || ch == ',' || ch == '-' ||
+            ch == '.' || ch == '/' || ch == ':' || ch == '=' || ch == '?' || ch == ' ';
+}
+
+/**
+ * Checks whether a given character should be considered whitespace, using a narrower definition
+ * than the standard-library isspace() function.
+ *
+ * @param[in] ch The character to check.
+ *
+ * @return A Boolean value indicating whether the given character should be considered whitespace.
+ */
+static int FwdLockConv_IsWhitespace(int ch) {
+    return ch == ' ' || ch == '\t';
+}
+
+/**
+ * Removes trailing spaces from the delimiter.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_RightTrimDelimiter(FwdLockConv_Session_t *pSession) {
+    while (pSession->delimiterLength > 4 &&
+           pSession->delimiter[pSession->delimiterLength - 1] == ' ') {
+        --pSession->delimiterLength;
+    }
+    if (pSession->delimiterLength > 4) {
+        return FwdLockConv_Status_OK;
+    }
+    return FwdLockConv_Status_SyntaxError;
+}
+
+/**
+ * Matches the open delimiter.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[in] ch A character.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_MatchOpenDelimiter(FwdLockConv_Session_t *pSession,
+                                                           int ch) {
+    FwdLockConv_Status_t status = FwdLockConv_Status_OK;
+    switch (pSession->scannerState) {
+    case FwdLockConv_ScannerState_WantsFirstDash:
+        if (ch == '-') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsSecondDash;
+        } else if (ch == '\r') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+        } else {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsSecondDash:
+        if (ch == '-') {
+            // The delimiter starts with "\r\n--" (the open delimiter may omit the initial "\r\n").
+            // The rest is the user-defined boundary that should come next.
+            pSession->delimiter[0] = '\r';
+            pSession->delimiter[1] = '\n';
+            pSession->delimiter[2] = '-';
+            pSession->delimiter[3] = '-';
+            pSession->delimiterLength = 4;
+            pSession->scannerState = FwdLockConv_ScannerState_WantsBoundary;
+        } else if (ch == '\r') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+        } else {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsCR:
+        if (ch == '\r') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsLF:
+        if (ch == '\n') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash;
+        } else if (ch != '\r') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsBoundary:
+        if (FwdLockConv_IsBoundaryChar(ch)) {
+            // The boundary may contain leading and internal spaces, so trailing spaces will also be
+            // matched here. These will be removed later.
+            if (pSession->delimiterLength < MAX_DELIMITER_LENGTH) {
+                pSession->delimiter[pSession->delimiterLength++] = ch;
+            } else if (ch != ' ') {
+                status = FwdLockConv_Status_SyntaxError;
+            }
+        } else if (ch == '\r') {
+            status = FwdLockConv_RightTrimDelimiter(pSession);
+            if (status == FwdLockConv_Status_OK) {
+                pSession->scannerState = FwdLockConv_ScannerState_WantsBoundaryEnd;
+            }
+        } else if (ch == '\t') {
+            status = FwdLockConv_RightTrimDelimiter(pSession);
+            if (status == FwdLockConv_Status_OK) {
+                pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace;
+            }
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsWhitespace:
+        if (ch == '\r') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsBoundaryEnd;
+        } else if (!FwdLockConv_IsWhitespace(ch)) {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsBoundaryEnd:
+        if (ch == '\n') {
+            pSession->parserState = FwdLockConv_ParserState_WantsMimeHeaders;
+            pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderNameStart;
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    default:
+        status = FwdLockConv_Status_ProgramError;
+        break;
+    }
+    return status;
+}
+
+/**
+ * Checks whether a given character is valid in a MIME header name.
+ *
+ * @param[in] ch The character to check.
+ *
+ * @return A Boolean value indicating whether the given character is valid in a MIME header name.
+ */
+static int FwdLockConv_IsMimeHeaderNameChar(int ch) {
+    return isgraph(ch) && ch != ':';
+}
+
+/**
+ * Checks whether a given character is valid in a MIME header value.
+ *
+ * @param[in] ch The character to check.
+ *
+ * @return A Boolean value indicating whether the given character is valid in a MIME header value.
+ */
+static int FwdLockConv_IsMimeHeaderValueChar(int ch) {
+    return isgraph(ch) && ch != ';';
+}
+
+/**
+ * Appends a character to the specified dynamically growing string.
+ *
+ * @param[in,out] pString A reference to a dynamically growing string.
+ * @param[in] ch The character to append.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_StringAppend(FwdLockConv_String_t *pString, int ch) {
+    if (pString->length == pString->maxLength) {
+        size_t newMaxLength = pString->maxLength + pString->lengthIncrement;
+        char *newPtr = realloc(pString->ptr, newMaxLength + 1);
+        if (newPtr == NULL) {
+            return FwdLockConv_Status_OutOfMemory;
+        }
+        pString->ptr = newPtr;
+        pString->maxLength = newMaxLength;
+    }
+    pString->ptr[pString->length++] = ch;
+    pString->ptr[pString->length] = '\0';
+    return FwdLockConv_Status_OK;
+}
+
+/**
+ * Attempts to recognize the MIME header name and changes the scanner state accordingly.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_RecognizeMimeHeaderName(FwdLockConv_Session_t *pSession) {
+    FwdLockConv_Status_t status = FwdLockConv_Status_OK;
+    if (strncmp(pSession->mimeHeaderName.ptr, strContent, strlenContent) == 0) {
+        if (strcmp(pSession->mimeHeaderName.ptr + strlenContent, strType) == 0) {
+            if (pSession->contentType.ptr == NULL) {
+                pSession->scannerState = FwdLockConv_ScannerState_WantsContentTypeStart;
+            } else {
+                status = FwdLockConv_Status_SyntaxError;
+            }
+        } else if (strcmp(pSession->mimeHeaderName.ptr + strlenContent, strTransferEncoding) == 0) {
+            if (pSession->contentTransferEncoding ==
+                    FwdLockConv_ContentTransferEncoding_Undefined) {
+                pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingStart;
+            } else {
+                status = FwdLockConv_Status_SyntaxError;
+            }
+        } else {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+        }
+    } else {
+        pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+    }
+    return status;
+}
+
+/**
+ * Applies defaults to missing MIME header values.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_ApplyDefaults(FwdLockConv_Session_t *pSession) {
+    if (pSession->contentType.ptr == NULL) {
+        // Content type is missing: default to "text/plain".
+        pSession->contentType.ptr = malloc(sizeof strTextPlain);
+        if (pSession->contentType.ptr == NULL) {
+            return FwdLockConv_Status_OutOfMemory;
+        }
+        memcpy(pSession->contentType.ptr, strTextPlain, sizeof strTextPlain);
+        pSession->contentType.length = strlenTextPlain;
+        pSession->contentType.maxLength = strlenTextPlain;
+    }
+    if (pSession->contentTransferEncoding == FwdLockConv_ContentTransferEncoding_Undefined) {
+        // Content transfer encoding is missing: default to binary.
+        pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Binary;
+    }
+    return FwdLockConv_Status_OK;
+}
+
+/**
+ * Verifies that the content type is supported.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_VerifyContentType(FwdLockConv_Session_t *pSession) {
+    FwdLockConv_Status_t status;
+    if (pSession->contentType.ptr == NULL) {
+        status = FwdLockConv_Status_ProgramError;
+    } else if (strcmp(pSession->contentType.ptr, strApplicationVndOmaDrmRightsXml) == 0 ||
+               strcmp(pSession->contentType.ptr, strApplicationVndOmaDrmContent) == 0) {
+        status = FwdLockConv_Status_UnsupportedFileFormat;
+    } else {
+        status = FwdLockConv_Status_OK;
+    }
+    return status;
+}
+
+/**
+ * Writes the header of the output file.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[out] pOutput The output from the conversion process.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_WriteHeader(FwdLockConv_Session_t *pSession,
+                                                    FwdLockConv_Output_t *pOutput) {
+    FwdLockConv_Status_t status;
+    if (pSession->contentType.length > UCHAR_MAX) {
+        status = FwdLockConv_Status_SyntaxError;
+    } else {
+        pSession->outputBufferSize = OUTPUT_BUFFER_SIZE_INCREMENT;
+        pOutput->fromConvertData.pBuffer = malloc(pSession->outputBufferSize);
+        if (pOutput->fromConvertData.pBuffer == NULL) {
+            status = FwdLockConv_Status_OutOfMemory;
+        } else {
+            size_t encryptedSessionKeyPos = TOP_HEADER_SIZE + pSession->contentType.length;
+            size_t dataSignaturePos = encryptedSessionKeyPos + pSession->encryptedSessionKeyLength;
+            size_t headerSignaturePos = dataSignaturePos + SHA1_HASH_SIZE;
+            pSession->dataOffset = headerSignaturePos + SHA1_HASH_SIZE;
+            memcpy(pSession->topHeader, topHeaderTemplate, sizeof topHeaderTemplate);
+            pSession->topHeader[CONTENT_TYPE_LENGTH_POS] =
+                    (unsigned char)pSession->contentType.length;
+            memcpy(pOutput->fromConvertData.pBuffer, pSession->topHeader, TOP_HEADER_SIZE);
+            memcpy((char *)pOutput->fromConvertData.pBuffer + TOP_HEADER_SIZE,
+                   pSession->contentType.ptr, pSession->contentType.length);
+            memcpy((char *)pOutput->fromConvertData.pBuffer + encryptedSessionKeyPos,
+                   pSession->pEncryptedSessionKey, pSession->encryptedSessionKeyLength);
+
+            // Set the signatures to all zeros for now; they will have to be updated later.
+            memset((char *)pOutput->fromConvertData.pBuffer + dataSignaturePos, 0,
+                   SHA1_HASH_SIZE);
+            memset((char *)pOutput->fromConvertData.pBuffer + headerSignaturePos, 0,
+                   SHA1_HASH_SIZE);
+
+            pOutput->fromConvertData.numBytes = pSession->dataOffset;
+            status = FwdLockConv_Status_OK;
+        }
+    }
+    return status;
+}
+
+/**
+ * Matches the MIME headers.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[in] ch A character.
+ * @param[out] pOutput The output from the conversion process.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_MatchMimeHeaders(FwdLockConv_Session_t *pSession,
+                                                         int ch,
+                                                         FwdLockConv_Output_t *pOutput) {
+    FwdLockConv_Status_t status = FwdLockConv_Status_OK;
+    switch (pSession->scannerState) {
+    case FwdLockConv_ScannerState_WantsMimeHeaderNameStart:
+        if (FwdLockConv_IsMimeHeaderNameChar(ch)) {
+            pSession->mimeHeaderName.length = 0;
+            status = FwdLockConv_StringAppend(&pSession->mimeHeaderName, tolower(ch));
+            if (status == FwdLockConv_Status_OK) {
+                pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderName;
+            }
+        } else if (ch == '\r') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeadersEnd;
+        } else if (!FwdLockConv_IsWhitespace(ch)) {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsMimeHeaderName:
+        if (FwdLockConv_IsMimeHeaderNameChar(ch)) {
+            status = FwdLockConv_StringAppend(&pSession->mimeHeaderName, tolower(ch));
+        } else if (ch == ':') {
+            status = FwdLockConv_RecognizeMimeHeaderName(pSession);
+        } else if (FwdLockConv_IsWhitespace(ch)) {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderNameEnd;
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsMimeHeaderNameEnd:
+        if (ch == ':') {
+            status = FwdLockConv_RecognizeMimeHeaderName(pSession);
+        } else if (!FwdLockConv_IsWhitespace(ch)) {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsContentTypeStart:
+        if (FwdLockConv_IsMimeHeaderValueChar(ch)) {
+            status = FwdLockConv_StringAppend(&pSession->contentType, tolower(ch));
+            if (status == FwdLockConv_Status_OK) {
+                pSession->scannerState = FwdLockConv_ScannerState_WantsContentType;
+            }
+        } else if (!FwdLockConv_IsWhitespace(ch)) {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsContentType:
+        if (FwdLockConv_IsMimeHeaderValueChar(ch)) {
+            status = FwdLockConv_StringAppend(&pSession->contentType, tolower(ch));
+        } else if (ch == ';') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+        } else if (ch == '\r') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+        } else if (FwdLockConv_IsWhitespace(ch)) {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderValueEnd;
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsContentTransferEncodingStart:
+        if (ch == 'b' || ch == 'B') {
+            pSession->scannerState = FwdLockConv_ScannerState_Wants_A_OR_I;
+        } else if (ch == '7' || ch == '8') {
+            pSession->scannerState = FwdLockConv_ScannerState_Wants_B;
+        } else if (!FwdLockConv_IsWhitespace(ch)) {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_Wants_A_OR_I:
+        if (ch == 'i' || ch == 'I') {
+            pSession->scannerState = FwdLockConv_ScannerState_Wants_N;
+        } else if (ch == 'a' || ch == 'A') {
+            pSession->scannerState = FwdLockConv_ScannerState_Wants_S;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_Wants_N:
+        if (ch == 'n' || ch == 'N') {
+            pSession->scannerState = FwdLockConv_ScannerState_Wants_A;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_Wants_A:
+        if (ch == 'a' || ch == 'A') {
+            pSession->scannerState = FwdLockConv_ScannerState_Wants_R;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_Wants_R:
+        if (ch == 'r' || ch == 'R') {
+            pSession->scannerState = FwdLockConv_ScannerState_Wants_Y;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_Wants_Y:
+        if (ch == 'y' || ch == 'Y') {
+            pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Binary;
+            pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingEnd;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_Wants_S:
+        if (ch == 's' || ch == 'S') {
+            pSession->scannerState = FwdLockConv_ScannerState_Wants_E;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_Wants_E:
+        if (ch == 'e' || ch == 'E') {
+            pSession->scannerState = FwdLockConv_ScannerState_Wants_6;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_Wants_6:
+        if (ch == '6') {
+            pSession->scannerState = FwdLockConv_ScannerState_Wants_4;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_Wants_4:
+        if (ch == '4') {
+            pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Base64;
+            pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingEnd;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_Wants_B:
+        if (ch == 'b' || ch == 'B') {
+            pSession->scannerState = FwdLockConv_ScannerState_Wants_I;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_Wants_I:
+        if (ch == 'i' || ch == 'I') {
+            pSession->scannerState = FwdLockConv_ScannerState_Wants_T;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_Wants_T:
+        if (ch == 't' || ch == 'T') {
+            pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Binary;
+            pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingEnd;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsContentTransferEncodingEnd:
+        if (ch == ';') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+        } else if (ch == '\r') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+        } else if (FwdLockConv_IsWhitespace(ch)) {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderValueEnd;
+        } else {
+            status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsMimeHeaderValueEnd:
+        if (ch == ';') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+        } else if (ch == '\r') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+        } else if (!FwdLockConv_IsWhitespace(ch)) {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsCR:
+        if (ch == '\r') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsLF:
+        if (ch == '\n') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderNameStart;
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsMimeHeadersEnd:
+        if (ch == '\n') {
+            status = FwdLockConv_ApplyDefaults(pSession);
+            if (status == FwdLockConv_Status_OK) {
+                status = FwdLockConv_VerifyContentType(pSession);
+            }
+            if (status == FwdLockConv_Status_OK) {
+                status = FwdLockConv_WriteHeader(pSession, pOutput);
+            }
+            if (status == FwdLockConv_Status_OK) {
+                if (pSession->contentTransferEncoding ==
+                        FwdLockConv_ContentTransferEncoding_Binary) {
+                    pSession->parserState = FwdLockConv_ParserState_WantsBinaryEncodedData;
+                } else {
+                    pSession->parserState = FwdLockConv_ParserState_WantsBase64EncodedData;
+                }
+                pSession->scannerState = FwdLockConv_ScannerState_WantsByte1;
+            }
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    default:
+        status = FwdLockConv_Status_ProgramError;
+        break;
+    }
+    return status;
+}
+
+/**
+ * Increments the counter, treated as a 16-byte little-endian number, by one.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ */
+static void FwdLockConv_IncrementCounter(FwdLockConv_Session_t *pSession) {
+    size_t i = 0;
+    while ((++pSession->counter[i] == 0) && (++i < AES_BLOCK_SIZE))
+        ;
+}
+
+/**
+ * Encrypts the given character and writes it to the output buffer.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[in] ch The character to encrypt and write.
+ * @param[in,out] pOutput The output from the conversion process.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_WriteEncryptedChar(FwdLockConv_Session_t *pSession,
+                                                           unsigned char ch,
+                                                           FwdLockConv_Output_t *pOutput) {
+    if (pOutput->fromConvertData.numBytes == pSession->outputBufferSize) {
+        void *pBuffer;
+        pSession->outputBufferSize += OUTPUT_BUFFER_SIZE_INCREMENT;
+        pBuffer = realloc(pOutput->fromConvertData.pBuffer, pSession->outputBufferSize);
+        if (pBuffer == NULL) {
+            return FwdLockConv_Status_OutOfMemory;
+        }
+        pOutput->fromConvertData.pBuffer = pBuffer;
+    }
+    if (++pSession->keyStreamIndex == AES_BLOCK_SIZE) {
+        FwdLockConv_IncrementCounter(pSession);
+        pSession->keyStreamIndex = 0;
+    }
+    if (pSession->keyStreamIndex == 0) {
+        AES_encrypt(pSession->counter, pSession->keyStream, &pSession->encryptionRoundKeys);
+    }
+    ch ^= pSession->keyStream[pSession->keyStreamIndex];
+    ((unsigned char *)pOutput->fromConvertData.pBuffer)[pOutput->fromConvertData.numBytes++] = ch;
+    ++pSession->numDataBytes;
+    return FwdLockConv_Status_OK;
+}
+
+/**
+ * Matches binary-encoded content data and encrypts it, while looking out for the close delimiter.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[in] ch A character.
+ * @param[in,out] pOutput The output from the conversion process.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_MatchBinaryEncodedData(FwdLockConv_Session_t *pSession,
+                                                               int ch,
+                                                               FwdLockConv_Output_t *pOutput) {
+    FwdLockConv_Status_t status = FwdLockConv_Status_OK;
+    switch (pSession->scannerState) {
+    case FwdLockConv_ScannerState_WantsByte1:
+        if (ch != pSession->delimiter[pSession->delimiterMatchPos]) {
+            // The partial match of the delimiter turned out to be spurious. Flush the matched bytes
+            // to the output buffer and start over.
+            size_t i;
+            for (i = 0; i < pSession->delimiterMatchPos; ++i) {
+                status = FwdLockConv_WriteEncryptedChar(pSession, pSession->delimiter[i], pOutput);
+                if (status != FwdLockConv_Status_OK) {
+                    return status;
+                }
+            }
+            pSession->delimiterMatchPos = 0;
+        }
+        if (ch != pSession->delimiter[pSession->delimiterMatchPos]) {
+            // The current character isn't part of the delimiter. Write it to the output buffer.
+            status = FwdLockConv_WriteEncryptedChar(pSession, ch, pOutput);
+        } else if (++pSession->delimiterMatchPos == pSession->delimiterLength) {
+            // The entire delimiter has been matched. The only valid characters now are the "--"
+            // that complete the close delimiter (no more message parts are expected).
+            pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsFirstDash:
+        if (ch == '-') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsSecondDash;
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsSecondDash:
+        if (ch == '-') {
+            pSession->parserState = FwdLockConv_ParserState_Done;
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    default:
+        status = FwdLockConv_Status_ProgramError;
+        break;
+    }
+    return status;
+}
+
+/**
+ * Checks whether a given character is valid in base64-encoded data.
+ *
+ * @param[in] ch The character to check.
+ *
+ * @return A Boolean value indicating whether the given character is valid in base64-encoded data.
+ */
+static int FwdLockConv_IsBase64Char(int ch) {
+    return 0 <= ch && ch <= 'z' && base64Values[ch] >= 0;
+}
+
+/**
+ * Matches base64-encoded content data and encrypts it, while looking out for the close delimiter.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[in] ch A character.
+ * @param[in,out] pOutput The output from the conversion process.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_MatchBase64EncodedData(FwdLockConv_Session_t *pSession,
+                                                               int ch,
+                                                               FwdLockConv_Output_t *pOutput) {
+    FwdLockConv_Status_t status = FwdLockConv_Status_OK;
+    switch (pSession->scannerState) {
+    case FwdLockConv_ScannerState_WantsByte1:
+    case FwdLockConv_ScannerState_WantsByte1_AfterCRLF:
+        if (FwdLockConv_IsBase64Char(ch)) {
+            pSession->ch = base64Values[ch] << 2;
+            pSession->scannerState = FwdLockConv_ScannerState_WantsByte2;
+        } else if (ch == '\r') {
+            pSession->savedScannerState = FwdLockConv_ScannerState_WantsByte1_AfterCRLF;
+            pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+        } else if (ch == '-') {
+            if (pSession->scannerState == FwdLockConv_ScannerState_WantsByte1_AfterCRLF) {
+                pSession->delimiterMatchPos = 3;
+                pSession->scannerState = FwdLockConv_ScannerState_WantsDelimiter;
+            } else {
+                status = FwdLockConv_Status_SyntaxError;
+            }
+        } else if (!FwdLockConv_IsWhitespace(ch)) {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsByte2:
+        if (FwdLockConv_IsBase64Char(ch)) {
+            pSession->ch |= base64Values[ch] >> 4;
+            status = FwdLockConv_WriteEncryptedChar(pSession, pSession->ch, pOutput);
+            if (status == FwdLockConv_Status_OK) {
+                pSession->ch = base64Values[ch] << 4;
+                pSession->scannerState = FwdLockConv_ScannerState_WantsByte3;
+            }
+        } else if (ch == '\r') {
+            pSession->savedScannerState = pSession->scannerState;
+            pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+        } else if (!FwdLockConv_IsWhitespace(ch)) {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsByte3:
+        if (FwdLockConv_IsBase64Char(ch)) {
+            pSession->ch |= base64Values[ch] >> 2;
+            status = FwdLockConv_WriteEncryptedChar(pSession, pSession->ch, pOutput);
+            if (status == FwdLockConv_Status_OK) {
+                pSession->ch = base64Values[ch] << 6;
+                pSession->scannerState = FwdLockConv_ScannerState_WantsByte4;
+            }
+        } else if (ch == '\r') {
+            pSession->savedScannerState = pSession->scannerState;
+            pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+        } else if (ch == '=') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsPadding;
+        } else if (!FwdLockConv_IsWhitespace(ch)) {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsByte4:
+        if (FwdLockConv_IsBase64Char(ch)) {
+            pSession->ch |= base64Values[ch];
+            status = FwdLockConv_WriteEncryptedChar(pSession, pSession->ch, pOutput);
+            if (status == FwdLockConv_Status_OK) {
+                pSession->scannerState = FwdLockConv_ScannerState_WantsByte1;
+            }
+        } else if (ch == '\r') {
+            pSession->savedScannerState = pSession->scannerState;
+            pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+        } else if (ch == '=') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace;
+        } else if (!FwdLockConv_IsWhitespace(ch)) {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsLF:
+        if (ch == '\n') {
+            pSession->scannerState = pSession->savedScannerState;
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsPadding:
+        if (ch == '=') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace;
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsWhitespace:
+    case FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF:
+        if (ch == '\r') {
+            pSession->savedScannerState = FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF;
+            pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+        } else if (ch == '-') {
+            if (pSession->scannerState == FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF) {
+                pSession->delimiterMatchPos = 3;
+                pSession->scannerState = FwdLockConv_ScannerState_WantsDelimiter;
+            } else {
+                status = FwdLockConv_Status_SyntaxError;
+            }
+        } else if (FwdLockConv_IsWhitespace(ch)) {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace;
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsDelimiter:
+        if (ch != pSession->delimiter[pSession->delimiterMatchPos]) {
+            status = FwdLockConv_Status_SyntaxError;
+        } else if (++pSession->delimiterMatchPos == pSession->delimiterLength) {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsFirstDash:
+        if (ch == '-') {
+            pSession->scannerState = FwdLockConv_ScannerState_WantsSecondDash;
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    case FwdLockConv_ScannerState_WantsSecondDash:
+        if (ch == '-') {
+            pSession->parserState = FwdLockConv_ParserState_Done;
+        } else {
+            status = FwdLockConv_Status_SyntaxError;
+        }
+        break;
+    default:
+        status = FwdLockConv_Status_ProgramError;
+        break;
+    }
+    return status;
+}
+
+/**
+ * Pushes a single character into the converter's state machine.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[in] ch A character.
+ * @param[in,out] pOutput The output from the conversion process.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_PushChar(FwdLockConv_Session_t *pSession,
+                                                 int ch,
+                                                 FwdLockConv_Output_t *pOutput) {
+    FwdLockConv_Status_t status;
+    ++pSession->numCharsConsumed;
+    switch (pSession->parserState) {
+    case FwdLockConv_ParserState_WantsOpenDelimiter:
+        status = FwdLockConv_MatchOpenDelimiter(pSession, ch);
+        break;
+    case FwdLockConv_ParserState_WantsMimeHeaders:
+        status = FwdLockConv_MatchMimeHeaders(pSession, ch, pOutput);
+        break;
+    case FwdLockConv_ParserState_WantsBinaryEncodedData:
+        status = FwdLockConv_MatchBinaryEncodedData(pSession, ch, pOutput);
+        break;
+    case FwdLockConv_ParserState_WantsBase64EncodedData:
+        status = FwdLockConv_MatchBase64EncodedData(pSession, ch, pOutput);
+        break;
+    case FwdLockConv_ParserState_Done:
+        status = FwdLockConv_Status_OK;
+        break;
+    default:
+        status = FwdLockConv_Status_ProgramError;
+        break;
+    }
+    return status;
+}
+
+FwdLockConv_Status_t FwdLockConv_OpenSession(int *pSessionId, FwdLockConv_Output_t *pOutput) {
+    FwdLockConv_Status_t status;
+    if (pSessionId == NULL || pOutput == NULL) {
+        status = FwdLockConv_Status_InvalidArgument;
+    } else {
+        *pSessionId = FwdLockConv_AcquireSession();
+        if (*pSessionId < 0) {
+            status = FwdLockConv_Status_TooManySessions;
+        } else {
+            FwdLockConv_Session_t *pSession = sessionPtrs[*pSessionId];
+            pSession->encryptedSessionKeyLength = FwdLockGlue_GetEncryptedKeyLength(KEY_SIZE);
+            if (pSession->encryptedSessionKeyLength < AES_BLOCK_SIZE) {
+                // The encrypted session key is used as the CTR-mode nonce, so it must be at least
+                // the size of a single AES block.
+                status = FwdLockConv_Status_ProgramError;
+            } else {
+                pSession->pEncryptedSessionKey = malloc(pSession->encryptedSessionKeyLength);
+                if (pSession->pEncryptedSessionKey == NULL) {
+                    status = FwdLockConv_Status_OutOfMemory;
+                } else {
+                    if (!FwdLockGlue_GetRandomNumber(pSession->sessionKey, KEY_SIZE)) {
+                        status = FwdLockConv_Status_RandomNumberGenerationFailed;
+                    } else if (!FwdLockGlue_EncryptKey(pSession->sessionKey, KEY_SIZE,
+                                                       pSession->pEncryptedSessionKey,
+                                                       pSession->encryptedSessionKeyLength)) {
+                        status = FwdLockConv_Status_KeyEncryptionFailed;
+                    } else {
+                        status = FwdLockConv_DeriveKeys(pSession);
+                    }
+                    if (status == FwdLockConv_Status_OK) {
+                        memset(pSession->sessionKey, 0, KEY_SIZE); // Zero out key data.
+                        memcpy(pSession->counter, pSession->pEncryptedSessionKey, AES_BLOCK_SIZE);
+                        pSession->parserState = FwdLockConv_ParserState_WantsOpenDelimiter;
+                        pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash;
+                        pSession->numCharsConsumed = 0;
+                        pSession->delimiterMatchPos = 0;
+                        pSession->mimeHeaderName = nullString;
+                        pSession->contentType = nullString;
+                        pSession->contentTransferEncoding =
+                                FwdLockConv_ContentTransferEncoding_Undefined;
+                        pSession->keyStreamIndex = -1;
+                        pOutput->fromConvertData.pBuffer = NULL;
+                        pOutput->fromConvertData.errorPos = INVALID_OFFSET;
+                    } else {
+                        free(pSession->pEncryptedSessionKey);
+                    }
+                }
+            }
+            if (status != FwdLockConv_Status_OK) {
+                FwdLockConv_ReleaseSession(*pSessionId);
+                *pSessionId = -1;
+            }
+        }
+    }
+    return status;
+}
+
+FwdLockConv_Status_t FwdLockConv_ConvertData(int sessionId,
+                                             const void *pBuffer,
+                                             size_t numBytes,
+                                             FwdLockConv_Output_t *pOutput) {
+    FwdLockConv_Status_t status;
+    if (!FwdLockConv_IsValidSession(sessionId) || pBuffer == NULL || pOutput == NULL) {
+        status = FwdLockConv_Status_InvalidArgument;
+    } else {
+        size_t i;
+        FwdLockConv_Session_t *pSession = sessionPtrs[sessionId];
+        pSession->dataOffset = 0;
+        pSession->numDataBytes = 0;
+        pOutput->fromConvertData.numBytes = 0;
+        status = FwdLockConv_Status_OK;
+
+        for (i = 0; i < numBytes; ++i) {
+            status = FwdLockConv_PushChar(pSession, ((char *)pBuffer)[i], pOutput);
+            if (status != FwdLockConv_Status_OK) {
+                break;
+            }
+        }
+        if (status == FwdLockConv_Status_OK) {
+            // Update the data signature.
+            HMAC_Update(&pSession->signingContext,
+                        &((unsigned char *)pOutput->fromConvertData.pBuffer)[pSession->dataOffset],
+                        pSession->numDataBytes);
+        } else if (status == FwdLockConv_Status_SyntaxError) {
+            pOutput->fromConvertData.errorPos = pSession->numCharsConsumed;
+        }
+    }
+    return status;
+}
+
+FwdLockConv_Status_t FwdLockConv_CloseSession(int sessionId, FwdLockConv_Output_t *pOutput) {
+    FwdLockConv_Status_t status;
+    if (!FwdLockConv_IsValidSession(sessionId) || pOutput == NULL) {
+        status = FwdLockConv_Status_InvalidArgument;
+    } else {
+        FwdLockConv_Session_t *pSession = sessionPtrs[sessionId];
+        free(pOutput->fromConvertData.pBuffer);
+        if (pSession->parserState != FwdLockConv_ParserState_Done) {
+            pOutput->fromCloseSession.errorPos = pSession->numCharsConsumed;
+            status = FwdLockConv_Status_SyntaxError;
+        } else {
+            // Finalize the data signature.
+            size_t signatureSize;
+            HMAC_Final(&pSession->signingContext, pOutput->fromCloseSession.signatures,
+                       &signatureSize);
+            if (signatureSize != SHA1_HASH_SIZE) {
+                status = FwdLockConv_Status_ProgramError;
+            } else {
+                // Calculate the header signature, which is a signature of the rest of the header
+                // including the data signature.
+                HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL);
+                HMAC_Update(&pSession->signingContext, pSession->topHeader, TOP_HEADER_SIZE);
+                HMAC_Update(&pSession->signingContext, (unsigned char *)pSession->contentType.ptr,
+                            pSession->contentType.length);
+                HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey,
+                            pSession->encryptedSessionKeyLength);
+                HMAC_Update(&pSession->signingContext, pOutput->fromCloseSession.signatures,
+                            signatureSize);
+                HMAC_Final(&pSession->signingContext, &pOutput->fromCloseSession.
+                           signatures[signatureSize], &signatureSize);
+                if (signatureSize != SHA1_HASH_SIZE) {
+                    status = FwdLockConv_Status_ProgramError;
+                } else {
+                    pOutput->fromCloseSession.fileOffset = TOP_HEADER_SIZE +
+                            pSession->contentType.length + pSession->encryptedSessionKeyLength;
+                    status = FwdLockConv_Status_OK;
+                }
+            }
+            pOutput->fromCloseSession.errorPos = INVALID_OFFSET;
+        }
+        free(pSession->mimeHeaderName.ptr);
+        free(pSession->contentType.ptr);
+        free(pSession->pEncryptedSessionKey);
+        HMAC_CTX_cleanup(&pSession->signingContext);
+        FwdLockConv_ReleaseSession(sessionId);
+    }
+    return status;
+}
+
+FwdLockConv_Status_t FwdLockConv_ConvertOpenFile(int inputFileDesc,
+                                                 FwdLockConv_ReadFunc_t *fpReadFunc,
+                                                 int outputFileDesc,
+                                                 FwdLockConv_WriteFunc_t *fpWriteFunc,
+                                                 FwdLockConv_LSeekFunc_t *fpLSeekFunc,
+                                                 off64_t *pErrorPos) {
+    FwdLockConv_Status_t status;
+    if (pErrorPos != NULL) {
+        *pErrorPos = INVALID_OFFSET;
+    }
+    if (fpReadFunc == NULL || fpWriteFunc == NULL || fpLSeekFunc == NULL || inputFileDesc < 0 ||
+        outputFileDesc < 0) {
+        status = FwdLockConv_Status_InvalidArgument;
+    } else {
+        char *pReadBuffer = malloc(READ_BUFFER_SIZE);
+        if (pReadBuffer == NULL) {
+            status = FwdLockConv_Status_OutOfMemory;
+        } else {
+            int sessionId;
+            FwdLockConv_Output_t output;
+            status = FwdLockConv_OpenSession(&sessionId, &output);
+            if (status == FwdLockConv_Status_OK) {
+                ssize_t numBytesRead;
+                FwdLockConv_Status_t closeStatus;
+                while ((numBytesRead =
+                        fpReadFunc(inputFileDesc, pReadBuffer, READ_BUFFER_SIZE)) > 0) {
+                    status = FwdLockConv_ConvertData(sessionId, pReadBuffer, (size_t)numBytesRead,
+                                                     &output);
+                    if (status == FwdLockConv_Status_OK) {
+                        if (output.fromConvertData.pBuffer != NULL &&
+                            output.fromConvertData.numBytes > 0) {
+                            ssize_t numBytesWritten = fpWriteFunc(outputFileDesc,
+                                                                  output.fromConvertData.pBuffer,
+                                                                  output.fromConvertData.numBytes);
+                            if (numBytesWritten != (ssize_t)output.fromConvertData.numBytes) {
+                                status = FwdLockConv_Status_FileWriteError;
+                                break;
+                            }
+                        }
+                    } else {
+                        if (status == FwdLockConv_Status_SyntaxError && pErrorPos != NULL) {
+                            *pErrorPos = output.fromConvertData.errorPos;
+                        }
+                        break;
+                    }
+                } // end while
+                if (numBytesRead < 0) {
+                    status = FwdLockConv_Status_FileReadError;
+                }
+                closeStatus = FwdLockConv_CloseSession(sessionId, &output);
+                if (status == FwdLockConv_Status_OK) {
+                    if (closeStatus != FwdLockConv_Status_OK) {
+                        if (closeStatus == FwdLockConv_Status_SyntaxError && pErrorPos != NULL) {
+                            *pErrorPos = output.fromCloseSession.errorPos;
+                        }
+                        status = closeStatus;
+                    } else if (fpLSeekFunc(outputFileDesc, output.fromCloseSession.fileOffset,
+                                           SEEK_SET) < 0) {
+                        status = FwdLockConv_Status_FileSeekError;
+                    } else if (fpWriteFunc(outputFileDesc, output.fromCloseSession.signatures,
+                                           FWD_LOCK_SIGNATURES_SIZE) != FWD_LOCK_SIGNATURES_SIZE) {
+                        status = FwdLockConv_Status_FileWriteError;
+                    }
+                }
+            }
+            free(pReadBuffer);
+        }
+    }
+    return status;
+}
+
+FwdLockConv_Status_t FwdLockConv_ConvertFile(const char *pInputFilename,
+                                             const char *pOutputFilename,
+                                             off64_t *pErrorPos) {
+    FwdLockConv_Status_t status;
+    if (pErrorPos != NULL) {
+        *pErrorPos = INVALID_OFFSET;
+    }
+    if (pInputFilename == NULL || pOutputFilename == NULL) {
+        status = FwdLockConv_Status_InvalidArgument;
+    } else {
+        int inputFileDesc = open(pInputFilename, O_RDONLY);
+        if (inputFileDesc < 0) {
+            status = FwdLockConv_Status_FileNotFound;
+        } else {
+            int outputFileDesc = open(pOutputFilename, O_CREAT | O_TRUNC | O_WRONLY,
+                                      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+            if (outputFileDesc < 0) {
+                status = FwdLockConv_Status_FileCreationFailed;
+            } else {
+                status = FwdLockConv_ConvertOpenFile(inputFileDesc, read, outputFileDesc, write,
+                                                     lseek64, pErrorPos);
+                if (close(outputFileDesc) == 0 && status != FwdLockConv_Status_OK) {
+                    remove(pOutputFilename);
+                }
+            }
+            (void)close(inputFileDesc);
+        }
+    }
+    return status;
+}
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h
new file mode 100644
index 0000000..e20c0c3
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __FWDLOCKCONV_H__
+#define __FWDLOCKCONV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+/**
+ * The size of the data and header signatures combined. The signatures are adjacent to each other in
+ * the produced output file.
+ */
+#define FWD_LOCK_SIGNATURES_SIZE (2 * 20)
+
+/**
+ * Data type for the output from FwdLockConv_ConvertData.
+ */
+typedef struct FwdLockConv_ConvertData_Output {
+    /// The converted data.
+    void *pBuffer;
+
+    /// The size of the converted data.
+    size_t numBytes;
+
+    /// The file position where the error occurred, in the case of a syntax error.
+    off64_t errorPos;
+} FwdLockConv_ConvertData_Output_t;
+
+/**
+ * Data type for the output from FwdLockConv_CloseSession.
+ */
+typedef struct FwdLockConv_CloseSession_Output {
+    /// The final set of signatures.
+    unsigned char signatures[FWD_LOCK_SIGNATURES_SIZE];
+
+    /// The offset in the produced output file where the signatures are located.
+    off64_t fileOffset;
+
+    /// The file position where the error occurred, in the case of a syntax error.
+    off64_t errorPos;
+} FwdLockConv_CloseSession_Output_t;
+
+/**
+ * Data type for the output from the conversion process.
+ */
+typedef union FwdLockConv_Output {
+    FwdLockConv_ConvertData_Output_t fromConvertData;
+    FwdLockConv_CloseSession_Output_t fromCloseSession;
+} FwdLockConv_Output_t;
+
+/**
+ * Data type for the Posix-style read function used by the converter in pull mode.
+ *
+ * @param[in] fileDesc The file descriptor of a file opened for reading.
+ * @param[out] pBuffer A reference to the buffer that should receive the read data.
+ * @param[in] numBytes The number of bytes to read.
+ *
+ * @return The number of bytes read.
+ * @retval -1 Failure.
+ */
+typedef ssize_t FwdLockConv_ReadFunc_t(int fileDesc, void *pBuffer, size_t numBytes);
+
+/**
+ * Data type for the Posix-style write function used by the converter in pull mode.
+ *
+ * @param[in] fileDesc The file descriptor of a file opened for writing.
+ * @param[in] pBuffer A reference to the buffer containing the data to be written.
+ * @param[in] numBytes The number of bytes to write.
+ *
+ * @return The number of bytes written.
+ * @retval -1 Failure.
+ */
+typedef ssize_t FwdLockConv_WriteFunc_t(int fileDesc, const void *pBuffer, size_t numBytes);
+
+/**
+ * Data type for the Posix-style lseek function used by the converter in pull mode.
+ *
+ * @param[in] fileDesc The file descriptor of a file opened for writing.
+ * @param[in] offset The offset with which to update the file position.
+ * @param[in] whence One of SEEK_SET, SEEK_CUR, and SEEK_END.
+ *
+ * @return The new file position.
+ * @retval ((off64_t)-1) Failure.
+ */
+typedef off64_t FwdLockConv_LSeekFunc_t(int fileDesc, off64_t offset, int whence);
+
+/**
+ * The status codes returned by the converter functions.
+ */
+typedef enum FwdLockConv_Status {
+    /// The operation was successful.
+    FwdLockConv_Status_OK = 0,
+
+    /// An actual argument to the function is invalid (a program error on the caller's part).
+    FwdLockConv_Status_InvalidArgument = 1,
+
+    /// There is not enough free dynamic memory to complete the operation.
+    FwdLockConv_Status_OutOfMemory = 2,
+
+    /// An error occurred while opening the input file.
+    FwdLockConv_Status_FileNotFound = 3,
+
+    /// An error occurred while creating the output file.
+    FwdLockConv_Status_FileCreationFailed = 4,
+
+    /// An error occurred while reading from the input file.
+    FwdLockConv_Status_FileReadError = 5,
+
+    /// An error occurred while writing to the output file.
+    FwdLockConv_Status_FileWriteError = 6,
+
+    /// An error occurred while seeking to a new file position within the output file.
+    FwdLockConv_Status_FileSeekError = 7,
+
+    /// The input file is not a syntactically correct OMA DRM v1 Forward Lock file.
+    FwdLockConv_Status_SyntaxError = 8,
+
+    /// Support for this DRM file format has been disabled in the current product configuration.
+    FwdLockConv_Status_UnsupportedFileFormat = 9,
+
+    /// The content transfer encoding is not one of "binary", "base64", "7bit", or "8bit"
+    /// (case-insensitive).
+    FwdLockConv_Status_UnsupportedContentTransferEncoding = 10,
+
+    /// The generation of a random number failed.
+    FwdLockConv_Status_RandomNumberGenerationFailed = 11,
+
+    /// Key encryption failed.
+    FwdLockConv_Status_KeyEncryptionFailed = 12,
+
+    /// The calculation of a keyed hash for integrity protection failed.
+    FwdLockConv_Status_IntegrityProtectionFailed = 13,
+
+    /// There are too many ongoing sessions for another one to be opened.
+    FwdLockConv_Status_TooManySessions = 14,
+
+    /// An unexpected error occurred.
+    FwdLockConv_Status_ProgramError = 15
+} FwdLockConv_Status_t;
+
+/**
+ * Opens a session for converting an OMA DRM v1 Forward Lock file to the internal Forward Lock file
+ * format.
+ *
+ * @param[out] pSessionId The session ID.
+ * @param[out] pOutput The output from the conversion process (initialized).
+ *
+ * @return A status code.
+ * @retval FwdLockConv_Status_OK
+ * @retval FwdLockConv_Status_InvalidArgument
+ * @retval FwdLockConv_Status_TooManySessions
+ */
+FwdLockConv_Status_t FwdLockConv_OpenSession(int *pSessionId, FwdLockConv_Output_t *pOutput);
+
+/**
+ * Supplies the converter with data to convert. The caller is expected to write the converted data
+ * to file. Can be called an arbitrary number of times.
+ *
+ * @param[in] sessionId The session ID.
+ * @param[in] pBuffer A reference to a buffer containing the data to convert.
+ * @param[in] numBytes The number of bytes to convert.
+ * @param[in,out] pOutput The output from the conversion process (allocated/reallocated).
+ *
+ * @return A status code.
+ * @retval FwdLockConv_Status_OK
+ * @retval FwdLockConv_Status_InvalidArgument
+ * @retval FwdLockConv_Status_OutOfMemory
+ * @retval FwdLockConv_Status_SyntaxError
+ * @retval FwdLockConv_Status_UnsupportedFileFormat
+ * @retval FwdLockConv_Status_UnsupportedContentTransferEncoding
+ * @retval FwdLockConv_Status_RandomNumberGenerationFailed
+ * @retval FwdLockConv_Status_KeyEncryptionFailed
+ * @retval FwdLockConv_Status_DataEncryptionFailed
+ */
+FwdLockConv_Status_t FwdLockConv_ConvertData(int sessionId,
+                                             const void *pBuffer,
+                                             size_t numBytes,
+                                             FwdLockConv_Output_t *pOutput);
+
+/**
+ * Closes a session for converting an OMA DRM v1 Forward Lock file to the internal Forward Lock
+ * file format. The caller must update the produced output file at the indicated file offset with
+ * the final set of signatures.
+ *
+ * @param[in] sessionId The session ID.
+ * @param[in,out] pOutput The output from the conversion process (deallocated and overwritten).
+ *
+ * @return A status code.
+ * @retval FwdLockConv_Status_OK
+ * @retval FwdLockConv_Status_InvalidArgument
+ * @retval FwdLockConv_Status_OutOfMemory
+ * @retval FwdLockConv_Status_IntegrityProtectionFailed
+ */
+FwdLockConv_Status_t FwdLockConv_CloseSession(int sessionId, FwdLockConv_Output_t *pOutput);
+
+/**
+ * Converts an open OMA DRM v1 Forward Lock file to the internal Forward Lock file format in pull
+ * mode.
+ *
+ * @param[in] inputFileDesc The file descriptor of the open input file.
+ * @param[in] fpReadFunc A reference to a read function that can operate on the open input file.
+ * @param[in] outputFileDesc The file descriptor of the open output file.
+ * @param[in] fpWriteFunc A reference to a write function that can operate on the open output file.
+ * @param[in] fpLSeekFunc A reference to an lseek function that can operate on the open output file.
+ * @param[out] pErrorPos
+ *   The file position where the error occurred, in the case of a syntax error. May be NULL.
+ *
+ * @return A status code.
+ * @retval FwdLockConv_Status_OK
+ * @retval FwdLockConv_Status_InvalidArgument
+ * @retval FwdLockConv_Status_OutOfMemory
+ * @retval FwdLockConv_Status_FileReadError
+ * @retval FwdLockConv_Status_FileWriteError
+ * @retval FwdLockConv_Status_FileSeekError
+ * @retval FwdLockConv_Status_SyntaxError
+ * @retval FwdLockConv_Status_UnsupportedFileFormat
+ * @retval FwdLockConv_Status_UnsupportedContentTransferEncoding
+ * @retval FwdLockConv_Status_RandomNumberGenerationFailed
+ * @retval FwdLockConv_Status_KeyEncryptionFailed
+ * @retval FwdLockConv_Status_DataEncryptionFailed
+ * @retval FwdLockConv_Status_IntegrityProtectionFailed
+ * @retval FwdLockConv_Status_TooManySessions
+ */
+FwdLockConv_Status_t FwdLockConv_ConvertOpenFile(int inputFileDesc,
+                                                 FwdLockConv_ReadFunc_t *fpReadFunc,
+                                                 int outputFileDesc,
+                                                 FwdLockConv_WriteFunc_t *fpWriteFunc,
+                                                 FwdLockConv_LSeekFunc_t *fpLSeekFunc,
+                                                 off64_t *pErrorPos);
+
+/**
+ * Converts an OMA DRM v1 Forward Lock file to the internal Forward Lock file format in pull mode.
+ *
+ * @param[in] pInputFilename A reference to the input filename.
+ * @param[in] pOutputFilename A reference to the output filename.
+ * @param[out] pErrorPos
+ *   The file position where the error occurred, in the case of a syntax error. May be NULL.
+ *
+ * @return A status code.
+ * @retval FwdLockConv_Status_OK
+ * @retval FwdLockConv_Status_InvalidArgument
+ * @retval FwdLockConv_Status_OutOfMemory
+ * @retval FwdLockConv_Status_FileNotFound
+ * @retval FwdLockConv_Status_FileCreationFailed
+ * @retval FwdLockConv_Status_FileReadError
+ * @retval FwdLockConv_Status_FileWriteError
+ * @retval FwdLockConv_Status_FileSeekError
+ * @retval FwdLockConv_Status_SyntaxError
+ * @retval FwdLockConv_Status_UnsupportedFileFormat
+ * @retval FwdLockConv_Status_UnsupportedContentTransferEncoding
+ * @retval FwdLockConv_Status_RandomNumberGenerationFailed
+ * @retval FwdLockConv_Status_KeyEncryptionFailed
+ * @retval FwdLockConv_Status_DataEncryptionFailed
+ * @retval FwdLockConv_Status_IntegrityProtectionFailed
+ * @retval FwdLockConv_Status_TooManySessions
+ */
+FwdLockConv_Status_t FwdLockConv_ConvertFile(const char *pInputFilename,
+                                             const char *pOutputFilename,
+                                             off64_t *pErrorPos);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __FWDLOCKCONV_H__
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
new file mode 100644
index 0000000..b625edf
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    FwdLockFile.c
+
+LOCAL_C_INCLUDES := \
+    frameworks/base/drm/libdrmframework/plugins/forward-lock/internal-format/common \
+    external/openssl/include
+
+LOCAL_SHARED_LIBRARIES := libcrypto
+
+LOCAL_WHOLE_STATIC_LIBRARIES := libfwdlock-common
+
+LOCAL_STATIC_LIBRARIES := libfwdlock-common
+
+LOCAL_MODULE := libfwdlock-decoder
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c
new file mode 100644
index 0000000..98284e72
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <openssl/aes.h>
+#include <openssl/hmac.h>
+
+#include "FwdLockFile.h"
+#include "FwdLockGlue.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define INVALID_OFFSET ((off64_t)-1)
+
+#define INVALID_BLOCK_INDEX ((uint64_t)-1)
+
+#define MAX_NUM_SESSIONS 128
+
+#define KEY_SIZE AES_BLOCK_SIZE
+#define KEY_SIZE_IN_BITS (KEY_SIZE * 8)
+
+#define SHA1_HASH_SIZE 20
+#define SHA1_BLOCK_SIZE 64
+
+#define FWD_LOCK_VERSION 0
+#define FWD_LOCK_SUBFORMAT 0
+#define USAGE_RESTRICTION_FLAGS 0
+#define CONTENT_TYPE_LENGTH_POS 7
+#define TOP_HEADER_SIZE 8
+
+#define SIG_CALC_BUFFER_SIZE (16 * SHA1_BLOCK_SIZE)
+
+/**
+ * Data type for the per-file state information needed by the decoder.
+ */
+typedef struct FwdLockFile_Session {
+    int fileDesc;
+    unsigned char topHeader[TOP_HEADER_SIZE];
+    char *pContentType;
+    size_t contentTypeLength;
+    void *pEncryptedSessionKey;
+    size_t encryptedSessionKeyLength;
+    unsigned char dataSignature[SHA1_HASH_SIZE];
+    unsigned char headerSignature[SHA1_HASH_SIZE];
+    off64_t dataOffset;
+    off64_t filePos;
+    AES_KEY encryptionRoundKeys;
+    HMAC_CTX signingContext;
+    unsigned char keyStream[AES_BLOCK_SIZE];
+    uint64_t blockIndex;
+} FwdLockFile_Session_t;
+
+static FwdLockFile_Session_t *sessionPtrs[MAX_NUM_SESSIONS] = { NULL };
+
+static pthread_mutex_t sessionAcquisitionMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static const unsigned char topHeaderTemplate[] =
+    { 'F', 'W', 'L', 'K', FWD_LOCK_VERSION, FWD_LOCK_SUBFORMAT, USAGE_RESTRICTION_FLAGS };
+
+/**
+ * Acquires an unused file session for the given file descriptor.
+ *
+ * @param[in] fileDesc A file descriptor.
+ *
+ * @return A session ID.
+ */
+static int FwdLockFile_AcquireSession(int fileDesc) {
+    int sessionId = -1;
+    if (fileDesc < 0) {
+        errno = EBADF;
+    } else {
+        int i;
+        pthread_mutex_lock(&sessionAcquisitionMutex);
+        for (i = 0; i < MAX_NUM_SESSIONS; ++i) {
+            int candidateSessionId = (fileDesc + i) % MAX_NUM_SESSIONS;
+            if (sessionPtrs[candidateSessionId] == NULL) {
+                sessionPtrs[candidateSessionId] = malloc(sizeof **sessionPtrs);
+                if (sessionPtrs[candidateSessionId] != NULL) {
+                    sessionPtrs[candidateSessionId]->fileDesc = fileDesc;
+                    sessionPtrs[candidateSessionId]->pContentType = NULL;
+                    sessionPtrs[candidateSessionId]->pEncryptedSessionKey = NULL;
+                    sessionId = candidateSessionId;
+                }
+                break;
+            }
+        }
+        pthread_mutex_unlock(&sessionAcquisitionMutex);
+        if (i == MAX_NUM_SESSIONS) {
+            errno = ENFILE;
+        }
+    }
+    return sessionId;
+}
+
+/**
+ * Finds the file session associated to the given file descriptor.
+ *
+ * @param[in] fileDesc A file descriptor.
+ *
+ * @return A session ID.
+ */
+static int FwdLockFile_FindSession(int fileDesc) {
+    int sessionId = -1;
+    if (fileDesc < 0) {
+        errno = EBADF;
+    } else {
+        int i;
+        pthread_mutex_lock(&sessionAcquisitionMutex);
+        for (i = 0; i < MAX_NUM_SESSIONS; ++i) {
+            int candidateSessionId = (fileDesc + i) % MAX_NUM_SESSIONS;
+            if (sessionPtrs[candidateSessionId] != NULL &&
+                sessionPtrs[candidateSessionId]->fileDesc == fileDesc) {
+                sessionId = candidateSessionId;
+                break;
+            }
+        }
+        pthread_mutex_unlock(&sessionAcquisitionMutex);
+        if (i == MAX_NUM_SESSIONS) {
+            errno = EBADF;
+        }
+    }
+    return sessionId;
+}
+
+/**
+ * Releases a file session.
+ *
+ * @param[in] sessionID A session ID.
+ */
+static void FwdLockFile_ReleaseSession(int sessionId) {
+    pthread_mutex_lock(&sessionAcquisitionMutex);
+    assert(0 <= sessionId && sessionId < MAX_NUM_SESSIONS && sessionPtrs[sessionId] != NULL);
+    free(sessionPtrs[sessionId]->pContentType);
+    free(sessionPtrs[sessionId]->pEncryptedSessionKey);
+    memset(sessionPtrs[sessionId], 0, sizeof *sessionPtrs[sessionId]); // Zero out key data.
+    free(sessionPtrs[sessionId]);
+    sessionPtrs[sessionId] = NULL;
+    pthread_mutex_unlock(&sessionAcquisitionMutex);
+}
+
+/**
+ * Derives keys for encryption and signing from the encrypted session key.
+ *
+ * @param[in,out] pSession A reference to a file session.
+ *
+ * @return A Boolean value indicating whether key derivation was successful.
+ */
+static int FwdLockFile_DeriveKeys(FwdLockFile_Session_t * pSession) {
+    int result;
+    struct FwdLockFile_DeriveKeys_Data {
+        AES_KEY sessionRoundKeys;
+        unsigned char value[KEY_SIZE];
+        unsigned char key[KEY_SIZE];
+    } *pData = malloc(sizeof *pData);
+    if (pData == NULL) {
+        result = FALSE;
+    } else {
+        result = FwdLockGlue_DecryptKey(pSession->pEncryptedSessionKey,
+                                        pSession->encryptedSessionKeyLength, pData->key, KEY_SIZE);
+        if (result) {
+            if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS, &pData->sessionRoundKeys) != 0) {
+                result = FALSE;
+            } else {
+                // Encrypt the 16-byte value {0, 0, ..., 0} to produce the encryption key.
+                memset(pData->value, 0, KEY_SIZE);
+                AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys);
+                if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS,
+                                        &pSession->encryptionRoundKeys) != 0) {
+                    result = FALSE;
+                } else {
+                    // Encrypt the 16-byte value {1, 0, ..., 0} to produce the signing key.
+                    ++pData->value[0];
+                    AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys);
+                    HMAC_CTX_init(&pSession->signingContext);
+                    HMAC_Init_ex(&pSession->signingContext, pData->key, KEY_SIZE, EVP_sha1(), NULL);
+                }
+            }
+        }
+        if (!result) {
+            errno = ENOSYS;
+        }
+        memset(pData, 0, sizeof pData); // Zero out key data.
+        free(pData);
+    }
+    return result;
+}
+
+/**
+ * Calculates the counter, treated as a 16-byte little-endian number, used to generate the keystream
+ * for the given block.
+ *
+ * @param[in] pNonce A reference to the nonce.
+ * @param[in] blockIndex The index number of the block.
+ * @param[out] pCounter A reference to the counter.
+ */
+static void FwdLockFile_CalculateCounter(const unsigned char *pNonce,
+                                         uint64_t blockIndex,
+                                         unsigned char *pCounter) {
+    unsigned char carry = 0;
+    size_t i = 0;
+    for (; i < sizeof blockIndex; ++i) {
+        unsigned char part = pNonce[i] + (unsigned char)(blockIndex >> (i * CHAR_BIT));
+        pCounter[i] = part + carry;
+        carry = (part < pNonce[i] || pCounter[i] < part) ? 1 : 0;
+    }
+    for (; i < AES_BLOCK_SIZE; ++i) {
+        pCounter[i] = pNonce[i] + carry;
+        carry = (pCounter[i] < pNonce[i]) ? 1 : 0;
+    }
+}
+
+/**
+ * Decrypts the byte at the current file position using AES-128-CTR. In CTR (or "counter") mode,
+ * encryption and decryption are performed using the same algorithm.
+ *
+ * @param[in,out] pSession A reference to a file session.
+ * @param[in] pByte The byte to decrypt.
+ */
+void FwdLockFile_DecryptByte(FwdLockFile_Session_t * pSession, unsigned char *pByte) {
+    uint64_t blockIndex = pSession->filePos / AES_BLOCK_SIZE;
+    uint64_t blockOffset = pSession->filePos % AES_BLOCK_SIZE;
+    if (blockIndex != pSession->blockIndex) {
+        // The first 16 bytes of the encrypted session key is used as the nonce.
+        unsigned char counter[AES_BLOCK_SIZE];
+        FwdLockFile_CalculateCounter(pSession->pEncryptedSessionKey, blockIndex, counter);
+        AES_encrypt(counter, pSession->keyStream, &pSession->encryptionRoundKeys);
+        pSession->blockIndex = blockIndex;
+    }
+    *pByte ^= pSession->keyStream[blockOffset];
+}
+
+int FwdLockFile_attach(int fileDesc) {
+    int sessionId = FwdLockFile_AcquireSession(fileDesc);
+    if (sessionId >= 0) {
+        FwdLockFile_Session_t *pSession = sessionPtrs[sessionId];
+        int isSuccess = FALSE;
+        if (read(fileDesc, pSession->topHeader, TOP_HEADER_SIZE) == TOP_HEADER_SIZE &&
+                memcmp(pSession->topHeader, topHeaderTemplate, sizeof topHeaderTemplate) == 0) {
+            pSession->contentTypeLength = pSession->topHeader[CONTENT_TYPE_LENGTH_POS];
+            assert(pSession->contentTypeLength <= UCHAR_MAX); // Untaint scalar for code checkers.
+            pSession->pContentType = malloc(pSession->contentTypeLength + 1);
+            if (pSession->pContentType != NULL &&
+                    read(fileDesc, pSession->pContentType, pSession->contentTypeLength) ==
+                            (ssize_t)pSession->contentTypeLength) {
+                pSession->pContentType[pSession->contentTypeLength] = '\0';
+                pSession->encryptedSessionKeyLength = FwdLockGlue_GetEncryptedKeyLength(KEY_SIZE);
+                pSession->pEncryptedSessionKey = malloc(pSession->encryptedSessionKeyLength);
+                if (pSession->pEncryptedSessionKey != NULL &&
+                        read(fileDesc, pSession->pEncryptedSessionKey,
+                             pSession->encryptedSessionKeyLength) ==
+                                (ssize_t)pSession->encryptedSessionKeyLength &&
+                        read(fileDesc, pSession->dataSignature, SHA1_HASH_SIZE) ==
+                                SHA1_HASH_SIZE &&
+                        read(fileDesc, pSession->headerSignature, SHA1_HASH_SIZE) ==
+                                SHA1_HASH_SIZE) {
+                    isSuccess = FwdLockFile_DeriveKeys(pSession);
+                }
+            }
+        }
+        if (isSuccess) {
+            pSession->dataOffset = pSession->contentTypeLength +
+                    pSession->encryptedSessionKeyLength + TOP_HEADER_SIZE + 2 * SHA1_HASH_SIZE;
+            pSession->filePos = 0;
+            pSession->blockIndex = INVALID_BLOCK_INDEX;
+        } else {
+            FwdLockFile_ReleaseSession(sessionId);
+            sessionId = -1;
+        }
+    }
+    return (sessionId >= 0) ? 0 : -1;
+}
+
+int FwdLockFile_open(const char *pFilename) {
+    int fileDesc = open(pFilename, O_RDONLY);
+    if (fileDesc >= 0 && FwdLockFile_attach(fileDesc) < 0) {
+        (void)close(fileDesc);
+        fileDesc = -1;
+    }
+    return fileDesc;
+}
+
+ssize_t FwdLockFile_read(int fileDesc, void *pBuffer, size_t numBytes) {
+    ssize_t numBytesRead;
+    int sessionId = FwdLockFile_FindSession(fileDesc);
+    if (sessionId < 0) {
+        numBytesRead = -1;
+    } else {
+        FwdLockFile_Session_t *pSession = sessionPtrs[sessionId];
+        ssize_t i;
+        numBytesRead = read(pSession->fileDesc, pBuffer, numBytes);
+        for (i = 0; i < numBytesRead; ++i) {
+            FwdLockFile_DecryptByte(pSession, &((unsigned char *)pBuffer)[i]);
+            ++pSession->filePos;
+        }
+    }
+    return numBytesRead;
+}
+
+off64_t FwdLockFile_lseek(int fileDesc, off64_t offset, int whence) {
+    off64_t newFilePos;
+    int sessionId = FwdLockFile_FindSession(fileDesc);
+    if (sessionId < 0) {
+        newFilePos = INVALID_OFFSET;
+    } else {
+        FwdLockFile_Session_t *pSession = sessionPtrs[sessionId];
+        switch (whence) {
+        case SEEK_SET:
+            newFilePos = lseek64(pSession->fileDesc, pSession->dataOffset + offset, whence);
+            break;
+        case SEEK_CUR:
+        case SEEK_END:
+            newFilePos = lseek64(pSession->fileDesc, offset, whence);
+            break;
+        default:
+            errno = EINVAL;
+            newFilePos = INVALID_OFFSET;
+            break;
+        }
+        if (newFilePos != INVALID_OFFSET) {
+            if (newFilePos < pSession->dataOffset) {
+                // The new file position is illegal for an internal Forward Lock file. Restore the
+                // original file position.
+                (void)lseek64(pSession->fileDesc, pSession->dataOffset + pSession->filePos,
+                              SEEK_SET);
+                errno = EINVAL;
+                newFilePos = INVALID_OFFSET;
+            } else {
+                // The return value should be the file position that lseek64() would have returned
+                // for the embedded content file.
+                pSession->filePos = newFilePos - pSession->dataOffset;
+                newFilePos = pSession->filePos;
+            }
+        }
+    }
+    return newFilePos;
+}
+
+int FwdLockFile_detach(int fileDesc) {
+    int sessionId = FwdLockFile_FindSession(fileDesc);
+    if (sessionId < 0) {
+        return -1;
+    }
+    HMAC_CTX_cleanup(&sessionPtrs[sessionId]->signingContext);
+    FwdLockFile_ReleaseSession(sessionId);
+    return 0;
+}
+
+int FwdLockFile_close(int fileDesc) {
+    return (FwdLockFile_detach(fileDesc) == 0) ? close(fileDesc) : -1;
+}
+
+int FwdLockFile_CheckDataIntegrity(int fileDesc) {
+    int result;
+    int sessionId = FwdLockFile_FindSession(fileDesc);
+    if (sessionId < 0) {
+        result = FALSE;
+    } else {
+        struct FwdLockFile_CheckDataIntegrity_Data {
+            unsigned char signature[SHA1_HASH_SIZE];
+            unsigned char buffer[SIG_CALC_BUFFER_SIZE];
+        } *pData = malloc(sizeof *pData);
+        if (pData == NULL) {
+            result = FALSE;
+        } else {
+            FwdLockFile_Session_t *pSession = sessionPtrs[sessionId];
+            if (lseek64(pSession->fileDesc, pSession->dataOffset, SEEK_SET) !=
+                    pSession->dataOffset) {
+                result = FALSE;
+            } else {
+                ssize_t numBytesRead;
+                size_t signatureSize = SHA1_HASH_SIZE;
+                while ((numBytesRead =
+                        read(pSession->fileDesc, pData->buffer, SIG_CALC_BUFFER_SIZE)) > 0) {
+                    HMAC_Update(&pSession->signingContext, pData->buffer, (size_t)numBytesRead);
+                }
+                if (numBytesRead < 0) {
+                    result = FALSE;
+                } else {
+                    HMAC_Final(&pSession->signingContext, pData->signature, &signatureSize);
+                    assert(signatureSize == SHA1_HASH_SIZE);
+                    result = memcmp(pData->signature, pSession->dataSignature, signatureSize) == 0;
+                }
+                HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL);
+                (void)lseek64(pSession->fileDesc, pSession->dataOffset + pSession->filePos,
+                              SEEK_SET);
+            }
+            free(pData);
+        }
+    }
+    return result;
+}
+
+int FwdLockFile_CheckHeaderIntegrity(int fileDesc) {
+    int result;
+    int sessionId = FwdLockFile_FindSession(fileDesc);
+    if (sessionId < 0) {
+        result = FALSE;
+    } else {
+        FwdLockFile_Session_t *pSession = sessionPtrs[sessionId];
+        unsigned char signature[SHA1_HASH_SIZE];
+        size_t signatureSize = SHA1_HASH_SIZE;
+        HMAC_Update(&pSession->signingContext, pSession->topHeader, TOP_HEADER_SIZE);
+        HMAC_Update(&pSession->signingContext, (unsigned char *)pSession->pContentType,
+                    pSession->contentTypeLength);
+        HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey,
+                    pSession->encryptedSessionKeyLength);
+        HMAC_Update(&pSession->signingContext, pSession->dataSignature, signatureSize);
+        HMAC_Final(&pSession->signingContext, signature, &signatureSize);
+        assert(signatureSize == SHA1_HASH_SIZE);
+        result = memcmp(signature, pSession->headerSignature, signatureSize) == 0;
+        HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL);
+    }
+    return result;
+}
+
+int FwdLockFile_CheckIntegrity(int fileDesc) {
+    return FwdLockFile_CheckHeaderIntegrity(fileDesc) && FwdLockFile_CheckDataIntegrity(fileDesc);
+}
+
+const char *FwdLockFile_GetContentType(int fileDesc) {
+    int sessionId = FwdLockFile_FindSession(fileDesc);
+    if (sessionId < 0) {
+        return NULL;
+    }
+    return sessionPtrs[sessionId]->pContentType;
+}
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.h b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.h
new file mode 100644
index 0000000..fc64050
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __FWDLOCKFILE_H__
+#define __FWDLOCKFILE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+/**
+ * Attaches to an open Forward Lock file. The file position is assumed to be at the beginning of the
+ * file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return A status code.
+ * @retval 0 Success.
+ * @retval -1 Failure.
+ */
+int FwdLockFile_attach(int fileDesc);
+
+/**
+ * Opens a Forward Lock file for reading.
+ *
+ * @param[in] pFilename A reference to a filename.
+ *
+ * @return A file descriptor.
+ * @retval -1 Failure.
+ */
+int FwdLockFile_open(const char *pFilename);
+
+/**
+ * Reads the specified number of bytes from an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ * @param[out] pBuffer A reference to the buffer that should receive the read data.
+ * @param[in] numBytes The number of bytes to read.
+ *
+ * @return The number of bytes read.
+ * @retval -1 Failure.
+ */
+ssize_t FwdLockFile_read(int fileDesc, void *pBuffer, size_t numBytes);
+
+/**
+ * Updates the file position within an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ * @param[in] offset The offset with which to update the file position.
+ * @param[in] whence One of SEEK_SET, SEEK_CUR, and SEEK_END.
+ *
+ * @return The new file position.
+ * @retval ((off64_t)-1) Failure.
+ */
+off64_t FwdLockFile_lseek(int fileDesc, off64_t offset, int whence);
+
+/**
+ * Detaches from an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return A status code.
+ * @retval 0 Success.
+ * @retval -1 Failure.
+ */
+int FwdLockFile_detach(int fileDesc);
+
+/**
+ * Closes an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return A status code.
+ * @retval 0 Success.
+ * @retval -1 Failure.
+ */
+int FwdLockFile_close(int fileDesc);
+
+/**
+ * Checks the data integrity of an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return A Boolean value indicating whether the integrity check was successful.
+ */
+int FwdLockFile_CheckDataIntegrity(int fileDesc);
+
+/**
+ * Checks the header integrity of an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return A Boolean value indicating whether the integrity check was successful.
+ */
+int FwdLockFile_CheckHeaderIntegrity(int fileDesc);
+
+/**
+ * Checks both the data and header integrity of an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return A Boolean value indicating whether the integrity check was successful.
+ */
+int FwdLockFile_CheckIntegrity(int fileDesc);
+
+/**
+ * Returns the content type of an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return
+ *   A reference to the content type. The reference remains valid as long as the file is kept open.
+ */
+const char *FwdLockFile_GetContentType(int fileDesc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __FWDLOCKFILE_H__
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html
new file mode 100755
index 0000000..8f95cd2
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html
@@ -0,0 +1,1039 @@
+<html>
+
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
+<meta name=Generator content="Microsoft Word 12 (filtered)">
+<title>Forward Lock Converter and Decoder</title>
+<style>
+<!--
+ /* Font Definitions */
+ @font-face
+	{font-family:SimSun;
+	panose-1:2 1 6 0 3 1 1 1 1 1;}
+@font-face
+	{font-family:"Cambria Math";
+	panose-1:2 4 5 3 5 4 6 3 2 4;}
+@font-face
+	{font-family:Tahoma;
+	panose-1:2 11 6 4 3 5 4 4 2 4;}
+@font-face
+	{font-family:"Lucida Console","DejaVu Sans Mono";
+	panose-1:2 11 6 9 4 5 4 2 2 4;}
+@font-face
+	{font-family:"\@SimSun";
+	panose-1:2 1 6 0 3 1 1 1 1 1;}
+ /* Style Definitions */
+ p.MsoNormal, li.MsoNormal, div.MsoNormal
+	{margin:0cm;
+	margin-bottom:.0001pt;
+	font-size:12.0pt;
+	font-family:"Times New Roman","serif";}
+h1
+	{margin-right:0cm;
+	margin-left:21.6pt;
+	text-indent:-21.6pt;
+	page-break-after:avoid;
+	font-size:16.0pt;
+	font-family:"Arial","sans-serif";}
+h2
+	{margin-top:12.0pt;
+	margin-right:0cm;
+	margin-bottom:3.0pt;
+	margin-left:28.8pt;
+	text-indent:-28.8pt;
+	page-break-after:avoid;
+	font-size:14.0pt;
+	font-family:"Arial","sans-serif";
+	font-style:italic;}
+h3
+	{margin-top:12.0pt;
+	margin-right:0cm;
+	margin-bottom:3.0pt;
+	margin-left:36.0pt;
+	text-indent:-36.0pt;
+	page-break-after:avoid;
+	font-size:13.0pt;
+	font-family:"Arial","sans-serif";}
+h4
+	{margin-top:12.0pt;
+	margin-right:0cm;
+	margin-bottom:3.0pt;
+	margin-left:43.2pt;
+	text-indent:-43.2pt;
+	page-break-after:avoid;
+	font-size:14.0pt;
+	font-family:"Times New Roman","serif";}
+h5
+	{margin-top:12.0pt;
+	margin-right:0cm;
+	margin-bottom:3.0pt;
+	margin-left:50.4pt;
+	text-indent:-50.4pt;
+	font-size:13.0pt;
+	font-family:"Times New Roman","serif";
+	font-style:italic;}
+h6
+	{margin-top:12.0pt;
+	margin-right:0cm;
+	margin-bottom:3.0pt;
+	margin-left:57.6pt;
+	text-indent:-57.6pt;
+	font-size:11.0pt;
+	font-family:"Times New Roman","serif";}
+p.MsoHeading7, li.MsoHeading7, div.MsoHeading7
+	{margin-top:12.0pt;
+	margin-right:0cm;
+	margin-bottom:3.0pt;
+	margin-left:64.8pt;
+	text-indent:-64.8pt;
+	font-size:12.0pt;
+	font-family:"Times New Roman","serif";}
+p.MsoHeading8, li.MsoHeading8, div.MsoHeading8
+	{margin-top:12.0pt;
+	margin-right:0cm;
+	margin-bottom:3.0pt;
+	margin-left:72.0pt;
+	text-indent:-72.0pt;
+	font-size:12.0pt;
+	font-family:"Times New Roman","serif";
+	font-style:italic;}
+p.MsoHeading9, li.MsoHeading9, div.MsoHeading9
+	{margin-top:12.0pt;
+	margin-right:0cm;
+	margin-bottom:3.0pt;
+	margin-left:79.2pt;
+	text-indent:-79.2pt;
+	font-size:11.0pt;
+	font-family:"Arial","sans-serif";}
+p.MsoToc1, li.MsoToc1, div.MsoToc1
+	{margin-top:6.0pt;
+	margin-right:0cm;
+	margin-bottom:6.0pt;
+	margin-left:0cm;
+	line-height:150%;
+	font-size:10.5pt;
+	font-family:"Times New Roman","serif";
+	text-transform:uppercase;
+	font-weight:bold;}
+p.MsoToc2, li.MsoToc2, div.MsoToc2
+	{margin-top:0cm;
+	margin-right:0cm;
+	margin-bottom:0cm;
+	margin-left:12.0pt;
+	margin-bottom:.0001pt;
+	line-height:150%;
+	font-size:10.5pt;
+	font-family:"Times New Roman","serif";
+	font-variant:small-caps;}
+p.MsoToc3, li.MsoToc3, div.MsoToc3
+	{margin-top:0cm;
+	margin-right:0cm;
+	margin-bottom:0cm;
+	margin-left:24.0pt;
+	margin-bottom:.0001pt;
+	line-height:150%;
+	font-size:10.5pt;
+	font-family:"Times New Roman","serif";
+	font-style:italic;}
+p.MsoToc4, li.MsoToc4, div.MsoToc4
+	{margin-top:0cm;
+	margin-right:0cm;
+	margin-bottom:0cm;
+	margin-left:36.0pt;
+	margin-bottom:.0001pt;
+	font-size:9.0pt;
+	font-family:"Times New Roman","serif";}
+p.MsoToc5, li.MsoToc5, div.MsoToc5
+	{margin-top:0cm;
+	margin-right:0cm;
+	margin-bottom:0cm;
+	margin-left:48.0pt;
+	margin-bottom:.0001pt;
+	font-size:9.0pt;
+	font-family:"Times New Roman","serif";}
+p.MsoToc6, li.MsoToc6, div.MsoToc6
+	{margin-top:0cm;
+	margin-right:0cm;
+	margin-bottom:0cm;
+	margin-left:60.0pt;
+	margin-bottom:.0001pt;
+	font-size:9.0pt;
+	font-family:"Times New Roman","serif";}
+p.MsoToc7, li.MsoToc7, div.MsoToc7
+	{margin-top:0cm;
+	margin-right:0cm;
+	margin-bottom:0cm;
+	margin-left:72.0pt;
+	margin-bottom:.0001pt;
+	font-size:9.0pt;
+	font-family:"Times New Roman","serif";}
+p.MsoToc8, li.MsoToc8, div.MsoToc8
+	{margin-top:0cm;
+	margin-right:0cm;
+	margin-bottom:0cm;
+	margin-left:84.0pt;
+	margin-bottom:.0001pt;
+	font-size:9.0pt;
+	font-family:"Times New Roman","serif";}
+p.MsoToc9, li.MsoToc9, div.MsoToc9
+	{margin-top:0cm;
+	margin-right:0cm;
+	margin-bottom:0cm;
+	margin-left:96.0pt;
+	margin-bottom:.0001pt;
+	font-size:9.0pt;
+	font-family:"Times New Roman","serif";}
+p.MsoFootnoteText, li.MsoFootnoteText, div.MsoFootnoteText
+	{margin:0cm;
+	margin-bottom:.0001pt;
+	font-size:10.0pt;
+	font-family:"Times New Roman","serif";}
+p.MsoHeader, li.MsoHeader, div.MsoHeader
+	{margin:0cm;
+	margin-bottom:.0001pt;
+	font-size:12.0pt;
+	font-family:"Times New Roman","serif";}
+p.MsoFooter, li.MsoFooter, div.MsoFooter
+	{margin:0cm;
+	margin-bottom:.0001pt;
+	font-size:12.0pt;
+	font-family:"Times New Roman","serif";}
+p.MsoCaption, li.MsoCaption, div.MsoCaption
+	{margin:0cm;
+	margin-bottom:.0001pt;
+	font-size:11.0pt;
+	font-family:"Times New Roman","serif";
+	font-weight:bold;}
+span.MsoFootnoteReference
+	{vertical-align:super;}
+p.MsoTitle, li.MsoTitle, div.MsoTitle
+	{margin-top:12.0pt;
+	margin-right:0cm;
+	margin-bottom:120.0pt;
+	margin-left:0cm;
+	text-align:center;
+	font-size:16.0pt;
+	font-family:"Arial","sans-serif";
+	font-weight:bold;}
+p.MsoBodyText, li.MsoBodyText, div.MsoBodyText
+	{mso-style-link:"Body Text Char";
+	margin-top:0cm;
+	margin-right:0cm;
+	margin-bottom:6.0pt;
+	margin-left:0cm;
+	font-size:12.0pt;
+	font-family:"Times New Roman","serif";}
+a:link, span.MsoHyperlink
+	{color:blue;
+	text-decoration:underline;}
+a:visited, span.MsoHyperlinkFollowed
+	{color:purple;
+	text-decoration:underline;}
+p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
+	{margin:0cm;
+	margin-bottom:.0001pt;
+	font-size:8.0pt;
+	font-family:"Tahoma","sans-serif";}
+span.BodyTextChar
+	{mso-style-name:"Body Text Char";
+	mso-style-link:"Body Text";}
+ /* Page Definitions */
+ @page WordSection1
+	{size:595.45pt 841.7pt;
+	margin:72.0pt 90.0pt 72.0pt 90.0pt;}
+div.WordSection1
+	{page:WordSection1;}
+@page WordSection2
+	{size:595.45pt 841.7pt;
+	margin:72.0pt 90.0pt 72.0pt 90.0pt;}
+div.WordSection2
+	{page:WordSection2;}
+ /* List Definitions */
+ ol
+	{margin-bottom:0cm;}
+ul
+	{margin-bottom:0cm;}
+-->
+</style>
+
+</head>
+
+<body lang=EN-US link=blue vlink=purple>
+
+<div class=WordSection1>
+
+<p class=MsoTitle>Forward Lock Converter And Decoder</p>
+
+<p class=MsoToc1><span
+class=MsoHyperlink><a href="#_Toc276471422">1<span style='font-size:12.0pt;
+line-height:150%;color:windowtext;text-transform:none;font-weight:normal;
+text-decoration:none'>      </span>Introduction<span style='color:windowtext;
+display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>3</span></a></span></p>
+
+<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471423">2<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none;
+font-weight:normal;text-decoration:none'>      </span>Overview<span
+style='color:windowtext;display:none;text-decoration:none'>... </span><span
+style='color:windowtext;display:none;text-decoration:none'>3</span></a></span></p>
+
+<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471424">3<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none;
+font-weight:normal;text-decoration:none'>      </span>Use Cases<span
+style='color:windowtext;display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>4</span></a></span></p>
+
+<p class=MsoToc2><span class=MsoHyperlink><span style='font-variant:normal !important;
+text-transform:uppercase'><a href="#_Toc276471425">3.1<span style='font-size:
+12.0pt;line-height:150%;color:windowtext;text-transform:none;text-decoration:
+none'>        </span>Converter<span style='color:windowtext;display:none;
+text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>4</span></a></span></span></p>
+
+<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471426">3.1.1<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal;
+text-decoration:none'>     </span>Convert Data (Push-Mode Conversion)<span
+style='color:windowtext;display:none;text-decoration:none'> </span><span
+style='color:windowtext;display:none;text-decoration:none'>4</span></a></span></p>
+
+<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471427">3.1.2<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal;
+text-decoration:none'>     </span>Convert File (Pull-Mode Conversion)<span
+style='color:windowtext;display:none;text-decoration:none'> </span><span
+style='color:windowtext;display:none;text-decoration:none'>6</span></a></span></p>
+
+<p class=MsoToc2><span class=MsoHyperlink><span style='font-variant:normal !important;
+text-transform:uppercase'><a href="#_Toc276471428">3.2<span style='font-size:
+12.0pt;line-height:150%;color:windowtext;text-transform:none;text-decoration:
+none'>        </span>Decoder<span style='color:windowtext;display:none;
+text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>7</span></a></span></span></p>
+
+<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471429">3.2.1<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal;
+text-decoration:none'>     </span>Check Integrity<span style='color:windowtext;
+display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>8</span></a></span></p>
+
+<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471430">3.2.2<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal;
+text-decoration:none'>     </span>Get Content Type<span style='color:windowtext;
+display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>9</span></a></span></p>
+
+<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471431">3.2.3<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal;
+text-decoration:none'>     </span>Decode File<span style='color:windowtext;
+display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>10</span></a></span></p>
+
+<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471432">4<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none;
+font-weight:normal;text-decoration:none'>      </span>Definition of the
+Internal Forward Lock File Format<span style='color:windowtext;display:none;
+text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>11</span></a></span></p>
+
+<p class=MsoToc2><span class=MsoHyperlink><span style='font-variant:normal !important;
+text-transform:uppercase'><a href="#_Toc276471433">4.1<span style='font-size:
+12.0pt;line-height:150%;color:windowtext;text-transform:none;text-decoration:
+none'>        </span>Key Derivation<span style='color:windowtext;display:none;
+text-decoration:none'>.. </span><span
+style='color:windowtext;display:none;text-decoration:none'>11</span></a></span></span></p>
+
+<p class=MsoToc2><span class=MsoHyperlink><span style='font-variant:normal !important;
+text-transform:uppercase'><a href="#_Toc276471434">4.2<span style='font-size:
+12.0pt;line-height:150%;color:windowtext;text-transform:none;text-decoration:
+none'>        </span>Calculation of the Counters<span style='color:windowtext;
+display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>12</span></a></span></span></p>
+
+<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471435">5<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none;
+font-weight:normal;text-decoration:none'>      </span>Unit Test Cases<span
+style='color:windowtext;display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>12</span></a></span></p>
+
+<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471436">6<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none;
+font-weight:normal;text-decoration:none'>      </span>References<span
+style='color:windowtext;display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>12</span></a></span></p>
+
+<p class=MsoBodyText></p>
+
+</div>
+
+<span style='font-size:12.0pt;font-family:"Times New Roman","serif"'><br
+clear=all style='page-break-before:right'>
+</span>
+
+<div class=WordSection2>
+
+<h1><a name="_Toc276471422"></a><a name="_Ref263085474">1<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Introduction</a></h1>
+
+<p class=MsoBodyText>The internal Forward Lock file format is used for encrypting
+inherently unencrypted OMA DRM version 1 Forward Lock and Combined Delivery
+files so they can be securely stored on externally accessible file system partitions
+such as memory stick.</p>
+
+<p class=MsoBodyText>Our general strategy is to convert such <i>OMA DRM Message</i>
+(‘.dm’) files to internal Forward Lock (‘.fl’) files as soon as they are
+downloaded or otherwise transferred to the phone, and not actually provide any
+decoders for ‘.dm’ files.</p>
+
+<h1><a name="_Toc276471423">2<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span>Overview</a></h1>
+
+<p class=MsoBodyText>The <i>Forward Lock Converter</i> converts OMA DRM Message
+files to the internal file format. The <i>Forward Lock Decoder</i> provides a
+POSIX-level API for transparent reading and seeking through such a converted
+file as if it were unencrypted. The API also includes functions for checking a
+file’s integrity and getting the MIME type of its embedded content.</p>
+
+<p class=MsoBodyText style='margin-bottom:24.0pt'>The converter and decoder are
+built into two separate libraries, which share common code for random number
+generation and key encryption in a third library. For test purposes there is
+also a unit test application. See Figure 1.</p>
+
+<p class=MsoBodyText style='page-break-after:avoid'><img width=288 height=364
+src="images/image001.gif"></p>
+
+<p class=MsoCaption style='margin-top:12.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm'><a name="_Ref262730885">Figure </a>1. Block diagram illustrating the dependencies between the executable modules.</p>
+
+<b><span style='font-size:16.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></b>
+
+<h1><a name="_Toc276471424">3<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span>Use Cases</a></h1>
+
+<p class=MsoBodyText>This section describes all the use cases for the converter
+and decoder. It shows the sequence of API calls that should be used to solve
+these use cases.</p>
+
+<h2><a name="_Toc276471425">3.1<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;
+</span>Converter</a></h2>
+
+<p class=MsoBodyText>Through the converter API, conversion can be performed in one
+of two ways:</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><i>Push-mode
+conversion</i> is when the client progressively feeds data to the converter as
+it arrives. This is appropriate when data arrives gradually in chunks, with
+idle time in between. Consequently, push mode is used for converting files
+being downloaded through HTTP. See section 3.1.1.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><i>Pull-mode
+conversion</i> is when the converter drives the process and consumes data from
+the client as it needs it. This is appropriate when the entire file to be
+converted is readily available. Hence, pull mode is used by the unit test application.
+See section 3.1.2.</p>
+
+<p class=MsoBodyText>Internally, pull-mode conversion is implemented in terms
+of the API for push-mode conversion.</p>
+
+<h3><a name="_Toc276471426"></a><a name="_Ref263085478">3.1.1<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span>Convert Data
+(Push-Mode Conversion)</a></h3>
+
+<p class=MsoBodyText>Push-mode conversion is performed as follows (see also Figure 2):</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockConv_OpenSession</span>
+initializes the output parameter and returns a <i>session ID</i> to be used in
+subsequent calls to the API. The output parameter is a union of return values
+whose correct use at any given moment is determined by the API function last
+called.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockConv_ConvertData</span>
+is called repeatedly until no more input data remains. Each call converts the
+maximum amount of data possible and writes it to the output buffer. The client then
+writes this data to file.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>3.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockConv_CloseSession</span>
+cleans up the session and deallocates the output buffer. If all has gone well, a
+two-part cryptographic signature of the output file is calculated. The client
+must go back and rewrite part of the file header with this updated signature
+information.</p>
+
+<p class=MsoBodyText>Every time a file is being converted, the converter calls <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_GetRandomNumber</span>
+to generate a new, unique session key. No two converted files look alike, even
+if the original files are the same.</p>
+
+<p class=MsoBodyText><b>Note:</b> The random bytes cannot come from any bare-minimum
+implementation of the C-library <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>rand</span>
+function—they must be cryptographically secure. Otherwise, security will be
+compromised.</p>
+
+<p class=MsoBodyText>The session key is encrypted and stored within the
+converted file. Key encryption is performed using <span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_GetEncryptedKeyLength</span> and <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_EncryptKey</span>.
+These two functions, together with the corresponding decryption function (<span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_DecryptKey</span>),
+are the integration points where an OEM manufacturer may implement their own
+key-encryption scheme.</p>
+
+<p class=MsoBodyText><b>Note:</b> The key-encryption key must be unique to each
+device; this is what makes the files forward lock–protected. Ideally, it should
+be derived from secret hardware parameters, but at the very least it should be
+persistent from one master reset to the next.</p>
+
+<div style='margin-bottom:24.0pt;border:solid windowtext 1.0pt;padding:1.0pt 4.0pt 1.0pt 4.0pt;
+background:#F2F2F2'>
+
+<p class=MsoBodyText style='background:#F2F2F2;border:
+none;padding:0cm'><b>Note:</b> In the open-source implementation of the <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>libfwdlock-common</span>
+library, a random key-encryption key is generated and stored in plaintext in
+the file system, without being obfuscated in any way (doing so would be futile
+since the source code is openly available). This key must be kept secret from
+the user, and shouldn’t be possible to extract through backup-and-restore
+functionality or the like. OEM manufacturers will probably want to implement a
+truly hardware-based device-unique key.</p>
+
+</div>
+
+<p class=MsoBodyText style='page-break-after:avoid'><img width=531 height=563
+src="images/image002.gif"></p>
+
+<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm'><a name="_Ref263085187">Figure </a>2. Converter UC: Convert Data.</p>
+
+<b><span style='font-size:13.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></b>
+
+<h3><a name="_Toc276471427"></a><a name="_Ref263163082">3.1.2<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span>Convert File
+(Pull-Mode Conversion)</a></h3>
+
+<p class=MsoBodyText>Pull-mode conversion is performed by calling <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_ConvertFile</span>
+with the filename, unless there is need for a specialized <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>read</span> function, in
+which case <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_ConvertOpenFile</span>
+should be used directly instead. See Figure 3.</p>
+
+<p class=MsoBodyText style='margin-bottom:24.0pt'>Internally, <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_ConvertFile</span>
+calls <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_ConvertOpenFile</span>.
+The latter then proceeds with the conversion using the push-mode API, acting as
+the client in the previous use case; see section 3.1.1.</p>
+
+<p class=MsoBodyText style='page-break-after:avoid'><img width=531 height=731
+src="images/image003.gif"></p>
+
+<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm'><a name="_Ref263085208">Figure </a>3. Converter UC: Convert File.</p>
+
+<b><i><span style='font-size:14.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></i></b>
+
+<h2><a name="_Toc276471428">3.2<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;
+</span>Decoder</a></h2>
+
+<p class=MsoBodyText>The decoder API allows the client to do the following:</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Check
+the integrity of an internal Forward Lock file, i.e., detect whether it has
+been manipulated in any way; see section 3.2.1.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Get
+the MIME type of the embedded content (the “original” MIME type before DRM protection
+was applied); see section 3.2.2.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>3.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Decode
+the file by random access, i.e., read and seek through it in an arbitrary
+manner; see section 3.2.3.</p>
+
+<p class=MsoBodyText>All subsequent operations on a file first require it to be
+opened. Opening a file returns a <i>file descriptor</i>—a handle to be used in
+these subsequent operations.</p>
+
+<p class=MsoBodyText>If the filename is known, an internal Forward Lock file
+can be opened using <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span>.
+If only the file descriptor of an already open file is available, a decoding
+session can instead be initialized using <span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>.</p>
+
+<p class=MsoBodyText>Internally, <span style='font-size:10.0pt;font-family:
+"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span> calls <span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>. For efficiency
+reasons, <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>
+therefore assumes that the file position is at the beginning of the file when
+the function gets called. A client who calls it directly must make sure that
+this assumption holds.</p>
+
+<p class=MsoBodyText>When a file is being attached, the session key stored in
+the file during conversion is decrypted using <span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_GetEncryptedKeyLength</span> and <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_DecryptKey</span>,
+in order to set up for decoding and integrity checking.</p>
+
+<p class=MsoBodyText>For just getting the content type, however, retrieving the
+session key would strictly speaking not be necessary, so there is an
+opportunity here to optimize for that if it proves necessary later.</p>
+
+<p class=MsoBodyText>Symmetrical to <span style='font-size:10.0pt;font-family:
+"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span> and <span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>, there are also functions
+for closing a file or detaching from it:</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>If
+it was opened with <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span>
+it should be closed with <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_close</span>.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>If
+it was attached with <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>
+it should be detached with <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_detach</span>.</p>
+
+<b><span style='font-size:13.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></b>
+
+<h3><a name="_Ref263163099"></a><a name="_Toc276471429">3.2.1<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span>Check Integrity</a></h3>
+
+<p class=MsoBodyText>There are three methods for checking the integrity of an
+internal Forward Lock file, in whole or in part (see also Figure 4):</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckDataIntegrity</span>,
+which checks the integrity of the encrypted content data.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckHeaderIntegrity</span>,
+which checks the integrity of the file header, including the content type and
+other fields not currently supported but reserved for future use.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>3.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckIntegrity</span>,
+which internally calls first <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckHeaderIntegrity</span>
+and then <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckDataIntegrity</span>.</p>
+
+<p class=MsoBodyText style='margin-bottom:24.0pt'><span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckHeaderIntegrity</span> is
+generally much faster than <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckDataIntegrity</span>,
+whose running time is directly proportional to the size of the file.</p>
+
+<p class=MsoBodyText style='page-break-after:avoid'><img width=543 height=575
+src="images/image004.gif"></p>
+
+<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm'><a name="_Ref263163308">Figure </a>4. Decoder UC: Check Integrity.</p>
+
+<b><span style='font-size:13.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></b>
+
+<h3><a name="_Toc276471430"></a><a name="_Ref263163117">3.2.2<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span>Get Content Type</a></h3>
+
+<p class=MsoBodyText style='margin-bottom:24.0pt'><span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_GetContentType</span> returns a
+read-only reference to an ASCII string containing the MIME type of the
+embedded content. This reference is valid as long as the file is kept open.
+Clients who need access to the content type after closing the file should make
+a copy of the string. See Figure 5 below.</p>
+
+<p class=MsoBodyText style='page-break-after:avoid'><img width=543 height=488
+src="images/image005.gif"></p>
+
+<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm'><a name="_Ref263163392">Figure </a>5. Decoder UC: Get Content Type.</p>
+
+<b><span style='font-size:13.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></b>
+
+<h3><a name="_Toc276471431"></a><a name="_Ref263163137">3.2.3<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span>Decode File</a></h3>
+
+<p class=MsoBodyText>After opening an internal Forward Lock file (or attaching
+to an already open one), it can be transparently read from as if it were
+unencrypted. Any number of calls to read data from the current file position or
+set it to a new one (which is what <span style='font-size:10.0pt;font-family:
+"Lucida Console","DejaVu Sans Mono"'>lseek</span> does) can be made in any order; this is what we
+call <i>random access</i>. See Figure 6.</p>
+
+<p class=MsoBodyText>The Forward Lock Decoder versions of the <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>read</span>, <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>lseek</span>, and <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>close</span> functions
+have the exact same signatures as their POSIX counterparts. So, for example,
+the call <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_lseek(fd,
+0, SEEK_END)</span> returns the size of the embedded content data, i.e., the
+size of the original file before DRM protection.</p>
+
+<p class=MsoBodyText style='margin-bottom:24.0pt'>Moreover, <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span>
+is like regular POSIX <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>open</span>
+except it takes only the filename as a parameter—access is always read-only.</p>
+
+<p class=MsoBodyText style='page-break-after:avoid'><img width=543 height=522
+src="images/image006.gif"></p>
+
+<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm'><a name="_Ref263166303">Figure </a>6. Decoder UC: Decode File.</p>
+
+<b><span style='font-size:16.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></b>
+
+<h1><a name="_Toc276471432">4<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span>Definition of the Internal Forward Lock File Format</a></h1>
+
+<p class=MsoBodyText style='margin-bottom:12.0pt'>The inner structure of an internal
+Forward Lock file is defined in Table 1 below.</p>
+
+<table class=MsoNormalTable border=1 cellspacing=0 cellpadding=0
+ style='border-collapse:collapse;border:none'>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'><b>Offset [bytes]</b></p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border:solid windowtext 1.0pt;
+  border-left:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'><b>Size [bytes]</b></p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border:solid windowtext 1.0pt;
+  border-left:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'><b>Description</b></p>
+  </td>
+ </tr>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>0</p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+  border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>4</p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+  none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>The file signature (so-called
+  <i>magic number</i>): a four-character code consisting of the letters
+  F-W-L-K.</p>
+  </td>
+ </tr>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>4</p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+  border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>1</p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+  none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>Version number (0 for the
+  first version).</p>
+  </td>
+ </tr>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>5</p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+  border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>1</p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+  none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>Indicates the subformat:</p>
+  <p class=MsoNormal style='page-break-after:avoid'><i>0x00 Forward Lock</i></p>
+  <p class=MsoNormal style='page-break-after:avoid'><i>0x01 Combined Delivery</i></p>
+  </td>
+ </tr>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>6</p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+  border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>1</p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+  none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>Usage restriction flags (prohibitions
+  against usage as ringtone or as wallpaper and screen saver). Also indicates
+  if the file is bound to a specific SIM card.</p>
+  <p class=MsoNormal style='page-break-after:avoid'><i>0x00 No usage
+  restrictions</i></p>
+  <p class=MsoNormal style='page-break-after:avoid'><i>0x01 Ringtone usage
+  prohibited</i></p>
+  <p class=MsoNormal style='page-break-after:avoid'><i>0x02 Screen usage
+  prohibited</i></p>
+  <p class=MsoNormal style='page-break-after:avoid'><i>0x80 Bound to SIM</i></p>
+  <p class=MsoNormal style='page-break-after:avoid'>(Any number of these may be
+  OR-ed together.)</p>
+  </td>
+ </tr>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>7</p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+  border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>1</p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+  none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>Length of the MIME content
+  type (<i>k</i>).</p>
+  </td>
+ </tr>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>8</p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+  border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'><i>k</i></p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+  none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>The MIME content type
+  (ASCII-encoded without null-character termination).</p>
+  </td>
+ </tr>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>8+<i>k</i></p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+  border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'><i>l </i>= 0 or 16</p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+  none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>If the subformat is
+  Combined Delivery, this field contains the auto-generated content ID (16&nbsp;bytes).
+  If not, this field is zero-size.</p>
+  </td>
+ </tr>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>8+<i>k</i>+<i>l</i></p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+  border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'><i>m </i>= 0 or 9</p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+  none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>If the file is bound to a
+  specific SIM card, this field contains the 9-byte packed IMSI number. If not,
+  this field is zero-size.</p>
+  </td>
+ </tr>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>8+<i>k</i>+<i>l</i>+<i>m</i></p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+  border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'><i>n</i> &#8805; 16</p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+  none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>The encrypted session key, the
+  first sixteen bytes of which are also used as the CTR-mode <i>nonce</i> (similar
+  to the CBC-mode <i>initialization vector</i>).</p>
+  </td>
+ </tr>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>8+<i>k</i>+<i>l</i>+<i>m</i>+<i>n</i></p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+  border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>20</p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+  none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>Data signature—the SHA-1
+  HMAC of the encrypted content data.</p>
+  </td>
+ </tr>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>28+<i>k</i>+<i>l</i>+<i>m</i>+<i>n</i></p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+  border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>20</p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+  none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>Header signature—the SHA-1
+  HMAC of all the fields above, including the encrypted session key and data
+  signature.</p>
+  </td>
+ </tr>
+ <tr>
+  <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+  border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>48+<i>k</i>+<i>l</i>+<i>m</i>+<i>n</i></p>
+  </td>
+  <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+  border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'><i>&lt;to the end of the
+  file&gt;</i></p>
+  </td>
+  <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+  none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+  padding:0cm 5.4pt 0cm 5.4pt'>
+  <p class=MsoNormal style='page-break-after:avoid'>The content data encrypted
+  using 128-bit AES in CTR mode.</p>
+  </td>
+ </tr>
+</table>
+
+<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm;page-break-after:avoid'><a name="_Ref151269206">Table </a>1. Definition of the fields of an internal Forward Lock file.</p>
+
+<p class=MsoBodyText>As of now, neither Combined Delivery nor usage
+restrictions (including SIM binding) are supported. These fields are reserved
+for future use.</p>
+
+<h2><a name="_Toc276471433">4.1<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;
+</span>Key Derivation</a></h2>
+
+<p class=MsoBodyText>The session key consists of sixteen bytes fetched from a
+cryptographically secure random number generator. From the session key, two
+separate keys are derived: one used for encryption, the other for signing.</p>
+
+<p class=MsoBodyText>The encryption key is the output from encrypting the
+16-byte all-zero input block {0, 0, …, 0} using 128-bit AES with the random session
+key as the key. The signing key is the output from encrypting the 16-byte input
+block {1, 0, …, 0} the same way. The keys so derived will be cryptographically
+independent from each other.</p>
+
+<p class=MsoBodyText>The session key is encrypted using a hardware-dependent
+key-encryption key unique to each device. The encrypted session key is stored
+inside the file, and its first sixteen bytes are also used as the <i>nonce</i>
+for the CTR-mode encryption of the content data.</p>
+
+<h2><a name="_Toc276471434">4.2<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;
+</span>Calculation of the Counters</a></h2>
+
+<p class=MsoBodyText>Using CTR (“counter”) mode, a block cipher such as AES can
+be turned into a stream cipher. The process of encryption and decryption is
+well defined in [1], except for the specifics of the calculation of the
+counters. For the internal Forward Lock file format, the counters are
+calculated as follows:</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>The
+nonce is interpreted as a 128-bit unsigned integer in little-endian format.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>The
+zero-based block sequence number (also a little-endian unsigned integer) is
+added modulo 2<sup>128</sup> to the nonce to produce the counter for a given
+block.</p>
+
+<h1><a name="_Toc276471435">5<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span>Unit Test Cases</a></h1>
+
+<p class=MsoBodyText>Unit test cases for the converter and decoder come in two
+varieties:</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><i>Black-box</i>
+test cases aim to verify that you get sensible results from malformed or
+“tricky” input data.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><i>White-box</i>
+test cases aim to maximize code coverage using knowledge of code internals.</p>
+
+<p class=MsoBodyText>The black-box test cases are dependent on a specifically
+designed set of input files found in the <span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>forward-lock/internal-format/test/res</span>
+directory in the repository. For ‘tests’ variants of the software, these input
+files will be automatically installed in the file system image during build.</p>
+
+<p class=MsoBodyText>Run the test cases from the ADB shell command line as
+follows:</p>
+
+<p class=MsoNormal style='margin-top:0cm;margin-right:0cm;margin-bottom:6.0pt;
+margin-left:21.55pt'><span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>#
+gtest_fwdlock</span></p>
+
+<p class=MsoBodyText>If all black-box but no white-box test cases fail, the
+input files probably can’t be found in the working directory.</p>
+
+<h1><a name="_Toc276471436">6<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span>References</a></h1>
+
+<p class=MsoBodyText style='margin-left:28.9pt;text-indent:-28.9pt'>[1]<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span><a
+href="http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf">Dworkin,
+Morris: “Recommendation for Block Cipher Modes of Operation—Methods and
+Techniques,” NIST Special Publication 800-38A, December 2001.</a><a
+name="_Ref151269073"></a></p>
+
+</div>
+
+</body>
+
+</html>
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image001.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image001.gif
new file mode 100644
index 0000000..ee94513
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image001.gif
Binary files differ
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image002.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image002.gif
new file mode 100644
index 0000000..8c12f46
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image002.gif
Binary files differ
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image003.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image003.gif
new file mode 100644
index 0000000..9e019ca
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image003.gif
Binary files differ
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image004.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image004.gif
new file mode 100644
index 0000000..cae1d01
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image004.gif
Binary files differ
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image005.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image005.gif
new file mode 100644
index 0000000..0d87be9
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image005.gif
Binary files differ
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image006.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image006.gif
new file mode 100644
index 0000000..9445b6b
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image006.gif
Binary files differ
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index fe723f2..8309f7a 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -213,19 +213,6 @@
         public boolean inInputShareable;
 
         /**
-         * Normally bitmap allocations count against the dalvik heap, which
-         * means they help trigger GCs when a lot have been allocated. However,
-         * in rare cases, the caller may want to allocate the bitmap outside of
-         * that heap. To request that, set inNativeAlloc to true. In these
-         * rare instances, it is solely up to the caller to ensure that OOM is
-         * managed explicitly by calling bitmap.recycle() as soon as such a
-         * bitmap is no longer needed.
-         *
-         * @hide pending API council approval
-         */
-        public boolean inNativeAlloc;
-
-        /**
          * If inPreferQualityOverSpeed is set to true, the decoder will try to
          * decode the reconstructed image to a higher quality even at the
          * expense of the decoding speed. Currently the field only affects JPEG
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
index 454eb4a..496e0c7 100644
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -39,7 +39,7 @@
 
     /**
      * Create a BitmapRegionDecoder from the specified byte array.
-     * Currently only the Jpeg format is supported.
+     * Currently only the JPEG and PNG formats are supported.
      *
      * @param data byte array of compressed image data.
      * @param offset offset into data for where the decoder should begin
@@ -67,7 +67,7 @@
      * Create a BitmapRegionDecoder from the file descriptor.
      * The position within the descriptor will not be changed when
      * this returns, so the descriptor can be used again as is.
-     * Currently only the Jpeg format is supported.
+     * Currently only the JPEG and PNG formats are supported.
      *
      * @param fd The file descriptor containing the data to decode
      * @param isShareable If this is true, then the BitmapRegionDecoder may keep a
@@ -89,7 +89,7 @@
      * Create a BitmapRegionDecoder from an input stream.
      * The stream's position will be where ever it was after the encoded data
      * was read.
-     * Currently only the Jpeg format is supported.
+     * Currently only the JPEG and PNG formats are supported.
      *
      * @param is The input stream that holds the raw data to be decoded into a
      *           BitmapRegionDecoder.
@@ -126,7 +126,7 @@
 
     /**
      * Create a BitmapRegionDecoder from a file path.
-     * Currently only the Jpeg format is supported.
+     * Currently only the JPEG and PNG formats are supported.
      *
      * @param pathName complete path name for the file to be decoded.
      * @param isShareable If this is true, then the BitmapRegionDecoder may keep a
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 4ba679b..f74d0ef 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -23,9 +23,10 @@
 public class BitmapShader extends Shader {
     /**
      * Prevent garbage collection.
+     * @hide
      */
     @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
-    private final Bitmap mBitmap;
+    public final Bitmap mBitmap;
 
     /**
      * Call this to create a new shader that will draw with a bitmap.
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 66c6d81..184620b 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -85,8 +85,12 @@
 
         @Override
         protected void finalize() throws Throwable {
-            if (mNativeCanvas != 0) {
-                finalizer(mNativeCanvas);
+            try {
+                if (mNativeCanvas != 0) {
+                    finalizer(mNativeCanvas);
+                }
+            } finally {
+                super.finalize();
             }
         }
     }
@@ -137,6 +141,8 @@
      * Returns null.
      * 
      * @deprecated This method is not supported and should not be invoked.
+     * 
+     * @hide
      */
     @Deprecated
     protected GL getGL() {
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index e3bb6eb..b739d83 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -559,7 +559,7 @@
     }
 
     /**
-     * Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit
+     * Helper for setFlags(), setting or clearing the FAKE_BOLD_TEXT_FLAG bit
      *
      * @param fakeBoldText true to set the fakeBoldText bit in the paint's
      *                     flags, false to clear it.
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 0400b5c..43758e7 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -34,6 +34,8 @@
      */
     public int native_shader;
 
+    private Matrix mLocalMatrix;
+
     public enum TileMode {
         /**
          * replicate the edge color if the shader draws outside of its
@@ -62,7 +64,11 @@
      * @return true if the shader has a non-identity local matrix
      */
     public boolean getLocalMatrix(Matrix localM) {
-        return nativeGetLocalMatrix(native_instance, localM.native_instance);
+        if (mLocalMatrix != null) {
+            localM.set(mLocalMatrix);
+            return !mLocalMatrix.isIdentity();
+        }
+        return false;
     }
 
     /**
@@ -71,6 +77,7 @@
      * @param localM The shader's new local matrix, or null to specify identity
      */
     public void setLocalMatrix(Matrix localM) {
+        mLocalMatrix = localM;
         nativeSetLocalMatrix(native_instance, native_shader,
                 localM == null ? 0 : localM.native_instance);
     }
@@ -84,8 +91,6 @@
     }
 
     private static native void nativeDestructor(int native_shader, int native_skiaShader);
-    private static native boolean nativeGetLocalMatrix(int native_shader,
-            int matrix_instance); 
     private static native void nativeSetLocalMatrix(int native_shader,
             int native_skiaShader, int matrix_instance);
 }
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
new file mode 100644
index 0000000..3eb0b03
--- /dev/null
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+/**
+ * Captures frames from an image stream as an OpenGL ES texture.
+ *
+ * <p>The image stream may come from either video playback or camera preview.  A SurfaceTexture may
+ * be used in place of a SurfaceHolder when specifying the output destination of a MediaPlayer or
+ * Camera object.  This will cause all the frames from that image stream to be sent to the
+ * SurfaceTexture object rather than to the device's display.  When {@link #updateTexImage} is
+ * called, the contents of the texture object specified when the SurfaceTexture was created is
+ * updated to contain the most recent image from the image stream.  This may cause some frames of
+ * the stream to be skipped.
+ *
+ * <p>The texture object uses the GL_TEXTURE_EXTERNAL_OES texture target, which is defined by the
+ * OES_EGL_image_external OpenGL ES extension.  This limits how the texture may be used.
+ */
+public class SurfaceTexture {
+
+    @SuppressWarnings("unused")
+    private int mSurfaceTexture;
+
+    /**
+     * Callback interface for being notified that a new stream frame is available.
+     */
+    public interface OnFrameAvailableListener {
+        void onFrameAvailable(SurfaceTexture surfaceTexture);
+    }
+
+    /**
+     * Exception thrown when a surface couldn't be created or resized
+     */
+    public static class OutOfResourcesException extends Exception {
+        public OutOfResourcesException() {
+        }
+        public OutOfResourcesException(String name) {
+            super(name);
+        }
+    }
+
+    /**
+     * Construct a new SurfaceTexture to stream images to a given OpenGL texture.
+     *
+     * @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
+     */
+    public SurfaceTexture(int texName) {
+        init(texName);
+    }
+
+    /**
+     * Register a callback to be invoked when a new image frame becomes available to the
+     * SurfaceTexture.  Note that this callback may be called on an arbitrary thread, so it is not
+     * safe to call {@link #updateTexImage} without first binding the OpenGL ES context to the
+     * thread invoking the callback.
+     */
+    public void setOnFrameAvailableListener(OnFrameAvailableListener l) {
+        // TODO: Implement this!
+    }
+
+    /**
+     * Update the texture image to the most recent frame from the image stream.  This may only be
+     * called while the OpenGL ES context that owns the texture is bound to the thread.  It will
+     * implicitly bind its texture to the GL_TEXTURE_EXTERNAL_OES texture target.
+     */
+    public native void updateTexImage();
+
+
+    /**
+     * Retrieve the 4x4 texture coordinate transform matrix associated with the texture image set by
+     * the most recent call to updateTexImage.
+     *
+     * This transform matrix maps 2D homogeneous texture coordinates of the form (s, t, 0, 1) with s
+     * and t in the inclusive range [0, 1] to the texture coordinate that should be used to sample
+     * that location from the texture.  Sampling the texture outside of the range of this transform
+     * is undefined.
+     *
+     * The matrix is stored in column-major order so that it may be passed directly to OpenGL ES via
+     * the glLoadMatrixf or glUniformMatrix4fv functions.
+     *
+     * @param mtx the array into which the 4x4 matrix will be stored.  The array must have exactly
+     *     16 elements.
+     */
+    public void getTransformMatrix(float[] mtx) {
+        if (mtx.length != 16) {
+            throw new IllegalArgumentException();
+        }
+        getTransformMatrixImpl(mtx);
+    }
+
+    private native void getTransformMatrixImpl(float[] mtx);
+
+    private native void init(int texName);
+
+    /*
+     * We use a class initializer to allow the native code to cache some
+     * field offsets.
+     */
+    private static native void nativeClassInit();
+    static { nativeClassInit(); }
+}
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index 39a7dd2..94a8488 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -207,7 +207,7 @@
     @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 032244f..2c09ddc 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -439,7 +439,7 @@
 
     @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 0d44591..b333e01 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -232,7 +232,7 @@
     @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 4d560be..4418e02 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -149,7 +149,7 @@
 
     @Override
     public ConstantState getConstantState() {
-        mState.mChangingConfigurations = super.getChangingConfigurations();
+        mState.mChangingConfigurations = getChangingConfigurations();
         return mState;
     }
 
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index c423550..159f371e 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -212,7 +212,7 @@
 
     /**
      * Return a mask of the configuration parameters for which this drawable
-     * mau change, requiring that it be re-created.  The default implementation
+     * may change, requiring that it be re-created.  The default implementation
      * returns whatever was provided through
      * {@link #setChangingConfigurations(int)} or 0 by default.  Subclasses
      * may extend this to or in the changing configurations of any other
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 0a580eb..a9414e8 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -389,7 +389,7 @@
     @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 da8bb1b..65c6ccf 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -861,7 +861,7 @@
     
     @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 3a74dfd..231234c 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -241,7 +241,7 @@
     @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 84da170..49dbbca 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -557,7 +557,7 @@
     @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 35b8319..a5175c5 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -323,7 +323,7 @@
     
     @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 212ddfa..4f74b37 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -192,7 +192,7 @@
     @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 055576d..a7ed0d0 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -241,7 +241,7 @@
     @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 92252fc..cb8774d 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -356,7 +356,7 @@
     
     @Override
     public ConstantState getConstantState() {
-        mShapeState.mChangingConfigurations = super.getChangingConfigurations();
+        mShapeState.mChangingConfigurations = getChangingConfigurations();
         return mShapeState;
     }
 
diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java
index 4470356..9a3ca40 100644
--- a/graphics/java/android/graphics/drawable/TransitionDrawable.java
+++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java
@@ -137,7 +137,7 @@
         final long time = SystemClock.uptimeMillis();
         // Animation is over
         if (time - mStartTimeMillis > mDuration) {
-            if (mAlpha == 0) {
+            if (mTo == 0) {
                 mFrom = 0;
                 mTo = 255;
                 mAlpha = 0;
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 1bddbae..579f314 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -18,7 +18,6 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-
 import android.content.res.Resources;
 import android.content.res.AssetManager;
 import android.graphics.Bitmap;
@@ -27,7 +26,19 @@
 import android.util.TypedValue;
 
 /**
- * @hide
+ * Memory allocation class for renderscript.  An allocation combines a Type with
+ * memory to provide storage for user data and objects.
+ *
+ * Allocations may exist in one or more memory spaces.  Currently those are
+ * Script: accessable by RS scripts.
+ * Graphics Texture: accessable as a graphics texture.
+ * Graphics Vertex: accessable as graphical vertex data.
+ * Graphics Constants: Accessable as constants in user shaders
+ *
+ * By default java side updates are always applied to the script accessable
+ * memory.  If this is not present they are then applied to the various HW
+ * memory types.  A syncAll call is necessary after the script data is update to
+ * keep the other memory spaces in sync.
  *
  **/
 public class Allocation extends BaseObj {
@@ -35,29 +46,62 @@
     Bitmap mBitmap;
     int mUsage;
 
+    /**
+     * The usage of the allocation.  These signal to renderscript
+     * where to place the allocation in memory.
+     *
+     * SCRIPT The allocation will be bound to and accessed by
+     * scripts.
+     */
     public static final int USAGE_SCRIPT = 0x0001;
+
+    /**
+     * GRAPHICS_TEXTURE The allcation will be used as a texture
+     * source by one or more graphcics programs.
+     *
+     */
     public static final int USAGE_GRAPHICS_TEXTURE = 0x0002;
+
+    /**
+     * GRAPHICS_VERTEX The allocation will be used as a graphics
+     * mesh.
+     *
+     */
     public static final int USAGE_GRAPHICS_VERTEX = 0x0004;
+
+
+    /**
+     * GRAPHICS_CONSTANTS The allocation will be used as the source
+     * of shader constants by one or more programs.
+     *
+     */
     public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008;
 
-    private static final int USAGE_ALL = 0x000F;
 
-
-    public enum CubemapLayout {
-        VERTICAL_FACE_LIST (0),
-        HORIZONTAL_FACE_LIST (1),
-        VERTICAL_CROSS (2),
-        HORIZONTAL_CROSS (3);
-
-        int mID;
-        CubemapLayout(int id) {
-            mID = id;
-        }
-    }
-
+    /**
+     * Controls mipmap behavior when using the bitmap creation and
+     * update functions.
+     */
     public enum MipmapControl {
+        /**
+         * No mipmaps will be generated and the type generated from the
+         * incoming bitmap will not contain additional LODs.
+         */
         MIPMAP_NONE(0),
+
+        /**
+         * A Full mipmap chain will be created in script memory.  The
+         * type of the allocation will contain a full mipmap chain.  On
+         * upload to graphics the full chain will be transfered.
+         */
         MIPMAP_FULL(1),
+
+        /**
+         * The type of the allocation will be the same as MIPMAP_NONE.
+         * It will not contain mipmaps.  On upload to graphics the
+         * graphics copy of the allocation data will contain a full
+         * mipmap chain generated from the top level in script memory.
+         */
         MIPMAP_ON_SYNC_TO_TEXTURE(2);
 
         int mID;
@@ -68,7 +112,10 @@
 
     Allocation(int id, RenderScript rs, Type t, int usage) {
         super(id, rs);
-        if (usage > USAGE_ALL) {
+        if ((usage & ~(USAGE_SCRIPT |
+                       USAGE_GRAPHICS_TEXTURE |
+                       USAGE_GRAPHICS_VERTEX |
+                       USAGE_GRAPHICS_CONSTANTS)) != 0) {
             throw new RSIllegalArgumentException("Unknown usage specified.");
         }
         mType = t;
@@ -102,22 +149,6 @@
         mRS.nAllocationSyncAll(getID(), srcLocation);
     }
 
-    public void uploadToTexture(int baseMipLevel) {
-        mRS.validate();
-        mRS.nAllocationUploadToTexture(getID(), false, baseMipLevel);
-    }
-
-    public void uploadToTexture(boolean genMips, int baseMipLevel) {
-        mRS.validate();
-        mRS.nAllocationUploadToTexture(getID(), genMips, baseMipLevel);
-    }
-
-    public void uploadToBufferObject() {
-        mRS.validate();
-        mRS.nAllocationUploadToBufferObject(getID());
-    }
-
-
     public void copyFrom(BaseObj[] d) {
         mRS.validate();
         if (d.length != mType.getCount()) {
@@ -128,11 +159,56 @@
         for (int ct=0; ct < d.length; ct++) {
             i[ct] = d[ct].getID();
         }
-        subData1D(0, mType.getCount(), i);
+        copy1DRangeFrom(0, mType.getCount(), i);
     }
 
-    private void validateBitmap(Bitmap b) {
-        mRS.validate();
+    private void validateBitmapFormat(Bitmap b) {
+        Bitmap.Config bc = b.getConfig();
+        switch (bc) {
+        case ALPHA_8:
+            if (mType.getElement().mKind != Element.DataKind.PIXEL_A) {
+                throw new RSIllegalArgumentException("Allocation kind is " +
+                                                     mType.getElement().mKind + ", type " +
+                                                     mType.getElement().mType +
+                                                     " of " + mType.getElement().getSizeBytes() +
+                                                     " bytes, passed bitmap was " + bc);
+            }
+            break;
+        case ARGB_8888:
+            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
+                (mType.getElement().getSizeBytes() != 4)) {
+                throw new RSIllegalArgumentException("Allocation kind is " +
+                                                     mType.getElement().mKind + ", type " +
+                                                     mType.getElement().mType +
+                                                     " of " + mType.getElement().getSizeBytes() +
+                                                     " bytes, passed bitmap was " + bc);
+            }
+            break;
+        case RGB_565:
+            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) ||
+                (mType.getElement().getSizeBytes() != 2)) {
+                throw new RSIllegalArgumentException("Allocation kind is " +
+                                                     mType.getElement().mKind + ", type " +
+                                                     mType.getElement().mType +
+                                                     " of " + mType.getElement().getSizeBytes() +
+                                                     " bytes, passed bitmap was " + bc);
+            }
+            break;
+        case ARGB_4444:
+            if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) ||
+                (mType.getElement().getSizeBytes() != 2)) {
+                throw new RSIllegalArgumentException("Allocation kind is " +
+                                                     mType.getElement().mKind + ", type " +
+                                                     mType.getElement().mType +
+                                                     " of " + mType.getElement().getSizeBytes() +
+                                                     " bytes, passed bitmap was " + bc);
+            }
+            break;
+
+        }
+    }
+
+    private void validateBitmapSize(Bitmap b) {
         if(mType.getX() != b.getWidth() ||
            mType.getY() != b.getHeight()) {
             throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
@@ -141,32 +217,37 @@
 
     public void copyFrom(int[] d) {
         mRS.validate();
-        subData1D(0, mType.getCount(), d);
+        copy1DRangeFrom(0, mType.getCount(), d);
     }
     public void copyFrom(short[] d) {
         mRS.validate();
-        subData1D(0, mType.getCount(), d);
+        copy1DRangeFrom(0, mType.getCount(), d);
     }
     public void copyFrom(byte[] d) {
         mRS.validate();
-        subData1D(0, mType.getCount(), d);
+        copy1DRangeFrom(0, mType.getCount(), d);
     }
     public void copyFrom(float[] d) {
         mRS.validate();
-        subData1D(0, mType.getCount(), d);
+        copy1DRangeFrom(0, mType.getCount(), d);
     }
     public void copyFrom(Bitmap b) {
-        validateBitmap(b);
+        mRS.validate();
+        validateBitmapSize(b);
+        validateBitmapFormat(b);
         mRS.nAllocationCopyFromBitmap(getID(), b);
     }
 
-    public void copyTo(Bitmap b) {
-        validateBitmap(b);
-        mRS.nAllocationCopyToBitmap(getID(), b);
-    }
-
-
-    public void subData(int xoff, FieldPacker fp) {
+    /**
+     * @hide
+     *
+     * This is only intended to be used by auto-generate code reflected from the
+     * renderscript script files.
+     *
+     * @param xoff
+     * @param fp
+     */
+    public void setOneElement(int xoff, FieldPacker fp) {
         int eSize = mType.mElement.getSizeBytes();
         final byte[] data = fp.getData();
 
@@ -176,11 +257,21 @@
                                                " not divisible by element size " + eSize + ".");
         }
         data1DChecks(xoff, count, data.length, data.length);
-        mRS.nAllocationSubData1D(getID(), xoff, count, data, data.length);
+        mRS.nAllocationData1D(getID(), xoff, 0, count, data, data.length);
     }
 
 
-    public void subElementData(int xoff, int component_number, FieldPacker fp) {
+    /**
+     * @hide
+     *
+     * This is only intended to be used by auto-generate code reflected from the
+     * renderscript script files.
+     *
+     * @param xoff
+     * @param component_number
+     * @param fp
+     */
+    public void setOneComponent(int xoff, int component_number, FieldPacker fp) {
         if (component_number >= mType.mElement.mElements.length) {
             throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
         }
@@ -196,7 +287,7 @@
                                                " does not match component size " + eSize + ".");
         }
 
-        mRS.nAllocationSubElementData1D(getID(), xoff, component_number, data, data.length);
+        mRS.nAllocationElementData1D(getID(), xoff, 0, component_number, data, data.length);
     }
 
     private void data1DChecks(int off, int count, int len, int dataSize) {
@@ -216,48 +307,145 @@
         }
     }
 
-    public void subData1D(int off, int count, int[] d) {
+    /**
+     * Generate a mipmap chain.  Requires the type of the allocation
+     * include mipmaps.
+     *
+     * This function will generate a complete set of mipmaps from
+     * the top level lod and place them into the script memoryspace.
+     *
+     * If the allocation is also using other memory spaces a
+     * followup sync will be required.
+     */
+    public void generateMipmaps() {
+        mRS.nAllocationGenerateMipmaps(getID());
+    }
+
+    public void copy1DRangeFrom(int off, int count, int[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length * 4, dataSize);
-        mRS.nAllocationSubData1D(getID(), off, count, d, dataSize);
+        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
     }
-    public void subData1D(int off, int count, short[] d) {
+    public void copy1DRangeFrom(int off, int count, short[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length * 2, dataSize);
-        mRS.nAllocationSubData1D(getID(), off, count, d, dataSize);
+        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
     }
-    public void subData1D(int off, int count, byte[] d) {
+    public void copy1DRangeFrom(int off, int count, byte[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length, dataSize);
-        mRS.nAllocationSubData1D(getID(), off, count, d, dataSize);
+        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
     }
-    public void subData1D(int off, int count, float[] d) {
+    public void copy1DRangeFrom(int off, int count, float[] d) {
         int dataSize = mType.mElement.getSizeBytes() * count;
         data1DChecks(off, count, d.length * 4, dataSize);
-        mRS.nAllocationSubData1D(getID(), off, count, d, dataSize);
+        mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize);
     }
 
+    private void validate2DRange(int xoff, int yoff, int w, int h) {
+        if (xoff < 0 || yoff < 0) {
+            throw new RSIllegalArgumentException("Offset cannot be negative.");
+        }
+        if (h < 0 || w < 0) {
+            throw new RSIllegalArgumentException("Height or width cannot be negative.");
+        }
+        if ((xoff + w) > mType.mDimX ||
+            (yoff + h) > mType.mDimY) {
+            throw new RSIllegalArgumentException("Updated region larger than allocation.");
+        }
+    }
 
-    public void subData2D(int xoff, int yoff, int w, int h, int[] d) {
+    /**
+     * Copy a rectanglular region from the array into the
+     * allocation.  The incoming array is assumed to be tightly
+     * packed.
+     *
+     * @param xoff X offset of the region to update
+     * @param yoff Y offset of the region to update
+     * @param w Width of the incoming region to update
+     * @param h Height of the incoming region to update
+     * @param data to be placed into the allocation
+     */
+    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
         mRS.validate();
-        mRS.nAllocationSubData2D(getID(), xoff, yoff, w, h, d, d.length * 4);
+        validate2DRange(xoff, yoff, w, h);
+        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length);
     }
 
-    public void subData2D(int xoff, int yoff, int w, int h, float[] d) {
+    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
         mRS.validate();
-        mRS.nAllocationSubData2D(getID(), xoff, yoff, w, h, d, d.length * 4);
+        validate2DRange(xoff, yoff, w, h);
+        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 2);
     }
 
-    public void readData(int[] d) {
+    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
+        mRS.validate();
+        validate2DRange(xoff, yoff, w, h);
+        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4);
+    }
+
+    public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
+        mRS.validate();
+        validate2DRange(xoff, yoff, w, h);
+        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4);
+    }
+
+    /**
+     * Copy a bitmap into an allocation.  The height and width of
+     * the update will use the height and width of the incoming
+     * bitmap.
+     *
+     * @param xoff X offset of the region to update
+     * @param yoff Y offset of the region to update
+     * @param data the bitmap to be copied
+     */
+    public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
+        mRS.validate();
+        validateBitmapFormat(data);
+        validate2DRange(xoff, yoff, data.getWidth(), data.getHeight());
+        mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, data);
+    }
+
+
+    public void copyTo(Bitmap b) {
+        mRS.validate();
+        validateBitmapFormat(b);
+        validateBitmapSize(b);
+        mRS.nAllocationCopyToBitmap(getID(), b);
+    }
+
+    public void copyTo(byte[] d) {
         mRS.validate();
         mRS.nAllocationRead(getID(), d);
     }
 
-    public void readData(float[] d) {
+    public void copyTo(short[] d) {
         mRS.validate();
         mRS.nAllocationRead(getID(), d);
     }
 
+    public void copyTo(int[] d) {
+        mRS.validate();
+        mRS.nAllocationRead(getID(), d);
+    }
+
+    public void copyTo(float[] d) {
+        mRS.validate();
+        mRS.nAllocationRead(getID(), d);
+    }
+
+    /**
+     * Resize a 1D allocation.  The contents of the allocation are
+     * preserved.  If new elements are allocated objects are created
+     * with null contents and the new region is otherwise undefined.
+     *
+     * If the new region is smaller the references of any objects
+     * outside the new region will be released.
+     *
+     * A new type will be created with the new dimension.
+     *
+     * @param dimX The new size of the allocation.
+     */
     public synchronized void resize(int dimX) {
         if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
             throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
@@ -282,118 +470,76 @@
     }
     */
 
-    /*
-    public class Adapter1D extends BaseObj {
-        Adapter1D(int id, RenderScript rs) {
-            super(id, rs);
-        }
-
-        public void setConstraint(Dimension dim, int value) {
-            mRS.validate();
-            mRS.nAdapter1DSetConstraint(getID(), dim.mID, value);
-        }
-
-        public void data(int[] d) {
-            mRS.validate();
-            mRS.nAdapter1DData(getID(), d);
-        }
-
-        public void data(float[] d) {
-            mRS.validate();
-            mRS.nAdapter1DData(getID(), d);
-        }
-
-        public void subData(int off, int count, int[] d) {
-            mRS.validate();
-            mRS.nAdapter1DSubData(getID(), off, count, d);
-        }
-
-        public void subData(int off, int count, float[] d) {
-            mRS.validate();
-            mRS.nAdapter1DSubData(getID(), off, count, d);
-        }
-    }
-
-    public Adapter1D createAdapter1D() {
-        mRS.validate();
-        int id = mRS.nAdapter1DCreate();
-        if(id == 0) {
-            throw new RSRuntimeException("Adapter creation failed.");
-        }
-        mRS.nAdapter1DBindAllocation(id, getID());
-        return new Adapter1D(id, mRS);
-    }
-    */
-
-
-    public class Adapter2D extends BaseObj {
-        Adapter2D(int id, RenderScript rs) {
-            super(id, rs);
-        }
-
-        public void setConstraint(Dimension dim, int value) {
-            mRS.validate();
-            mRS.nAdapter2DSetConstraint(getID(), dim.mID, value);
-        }
-
-        public void data(int[] d) {
-            mRS.validate();
-            mRS.nAdapter2DData(getID(), d);
-        }
-
-        public void data(float[] d) {
-            mRS.validate();
-            mRS.nAdapter2DData(getID(), d);
-        }
-
-        public void subData(int xoff, int yoff, int w, int h, int[] d) {
-            mRS.validate();
-            mRS.nAdapter2DSubData(getID(), xoff, yoff, w, h, d);
-        }
-
-        public void subData(int xoff, int yoff, int w, int h, float[] d) {
-            mRS.validate();
-            mRS.nAdapter2DSubData(getID(), xoff, yoff, w, h, d);
-        }
-    }
-
-    public Adapter2D createAdapter2D() {
-        mRS.validate();
-        int id = mRS.nAdapter2DCreate();
-        if(id == 0) {
-            throw new RSRuntimeException("allocation failed.");
-        }
-        mRS.nAdapter2DBindAllocation(id, getID());
-        if(id == 0) {
-            throw new RSRuntimeException("Adapter creation failed.");
-        }
-        return new Adapter2D(id, mRS);
-    }
 
 
     // creation
 
-    private static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
+    static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
     static {
         mBitmapOptions.inScaled = false;
     }
 
-    static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mc, int usage) {
+    /**
+     *
+     * @param type renderscript type describing data layout
+     * @param mips specifies desired mipmap behaviour for the
+     *             allocation
+     * @param usage bit field specifying how the allocation is
+     *              utilized
+     */
+    static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
         rs.validate();
         if (type.getID() == 0) {
             throw new RSInvalidStateException("Bad Type");
         }
-        int id = rs.nAllocationCreateTyped(type.getID(), mc.mID, usage);
+        int id = rs.nAllocationCreateTyped(type.getID(), mips.mID, usage);
         if (id == 0) {
             throw new RSRuntimeException("Allocation creation failed.");
         }
         return new Allocation(id, rs, type, usage);
     }
 
+    /**
+     * Creates a renderscript allocation with the size specified by
+     * the type and no mipmaps generated by default
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param type renderscript type describing data layout
+     * @param usage bit field specifying how the allocation is
+     *              utilized
+     *
+     * @return allocation
+     */
+    static public Allocation createTyped(RenderScript rs, Type type, int usage) {
+        return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage);
+    }
+
+    /**
+     * Creates a renderscript allocation for use by the script with
+     * the size specified by the type and no mipmaps generated by
+     * default
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param type renderscript type describing data layout
+     *
+     * @return allocation
+     */
     static public Allocation createTyped(RenderScript rs, Type type) {
         return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT);
     }
 
+    /**
+     * Creates a renderscript allocation with a specified number of
+     * given elements
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param e describes what each element of an allocation is
+     * @param count specifies the number of element in the allocation
+     * @param usage bit field specifying how the allocation is
+     *              utilized
+     *
+     * @return allocation
+     */
     static public Allocation createSized(RenderScript rs, Element e,
                                          int count, int usage) {
         rs.validate();
@@ -408,11 +554,21 @@
         return new Allocation(id, rs, t, usage);
     }
 
+    /**
+     * Creates a renderscript allocation with a specified number of
+     * given elements
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param e describes what each element of an allocation is
+     * @param count specifies the number of element in the allocation
+     *
+     * @return allocation
+     */
     static public Allocation createSized(RenderScript rs, Element e, int count) {
         return createSized(rs, e, count, USAGE_SCRIPT);
     }
 
-    static private Element elementFromBitmap(RenderScript rs, Bitmap b) {
+    static Element elementFromBitmap(RenderScript rs, Bitmap b) {
         final Bitmap.Config bc = b.getConfig();
         if (bc == Bitmap.Config.ALPHA_8) {
             return Element.A_8(rs);
@@ -429,7 +585,7 @@
         throw new RSInvalidStateException("Bad bitmap type: " + bc);
     }
 
-    static private Type typeFromBitmap(RenderScript rs, Bitmap b,
+    static Type typeFromBitmap(RenderScript rs, Bitmap b,
                                        MipmapControl mip) {
         Element e = elementFromBitmap(rs, b);
         Type.Builder tb = new Type.Builder(rs, e);
@@ -439,6 +595,19 @@
         return tb.create();
     }
 
+    /**
+     * Creates a renderscript allocation from a bitmap
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param b bitmap source for the allocation data
+     * @param mips specifies desired mipmap behaviour for the
+     *             allocation
+     * @param usage bit field specifying how the allocation is
+     *              utilized
+     *
+     * @return renderscript allocation containing bitmap data
+     *
+     */
     static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
                                               MipmapControl mips,
                                               int usage) {
@@ -452,38 +621,58 @@
         return new Allocation(id, rs, t, usage);
     }
 
+    /**
+     * Creates a non-mipmapped renderscript allocation to use as a
+     * graphics texture
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param b bitmap source for the allocation data
+     *
+     * @return renderscript allocation containing bitmap data
+     *
+     */
     static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
         return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
                                 USAGE_GRAPHICS_TEXTURE);
     }
 
+    /**
+     * Creates a cubemap allocation from a bitmap containing the
+     * horizontal list of cube faces. Each individual face must be
+     * the same size and power of 2
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param b bitmap with cubemap faces layed out in the following
+     *          format: right, left, top, bottom, front, back
+     * @param mips specifies desired mipmap behaviour for the cubemap
+     * @param usage bit field specifying how the cubemap is utilized
+     *
+     * @return allocation containing cubemap data
+     *
+     */
     static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
                                                      MipmapControl mips,
-                                                     CubemapLayout layout,
                                                      int usage) {
         rs.validate();
 
         int height = b.getHeight();
         int width = b.getWidth();
 
-        if (layout != CubemapLayout.VERTICAL_FACE_LIST) {
-            throw new RSIllegalArgumentException("Only vertical face list supported");
-        }
-        if (height % 6 != 0) {
+        if (width % 6 != 0) {
             throw new RSIllegalArgumentException("Cubemap height must be multiple of 6");
         }
-        if (height / 6 != width) {
-            throw new RSIllegalArgumentException("Only square cobe map faces supported");
+        if (width / 6 != height) {
+            throw new RSIllegalArgumentException("Only square cube map faces supported");
         }
-        boolean isPow2 = (width & (width - 1)) == 0;
+        boolean isPow2 = (height & (height - 1)) == 0;
         if (!isPow2) {
             throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
         }
 
         Element e = elementFromBitmap(rs, b);
         Type.Builder tb = new Type.Builder(rs, e);
-        tb.setX(width);
-        tb.setY(width);
+        tb.setX(height);
+        tb.setY(height);
         tb.setFaces(true);
         tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
         Type t = tb.create();
@@ -495,12 +684,136 @@
         return new Allocation(id, rs, t, usage);
     }
 
-    static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
-                                                     CubemapLayout layout) {
+    /**
+     * Creates a non-mipmapped cubemap allocation for use as a
+     * graphics texture from a bitmap containing the horizontal list
+     * of cube faces. Each individual face must be the same size and
+     * power of 2
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param b bitmap with cubemap faces layed out in the following
+     *          format: right, left, top, bottom, front, back
+     *
+     * @return allocation containing cubemap data
+     *
+     */
+    static public Allocation createCubemapFromBitmap(RenderScript rs,
+                                                     Bitmap b) {
         return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
-                                       layout, USAGE_GRAPHICS_TEXTURE);
+                                       USAGE_GRAPHICS_TEXTURE);
     }
 
+    /**
+     * Creates a cubemap allocation from 6 bitmaps containing
+     * the cube faces. All the faces must be the same size and
+     * power of 2
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param xpos cubemap face in the positive x direction
+     * @param xneg cubemap face in the negative x direction
+     * @param ypos cubemap face in the positive y direction
+     * @param yneg cubemap face in the negative y direction
+     * @param zpos cubemap face in the positive z direction
+     * @param zneg cubemap face in the negative z direction
+     * @param mips specifies desired mipmap behaviour for the cubemap
+     * @param usage bit field specifying how the cubemap is utilized
+     *
+     * @return allocation containing cubemap data
+     *
+     */
+    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
+                                                        Bitmap xpos,
+                                                        Bitmap xneg,
+                                                        Bitmap ypos,
+                                                        Bitmap yneg,
+                                                        Bitmap zpos,
+                                                        Bitmap zneg,
+                                                        MipmapControl mips,
+                                                        int usage) {
+        int height = xpos.getHeight();
+        if (xpos.getWidth() != height ||
+            xneg.getWidth() != height || xneg.getHeight() != height ||
+            ypos.getWidth() != height || ypos.getHeight() != height ||
+            yneg.getWidth() != height || yneg.getHeight() != height ||
+            zpos.getWidth() != height || zpos.getHeight() != height ||
+            zneg.getWidth() != height || zneg.getHeight() != height) {
+            throw new RSIllegalArgumentException("Only square cube map faces supported");
+        }
+        boolean isPow2 = (height & (height - 1)) == 0;
+        if (!isPow2) {
+            throw new RSIllegalArgumentException("Only power of 2 cube faces supported");
+        }
+
+        Element e = elementFromBitmap(rs, xpos);
+        Type.Builder tb = new Type.Builder(rs, e);
+        tb.setX(height);
+        tb.setY(height);
+        tb.setFaces(true);
+        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
+        Type t = tb.create();
+        Allocation cubemap = Allocation.createTyped(rs, t, mips, usage);
+
+        AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap);
+        adapter.setFace(Type.CubemapFace.POSITVE_X);
+        adapter.copyFrom(xpos);
+        adapter.setFace(Type.CubemapFace.NEGATIVE_X);
+        adapter.copyFrom(xneg);
+        adapter.setFace(Type.CubemapFace.POSITVE_Y);
+        adapter.copyFrom(ypos);
+        adapter.setFace(Type.CubemapFace.NEGATIVE_Y);
+        adapter.copyFrom(yneg);
+        adapter.setFace(Type.CubemapFace.POSITVE_Z);
+        adapter.copyFrom(zpos);
+        adapter.setFace(Type.CubemapFace.NEGATIVE_Z);
+        adapter.copyFrom(zneg);
+
+        return cubemap;
+    }
+
+    /**
+     * Creates a non-mipmapped cubemap allocation for use as a
+     * graphics texture from 6 bitmaps containing
+     * the cube faces. All the faces must be the same size and
+     * power of 2
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param xpos cubemap face in the positive x direction
+     * @param xneg cubemap face in the negative x direction
+     * @param ypos cubemap face in the positive y direction
+     * @param yneg cubemap face in the negative y direction
+     * @param zpos cubemap face in the positive z direction
+     * @param zneg cubemap face in the negative z direction
+     *
+     * @return allocation containing cubemap data
+     *
+     */
+    static public Allocation createCubemapFromCubeFaces(RenderScript rs,
+                                                        Bitmap xpos,
+                                                        Bitmap xneg,
+                                                        Bitmap ypos,
+                                                        Bitmap yneg,
+                                                        Bitmap zpos,
+                                                        Bitmap zneg) {
+        return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg,
+                                          zpos, zneg, MipmapControl.MIPMAP_NONE,
+                                          USAGE_GRAPHICS_TEXTURE);
+    }
+
+    /**
+     * Creates a renderscript allocation from the bitmap referenced
+     * by resource id
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param res application resources
+     * @param id resource id to load the data from
+     * @param mips specifies desired mipmap behaviour for the
+     *             allocation
+     * @param usage bit field specifying how the allocation is
+     *              utilized
+     *
+     * @return renderscript allocation containing resource data
+     *
+     */
     static public Allocation createFromBitmapResource(RenderScript rs,
                                                       Resources res,
                                                       int id,
@@ -514,6 +827,17 @@
         return alloc;
     }
 
+    /**
+     * Creates a non-mipmapped renderscript allocation to use as a
+     * graphics texture from the bitmap referenced by resource id
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param res application resources
+     * @param id resource id to load the data from
+     *
+     * @return renderscript allocation containing resource data
+     *
+     */
     static public Allocation createFromBitmapResource(RenderScript rs,
                                                       Resources res,
                                                       int id) {
@@ -522,19 +846,16 @@
                                         USAGE_GRAPHICS_TEXTURE);
     }
 
-/*
-    static public Allocation createFromBitmapResource(RenderScript rs,
-                                                      Resources res,
-                                                      int id,
-                                                      Element dstFmt,
-                                                      boolean genMips) {
-        MipmapControl mc = MipmapControl.MIPMAP_NONE;
-        if (genMips) {
-            mc = MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE;
-        }
-        return createFromBitmapResource(rs, res, id, mc, USAGE_GRAPHICS_TEXTURE);
-    }
-*/
+    /**
+     * Creates a renderscript allocation containing string data
+     * encoded in UTF-8 format
+     *
+     * @param rs Context to which the allocation will belong.
+     * @param str string to create the allocation from
+     * @param usage bit field specifying how the allocaiton is
+     *              utilized
+     *
+     */
     static public Allocation createFromString(RenderScript rs,
                                               String str,
                                               int usage) {
diff --git a/graphics/java/android/renderscript/AllocationAdapter.java b/graphics/java/android/renderscript/AllocationAdapter.java
new file mode 100644
index 0000000..f2fedea
--- /dev/null
+++ b/graphics/java/android/renderscript/AllocationAdapter.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.content.res.Resources;
+import android.content.res.AssetManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.util.Log;
+import android.util.TypedValue;
+
+/**
+ *
+ **/
+public class AllocationAdapter extends Allocation {
+    private int mSelectedDimX;
+    private int mSelectedDimY;
+    private int mSelectedCount;
+    private Allocation mAlloc;
+
+    private int mSelectedLOD = 0;
+    private Type.CubemapFace mSelectedFace = Type.CubemapFace.POSITVE_X;;
+
+    AllocationAdapter(int id, RenderScript rs, Allocation alloc) {
+        super(id, rs, null, alloc.mUsage);
+        Type t = alloc.getType();
+        mSelectedDimX = t.getX();
+        mSelectedDimY = t.getY();
+        mSelectedCount = t.getCount();
+    }
+
+
+    public void copyFrom(BaseObj[] d) {
+        mRS.validate();
+        if (d.length != mSelectedCount) {
+            throw new RSIllegalArgumentException("Array size mismatch, allocation size = " +
+                                                 mSelectedCount + ", array length = " + d.length);
+        }
+        int i[] = new int[d.length];
+        for (int ct=0; ct < d.length; ct++) {
+            i[ct] = d[ct].getID();
+        }
+        subData1D(0, mType.getCount(), i);
+    }
+
+    void validateBitmap(Bitmap b) {
+        mRS.validate();
+        if(mSelectedDimX != b.getWidth() ||
+           mSelectedDimY != b.getHeight()) {
+            throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
+        }
+    }
+
+    public void copyFrom(int[] d) {
+        mRS.validate();
+        subData1D(0, mSelectedCount, d);
+    }
+    public void copyFrom(short[] d) {
+        mRS.validate();
+        subData1D(0, mSelectedCount, d);
+    }
+    public void copyFrom(byte[] d) {
+        mRS.validate();
+        subData1D(0, mSelectedCount, d);
+    }
+    public void copyFrom(float[] d) {
+        mRS.validate();
+        subData1D(0, mSelectedCount, d);
+    }
+    public void copyFrom(Bitmap b) {
+        validateBitmap(b);
+        mRS.nAllocationCopyFromBitmap(getID(), b);
+    }
+
+    public void copyTo(Bitmap b) {
+        validateBitmap(b);
+        mRS.nAllocationCopyToBitmap(getID(), b);
+    }
+
+
+    public void subData(int xoff, FieldPacker fp) {
+        int eSize = mType.mElement.getSizeBytes();
+        final byte[] data = fp.getData();
+
+        int count = data.length / eSize;
+        if ((eSize * count) != data.length) {
+            throw new RSIllegalArgumentException("Field packer length " + data.length +
+                                               " not divisible by element size " + eSize + ".");
+        }
+        data1DChecks(xoff, count, data.length, data.length);
+        mRS.nAllocationData1D(getID(), xoff, mSelectedLOD, count, data, data.length);
+    }
+
+
+    public void subElementData(int xoff, int component_number, FieldPacker fp) {
+        if (component_number >= mType.mElement.mElements.length) {
+            throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
+        }
+        if(xoff < 0) {
+            throw new RSIllegalArgumentException("Offset must be >= 0.");
+        }
+
+        final byte[] data = fp.getData();
+        int eSize = mType.mElement.mElements[component_number].getSizeBytes();
+
+        if (data.length != eSize) {
+            throw new RSIllegalArgumentException("Field packer sizelength " + data.length +
+                                               " does not match component size " + eSize + ".");
+        }
+
+        mRS.nAllocationElementData1D(getID(), xoff, mSelectedLOD, component_number, data, data.length);
+    }
+
+    void data1DChecks(int off, int count, int len, int dataSize) {
+        mRS.validate();
+        if(off < 0) {
+            throw new RSIllegalArgumentException("Offset must be >= 0.");
+        }
+        if(count < 1) {
+            throw new RSIllegalArgumentException("Count must be >= 1.");
+        }
+        if((off + count) > mSelectedDimX * mSelectedDimY) {
+            throw new RSIllegalArgumentException("Overflow, Available count " + mType.getCount() +
+                                               ", got " + count + " at offset " + off + ".");
+        }
+        if((len) < dataSize) {
+            throw new RSIllegalArgumentException("Array too small for allocation type.");
+        }
+    }
+
+    public void subData1D(int off, int count, int[] d) {
+        int dataSize = mAlloc.mType.mElement.getSizeBytes() * count;
+        data1DChecks(off, count, d.length * 4, dataSize);
+        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+    }
+    public void subData1D(int off, int count, short[] d) {
+        int dataSize = mAlloc.mType.mElement.getSizeBytes() * count;
+        data1DChecks(off, count, d.length * 2, dataSize);
+        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+    }
+    public void subData1D(int off, int count, byte[] d) {
+        int dataSize = mAlloc.mType.mElement.getSizeBytes() * count;
+        data1DChecks(off, count, d.length, dataSize);
+        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+    }
+    public void subData1D(int off, int count, float[] d) {
+        int dataSize = mAlloc.mType.mElement.getSizeBytes() * count;
+        data1DChecks(off, count, d.length * 4, dataSize);
+        mRS.nAllocationData1D(getID(), off, mSelectedLOD, count, d, dataSize);
+    }
+
+
+    public void subData2D(int xoff, int yoff, int w, int h, int[] d) {
+        mRS.validate();
+        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h, d, d.length * 4);
+    }
+
+    public void subData2D(int xoff, int yoff, int w, int h, float[] d) {
+        mRS.validate();
+        mRS.nAllocationData2D(getID(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h, d, d.length * 4);
+    }
+
+    public void readData(int[] d) {
+        mRS.validate();
+        mRS.nAllocationRead(getID(), d);
+    }
+
+    public void readData(float[] d) {
+        mRS.validate();
+        mRS.nAllocationRead(getID(), d);
+    }
+
+    public void setLOD(int lod) {
+    }
+
+    public void setFace(Type.CubemapFace cf) {
+    }
+
+    public void setY(int y) {
+    }
+
+    public void setZ(int z) {
+    }
+
+    // creation
+    //static public AllocationAdapter create1D(RenderScript rs, Allocation a) {
+    //}
+
+    static public AllocationAdapter create2D(RenderScript rs, Allocation a) {
+        rs.validate();
+        AllocationAdapter aa = new AllocationAdapter(0, rs, a);
+        return aa;
+    }
+
+
+}
+
+
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index 05f1bec..669beac 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -19,8 +19,6 @@
 import android.util.Log;
 
 /**
- * @hide
- *
  * BaseObj is the base class for interfacing with native renderscript objects.
  * It primarly contains code for tracking the native object ID and forcably
  * disconecting the object from the native allocation for early cleanup.
diff --git a/graphics/java/android/renderscript/Byte2.java b/graphics/java/android/renderscript/Byte2.java
index 95cf88c..6d2994d 100644
--- a/graphics/java/android/renderscript/Byte2.java
+++ b/graphics/java/android/renderscript/Byte2.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs byte2 type back to java applications.
  *
  **/
 public class Byte2 {
diff --git a/graphics/java/android/renderscript/Byte3.java b/graphics/java/android/renderscript/Byte3.java
index a6c0ca9..dd73914 100644
--- a/graphics/java/android/renderscript/Byte3.java
+++ b/graphics/java/android/renderscript/Byte3.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs byte3 type back to java applications.
  *
  **/
 public class Byte3 {
diff --git a/graphics/java/android/renderscript/Byte4.java b/graphics/java/android/renderscript/Byte4.java
index a5bfc61..ebea589 100644
--- a/graphics/java/android/renderscript/Byte4.java
+++ b/graphics/java/android/renderscript/Byte4.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs byte4 type back to java applications.
  *
  **/
 public class Byte4 {
diff --git a/graphics/java/android/renderscript/Dimension.java b/graphics/java/android/renderscript/Dimension.java
deleted file mode 100644
index f29057d..0000000
--- a/graphics/java/android/renderscript/Dimension.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.renderscript;
-
-/**
- * @hide
- **/
-public enum Dimension {
-    X (0),
-    Y (1),
-    Z (2),
-    LOD (3),
-    FACE (4),
-    ARRAY_0 (100);
-
-    int mID;
-    Dimension(int id) {
-        mID = id;
-    }
-}
-
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 7616316..10dc35b 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -20,8 +20,6 @@
 import android.util.Log;
 
 /**
- * @hide
- *
  * Element is the basic data type of RenderScript.  An element can be of 2
  * forms.  Basic elements contain a single component of data.  This can be of
  * any of the legal RS types.  Examples of basic element types.
@@ -427,7 +425,13 @@
 
     Element(int id, RenderScript rs, DataType dt, DataKind dk, boolean norm, int size) {
         super(id, rs);
-        mSize = dt.mSize * size;
+        if ((dt != DataType.UNSIGNED_5_6_5) &&
+            (dt != DataType.UNSIGNED_4_4_4_4) &&
+            (dt != DataType.UNSIGNED_5_5_5_1)) {
+            mSize = dt.mSize * size;
+        } else {
+            mSize = dt.mSize;
+        }
         mType = dt;
         mKind = dk;
         mNormalized = norm;
diff --git a/graphics/java/android/renderscript/FieldPacker.java b/graphics/java/android/renderscript/FieldPacker.java
index ff3e22b..2fb3d95 100644
--- a/graphics/java/android/renderscript/FieldPacker.java
+++ b/graphics/java/android/renderscript/FieldPacker.java
@@ -18,7 +18,8 @@
 
 
 /**
- * @hide
+ * Utility class for packing arguments and structures from java objects to rs
+ * objects.
  *
  **/
 public class FieldPacker {
@@ -248,19 +249,19 @@
         addU32(v.w);
     }
 
-    public void addObj(Matrix4f v) {
+    public void addMatrix(Matrix4f v) {
         for (int i=0; i < v.mMat.length; i++) {
             addF32(v.mMat[i]);
         }
     }
 
-    public void addObj(Matrix3f v) {
+    public void addMatrix(Matrix3f v) {
         for (int i=0; i < v.mMat.length; i++) {
             addF32(v.mMat[i]);
         }
     }
 
-    public void addObj(Matrix2f v) {
+    public void addMatrix(Matrix2f v) {
         for (int i=0; i < v.mMat.length; i++) {
             addF32(v.mMat[i]);
         }
diff --git a/graphics/java/android/renderscript/FileA3D.java b/graphics/java/android/renderscript/FileA3D.java
index af85d8e..fe3971a 100644
--- a/graphics/java/android/renderscript/FileA3D.java
+++ b/graphics/java/android/renderscript/FileA3D.java
@@ -16,73 +16,102 @@
 
 package android.renderscript;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 
-import android.content.res.Resources;
 import android.content.res.AssetManager;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.util.Log;
 import android.util.TypedValue;
 
 /**
- * @hide
+ * FileA3D allows users to load renderscript objects from files
+ * or resources stored on disk. It could be used to load items
+ * such as 3d geometry data converted a renderscript format from
+ * content creation tools. Currently only meshes are supported
+ * in FileA3D.
+ *
+ * When successfully loaded, FileA3D will contain a list of
+ * index entries for all the objects stored inside it.
  *
  **/
 public class FileA3D extends BaseObj {
 
-    public enum ClassID {
+    /**
+    * Specifies what renderscript object type is contained within
+    * the FileA3D IndexEntry
+    **/
+    public enum EntryType {
 
-        UNKNOWN,
-        MESH,
-        TYPE,
-        ELEMENT,
-        ALLOCATION,
-        PROGRAM_VERTEX,
-        PROGRAM_RASTER,
-        PROGRAM_FRAGMENT,
-        PROGRAM_STORE,
-        SAMPLER,
-        ANIMATION,
-        ADAPTER_1D,
-        ADAPTER_2D,
-        SCRIPT_C;
+        UNKNOWN (0),
+        MESH (1);
 
-        public static ClassID toClassID(int intID) {
-            return ClassID.values()[intID];
+        int mID;
+        EntryType(int id) {
+            mID = id;
+        }
+
+        static EntryType toEntryType(int intID) {
+            return EntryType.values()[intID];
         }
     }
 
-    // Read only class with index entries
+    /**
+    * IndexEntry contains information about one of the renderscript
+    * objects inside the file's index. It could be used to query the
+    * object's type and name and load the object itself if
+    * necessary.
+    */
     public static class IndexEntry {
         RenderScript mRS;
         int mIndex;
         int mID;
         String mName;
-        ClassID mClassID;
+        EntryType mEntryType;
         BaseObj mLoadedObj;
 
+        /**
+        * @return name of a renderscript object the index entry
+        *         describes
+        */
         public String getName() {
             return mName;
         }
 
-        public ClassID getClassID() {
-            return mClassID;
+        /**
+        * @return type of a renderscript object the index entry
+        *         describes
+        */
+        public EntryType getEntryType() {
+            return mEntryType;
         }
 
+        /**
+        * @return renderscript object described by the entry
+        */
         public BaseObj getObject() {
             mRS.validate();
             BaseObj obj = internalCreate(mRS, this);
             return obj;
         }
 
+        /**
+        * @return renderscript mesh object described by the entry
+        */
+        public Mesh getMesh() {
+            return (Mesh)getObject();
+        }
+
         static synchronized BaseObj internalCreate(RenderScript rs, IndexEntry entry) {
             if(entry.mLoadedObj != null) {
                 return entry.mLoadedObj;
             }
 
-            if(entry.mClassID == ClassID.UNKNOWN) {
+            // to be purged on cleanup
+            if(entry.mEntryType == EntryType.UNKNOWN) {
                 return null;
             }
 
@@ -91,51 +120,22 @@
                 return null;
             }
 
-            switch (entry.mClassID) {
+            switch (entry.mEntryType) {
             case MESH:
                 entry.mLoadedObj = new Mesh(objectID, rs);
                 break;
-            case TYPE:
-                entry.mLoadedObj = new Type(objectID, rs);
-                break;
-            case ELEMENT:
-                entry.mLoadedObj = null;
-                break;
-            case ALLOCATION:
-                entry.mLoadedObj = null;
-                break;
-            case PROGRAM_VERTEX:
-                entry.mLoadedObj = new ProgramVertex(objectID, rs);
-                break;
-            case PROGRAM_RASTER:
-                break;
-            case PROGRAM_FRAGMENT:
-                break;
-            case PROGRAM_STORE:
-                break;
-            case SAMPLER:
-                break;
-            case ANIMATION:
-                break;
-            case ADAPTER_1D:
-                break;
-            case ADAPTER_2D:
-                break;
-            case SCRIPT_C:
-                break;
             }
 
             entry.mLoadedObj.updateFromNative();
-
             return entry.mLoadedObj;
         }
 
-        IndexEntry(RenderScript rs, int index, int id, String name, ClassID classID) {
+        IndexEntry(RenderScript rs, int index, int id, String name, EntryType type) {
             mRS = rs;
             mIndex = index;
             mID = id;
             mName = name;
-            mClassID = classID;
+            mEntryType = type;
             mLoadedObj = null;
         }
     }
@@ -161,48 +161,114 @@
         mRS.nFileA3DGetIndexEntries(getID(), numFileEntries, ids, names);
 
         for(int i = 0; i < numFileEntries; i ++) {
-            mFileEntries[i] = new IndexEntry(mRS, i, getID(), names[i], ClassID.toClassID(ids[i]));
+            mFileEntries[i] = new IndexEntry(mRS, i, getID(), names[i], EntryType.toEntryType(ids[i]));
         }
     }
 
-    public int getNumIndexEntries() {
+    /**
+    * @return the numberof objects stored inside a FileA3D
+    */
+    public int getIndexEntryCount() {
         if(mFileEntries == null) {
             return 0;
         }
         return mFileEntries.length;
     }
 
+    /**
+    * Returns an index entry from the list of all objects inside
+    * FileA3D
+    *
+    * @param index number of the entry from the list to return
+    */
     public IndexEntry getIndexEntry(int index) {
-        if(getNumIndexEntries() == 0 || index < 0 || index >= mFileEntries.length) {
+        if(getIndexEntryCount() == 0 || index < 0 || index >= mFileEntries.length) {
             return null;
         }
         return mFileEntries[index];
     }
 
-    static public FileA3D createFromResource(RenderScript rs, Resources res, int id)
-        throws IllegalArgumentException {
+    /**
+    * Creates a FileA3D object from an asset stored on disk
+    *
+    * @param rs Context to which the object will belong.
+    * @param mgr asset manager used to load asset
+    * @param path location of the file to load
+    *
+    */
+    static public FileA3D createFromAsset(RenderScript rs, AssetManager mgr, String path) {
+        rs.validate();
+        int fileId = rs.nFileA3DCreateFromAsset(mgr, path);
+
+        if(fileId == 0) {
+            throw new RSRuntimeException("Unable to create a3d file from asset " + path);
+        }
+        FileA3D fa3d = new FileA3D(fileId, rs, null);
+        fa3d.initEntries();
+        return fa3d;
+    }
+
+    /**
+    * Creates a FileA3D object from a file stored on disk
+    *
+    * @param rs Context to which the object will belong.
+    * @param path location of the file to load
+    *
+    */
+    static public FileA3D createFromFile(RenderScript rs, String path) {
+        int fileId = rs.nFileA3DCreateFromFile(path);
+
+        if(fileId == 0) {
+            throw new RSRuntimeException("Unable to create a3d file from " + path);
+        }
+        FileA3D fa3d = new FileA3D(fileId, rs, null);
+        fa3d.initEntries();
+        return fa3d;
+    }
+
+    /**
+    * Creates a FileA3D object from a file stored on disk
+    *
+    * @param rs Context to which the object will belong.
+    * @param path location of the file to load
+    *
+    */
+    static public FileA3D createFromFile(RenderScript rs, File path) {
+        return createFromFile(rs, path.getAbsolutePath());
+    }
+
+    /**
+    * Creates a FileA3D object from an application resource
+    *
+    * @param rs Context to which the object will belong.
+    * @param res resource manager used for loading
+    * @param id resource to create FileA3D from
+    *
+    */
+    static public FileA3D createFromResource(RenderScript rs, Resources res, int id) {
 
         rs.validate();
         InputStream is = null;
         try {
-            final TypedValue value = new TypedValue();
-            is = res.openRawResource(id, value);
-
-            int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
-
-            int fileId = rs.nFileA3DCreateFromAssetStream(asset);
-
-            if(fileId == 0) {
-                throw new IllegalStateException("Load failed.");
-            }
-            FileA3D fa3d = new FileA3D(fileId, rs, is);
-            fa3d.initEntries();
-            return fa3d;
-
+            is = res.openRawResource(id);
         } catch (Exception e) {
-            // Ignore
+            throw new RSRuntimeException("Unable to open resource " + id);
         }
 
-        return null;
+        int fileId = 0;
+        if (is instanceof AssetManager.AssetInputStream) {
+            int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
+            fileId = rs.nFileA3DCreateFromAssetStream(asset);
+        } else {
+            throw new RSRuntimeException("Unsupported asset stream");
+        }
+
+        if(fileId == 0) {
+            throw new RSRuntimeException("Unable to create a3d file from resource " + id);
+        }
+        FileA3D fa3d = new FileA3D(fileId, rs, is);
+        fa3d.initEntries();
+        return fa3d;
+
     }
 }
diff --git a/graphics/java/android/renderscript/Float2.java b/graphics/java/android/renderscript/Float2.java
index 889bf7b..0a099f1 100644
--- a/graphics/java/android/renderscript/Float2.java
+++ b/graphics/java/android/renderscript/Float2.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs float2 type back to java applications.
  *
  **/
 public class Float2 {
diff --git a/graphics/java/android/renderscript/Float3.java b/graphics/java/android/renderscript/Float3.java
index ebe140d..2ffa326 100644
--- a/graphics/java/android/renderscript/Float3.java
+++ b/graphics/java/android/renderscript/Float3.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs float3 type back to java applications.
  *
  **/
 public class Float3 {
diff --git a/graphics/java/android/renderscript/Float4.java b/graphics/java/android/renderscript/Float4.java
index 847732f..19d91dc 100644
--- a/graphics/java/android/renderscript/Float4.java
+++ b/graphics/java/android/renderscript/Float4.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs float4 type back to java applications.
  *
  **/
 public class Float4 {
diff --git a/graphics/java/android/renderscript/Font.java b/graphics/java/android/renderscript/Font.java
index de25014..252ffc1 100644
--- a/graphics/java/android/renderscript/Font.java
+++ b/graphics/java/android/renderscript/Font.java
@@ -16,18 +16,20 @@
 
 package android.renderscript;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.Map;
 import java.util.HashMap;
+import java.util.Map;
 
-import android.content.res.Resources;
+import android.os.Environment;
+
 import android.content.res.AssetManager;
+import android.content.res.Resources;
 import android.util.Log;
 import android.util.TypedValue;
 
 /**
- * @hide
  *
  **/
 public class Font extends BaseObj {
@@ -126,26 +128,62 @@
     /**
      * Takes a specific file name as an argument
      */
-    static public Font create(RenderScript rs, Resources res, String fileName, int size)
-        throws IllegalArgumentException {
+    static public Font createFromFile(RenderScript rs, Resources res, String path, float pointSize) {
+        rs.validate();
+        int dpi = res.getDisplayMetrics().densityDpi;
+        int fontId = rs.nFontCreateFromFile(path, pointSize, dpi);
+
+        if(fontId == 0) {
+            throw new RSRuntimeException("Unable to create font from file " + path);
+        }
+        Font rsFont = new Font(fontId, rs);
+
+        return rsFont;
+    }
+
+    static public Font createFromFile(RenderScript rs, Resources res, File path, float pointSize) {
+        return createFromFile(rs, res, path.getAbsolutePath(), pointSize);
+    }
+
+    static public Font createFromAsset(RenderScript rs, Resources res, String path, float pointSize) {
+        rs.validate();
+        AssetManager mgr = res.getAssets();
+        int dpi = res.getDisplayMetrics().densityDpi;
+
+        int fontId = rs.nFontCreateFromAsset(mgr, path, pointSize, dpi);
+        if(fontId == 0) {
+            throw new RSRuntimeException("Unable to create font from asset " + path);
+        }
+        Font rsFont = new Font(fontId, rs);
+        return rsFont;
+    }
+
+    static public Font createFromResource(RenderScript rs, Resources res, int id, float pointSize) {
+        String name = "R." + Integer.toString(id);
 
         rs.validate();
+        InputStream is = null;
         try {
-            int dpi = res.getDisplayMetrics().densityDpi;
-            int fontId = rs.nFontCreateFromFile(fileName, size, dpi);
-
-            if(fontId == 0) {
-                throw new IllegalStateException("Failed loading a font");
-            }
-            Font rsFont = new Font(fontId, rs);
-
-            return rsFont;
-
+            is = res.openRawResource(id);
         } catch (Exception e) {
-            // Ignore
+            throw new RSRuntimeException("Unable to open resource " + id);
         }
 
-        return null;
+        int dpi = res.getDisplayMetrics().densityDpi;
+
+        int fontId = 0;
+        if (is instanceof AssetManager.AssetInputStream) {
+            int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
+            fontId = rs.nFontCreateFromAssetStream(name, pointSize, dpi, asset);
+        } else {
+            throw new RSRuntimeException("Unsupported asset stream created");
+        }
+
+        if(fontId == 0) {
+            throw new RSRuntimeException("Unable to create font from resource " + id);
+        }
+        Font rsFont = new Font(fontId, rs);
+        return rsFont;
     }
 
     /**
@@ -157,9 +195,11 @@
      * "monospace" "courier" "courier new" "monaco"
      * Returns default font if no match could be found
      */
-    static public Font createFromFamily(RenderScript rs, Resources res, String familyName, Style fontStyle, int size)
-    throws IllegalArgumentException {
+    static public Font create(RenderScript rs, Resources res, String familyName, Style fontStyle, float pointSize) {
         String fileName = getFontFileName(familyName, fontStyle);
-        return create(rs, res, fileName, size);
+        String fontPath = Environment.getRootDirectory().getAbsolutePath();
+        fontPath += "/fonts/" + fileName;
+        return createFromFile(rs, res, fontPath, pointSize);
     }
+
 }
diff --git a/graphics/java/android/renderscript/Int2.java b/graphics/java/android/renderscript/Int2.java
index 56e2fe9..8eceb71 100644
--- a/graphics/java/android/renderscript/Int2.java
+++ b/graphics/java/android/renderscript/Int2.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs int2 type back to java applications.
  *
  **/
 public class Int2 {
diff --git a/graphics/java/android/renderscript/Int3.java b/graphics/java/android/renderscript/Int3.java
index 1b27509..bbd296e 100644
--- a/graphics/java/android/renderscript/Int3.java
+++ b/graphics/java/android/renderscript/Int3.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs int3 type back to java applications.
  *
  **/
 public class Int3 {
diff --git a/graphics/java/android/renderscript/Int4.java b/graphics/java/android/renderscript/Int4.java
index 3d6f3f5..c3ae112c 100644
--- a/graphics/java/android/renderscript/Int4.java
+++ b/graphics/java/android/renderscript/Int4.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs int4 type back to java applications.
  *
  **/
 public class Int4 {
diff --git a/graphics/java/android/renderscript/Long2.java b/graphics/java/android/renderscript/Long2.java
index 11ead2f..834d13c 100644
--- a/graphics/java/android/renderscript/Long2.java
+++ b/graphics/java/android/renderscript/Long2.java
@@ -21,7 +21,6 @@
 
 
 /**
- * @hide
  *
  **/
 public class Long2 {
diff --git a/graphics/java/android/renderscript/Long3.java b/graphics/java/android/renderscript/Long3.java
index 1604532..c6d7289 100644
--- a/graphics/java/android/renderscript/Long3.java
+++ b/graphics/java/android/renderscript/Long3.java
@@ -21,7 +21,6 @@
 
 
 /**
- * @hide
  *
  **/
 public class Long3 {
diff --git a/graphics/java/android/renderscript/Long4.java b/graphics/java/android/renderscript/Long4.java
index 2fd2747..032c1d3 100644
--- a/graphics/java/android/renderscript/Long4.java
+++ b/graphics/java/android/renderscript/Long4.java
@@ -21,7 +21,6 @@
 
 
 /**
- * @hide
  *
  **/
 public class Long4 {
diff --git a/graphics/java/android/renderscript/Matrix2f.java b/graphics/java/android/renderscript/Matrix2f.java
index 99d23db..2fffe8c 100644
--- a/graphics/java/android/renderscript/Matrix2f.java
+++ b/graphics/java/android/renderscript/Matrix2f.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs_matrix2x2 type back to java applications.
  *
  **/
 public class Matrix2f {
@@ -31,6 +31,15 @@
         loadIdentity();
     }
 
+    public Matrix2f(float[] dataArray) {
+        mMat = new float[2];
+        System.arraycopy(dataArray, 0, mMat, 0, mMat.length);
+    }
+
+    public float[] getArray() {
+        return mMat;
+    }
+
     public float get(int i, int j) {
         return mMat[i*2 + j];
     }
@@ -48,7 +57,7 @@
     }
 
     public void load(Matrix2f src) {
-        System.arraycopy(mMat, 0, src, 0, 4);
+        System.arraycopy(src.getArray(), 0, mMat, 0, mMat.length);
     }
 
     public void loadRotate(float rot) {
diff --git a/graphics/java/android/renderscript/Matrix3f.java b/graphics/java/android/renderscript/Matrix3f.java
index 961bc5d..e4c5e00 100644
--- a/graphics/java/android/renderscript/Matrix3f.java
+++ b/graphics/java/android/renderscript/Matrix3f.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs_matrix3x3 type back to java applications.
  *
  **/
 public class Matrix3f {
@@ -31,6 +31,15 @@
         loadIdentity();
     }
 
+    public Matrix3f(float[] dataArray) {
+        mMat = new float[9];
+        System.arraycopy(dataArray, 0, mMat, 0, mMat.length);
+    }
+
+    public float[] getArray() {
+        return mMat;
+    }
+
     public float get(int i, int j) {
         return mMat[i*3 + j];
     }
@@ -54,7 +63,7 @@
     }
 
     public void load(Matrix3f src) {
-        System.arraycopy(mMat, 0, src, 0, 9);
+        System.arraycopy(src.getArray(), 0, mMat, 0, mMat.length);
     }
 
     public void loadRotate(float rot, float x, float y, float z) {
diff --git a/graphics/java/android/renderscript/Matrix4f.java b/graphics/java/android/renderscript/Matrix4f.java
index 5ffc21a..ec07cd5 100644
--- a/graphics/java/android/renderscript/Matrix4f.java
+++ b/graphics/java/android/renderscript/Matrix4f.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs_matrix4x4 type back to java applications.
  *
  **/
 public class Matrix4f {
@@ -31,6 +31,15 @@
         loadIdentity();
     }
 
+    public Matrix4f(float[] dataArray) {
+        mMat = new float[16];
+        System.arraycopy(dataArray, 0, mMat, 0, mMat.length);
+    }
+
+    public float[] getArray() {
+        return mMat;
+    }
+
     public float get(int i, int j) {
         return mMat[i*4 + j];
     }
@@ -62,7 +71,7 @@
     }
 
     public void load(Matrix4f src) {
-        System.arraycopy(mMat, 0, src, 0, 16);
+        System.arraycopy(src.getArray(), 0, mMat, 0, mMat.length);
     }
 
     public void loadRotate(float rot, float x, float y, float z) {
@@ -147,6 +156,10 @@
         mMat[14]= -(f + n) / (f - n);
     }
 
+    public void loadOrthoWindow(int w, int h) {
+        loadOrtho(0,w, h,0, -1,1);
+    }
+
     public void loadFrustum(float l, float r, float b, float t, float n, float f) {
         loadIdentity();
         mMat[0] = 2 * n / (r - l);
@@ -159,6 +172,40 @@
         mMat[15]= 0;
     }
 
+    public void loadPerspective(float fovy, float aspect, float near, float far) {
+        float top = near * (float)Math.tan((float) (fovy * Math.PI / 360.0f));
+        float bottom = -top;
+        float left = bottom * aspect;
+        float right = top * aspect;
+        loadFrustum(left, right, bottom, top, near, far);
+    }
+
+    public void loadProjectionNormalized(int w, int h) {
+        // range -1,1 in the narrow axis at z = 0.
+        Matrix4f m1 = new Matrix4f();
+        Matrix4f m2 = new Matrix4f();
+
+        if(w > h) {
+            float aspect = ((float)w) / h;
+            m1.loadFrustum(-aspect,aspect,  -1,1,  1,100);
+        } else {
+            float aspect = ((float)h) / w;
+            m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
+        }
+
+        m2.loadRotate(180, 0, 1, 0);
+        m1.loadMultiply(m1, m2);
+
+        m2.loadScale(-2, 2, 1);
+        m1.loadMultiply(m1, m2);
+
+        m2.loadTranslate(0, 0, 2);
+        m1.loadMultiply(m1, m2);
+
+        load(m1);
+    }
+
+
     public void multiply(Matrix4f rhs) {
         Matrix4f tmp = new Matrix4f();
         tmp.loadMultiply(this, rhs);
diff --git a/graphics/java/android/renderscript/Mesh.java b/graphics/java/android/renderscript/Mesh.java
index b103af4..fcf8178 100644
--- a/graphics/java/android/renderscript/Mesh.java
+++ b/graphics/java/android/renderscript/Mesh.java
@@ -22,11 +22,43 @@
 import android.util.Log;
 
 /**
- * @hide
+ * Mesh class is a container for geometric data displayed in
+ * renderscript.
+ *
+ * Internally, mesh is a collection of allocations that
+ * represent vertex data (positions, normals, texture
+ * coordinates) and index data such as triangles and lines.
+ *
+ * Vertex data could either be interlieved within one
+ * allocation, provided separately as multiple allocation
+ * objects or done as a combination of the above. When a
+ * vertex channel name matches an input in the vertex program,
+ * renderscript will automatically connect the two together.
+ *
+ *  Parts of the mesh could be rendered with either explicit
+ *  index sets or primitive types.
  *
  **/
 public class Mesh extends BaseObj {
 
+    /**
+    * Describes the way mesh vertex data is interpreted when rendering
+    *
+    **/
+    public enum Primitive {
+        POINT (0),
+        LINE (1),
+        LINE_STRIP (2),
+        TRIANGLE (3),
+        TRIANGLE_STRIP (4),
+        TRIANGLE_FAN (5);
+
+        int mID;
+        Primitive(int id) {
+            mID = id;
+        }
+    }
+
     Allocation[] mVertexBuffers;
     Allocation[] mIndexBuffers;
     Primitive[] mPrimitives;
@@ -35,25 +67,50 @@
         super(id, rs);
     }
 
+    /**
+    * @return number of allocations containing vertex data
+    *
+    **/
     public int getVertexAllocationCount() {
         if(mVertexBuffers == null) {
             return 0;
         }
         return mVertexBuffers.length;
     }
+    /**
+    * @param slot index in the list of allocations to return
+    * @return vertex data allocation at the given index
+    *
+    **/
     public Allocation getVertexAllocation(int slot) {
         return mVertexBuffers[slot];
     }
 
+    /**
+    * @return number of primitives or index sets in the mesh
+    *
+    **/
     public int getPrimitiveCount() {
         if(mIndexBuffers == null) {
             return 0;
         }
         return mIndexBuffers.length;
     }
-    public Allocation getIndexAllocation(int slot) {
+
+    /**
+    * @param slot locaton within the list of index set allocation
+    * @return allocation containing primtive index data or null if
+    *         the index data is not specified explicitly
+    *
+    **/
+    public Allocation getIndexSetAllocation(int slot) {
         return mIndexBuffers[slot];
     }
+    /**
+    * @param slot locaiton within the list of index set primitives
+    * @return index set primitive type
+    *
+    **/
     public Primitive getPrimitive(int slot) {
         return mPrimitives[slot];
     }
@@ -91,85 +148,151 @@
         }
     }
 
+    /**
+    * Mesh builder object. It starts empty and requires the user to
+    * add the types necessary to create vertex and index
+    * allocations
+    *
+    */
     public static class Builder {
         RenderScript mRS;
+        int mUsage;
 
         class Entry {
             Type t;
             Element e;
             int size;
             Primitive prim;
+            int usage;
         }
 
         int mVertexTypeCount;
         Entry[] mVertexTypes;
         Vector mIndexTypes;
 
-        public Builder(RenderScript rs) {
+        /**
+        * Creates builder object
+        * @param rs Context to which the mesh will belong.
+        * @param usage specifies how the mesh allocations are to be
+        *              handled, whether they need to be uploaded to a
+        *              buffer on the gpu, maintain a cpu copy, etc
+        */
+        public Builder(RenderScript rs, int usage) {
             mRS = rs;
+            mUsage = usage;
             mVertexTypeCount = 0;
             mVertexTypes = new Entry[16];
             mIndexTypes = new Vector();
         }
 
-        public int addVertexType(Type t) throws IllegalStateException {
+        /**
+        * @return internal index of the last vertex buffer type added to
+        *         builder
+        **/
+        public int getCurrentVertexTypeIndex() {
+            return mVertexTypeCount - 1;
+        }
+
+        /**
+        * @return internal index of the last index set added to the
+        *         builder
+        **/
+        public int getCurrentIndexSetIndex() {
+            return mIndexTypes.size() - 1;
+        }
+
+        /**
+        * Adds a vertex data type to the builder object
+        *
+        * @param t type of the vertex data allocation to be created
+        *
+        * @return this
+        **/
+        public Builder addVertexType(Type t) throws IllegalStateException {
             if (mVertexTypeCount >= mVertexTypes.length) {
                 throw new IllegalStateException("Max vertex types exceeded.");
             }
 
-            int addedIndex = mVertexTypeCount;
             mVertexTypes[mVertexTypeCount] = new Entry();
             mVertexTypes[mVertexTypeCount].t = t;
             mVertexTypes[mVertexTypeCount].e = null;
             mVertexTypeCount++;
-            return addedIndex;
+            return this;
         }
 
-        public int addVertexType(Element e, int size) throws IllegalStateException {
+        /**
+        * Adds a vertex data type to the builder object
+        *
+        * @param e element describing the vertex data layout
+        * @param size number of elements in the buffer
+        *
+        * @return this
+        **/
+        public Builder addVertexType(Element e, int size) throws IllegalStateException {
             if (mVertexTypeCount >= mVertexTypes.length) {
                 throw new IllegalStateException("Max vertex types exceeded.");
             }
 
-            int addedIndex = mVertexTypeCount;
             mVertexTypes[mVertexTypeCount] = new Entry();
             mVertexTypes[mVertexTypeCount].t = null;
             mVertexTypes[mVertexTypeCount].e = e;
             mVertexTypes[mVertexTypeCount].size = size;
             mVertexTypeCount++;
-            return addedIndex;
+            return this;
         }
 
-        public int addIndexType(Type t, Primitive p) {
-            int addedIndex  = mIndexTypes.size();
+        /**
+        * Adds an index set data type to the builder object
+        *
+        * @param t type of the index set data, could be null
+        * @param p primitive type
+        *
+        * @return this
+        **/
+        public Builder addIndexSetType(Type t, Primitive p) {
             Entry indexType = new Entry();
             indexType.t = t;
             indexType.e = null;
             indexType.size = 0;
             indexType.prim = p;
             mIndexTypes.addElement(indexType);
-            return addedIndex;
+            return this;
         }
 
-        public int addIndexType(Primitive p) {
-            int addedIndex  = mIndexTypes.size();
+        /**
+        * Adds an index set primitive type to the builder object
+        *
+        * @param p primitive type
+        *
+        * @return this
+        **/
+        public Builder addIndexSetType(Primitive p) {
             Entry indexType = new Entry();
             indexType.t = null;
             indexType.e = null;
             indexType.size = 0;
             indexType.prim = p;
             mIndexTypes.addElement(indexType);
-            return addedIndex;
+            return this;
         }
 
-        public int addIndexType(Element e, int size, Primitive p) {
-            int addedIndex  = mIndexTypes.size();
+        /**
+        * Adds an index set data type to the builder object
+        *
+        * @param e element describing the index set data layout
+        * @param size number of elements in the buffer
+        * @param p primitive type
+        *
+        * @return this
+        **/
+        public Builder addIndexSetType(Element e, int size, Primitive p) {
             Entry indexType = new Entry();
             indexType.t = null;
             indexType.e = e;
             indexType.size = size;
             indexType.prim = p;
             mIndexTypes.addElement(indexType);
-            return addedIndex;
+            return this;
         }
 
         Type newType(Element e, int size) {
@@ -190,10 +313,10 @@
                 Allocation alloc = null;
                 Entry entry = (Entry)b.mIndexTypes.elementAt(ct);
                 if (entry.t != null) {
-                    alloc = Allocation.createTyped(rs, entry.t);
+                    alloc = Allocation.createTyped(rs, entry.t, b.mUsage);
                 }
                 else if(entry.e != null) {
-                    alloc = Allocation.createSized(rs, entry.e, entry.size);
+                    alloc = Allocation.createSized(rs, entry.e, entry.size, b.mUsage);
                 }
                 int allocID = (alloc == null) ? 0 : alloc.getID();
                 rs.nMeshBindIndex(id, allocID, entry.prim.mID, ct);
@@ -205,9 +328,9 @@
                 Allocation alloc = null;
                 Entry entry = b.mVertexTypes[ct];
                 if (entry.t != null) {
-                    alloc = Allocation.createTyped(rs, entry.t);
+                    alloc = Allocation.createTyped(rs, entry.t, b.mUsage);
                 } else if(entry.e != null) {
-                    alloc = Allocation.createSized(rs, entry.e, entry.size);
+                    alloc = Allocation.createSized(rs, entry.e, entry.size, b.mUsage);
                 }
                 rs.nMeshBindVertex(id, alloc.getID(), ct);
                 newMesh.mVertexBuffers[ct] = alloc;
@@ -217,6 +340,10 @@
             return newMesh;
         }
 
+        /**
+        * Create a Mesh object from the current state of the builder
+        *
+        **/
         public Mesh create() {
             mRS.validate();
             Mesh sm = internalCreate(mRS, this);
@@ -224,6 +351,12 @@
         }
     }
 
+    /**
+    * Mesh builder object. It starts empty and requires the user to
+    * add all the vertex and index allocations that comprise the
+    * mesh
+    *
+    */
     public static class AllocationBuilder {
         RenderScript mRS;
 
@@ -244,34 +377,71 @@
             mIndexTypes = new Vector();
         }
 
-        public int addVertexAllocation(Allocation a) throws IllegalStateException {
+        /**
+        * @return internal index of the last vertex buffer type added to
+        *         builder
+        **/
+        public int getCurrentVertexTypeIndex() {
+            return mVertexTypeCount - 1;
+        }
+
+        /**
+        * @return internal index of the last index set added to the
+        *         builder
+        **/
+        public int getCurrentIndexSetIndex() {
+            return mIndexTypes.size() - 1;
+        }
+
+        /**
+        * Adds an allocation containing vertex buffer data to the
+        * builder
+        *
+        * @param a vertex data allocation
+        *
+        * @return this
+        **/
+        public AllocationBuilder addVertexAllocation(Allocation a) throws IllegalStateException {
             if (mVertexTypeCount >= mVertexTypes.length) {
                 throw new IllegalStateException("Max vertex types exceeded.");
             }
 
-            int addedIndex = mVertexTypeCount;
             mVertexTypes[mVertexTypeCount] = new Entry();
             mVertexTypes[mVertexTypeCount].a = a;
             mVertexTypeCount++;
-            return addedIndex;
+            return this;
         }
 
-        public int addIndexAllocation(Allocation a, Primitive p) {
-            int addedIndex  = mIndexTypes.size();
+        /**
+        * Adds an allocation containing index buffer data and index type
+        * to the builder
+        *
+        * @param a index set data allocation, could be null
+        * @param p index set primitive type
+        *
+        * @return this
+        **/
+        public AllocationBuilder addIndexSetAllocation(Allocation a, Primitive p) {
             Entry indexType = new Entry();
             indexType.a = a;
             indexType.prim = p;
             mIndexTypes.addElement(indexType);
-            return addedIndex;
+            return this;
         }
 
-        public int addIndexType(Primitive p) {
-            int addedIndex  = mIndexTypes.size();
+        /**
+        * Adds an index set type to the builder
+        *
+        * @param p index set primitive type
+        *
+        * @return this
+        **/
+        public AllocationBuilder addIndexSetType(Primitive p) {
             Entry indexType = new Entry();
             indexType.a = null;
             indexType.prim = p;
             mIndexTypes.addElement(indexType);
-            return addedIndex;
+            return this;
         }
 
         static synchronized Mesh internalCreate(RenderScript rs, AllocationBuilder b) {
@@ -300,6 +470,10 @@
             return newMesh;
         }
 
+        /**
+        * Create a Mesh object from the current state of the builder
+        *
+        **/
         public Mesh create() {
             mRS.validate();
             Mesh sm = internalCreate(mRS, this);
@@ -307,7 +481,11 @@
         }
     }
 
-
+    /**
+    * Builder that allows creation of a mesh object point by point
+    * and triangle by triangle
+    *
+    **/
     public static class TriangleMeshBuilder {
         float mVtxData[];
         int mVtxCount;
@@ -333,6 +511,15 @@
         public static final int NORMAL = 0x0002;
         public static final int TEXTURE_0 = 0x0100;
 
+        /**
+        * @param rs Context to which the mesh will belong.
+        * @param vtxSize specifies whether the vertex is a float2 or
+        *                float3
+        * @param flags bitfield that is a combination of COLOR, NORMAL,
+        *              and TEXTURE_0 that specifies what vertex data
+        *              channels are present in the mesh
+        *
+        **/
         public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) {
             mRS = rs;
             mVtxCount = 0;
@@ -376,7 +563,16 @@
             }
         }
 
-        public void addVertex(float x, float y) {
+        /**
+        * Adds a float2 vertex to the mesh
+        *
+        * @param x position x
+        * @param y position y
+        *
+        * @return this
+        *
+        **/
+        public TriangleMeshBuilder addVertex(float x, float y) {
             if (mVtxSize != 2) {
                 throw new IllegalStateException("add mistmatch with declared components.");
             }
@@ -384,9 +580,20 @@
             mVtxData[mVtxCount++] = x;
             mVtxData[mVtxCount++] = y;
             latch();
+            return this;
         }
 
-        public void addVertex(float x, float y, float z) {
+        /**
+        * Adds a float3 vertex to the mesh
+        *
+        * @param x position x
+        * @param y position y
+        * @param z position z
+        *
+        * @return this
+        *
+        **/
+        public TriangleMeshBuilder addVertex(float x, float y, float z) {
             if (mVtxSize != 3) {
                 throw new IllegalStateException("add mistmatch with declared components.");
             }
@@ -395,26 +602,56 @@
             mVtxData[mVtxCount++] = y;
             mVtxData[mVtxCount++] = z;
             latch();
+            return this;
         }
 
-        public void setTexture(float s, float t) {
+        /**
+        * Sets the texture coordinate for the last added vertex
+        *
+        * @param s texture coordinate s
+        * @param t texture coordinate t
+        *
+        * @return this
+        **/
+        public TriangleMeshBuilder setTexture(float s, float t) {
             if ((mFlags & TEXTURE_0) == 0) {
                 throw new IllegalStateException("add mistmatch with declared components.");
             }
             mS0 = s;
             mT0 = t;
+            return this;
         }
 
-        public void setNormal(float x, float y, float z) {
+        /**
+        * Sets the normal vector for the last added vertex
+        *
+        * @param x normal vector x
+        * @param y normal vector y
+        * @param z normal vector z
+        *
+        * @return this
+        **/
+        public TriangleMeshBuilder setNormal(float x, float y, float z) {
             if ((mFlags & NORMAL) == 0) {
                 throw new IllegalStateException("add mistmatch with declared components.");
             }
             mNX = x;
             mNY = y;
             mNZ = z;
+            return this;
         }
 
-        public void setColor(float r, float g, float b, float a) {
+        /**
+        * Sets the color for the last added vertex
+        *
+        * @param r red component
+        * @param g green component
+        * @param b blue component
+        * @param a alpha component
+        *
+        * @return this
+        **/
+        public TriangleMeshBuilder setColor(float r, float g, float b, float a) {
             if ((mFlags & COLOR) == 0) {
                 throw new IllegalStateException("add mistmatch with declared components.");
             }
@@ -422,9 +659,19 @@
             mG = g;
             mB = b;
             mA = a;
+            return this;
         }
 
-        public void addTriangle(int idx1, int idx2, int idx3) {
+        /**
+        * Adds a new triangle to the mesh builder
+        *
+        * @param idx1 index of the first vertex in the triangle
+        * @param idx2 index of the second vertex in the triangle
+        * @param idx3 index of the third vertex in the triangle
+        *
+        * @return this
+        **/
+        public TriangleMeshBuilder addTriangle(int idx1, int idx2, int idx3) {
             if((idx1 >= mVtxCount) || (idx1 < 0) ||
                (idx2 >= mVtxCount) || (idx2 < 0) ||
                (idx3 >= mVtxCount) || (idx3 < 0)) {
@@ -438,8 +685,23 @@
             mIndexData[mIndexCount++] = (short)idx1;
             mIndexData[mIndexCount++] = (short)idx2;
             mIndexData[mIndexCount++] = (short)idx3;
+            return this;
         }
 
+        /**
+        * Creates the mesh object from the current state of the builder
+        *
+        * @param uploadToBufferObject specifies whether the vertex data
+        *                             is to be uploaded into the buffer
+        *                             object indicating that it's likely
+        *                             not going to be modified and
+        *                             rendered many times.
+        *                             Alternatively, it indicates the
+        *                             mesh data will be updated
+        *                             frequently and remain in script
+        *                             accessible memory
+        *
+        **/
         public Mesh create(boolean uploadToBufferObject) {
             Element.Builder b = new Element.Builder(mRS);
             int floatCount = mVtxSize;
@@ -460,19 +722,28 @@
             }
             mElement = b.create();
 
-            Builder smb = new Builder(mRS);
+            int usage = Allocation.USAGE_SCRIPT;
+            if (uploadToBufferObject) {
+                usage |= Allocation.USAGE_GRAPHICS_VERTEX;
+            }
+
+            Builder smb = new Builder(mRS, usage);
             smb.addVertexType(mElement, mVtxCount / floatCount);
-            smb.addIndexType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE);
+            smb.addIndexSetType(Element.U16(mRS), mIndexCount, Primitive.TRIANGLE);
 
             Mesh sm = smb.create();
 
             sm.getVertexAllocation(0).copyFrom(mVtxData);
             if(uploadToBufferObject) {
-                sm.getVertexAllocation(0).uploadToBufferObject();
+                if (uploadToBufferObject) {
+                    sm.getVertexAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
+                }
             }
 
-            sm.getIndexAllocation(0).copyFrom(mIndexData);
-            sm.getIndexAllocation(0).uploadToBufferObject();
+            sm.getIndexSetAllocation(0).copyFrom(mIndexData);
+            if (uploadToBufferObject) {
+                sm.getIndexSetAllocation(0).syncAll(Allocation.USAGE_SCRIPT);
+            }
 
             return sm;
         }
diff --git a/graphics/java/android/renderscript/Primitive.java b/graphics/java/android/renderscript/Primitive.java
deleted file mode 100644
index 7925cac..0000000
--- a/graphics/java/android/renderscript/Primitive.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.renderscript;
-
-/**
- * @hide
- **/
-public enum Primitive {
-    POINT (0),
-    LINE (1),
-    LINE_STRIP (2),
-    TRIANGLE (3),
-    TRIANGLE_STRIP (4),
-    TRIANGLE_FAN (5);
-
-    int mID;
-    Primitive(int id) {
-        mID = id;
-    }
-}
-
-
-
diff --git a/graphics/java/android/renderscript/Program.java b/graphics/java/android/renderscript/Program.java
index c3536c3..323225f 100644
--- a/graphics/java/android/renderscript/Program.java
+++ b/graphics/java/android/renderscript/Program.java
@@ -27,15 +27,23 @@
 
 
 /**
- * @hide
+ *
+ * Program is a base class for all the objects that modify
+ * various stages of the graphics pipeline
  *
  **/
 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;
 
+    /**
+     *
+     * TextureType specifies what textures are attached to Program
+     * objects
+     *
+     **/
     public enum TextureType {
         TEXTURE_2D (0),
         TEXTURE_CUBE (1);
@@ -69,6 +77,14 @@
         super(id, rs);
     }
 
+    /**
+     * Binds a constant buffer to be used as uniform inputs to the
+     * program
+     *
+     * @param a allocation containing uniform data
+     * @param slot index within the program's list of constant
+     *             buffer allocations
+     */
     public void bindConstants(Allocation a, int slot) {
         if (slot < 0 || slot >= mConstants.length) {
             throw new IllegalArgumentException("Slot ID out of range.");
@@ -81,6 +97,13 @@
         mRS.nProgramBindConstants(getID(), slot, id);
     }
 
+    /**
+     * Binds a texture to be used in the program
+     *
+     * @param va allocation containing texture data
+     * @param slot index within the program's list of textures
+     *
+     */
     public void bindTexture(Allocation va, int slot)
         throws IllegalArgumentException {
         mRS.validate();
@@ -96,6 +119,15 @@
         mRS.nProgramBindTexture(getID(), slot, id);
     }
 
+    /**
+     * Binds an object that describes how a texture at the
+     * corresponding location is sampled
+     *
+     * @param vs sampler for a corresponding texture
+     * @param slot index within the program's list of textures to
+     *             use the sampler on
+     *
+     */
     public void bindSampler(Sampler vs, int slot)
         throws IllegalArgumentException {
         mRS.validate();
@@ -134,11 +166,25 @@
             mTextureTypes = new TextureType[MAX_TEXTURE];
         }
 
+        /**
+         * Sets the GLSL shader code to be used in the program
+         *
+         * @param s GLSL shader string
+         * @return  self
+         */
         public BaseProgramBuilder setShader(String s) {
             mShader = s;
             return this;
         }
 
+        /**
+         * Sets the GLSL shader code to be used in the program
+         *
+         * @param resources application resources
+         * @param resourceID id of the file containing GLSL shader code
+         *
+         * @return  self
+         */
         public BaseProgramBuilder setShader(Resources resources, int resourceID) {
             byte[] str;
             int strLength;
@@ -177,36 +223,30 @@
             return this;
         }
 
-        public void addInput(Element e) throws IllegalStateException {
-            // Should check for consistant and non-conflicting names...
-            if(mInputCount >= MAX_INPUT) {
-                throw new RSIllegalArgumentException("Max input count exceeded.");
-            }
-            if (e.isComplex()) {
-                throw new RSIllegalArgumentException("Complex elements not allowed.");
-            }
-            mInputs[mInputCount++] = e;
+        /**
+         * Queries the index of the last added constant buffer type
+         *
+         */
+        public int getCurrentConstantIndex() {
+            return mConstantCount - 1;
         }
 
-        public void addOutput(Element e) throws IllegalStateException {
-            // Should check for consistant and non-conflicting names...
-            if(mOutputCount >= MAX_OUTPUT) {
-                throw new RSIllegalArgumentException("Max output count exceeded.");
-            }
-            if (e.isComplex()) {
-                throw new RSIllegalArgumentException("Complex elements not allowed.");
-            }
-            mOutputs[mOutputCount++] = e;
+        /**
+         * Queries the index of the last added texture type
+         *
+         */
+        public int getCurrentTextureIndex() {
+            return mTextureCount - 1;
         }
 
-        void resetConstant() {
-            mConstantCount = 0;
-            for(int i = 0; i < MAX_CONSTANT; i ++) {
-                mConstants[i] = null;
-            }
-        }
-
-        public int addConstant(Type t) throws IllegalStateException {
+        /**
+         * Adds constant (uniform) inputs to the program
+         *
+         * @param t Type that describes the layout of the Allocation
+         *          object to be used as constant inputs to the Program
+         * @return  self
+         */
+        public BaseProgramBuilder addConstant(Type t) throws IllegalStateException {
             // Should check for consistant and non-conflicting names...
             if(mConstantCount >= MAX_CONSTANT) {
                 throw new RSIllegalArgumentException("Max input count exceeded.");
@@ -215,21 +255,17 @@
                 throw new RSIllegalArgumentException("Complex elements not allowed.");
             }
             mConstants[mConstantCount] = t;
-            return mConstantCount++;
-        }
-
-        public BaseProgramBuilder setTextureCount(int count) throws IllegalArgumentException {
-            // Should check for consistant and non-conflicting names...
-            if(count >= MAX_TEXTURE) {
-                throw new IllegalArgumentException("Max texture count exceeded.");
-            }
-            mTextureCount = count;
-            for (int i = 0; i < mTextureCount; i ++) {
-                mTextureTypes[i] = TextureType.TEXTURE_2D;
-            }
+            mConstantCount++;
             return this;
         }
 
+        /**
+         * Adds a texture input to the Program
+         *
+         * @param texType describes that the texture to append it (2D,
+         *                Cubemap, etc.)
+         * @return  self
+         */
         public BaseProgramBuilder addTexture(TextureType texType) throws IllegalArgumentException {
             if(mTextureCount >= MAX_TEXTURE) {
                 throw new IllegalArgumentException("Max texture count exceeded.");
diff --git a/graphics/java/android/renderscript/ProgramFragment.java b/graphics/java/android/renderscript/ProgramFragment.java
index 074c393..333880d 100644
--- a/graphics/java/android/renderscript/ProgramFragment.java
+++ b/graphics/java/android/renderscript/ProgramFragment.java
@@ -22,7 +22,9 @@
 
 
 /**
- * @hide
+ * ProgramFragment, also know as a fragment shader, describes a
+ * stage in the graphics pipeline responsible for manipulating
+ * pixel data in a user-defined way.
  *
  **/
 public class ProgramFragment extends Program {
@@ -30,11 +32,21 @@
         super(id, rs);
     }
 
-    public static class ShaderBuilder extends BaseProgramBuilder {
-        public ShaderBuilder(RenderScript rs) {
+    public static class Builder extends BaseProgramBuilder {
+        /**
+         * Create a builder object.
+         *
+         * @param rs Context to which the program will belong.
+         */
+        public Builder(RenderScript rs) {
             super(rs);
         }
 
+        /**
+         * Creates ProgramFragment from the current state of the builder
+         *
+         * @return  ProgramFragment
+         */
         public ProgramFragment create() {
             mRS.validate();
             int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
@@ -63,169 +75,6 @@
             return pf;
         }
     }
-
-    public static class Builder extends ShaderBuilder {
-        public static final int MAX_TEXTURE = 2;
-        int mNumTextures;
-        boolean mPointSpriteEnable;
-        boolean mVaryingColorEnable;
-
-        public enum EnvMode {
-            REPLACE (1),
-            MODULATE (2),
-            DECAL (3);
-
-            int mID;
-            EnvMode(int id) {
-                mID = id;
-            }
-        }
-
-        public enum Format {
-            ALPHA (1),
-            LUMINANCE_ALPHA (2),
-            RGB (3),
-            RGBA (4);
-
-            int mID;
-            Format(int id) {
-                mID = id;
-            }
-        }
-
-        private class Slot {
-            EnvMode env;
-            Format format;
-            Slot(EnvMode _env, Format _fmt) {
-                env = _env;
-                format = _fmt;
-            }
-        }
-        Slot[] mSlots;
-
-        private void buildShaderString() {
-            mShader  = "//rs_shader_internal\n";
-            mShader += "varying lowp vec4 varColor;\n";
-            mShader += "varying vec2 varTex0;\n";
-
-            mShader += "void main() {\n";
-            if (mVaryingColorEnable) {
-                mShader += "  lowp vec4 col = varColor;\n";
-            } else {
-                mShader += "  lowp vec4 col = UNI_Color;\n";
-            }
-
-            if (mNumTextures != 0) {
-                if (mPointSpriteEnable) {
-                    mShader += "  vec2 t0 = gl_PointCoord;\n";
-                } else {
-                    mShader += "  vec2 t0 = varTex0.xy;\n";
-                }
-            }
-
-            for(int i = 0; i < mNumTextures; i ++) {
-                switch(mSlots[i].env) {
-                case REPLACE:
-                    switch (mSlots[i].format) {
-                    case ALPHA:
-                        mShader += "  col.a = texture2D(UNI_Tex0, t0).a;\n";
-                        break;
-                    case LUMINANCE_ALPHA:
-                        mShader += "  col.rgba = texture2D(UNI_Tex0, t0).rgba;\n";
-                        break;
-                    case RGB:
-                        mShader += "  col.rgb = texture2D(UNI_Tex0, t0).rgb;\n";
-                        break;
-                    case RGBA:
-                        mShader += "  col.rgba = texture2D(UNI_Tex0, t0).rgba;\n";
-                        break;
-                    }
-                    break;
-                case MODULATE:
-                    switch (mSlots[i].format) {
-                    case ALPHA:
-                        mShader += "  col.a *= texture2D(UNI_Tex0, t0).a;\n";
-                        break;
-                    case LUMINANCE_ALPHA:
-                        mShader += "  col.rgba *= texture2D(UNI_Tex0, t0).rgba;\n";
-                        break;
-                    case RGB:
-                        mShader += "  col.rgb *= texture2D(UNI_Tex0, t0).rgb;\n";
-                        break;
-                    case RGBA:
-                        mShader += "  col.rgba *= texture2D(UNI_Tex0, t0).rgba;\n";
-                        break;
-                    }
-                    break;
-                case DECAL:
-                    mShader += "  col = texture2D(UNI_Tex0, t0);\n";
-                    break;
-                }
-            }
-
-            mShader += "  gl_FragColor = col;\n";
-            mShader += "}\n";
-        }
-
-        public Builder(RenderScript rs) {
-            super(rs);
-            mRS = rs;
-            mSlots = new Slot[MAX_TEXTURE];
-            mPointSpriteEnable = false;
-        }
-
-        public Builder setTexture(EnvMode env, Format fmt, int slot)
-            throws IllegalArgumentException {
-            if((slot < 0) || (slot >= MAX_TEXTURE)) {
-                throw new IllegalArgumentException("MAX_TEXTURE exceeded.");
-            }
-            mSlots[slot] = new Slot(env, fmt);
-            return this;
-        }
-
-        public Builder setPointSpriteTexCoordinateReplacement(boolean enable) {
-            mPointSpriteEnable = enable;
-            return this;
-        }
-
-        public Builder setVaryingColor(boolean enable) {
-            mVaryingColorEnable = enable;
-            return this;
-        }
-
-        @Override
-        public ProgramFragment create() {
-            mNumTextures = 0;
-            for(int i = 0; i < MAX_TEXTURE; i ++) {
-                if(mSlots[i] != null) {
-                    mNumTextures ++;
-                }
-            }
-            resetConstant();
-            buildShaderString();
-            Type constType = null;
-            if (!mVaryingColorEnable) {
-                Element.Builder b = new Element.Builder(mRS);
-                b.add(Element.F32_4(mRS), "Color");
-                Type.Builder typeBuilder = new Type.Builder(mRS, b.create());
-                typeBuilder.setX(1);
-                constType = typeBuilder.create();
-                addConstant(constType);
-            }
-            setTextureCount(mNumTextures);
-
-            ProgramFragment pf = super.create();
-            pf.mTextureCount = MAX_TEXTURE;
-            if (!mVaryingColorEnable) {
-                Allocation constantData = Allocation.createTyped(mRS,constType);
-                float[] data = new float[4];
-                data[0] = data[1] = data[2] = data[3] = 1.0f;
-                constantData.copyFrom(data);
-                pf.bindConstants(constantData, 0);
-            }
-            return pf;
-        }
-    }
 }
 
 
diff --git a/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java b/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
new file mode 100644
index 0000000..1af31f8
--- /dev/null
+++ b/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+import android.util.Config;
+import android.util.Log;
+
+
+/**
+ * ProgramFragmentFixedFunction is a helper class that provides
+ * a way to make a simple fragment shader without writing any
+ * GLSL code.
+ *
+ * This class allows for display of constant color, interpolated
+ * color from vertex shader, or combinations of the above
+ * blended with results of up to two texture lookups.
+ *
+ **/
+public class ProgramFragmentFixedFunction extends ProgramFragment {
+    ProgramFragmentFixedFunction(int id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    static class InternalBuilder extends BaseProgramBuilder {
+        public InternalBuilder(RenderScript rs) {
+            super(rs);
+        }
+
+        /**
+         * Creates ProgramFragmentFixedFunction from the current state
+         * of the builder
+         *
+         * @return  ProgramFragmentFixedFunction
+         */
+        public ProgramFragmentFixedFunction create() {
+            mRS.validate();
+            int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            int idx = 0;
+
+            for (int i=0; i < mInputCount; i++) {
+                tmp[idx++] = ProgramParam.INPUT.mID;
+                tmp[idx++] = mInputs[i].getID();
+            }
+            for (int i=0; i < mOutputCount; i++) {
+                tmp[idx++] = ProgramParam.OUTPUT.mID;
+                tmp[idx++] = mOutputs[i].getID();
+            }
+            for (int i=0; i < mConstantCount; i++) {
+                tmp[idx++] = ProgramParam.CONSTANT.mID;
+                tmp[idx++] = mConstants[i].getID();
+            }
+            for (int i=0; i < mTextureCount; i++) {
+                tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
+                tmp[idx++] = mTextureTypes[i].mID;
+            }
+
+            int id = mRS.nProgramFragmentCreate(mShader, tmp);
+            ProgramFragmentFixedFunction pf = new ProgramFragmentFixedFunction(id, mRS);
+            initProgram(pf);
+            return pf;
+        }
+    }
+
+    public static class Builder {
+        public static final int MAX_TEXTURE = 2;
+        int mNumTextures;
+        boolean mPointSpriteEnable;
+        boolean mVaryingColorEnable;
+        String mShader;
+        RenderScript mRS;
+
+        /**
+         * EnvMode describes how textures are combined with the existing
+         * color in the fixed function fragment shader
+         *
+         **/
+        public enum EnvMode {
+            REPLACE (1),
+            MODULATE (2),
+            DECAL (3);
+
+            int mID;
+            EnvMode(int id) {
+                mID = id;
+            }
+        }
+
+        /**
+         * Format describes the pixel format of textures in the fixed
+         * function fragment shader and how they are sampled
+         *
+         **/
+        public enum Format {
+            ALPHA (1),
+            LUMINANCE_ALPHA (2),
+            RGB (3),
+            RGBA (4);
+
+            int mID;
+            Format(int id) {
+                mID = id;
+            }
+        }
+
+        private class Slot {
+            EnvMode env;
+            Format format;
+            Slot(EnvMode _env, Format _fmt) {
+                env = _env;
+                format = _fmt;
+            }
+        }
+        Slot[] mSlots;
+
+        private void buildShaderString() {
+            mShader  = "//rs_shader_internal\n";
+            mShader += "varying lowp vec4 varColor;\n";
+            mShader += "varying vec2 varTex0;\n";
+
+            mShader += "void main() {\n";
+            if (mVaryingColorEnable) {
+                mShader += "  lowp vec4 col = varColor;\n";
+            } else {
+                mShader += "  lowp vec4 col = UNI_Color;\n";
+            }
+
+            if (mNumTextures != 0) {
+                if (mPointSpriteEnable) {
+                    mShader += "  vec2 t0 = gl_PointCoord;\n";
+                } else {
+                    mShader += "  vec2 t0 = varTex0.xy;\n";
+                }
+            }
+
+            for(int i = 0; i < mNumTextures; i ++) {
+                switch(mSlots[i].env) {
+                case REPLACE:
+                    switch (mSlots[i].format) {
+                    case ALPHA:
+                        mShader += "  col.a = texture2D(UNI_Tex0, t0).a;\n";
+                        break;
+                    case LUMINANCE_ALPHA:
+                        mShader += "  col.rgba = texture2D(UNI_Tex0, t0).rgba;\n";
+                        break;
+                    case RGB:
+                        mShader += "  col.rgb = texture2D(UNI_Tex0, t0).rgb;\n";
+                        break;
+                    case RGBA:
+                        mShader += "  col.rgba = texture2D(UNI_Tex0, t0).rgba;\n";
+                        break;
+                    }
+                    break;
+                case MODULATE:
+                    switch (mSlots[i].format) {
+                    case ALPHA:
+                        mShader += "  col.a *= texture2D(UNI_Tex0, t0).a;\n";
+                        break;
+                    case LUMINANCE_ALPHA:
+                        mShader += "  col.rgba *= texture2D(UNI_Tex0, t0).rgba;\n";
+                        break;
+                    case RGB:
+                        mShader += "  col.rgb *= texture2D(UNI_Tex0, t0).rgb;\n";
+                        break;
+                    case RGBA:
+                        mShader += "  col.rgba *= texture2D(UNI_Tex0, t0).rgba;\n";
+                        break;
+                    }
+                    break;
+                case DECAL:
+                    mShader += "  col = texture2D(UNI_Tex0, t0);\n";
+                    break;
+                }
+            }
+
+            mShader += "  gl_FragColor = col;\n";
+            mShader += "}\n";
+        }
+
+        /**
+         * Creates a builder for fixed function fragment program
+         *
+         * @param rs Context to which the program will belong.
+         */
+        public Builder(RenderScript rs) {
+            mRS = rs;
+            mSlots = new Slot[MAX_TEXTURE];
+            mPointSpriteEnable = false;
+        }
+
+        /**
+         * Adds a texture to be fetched as part of the fixed function
+         * fragment program
+         *
+         * @param env specifies how the texture is combined with the
+         *            current color
+         * @param fmt specifies the format of the texture and how its
+         *            components will be used to combine with the
+         *            current color
+         * @param slot index of the texture to apply the operations on
+         *
+         * @return this
+         */
+        public Builder setTexture(EnvMode env, Format fmt, int slot)
+            throws IllegalArgumentException {
+            if((slot < 0) || (slot >= MAX_TEXTURE)) {
+                throw new IllegalArgumentException("MAX_TEXTURE exceeded.");
+            }
+            mSlots[slot] = new Slot(env, fmt);
+            return this;
+        }
+
+        /**
+         * Specifies whether the texture coordinate passed from the
+         * vertex program is replaced with an openGL internal point
+         * sprite texture coordinate
+         *
+         **/
+        public Builder setPointSpriteTexCoordinateReplacement(boolean enable) {
+            mPointSpriteEnable = enable;
+            return this;
+        }
+
+        /**
+         * Specifies whether the varying color passed from the vertex
+         * program or the constant color set on the fragment program is
+         * used in the final color calculation in the fixed function
+         * fragment shader
+         *
+         **/
+        public Builder setVaryingColor(boolean enable) {
+            mVaryingColorEnable = enable;
+            return this;
+        }
+
+        /**
+        * Creates the fixed function fragment program from the current
+        * state of the builder.
+        *
+        */
+        public ProgramFragmentFixedFunction create() {
+            InternalBuilder sb = new InternalBuilder(mRS);
+            mNumTextures = 0;
+            for(int i = 0; i < MAX_TEXTURE; i ++) {
+                if(mSlots[i] != null) {
+                    mNumTextures ++;
+                }
+            }
+            buildShaderString();
+            sb.setShader(mShader);
+
+            Type constType = null;
+            if (!mVaryingColorEnable) {
+                Element.Builder b = new Element.Builder(mRS);
+                b.add(Element.F32_4(mRS), "Color");
+                Type.Builder typeBuilder = new Type.Builder(mRS, b.create());
+                typeBuilder.setX(1);
+                constType = typeBuilder.create();
+                sb.addConstant(constType);
+            }
+            for (int i = 0; i < mNumTextures; i ++) {
+                sb.addTexture(TextureType.TEXTURE_2D);
+            }
+
+            ProgramFragmentFixedFunction pf = sb.create();
+            pf.mTextureCount = MAX_TEXTURE;
+            if (!mVaryingColorEnable) {
+                Allocation constantData = Allocation.createTyped(mRS,constType);
+                float[] data = new float[4];
+                data[0] = data[1] = data[2] = data[3] = 1.0f;
+                constantData.copyFrom(data);
+                pf.bindConstants(constantData, 0);
+            }
+            return pf;
+        }
+    }
+}
+
+
+
+
diff --git a/graphics/java/android/renderscript/ProgramRaster.java b/graphics/java/android/renderscript/ProgramRaster.java
index 5b55015..71c527d 100644
--- a/graphics/java/android/renderscript/ProgramRaster.java
+++ b/graphics/java/android/renderscript/ProgramRaster.java
@@ -22,7 +22,6 @@
 
 
 /**
- * @hide
  *
  **/
 public class ProgramRaster extends BaseObj {
@@ -109,21 +108,11 @@
             mCullMode = CullMode.BACK;
         }
 
-        public Builder setPointSpriteEnable(boolean enable) {
+        public Builder setPointSpriteEnabled(boolean enable) {
             mPointSprite = enable;
             return this;
         }
 
-        public Builder setPointSmoothEnable(boolean enable) {
-            mPointSmooth = enable;
-            return this;
-        }
-
-        public Builder setLineSmoothEnable(boolean enable) {
-            mLineSmooth = enable;
-            return this;
-        }
-
         public Builder setCullMode(CullMode m) {
             mCullMode = m;
             return this;
diff --git a/graphics/java/android/renderscript/ProgramStore.java b/graphics/java/android/renderscript/ProgramStore.java
index d191b06..9128f9b 100644
--- a/graphics/java/android/renderscript/ProgramStore.java
+++ b/graphics/java/android/renderscript/ProgramStore.java
@@ -22,18 +22,62 @@
 
 
 /**
- * @hide
+ * ProgarmStore contains a set of parameters that control how
+ * the graphics hardware handles writes to the framebuffer.
+ *
+ * It could be used to:
+ *   - enable/diable depth testing
+ *   - specify wheather depth writes are performed
+ *   - setup various blending modes for use in effects like
+ *     transparency
+ *   - define write masks for color components written into the
+ *     framebuffer
  *
  **/
 public class ProgramStore extends BaseObj {
-        public enum DepthFunc {
+    /**
+    * Specifies the function used to determine whether a fragment
+    * will be drawn during the depth testing stage in the rendering
+    * pipeline by comparing its value with that already in the depth
+    * buffer. DepthFunc is only valid when depth buffer is present
+    * and depth testing is enabled
+    */
+    public enum DepthFunc {
+
+        /**
+        * Always drawn
+        */
         ALWAYS (0),
+        /**
+        * Drawn if the incoming depth value is less than that in the
+        * depth buffer
+        */
         LESS (1),
-        LEQUAL (2),
+        /**
+        * Drawn if the incoming depth value is less or equal to that in
+        * the depth buffer
+        */
+        LESS_OR_EQUAL (2),
+        /**
+        * Drawn if the incoming depth value is greater than that in the
+        * depth buffer
+        */
         GREATER (3),
-        GEQUAL (4),
+        /**
+        * Drawn if the incoming depth value is greater or equal to that
+        * in the depth buffer
+        */
+        GREATER_OR_EQUAL (4),
+        /**
+        * Drawn if the incoming depth value is equal to that in the
+        * depth buffer
+        */
         EQUAL (5),
-        NOTEQUAL (6);
+        /**
+        * Drawn if the incoming depth value is not equal to that in the
+        * depth buffer
+        */
+        NOT_EQUAL (6);
 
         int mID;
         DepthFunc(int id) {
@@ -41,6 +85,14 @@
         }
     }
 
+    /**
+    * Specifies the functions used to combine incoming pixels with
+    * those already in the frame buffer.
+    *
+    * BlendSrcFunc describes how the coefficient used to scale the
+    * source pixels during the blending operation is computed
+    *
+    */
     public enum BlendSrcFunc {
         ZERO (0),
         ONE (1),
@@ -58,6 +110,15 @@
         }
     }
 
+    /**
+    * Specifies the functions used to combine incoming pixels with
+    * those already in the frame buffer.
+    *
+    * BlendDstFunc describes how the coefficient used to scale the
+    * pixels already in the framebuffer is computed during the
+    * blending operation
+    *
+    */
     public enum BlendDstFunc {
         ZERO (0),
         ONE (1),
@@ -79,145 +140,103 @@
         super(id, rs);
     }
 
+    /**
+    * Returns a pre-defined program store object with the following
+    * characteristics:
+    *  - incoming pixels are drawn if their depth value is less than
+    *    the stored value in the depth buffer. If the pixel is
+    *    drawn, its value is also stored in the depth buffer
+    *  - incoming pixels override the value stored in the color
+    *    buffer if it passes the depth test
+    *
+    *  @param rs Context to which the program will belong.
+    **/
     public static ProgramStore BLEND_NONE_DEPTH_TEST(RenderScript rs) {
         if(rs.mProgramStore_BLEND_NONE_DEPTH_TEST == null) {
             ProgramStore.Builder builder = new ProgramStore.Builder(rs);
             builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
             builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
-            builder.setDitherEnable(false);
-            builder.setDepthMask(true);
+            builder.setDitherEnabled(false);
+            builder.setDepthMaskEnabled(true);
             rs.mProgramStore_BLEND_NONE_DEPTH_TEST = builder.create();
         }
         return rs.mProgramStore_BLEND_NONE_DEPTH_TEST;
     }
-    public static ProgramStore BLEND_NONE_DEPTH_NO_DEPTH(RenderScript rs) {
+    /**
+    * Returns a pre-defined program store object with the following
+    * characteristics:
+    *  - incoming pixels always pass the depth test and their value
+    *    is not stored in the depth buffer
+    *  - incoming pixels override the value stored in the color
+    *    buffer
+    *
+    *  @param rs Context to which the program will belong.
+    **/
+    public static ProgramStore BLEND_NONE_DEPTH_NONE(RenderScript rs) {
         if(rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH == null) {
             ProgramStore.Builder builder = new ProgramStore.Builder(rs);
             builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
             builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
-            builder.setDitherEnable(false);
-            builder.setDepthMask(false);
+            builder.setDitherEnabled(false);
+            builder.setDepthMaskEnabled(false);
             rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH = builder.create();
         }
         return rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH;
     }
-    public static ProgramStore BLEND_NONE_DEPTH_NO_TEST(RenderScript rs) {
-        if(rs.mProgramStore_BLEND_NONE_DEPTH_NO_TEST == null) {
-            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
-            builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
-            builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
-            builder.setDitherEnable(false);
-            builder.setDepthMask(true);
-            rs.mProgramStore_BLEND_NONE_DEPTH_NO_TEST = builder.create();
-        }
-        return rs.mProgramStore_BLEND_NONE_DEPTH_NO_TEST;
-    }
-    public static ProgramStore BLEND_NONE_DEPTH_NO_WRITE(RenderScript rs) {
-        if(rs.mProgramStore_BLEND_NONE_DEPTH_NO_WRITE == null) {
-            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
-            builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
-            builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
-            builder.setDitherEnable(false);
-            builder.setDepthMask(false);
-            rs.mProgramStore_BLEND_NONE_DEPTH_NO_WRITE = builder.create();
-        }
-        return rs.mProgramStore_BLEND_NONE_DEPTH_NO_WRITE;
-    }
-
+    /**
+    * Returns a pre-defined program store object with the following
+    * characteristics:
+    *  - incoming pixels are drawn if their depth value is less than
+    *    the stored value in the depth buffer. If the pixel is
+    *    drawn, its value is also stored in the depth buffer
+    *  - if the incoming (Source) pixel passes depth test, its value
+    *    is combined with the stored color (Dest) using the
+    *    following formula
+    *  Final.RGB = Source.RGB * Source.A + Dest.RGB * (1 - Source.A)
+    *
+    *  @param rs Context to which the program will belong.
+    **/
     public static ProgramStore BLEND_ALPHA_DEPTH_TEST(RenderScript rs) {
         if(rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST == null) {
             ProgramStore.Builder builder = new ProgramStore.Builder(rs);
             builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
             builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-            builder.setDitherEnable(false);
-            builder.setDepthMask(true);
+            builder.setDitherEnabled(false);
+            builder.setDepthMaskEnabled(true);
             rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST = builder.create();
         }
         return rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST;
     }
-    public static ProgramStore BLEND_ALPHA_DEPTH_NO_DEPTH(RenderScript rs) {
+    /**
+    * Returns a pre-defined program store object with the following
+    * characteristics:
+    *  - incoming pixels always pass the depth test and their value
+    *    is not stored in the depth buffer
+    *  - incoming pixel's value is combined with the stored color
+    *    (Dest) using the following formula
+    *  Final.RGB = Source.RGB * Source.A + Dest.RGB * (1 - Source.A)
+    *
+    *  @param rs Context to which the program will belong.
+    **/
+    public static ProgramStore BLEND_ALPHA_DEPTH_NONE(RenderScript rs) {
         if(rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH == null) {
             ProgramStore.Builder builder = new ProgramStore.Builder(rs);
             builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
             builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-            builder.setDitherEnable(false);
-            builder.setDepthMask(false);
+            builder.setDitherEnabled(false);
+            builder.setDepthMaskEnabled(false);
             rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH = builder.create();
         }
         return rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH;
     }
-    public static ProgramStore BLEND_ALPHA_DEPTH_NO_TEST(RenderScript rs) {
-        if(rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_TEST == null) {
-            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
-            builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
-            builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-            builder.setDitherEnable(false);
-            builder.setDepthMask(true);
-            rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_TEST = builder.create();
-        }
-        return rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_TEST;
-    }
-    public static ProgramStore BLEND_ALPHA_DEPTH_NO_WRITE(RenderScript rs) {
-        if(rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_WRITE == null) {
-            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
-            builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
-            builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-            builder.setDitherEnable(false);
-            builder.setDepthMask(false);
-            rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_WRITE = builder.create();
-        }
-        return rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_WRITE;
-    }
 
-    public static ProgramStore BLEND_ADD_DEPTH_TEST(RenderScript rs) {
-        if(rs.mProgramStore_BLEND_ADD_DEPTH_TEST == null) {
-            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
-            builder.setDepthFunc(ProgramStore.DepthFunc.LESS);
-            builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
-            builder.setDitherEnable(false);
-            builder.setDepthMask(true);
-            rs.mProgramStore_BLEND_ADD_DEPTH_TEST = builder.create();
-        }
-        return rs.mProgramStore_BLEND_ADD_DEPTH_TEST;
-    }
-    public static ProgramStore BLEND_ADD_DEPTH_NO_DEPTH(RenderScript rs) {
-        if(rs.mProgramStore_BLEND_ADD_DEPTH_NO_DEPTH == null) {
-            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
-            builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
-            builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
-            builder.setDitherEnable(false);
-            builder.setDepthMask(false);
-            rs.mProgramStore_BLEND_ADD_DEPTH_NO_DEPTH = builder.create();
-        }
-        return rs.mProgramStore_BLEND_ADD_DEPTH_NO_DEPTH;
-    }
-    public static ProgramStore BLEND_ADD_DEPTH_NO_TEST(RenderScript rs) {
-        if(rs.mProgramStore_BLEND_ADD_DEPTH_NO_TEST == null) {
-            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
-            builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
-            builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
-            builder.setDitherEnable(false);
-            builder.setDepthMask(true);
-            rs.mProgramStore_BLEND_ADD_DEPTH_NO_DEPTH = builder.create();
-        }
-        return rs.mProgramStore_BLEND_ADD_DEPTH_NO_TEST;
-    }
-    public static ProgramStore BLEND_ADD_DEPTH_NO_WRITE(RenderScript rs) {
-        if(rs.mProgramStore_BLEND_ADD_DEPTH_NO_WRITE == null) {
-            ProgramStore.Builder builder = new ProgramStore.Builder(rs);
-            builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
-            builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
-            builder.setDitherEnable(false);
-            builder.setDepthMask(false);
-            rs.mProgramStore_BLEND_ADD_DEPTH_NO_WRITE = builder.create();
-        }
-        return rs.mProgramStore_BLEND_ADD_DEPTH_NO_WRITE;
-    }
-
+    /**
+    * Builder class for ProgramStore object. If the builder is left
+    * empty, the equivalent of BLEND_NONE_DEPTH_NONE would be
+    * returned
+    */
     public static class Builder {
         RenderScript mRS;
-        Element mIn;
-        Element mOut;
         DepthFunc mDepthFunc;
         boolean mDepthMask;
         boolean mColorMaskR;
@@ -228,26 +247,8 @@
         BlendDstFunc mBlendDst;
         boolean mDither;
 
-
-
-        public Builder(RenderScript rs, Element in, Element out) {
-            mRS = rs;
-            mIn = in;
-            mOut = out;
-            mDepthFunc = DepthFunc.ALWAYS;
-            mDepthMask = false;
-            mColorMaskR = true;
-            mColorMaskG = true;
-            mColorMaskB = true;
-            mColorMaskA = true;
-            mBlendSrc = BlendSrcFunc.ONE;
-            mBlendDst = BlendDstFunc.ZERO;
-        }
-
         public Builder(RenderScript rs) {
             mRS = rs;
-            mIn = null;
-            mOut = null;
             mDepthFunc = DepthFunc.ALWAYS;
             mDepthMask = false;
             mColorMaskR = true;
@@ -258,17 +259,42 @@
             mBlendDst = BlendDstFunc.ZERO;
         }
 
+        /**
+        * Specifies the depth testing behavior
+        *
+        * @param func function used for depth testing
+        *
+        * @return this
+        */
         public Builder setDepthFunc(DepthFunc func) {
             mDepthFunc = func;
             return this;
         }
 
-        public Builder setDepthMask(boolean enable) {
+        /**
+        * Enables writes into the depth buffer
+        *
+        * @param enable specifies whether depth writes are
+        *         enabled or disabled
+        *
+        * @return this
+        */
+        public Builder setDepthMaskEnabled(boolean enable) {
             mDepthMask = enable;
             return this;
         }
 
-        public Builder setColorMask(boolean r, boolean g, boolean b, boolean a) {
+        /**
+        * Enables writes into the color buffer
+        *
+        * @param r specifies whether red channel is written
+        * @param g specifies whether green channel is written
+        * @param b specifies whether blue channel is written
+        * @param a specifies whether alpha channel is written
+        *
+        * @return this
+        */
+        public Builder setColorMaskEnabled(boolean r, boolean g, boolean b, boolean a) {
             mColorMaskR = r;
             mColorMaskG = g;
             mColorMaskB = b;
@@ -276,13 +302,32 @@
             return this;
         }
 
+        /**
+        * Specifies how incoming pixels are combined with the pixels
+        * stored in the framebuffer
+        *
+        * @param src specifies how the source blending factor is
+        *            computed
+        * @param dst specifies how the destination blending factor is
+        *            computed
+        *
+        * @return this
+        */
         public Builder setBlendFunc(BlendSrcFunc src, BlendDstFunc dst) {
             mBlendSrc = src;
             mBlendDst = dst;
             return this;
         }
 
-        public Builder setDitherEnable(boolean enable) {
+        /**
+        * Enables dithering
+        *
+        * @param enable specifies whether dithering is enabled or
+        *               disabled
+        *
+        * @return this
+        */
+        public Builder setDitherEnabled(boolean enable) {
             mDither = enable;
             return this;
         }
@@ -302,6 +347,9 @@
             return new ProgramStore(id, rs);
         }
 
+        /**
+        * Creates a program store from the current state of the builder
+        */
         public ProgramStore create() {
             mRS.validate();
             return internalCreate(mRS, this);
diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java
index 5d41f63..a965b81 100644
--- a/graphics/java/android/renderscript/ProgramVertex.java
+++ b/graphics/java/android/renderscript/ProgramVertex.java
@@ -23,27 +23,59 @@
 
 
 /**
- * @hide
+ * ProgramVertex, also know as a vertex shader, describes a
+ * stage in the graphics pipeline responsible for manipulating
+ * geometric data in a user-defined way.
  *
  **/
 public class ProgramVertex extends Program {
-    public static final int MAX_LIGHT = 8;
-
 
     ProgramVertex(int id, RenderScript rs) {
         super(id, rs);
     }
 
-    public void bindAllocation(MatrixAllocation va) {
-        mRS.validate();
-        bindConstants(va.mAlloc, 0);
-    }
-
-    public static class ShaderBuilder extends BaseProgramBuilder {
-        public ShaderBuilder(RenderScript rs) {
+    /**
+    * Builder class for creating ProgramVertex objects.
+    * The builder starts empty and the user must minimally provide
+    * the GLSL shader code, and the varying inputs. Constant, or
+    * uniform parameters to the shader may optionally be provided as
+    * well.
+    *
+    **/
+    public static class Builder extends BaseProgramBuilder {
+        /**
+         * Create a builder object.
+         *
+         * @param rs Context to which the program will belong.
+         */
+        public Builder(RenderScript rs) {
             super(rs);
         }
 
+        /**
+         * Add varying inputs to the program
+         *
+         * @param e element describing the layout of the varying input
+         *          structure
+         * @return  self
+         */
+        public Builder addInput(Element e) throws IllegalStateException {
+            // Should check for consistant and non-conflicting names...
+            if(mInputCount >= MAX_INPUT) {
+                throw new RSIllegalArgumentException("Max input count exceeded.");
+            }
+            if (e.isComplex()) {
+                throw new RSIllegalArgumentException("Complex elements not allowed.");
+            }
+            mInputs[mInputCount++] = e;
+            return this;
+        }
+
+        /**
+         * Creates ProgramVertex from the current state of the builder
+         *
+         * @return  ProgramVertex
+         */
         public ProgramVertex create() {
             mRS.validate();
             int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
@@ -73,165 +105,4 @@
         }
     }
 
-    public static class Builder extends ShaderBuilder {
-        boolean mTextureMatrixEnable;
-
-        public Builder(RenderScript rs, Element in, Element out) {
-            super(rs);
-        }
-        public Builder(RenderScript rs) {
-            super(rs);
-        }
-
-        public Builder setTextureMatrixEnable(boolean enable) {
-            mTextureMatrixEnable = enable;
-            return this;
-        }
-        static Type getConstantInputType(RenderScript rs) {
-            Element.Builder b = new Element.Builder(rs);
-            b.add(Element.MATRIX4X4(rs), "MV");
-            b.add(Element.MATRIX4X4(rs), "P");
-            b.add(Element.MATRIX4X4(rs), "TexMatrix");
-            b.add(Element.MATRIX4X4(rs), "MVP");
-
-            Type.Builder typeBuilder = new Type.Builder(rs, b.create());
-            typeBuilder.setX(1);
-            return typeBuilder.create();
-        }
-
-        private void buildShaderString() {
-
-            mShader  = "//rs_shader_internal\n";
-            mShader += "varying vec4 varColor;\n";
-            mShader += "varying vec2 varTex0;\n";
-
-            mShader += "void main() {\n";
-            mShader += "  gl_Position = UNI_MVP * ATTRIB_position;\n";
-            mShader += "  gl_PointSize = 1.0;\n";
-
-            mShader += "  varColor = ATTRIB_color;\n";
-            if (mTextureMatrixEnable) {
-                mShader += "  varTex0 = (UNI_TexMatrix * vec4(ATTRIB_texture0, 0.0, 1.0)).xy;\n";
-            } else {
-                mShader += "  varTex0 = ATTRIB_texture0;\n";
-            }
-            mShader += "}\n";
-        }
-
-        @Override
-        public ProgramVertex create() {
-            buildShaderString();
-
-            addConstant(getConstantInputType(mRS));
-
-            Element.Builder b = new Element.Builder(mRS);
-            b.add(Element.F32_4(mRS), "position");
-            b.add(Element.F32_4(mRS), "color");
-            b.add(Element.F32_3(mRS), "normal");
-            b.add(Element.F32_2(mRS), "texture0");
-            addInput(b.create());
-
-            return super.create();
-        }
-    }
-
-
-
-    public static class MatrixAllocation {
-        static final int MODELVIEW_OFFSET = 0;
-        static final int PROJECTION_OFFSET = 16;
-        static final int TEXTURE_OFFSET = 32;
-
-        Matrix4f mModel;
-        Matrix4f mProjection;
-        Matrix4f mTexture;
-
-        public Allocation mAlloc;
-        private FieldPacker mIOBuffer;
-
-        public MatrixAllocation(RenderScript rs) {
-            Type constInputType = ProgramVertex.Builder.getConstantInputType(rs);
-            mAlloc = Allocation.createTyped(rs, constInputType);
-            int bufferSize = constInputType.getElement().getSizeBytes()*
-                             constInputType.getCount();
-            mIOBuffer = new FieldPacker(bufferSize);
-            loadModelview(new Matrix4f());
-            loadProjection(new Matrix4f());
-            loadTexture(new Matrix4f());
-        }
-
-        public void destroy() {
-            mAlloc.destroy();
-            mAlloc = null;
-        }
-
-        private void addToBuffer(int offset, Matrix4f m) {
-            mIOBuffer.reset(offset);
-            for(int i = 0; i < 16; i ++) {
-                mIOBuffer.addF32(m.mMat[i]);
-            }
-            mAlloc.copyFrom(mIOBuffer.getData());
-        }
-
-        public void loadModelview(Matrix4f m) {
-            mModel = m;
-            addToBuffer(MODELVIEW_OFFSET*4, m);
-        }
-
-        public void loadProjection(Matrix4f m) {
-            mProjection = m;
-            addToBuffer(PROJECTION_OFFSET*4, m);
-        }
-
-        public void loadTexture(Matrix4f m) {
-            mTexture = m;
-            addToBuffer(TEXTURE_OFFSET*4, m);
-        }
-
-        public void setupOrthoWindow(int w, int h) {
-            mProjection.loadOrtho(0,w, h,0, -1,1);
-            addToBuffer(PROJECTION_OFFSET*4, mProjection);
-        }
-
-        public void setupOrthoNormalized(int w, int h) {
-            // range -1,1 in the narrow axis.
-            if(w > h) {
-                float aspect = ((float)w) / h;
-                mProjection.loadOrtho(-aspect,aspect,  -1,1,  -1,1);
-            } else {
-                float aspect = ((float)h) / w;
-                mProjection.loadOrtho(-1,1, -aspect,aspect,  -1,1);
-            }
-            addToBuffer(PROJECTION_OFFSET*4, mProjection);
-        }
-
-        public void setupProjectionNormalized(int w, int h) {
-            // range -1,1 in the narrow axis at z = 0.
-            Matrix4f m1 = new Matrix4f();
-            Matrix4f m2 = new Matrix4f();
-
-            if(w > h) {
-                float aspect = ((float)w) / h;
-                m1.loadFrustum(-aspect,aspect,  -1,1,  1,100);
-            } else {
-                float aspect = ((float)h) / w;
-                m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
-            }
-
-            m2.loadRotate(180, 0, 1, 0);
-            m1.loadMultiply(m1, m2);
-
-            m2.loadScale(-2, 2, 1);
-            m1.loadMultiply(m1, m2);
-
-            m2.loadTranslate(0, 0, 2);
-            m1.loadMultiply(m1, m2);
-
-            mProjection = m1;
-            addToBuffer(PROJECTION_OFFSET*4, mProjection);
-        }
-
-    }
-
 }
-
diff --git a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java b/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
new file mode 100644
index 0000000..666c7ec
--- /dev/null
+++ b/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+
+import android.graphics.Matrix;
+import android.util.Config;
+import android.util.Log;
+
+
+/**
+ * ProgramVertexFixedFunction is a helper class that provides a
+ * simple way to create a fixed function emulation vertex shader
+ * without writing any GLSL code.
+ *
+ **/
+public class ProgramVertexFixedFunction extends ProgramVertex {
+
+    ProgramVertexFixedFunction(int id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Binds the constant buffer containing fixed function emulation
+     * matrices
+     *
+     * @param va allocation containing fixed function matrices
+     */
+    public void bindConstants(Constants va) {
+        mRS.validate();
+        bindConstants(va.getAllocation(), 0);
+    }
+
+    static class InternalBuilder extends BaseProgramBuilder {
+        public InternalBuilder(RenderScript rs) {
+            super(rs);
+        }
+
+        public InternalBuilder addInput(Element e) throws IllegalStateException {
+            // Should check for consistant and non-conflicting names...
+            if(mInputCount >= MAX_INPUT) {
+                throw new RSIllegalArgumentException("Max input count exceeded.");
+            }
+            if (e.isComplex()) {
+                throw new RSIllegalArgumentException("Complex elements not allowed.");
+            }
+            mInputs[mInputCount++] = e;
+            return this;
+        }
+
+        /**
+         * Creates ProgramVertexFixedFunction from the current state of
+         * the builder
+         *
+         * @return  ProgramVertexFixedFunction
+         */
+        public ProgramVertexFixedFunction create() {
+            mRS.validate();
+            int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            int idx = 0;
+
+            for (int i=0; i < mInputCount; i++) {
+                tmp[idx++] = ProgramParam.INPUT.mID;
+                tmp[idx++] = mInputs[i].getID();
+            }
+            for (int i=0; i < mOutputCount; i++) {
+                tmp[idx++] = ProgramParam.OUTPUT.mID;
+                tmp[idx++] = mOutputs[i].getID();
+            }
+            for (int i=0; i < mConstantCount; i++) {
+                tmp[idx++] = ProgramParam.CONSTANT.mID;
+                tmp[idx++] = mConstants[i].getID();
+            }
+            for (int i=0; i < mTextureCount; i++) {
+                tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
+                tmp[idx++] = mTextureTypes[i].mID;
+            }
+
+            int id = mRS.nProgramVertexCreate(mShader, tmp);
+            ProgramVertexFixedFunction pv = new ProgramVertexFixedFunction(id, mRS);
+            initProgram(pv);
+            return pv;
+        }
+    }
+
+    public static class Builder {
+        boolean mTextureMatrixEnable;
+        String mShader;
+        RenderScript mRS;
+
+        /**
+         * Creates a builder for fixed function vertex program
+         *
+         * @param rs Context to which the program will belong.
+         */
+        public Builder(RenderScript rs) {
+            mRS = rs;
+        }
+
+        /**
+         * Specifies whether texture matrix calculations are to be added
+         * to the shader
+         *
+         */
+        public Builder setTextureMatrixEnable(boolean enable) {
+            mTextureMatrixEnable = enable;
+            return this;
+        }
+        static Type getConstantInputType(RenderScript rs) {
+            Element.Builder b = new Element.Builder(rs);
+            b.add(Element.MATRIX4X4(rs), "MV");
+            b.add(Element.MATRIX4X4(rs), "P");
+            b.add(Element.MATRIX4X4(rs), "TexMatrix");
+            b.add(Element.MATRIX4X4(rs), "MVP");
+
+            Type.Builder typeBuilder = new Type.Builder(rs, b.create());
+            typeBuilder.setX(1);
+            return typeBuilder.create();
+        }
+
+        private void buildShaderString() {
+
+            mShader  = "//rs_shader_internal\n";
+            mShader += "varying vec4 varColor;\n";
+            mShader += "varying vec2 varTex0;\n";
+
+            mShader += "void main() {\n";
+            mShader += "  gl_Position = UNI_MVP * ATTRIB_position;\n";
+            mShader += "  gl_PointSize = 1.0;\n";
+
+            mShader += "  varColor = ATTRIB_color;\n";
+            if (mTextureMatrixEnable) {
+                mShader += "  varTex0 = (UNI_TexMatrix * vec4(ATTRIB_texture0, 0.0, 1.0)).xy;\n";
+            } else {
+                mShader += "  varTex0 = ATTRIB_texture0;\n";
+            }
+            mShader += "}\n";
+        }
+
+        /**
+         * Creates ProgramVertexFixedFunction from the current state of
+         * the builder
+         *
+         * @return Fixed function emulation ProgramVertex
+         */
+        public ProgramVertexFixedFunction create() {
+            buildShaderString();
+
+            InternalBuilder sb = new InternalBuilder(mRS);
+            sb.setShader(mShader);
+            sb.addConstant(getConstantInputType(mRS));
+
+            Element.Builder b = new Element.Builder(mRS);
+            b.add(Element.F32_4(mRS), "position");
+            b.add(Element.F32_4(mRS), "color");
+            b.add(Element.F32_3(mRS), "normal");
+            b.add(Element.F32_2(mRS), "texture0");
+            sb.addInput(b.create());
+
+            return sb.create();
+        }
+    }
+
+    /**
+     * Helper class to store modelview, projection and texture
+     * matrices for ProgramVertexFixedFunction
+     *
+     */
+    public static class Constants {
+        static final int MODELVIEW_OFFSET = 0;
+        static final int PROJECTION_OFFSET = 16;
+        static final int TEXTURE_OFFSET = 32;
+
+        Matrix4f mModel;
+        Matrix4f mProjection;
+        Matrix4f mTexture;
+
+        Allocation mAlloc;
+        Allocation getAllocation() {
+            return mAlloc;
+        }
+        private FieldPacker mIOBuffer;
+
+        /**
+        * Creates a buffer to store fixed function emulation matrices
+        *
+        * @param rs Context to which the allocation will belong.
+        **/
+        public Constants(RenderScript rs) {
+            Type constInputType = ProgramVertexFixedFunction.Builder.getConstantInputType(rs);
+            mAlloc = Allocation.createTyped(rs, constInputType);
+            int bufferSize = constInputType.getElement().getSizeBytes()*
+                             constInputType.getCount();
+            mIOBuffer = new FieldPacker(bufferSize);
+            mModel = new Matrix4f();
+            mProjection = new Matrix4f();
+            mTexture = new Matrix4f();
+            setModelview(new Matrix4f());
+            setProjection(new Matrix4f());
+            setTexture(new Matrix4f());
+        }
+
+        /**
+        * Forces deallocation of memory backing the contant matrices.
+        * Normally, this is unnecessary and will be garbage collected
+        *
+        */
+        public void destroy() {
+            mAlloc.destroy();
+            mAlloc = null;
+        }
+
+        private void addToBuffer(int offset, Matrix4f m) {
+            mIOBuffer.reset(offset);
+            for(int i = 0; i < 16; i ++) {
+                mIOBuffer.addF32(m.mMat[i]);
+            }
+            mAlloc.copyFrom(mIOBuffer.getData());
+        }
+
+        /**
+        * Sets the modelview matrix in the fixed function matrix buffer
+        *
+        * @param m modelview matrix
+        */
+        public void setModelview(Matrix4f m) {
+            mModel.load(m);
+            addToBuffer(MODELVIEW_OFFSET*4, m);
+        }
+
+        /**
+        * Sets the projection matrix in the fixed function matrix buffer
+        *
+        * @param m projection matrix
+        */
+        public void setProjection(Matrix4f m) {
+            mProjection.load(m);
+            addToBuffer(PROJECTION_OFFSET*4, m);
+        }
+
+        /**
+        * Sets the texture matrix in the fixed function matrix buffer.
+        * Texture matrix must be enabled in the
+        * ProgramVertexFixedFunction builder for the shader to utilize
+        * it.
+        *
+        * @param m modelview matrix
+        */
+        public void setTexture(Matrix4f m) {
+            mTexture.load(m);
+            addToBuffer(TEXTURE_OFFSET*4, m);
+        }
+    }
+}
diff --git a/graphics/java/android/renderscript/RSDriverException.java b/graphics/java/android/renderscript/RSDriverException.java
index 61787e6..ce85b53 100644
--- a/graphics/java/android/renderscript/RSDriverException.java
+++ b/graphics/java/android/renderscript/RSDriverException.java
@@ -20,7 +20,6 @@
 /**
  * Base class for all exceptions thrown by the Android
  * Renderscript
- * @hide
  */
 public class RSDriverException extends RSRuntimeException {
     public RSDriverException(String string) {
diff --git a/graphics/java/android/renderscript/RSIllegalArgumentException.java b/graphics/java/android/renderscript/RSIllegalArgumentException.java
index 8d67a8d..954c0e8 100644
--- a/graphics/java/android/renderscript/RSIllegalArgumentException.java
+++ b/graphics/java/android/renderscript/RSIllegalArgumentException.java
@@ -20,7 +20,6 @@
 /**
  * Base class for all exceptions thrown by the Android
  * Renderscript
- * @hide
  */
 public class RSIllegalArgumentException extends RSRuntimeException {
     public RSIllegalArgumentException(String string) {
diff --git a/graphics/java/android/renderscript/RSInvalidStateException.java b/graphics/java/android/renderscript/RSInvalidStateException.java
index 53b9479..691aeba 100644
--- a/graphics/java/android/renderscript/RSInvalidStateException.java
+++ b/graphics/java/android/renderscript/RSInvalidStateException.java
@@ -20,7 +20,6 @@
 /**
  * Base class for all exceptions thrown by the Android
  * Renderscript
- * @hide
  */
 public class RSInvalidStateException extends RSRuntimeException {
     public RSInvalidStateException(String string) {
diff --git a/graphics/java/android/renderscript/RSRuntimeException.java b/graphics/java/android/renderscript/RSRuntimeException.java
index 4c97937..5a16478 100644
--- a/graphics/java/android/renderscript/RSRuntimeException.java
+++ b/graphics/java/android/renderscript/RSRuntimeException.java
@@ -20,7 +20,6 @@
 /**
  * Base class for all exceptions thrown by the Android
  * Renderscript
- * @hide
  */
 public class RSRuntimeException
   extends java.lang.RuntimeException {
diff --git a/graphics/java/android/renderscript/RSSurfaceView.java b/graphics/java/android/renderscript/RSSurfaceView.java
index 507f41f..be893bb 100644
--- a/graphics/java/android/renderscript/RSSurfaceView.java
+++ b/graphics/java/android/renderscript/RSSurfaceView.java
@@ -30,16 +30,16 @@
 import android.view.SurfaceView;
 
 /**
- * @hide
  *
- **/
+ */
 public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
     private SurfaceHolder mSurfaceHolder;
     private RenderScriptGL mRS;
 
     /**
      * Standard View constructor. In order to render something, you
-     * must call {@link #setRenderer} to register a renderer.
+     * must call {@link android.opengl.GLSurfaceView#setRenderer} to
+     * register a renderer.
      */
     public RSSurfaceView(Context context) {
         super(context);
@@ -49,7 +49,8 @@
 
     /**
      * Standard View constructor. In order to render something, you
-     * must call {@link #setRenderer} to register a renderer.
+     * must call {@link android.opengl.GLSurfaceView#setRenderer} to
+     * register a renderer.
      */
     public RSSurfaceView(Context context, AttributeSet attrs) {
         super(context, attrs);
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 5f93f5b..28b32d5 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -19,6 +19,7 @@
 import java.lang.reflect.Field;
 
 import android.content.Context;
+import android.content.res.AssetManager;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.util.Config;
@@ -27,8 +28,6 @@
 
 
 /**
- * @hide
- *
  * RenderScript base master class.  An instance of this class creates native
  * worker threads for processing commands from this object.  This base class
  * does not provide any extended capabilities beyond simple data processing.
@@ -61,7 +60,8 @@
             _nInit();
             sInitialized = true;
         } catch (UnsatisfiedLinkError e) {
-            Log.d(LOG_TAG, "RenderScript JNI library not found!");
+            Log.e(LOG_TAG, "Error loading RS jni library: " + e);
+            throw new RSRuntimeException("Error loading RS jni library: " + e);
         }
     }
 
@@ -223,48 +223,66 @@
     synchronized void nAllocationSyncAll(int alloc, int src) {
         rsnAllocationSyncAll(mContext, alloc, src);
     }
+    native void rsnAllocationGenerateMipmaps(int con, int alloc);
+    synchronized void nAllocationGenerateMipmaps(int alloc) {
+        rsnAllocationGenerateMipmaps(mContext, alloc);
+    }
     native void  rsnAllocationCopyFromBitmap(int con, int alloc, Bitmap bmp);
     synchronized void nAllocationCopyFromBitmap(int alloc, Bitmap bmp) {
         rsnAllocationCopyFromBitmap(mContext, alloc, bmp);
     }
 
-    native void rsnAllocationUploadToTexture(int con, int alloc, boolean genMips, int baseMioLevel);
-    synchronized void nAllocationUploadToTexture(int alloc, boolean genMips, int baseMioLevel) {
-        rsnAllocationUploadToTexture(mContext, alloc, genMips, baseMioLevel);
+
+    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, int[] d, int sizeBytes);
+    synchronized void nAllocationData1D(int id, int off, int mip, int count, int[] d, int sizeBytes) {
+        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
     }
-    native void rsnAllocationUploadToBufferObject(int con, int alloc);
-    synchronized void nAllocationUploadToBufferObject(int alloc) {
-        rsnAllocationUploadToBufferObject(mContext, alloc);
+    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, short[] d, int sizeBytes);
+    synchronized void nAllocationData1D(int id, int off, int mip, int count, short[] d, int sizeBytes) {
+        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
+    }
+    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, byte[] d, int sizeBytes);
+    synchronized void nAllocationData1D(int id, int off, int mip, int count, byte[] d, int sizeBytes) {
+        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
+    }
+    native void rsnAllocationData1D(int con, int id, int off, int mip, int count, float[] d, int sizeBytes);
+    synchronized void nAllocationData1D(int id, int off, int mip, int count, float[] d, int sizeBytes) {
+        rsnAllocationData1D(mContext, id, off, mip, count, d, sizeBytes);
     }
 
-    native void rsnAllocationSubData1D(int con, int id, int off, int count, int[] d, int sizeBytes);
-    synchronized void nAllocationSubData1D(int id, int off, int count, int[] d, int sizeBytes) {
-        rsnAllocationSubData1D(mContext, id, off, count, d, sizeBytes);
-    }
-    native void rsnAllocationSubData1D(int con, int id, int off, int count, short[] d, int sizeBytes);
-    synchronized void nAllocationSubData1D(int id, int off, int count, short[] d, int sizeBytes) {
-        rsnAllocationSubData1D(mContext, id, off, count, d, sizeBytes);
-    }
-    native void rsnAllocationSubData1D(int con, int id, int off, int count, byte[] d, int sizeBytes);
-    synchronized void nAllocationSubData1D(int id, int off, int count, byte[] d, int sizeBytes) {
-        rsnAllocationSubData1D(mContext, id, off, count, d, sizeBytes);
-    }
-    native void rsnAllocationSubElementData1D(int con, int id, int xoff, int compIdx, byte[] d, int sizeBytes);
-    synchronized void nAllocationSubElementData1D(int id, int xoff, int compIdx, byte[] d, int sizeBytes) {
-        rsnAllocationSubElementData1D(mContext, id, xoff, compIdx, d, sizeBytes);
-    }
-    native void rsnAllocationSubData1D(int con, int id, int off, int count, float[] d, int sizeBytes);
-    synchronized void nAllocationSubData1D(int id, int off, int count, float[] d, int sizeBytes) {
-        rsnAllocationSubData1D(mContext, id, off, count, d, sizeBytes);
+    native void rsnAllocationElementData1D(int con, int id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes);
+    synchronized void nAllocationElementData1D(int id, int xoff, int mip, int compIdx, byte[] d, int sizeBytes) {
+        rsnAllocationElementData1D(mContext, id, xoff, mip, compIdx, d, sizeBytes);
     }
 
-    native void rsnAllocationSubData2D(int con, int id, int xoff, int yoff, int w, int h, int[] d, int sizeBytes);
-    synchronized void nAllocationSubData2D(int id, int xoff, int yoff, int w, int h, int[] d, int sizeBytes) {
-        rsnAllocationSubData2D(mContext, id, xoff, yoff, w, h, d, sizeBytes);
+    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes);
+    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, byte[] d, int sizeBytes) {
+        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
     }
-    native void rsnAllocationSubData2D(int con, int id, int xoff, int yoff, int w, int h, float[] d, int sizeBytes);
-    synchronized void nAllocationSubData2D(int id, int xoff, int yoff, int w, int h, float[] d, int sizeBytes) {
-        rsnAllocationSubData2D(mContext, id, xoff, yoff, w, h, d, sizeBytes);
+    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, short[] d, int sizeBytes);
+    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, short[] d, int sizeBytes) {
+        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
+    }
+    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, int[] d, int sizeBytes);
+    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, int[] d, int sizeBytes) {
+        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
+    }
+    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, int w, int h, float[] d, int sizeBytes);
+    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, int w, int h, float[] d, int sizeBytes) {
+        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, w, h, d, sizeBytes);
+    }
+    native void rsnAllocationData2D(int con, int id, int xoff, int yoff, int mip, int face, Bitmap b);
+    synchronized void nAllocationData2D(int id, int xoff, int yoff, int mip, int face, Bitmap b) {
+        rsnAllocationData2D(mContext, id, xoff, yoff, mip, face, b);
+    }
+
+    native void rsnAllocationRead(int con, int id, byte[] d);
+    synchronized void nAllocationRead(int id, byte[] d) {
+        rsnAllocationRead(mContext, id, d);
+    }
+    native void rsnAllocationRead(int con, int id, short[] d);
+    synchronized void nAllocationRead(int id, short[] d) {
+        rsnAllocationRead(mContext, id, d);
     }
     native void rsnAllocationRead(int con, int id, int[] d);
     synchronized void nAllocationRead(int id, int[] d) {
@@ -292,6 +310,14 @@
     synchronized int nFileA3DCreateFromAssetStream(int assetStream) {
         return rsnFileA3DCreateFromAssetStream(mContext, assetStream);
     }
+    native int  rsnFileA3DCreateFromFile(int con, String path);
+    synchronized int nFileA3DCreateFromFile(String path) {
+        return rsnFileA3DCreateFromFile(mContext, path);
+    }
+    native int  rsnFileA3DCreateFromAsset(int con, AssetManager mgr, String path);
+    synchronized int nFileA3DCreateFromAsset(AssetManager mgr, String path) {
+        return rsnFileA3DCreateFromAsset(mContext, mgr, path);
+    }
     native int  rsnFileA3DGetNumIndexEntries(int con, int fileA3D);
     synchronized int nFileA3DGetNumIndexEntries(int fileA3D) {
         return rsnFileA3DGetNumIndexEntries(mContext, fileA3D);
@@ -305,68 +331,19 @@
         return rsnFileA3DGetEntryByIndex(mContext, fileA3D, index);
     }
 
-    native int  rsnFontCreateFromFile(int con, String fileName, int size, int dpi);
-    synchronized int nFontCreateFromFile(String fileName, int size, int dpi) {
+    native int  rsnFontCreateFromFile(int con, String fileName, float size, int dpi);
+    synchronized int nFontCreateFromFile(String fileName, float size, int dpi) {
         return rsnFontCreateFromFile(mContext, fileName, size, dpi);
     }
-
-    native void rsnAdapter1DBindAllocation(int con, int ad, int alloc);
-    synchronized void nAdapter1DBindAllocation(int ad, int alloc) {
-        rsnAdapter1DBindAllocation(mContext, ad, alloc);
+    native int  rsnFontCreateFromAssetStream(int con, String name, float size, int dpi, int assetStream);
+    synchronized int nFontCreateFromAssetStream(String name, float size, int dpi, int assetStream) {
+        return rsnFontCreateFromAssetStream(mContext, name, size, dpi, assetStream);
     }
-    native void rsnAdapter1DSetConstraint(int con, int ad, int dim, int value);
-    synchronized void nAdapter1DSetConstraint(int ad, int dim, int value) {
-        rsnAdapter1DSetConstraint(mContext, ad, dim, value);
-    }
-    native void rsnAdapter1DData(int con, int ad, int[] d);
-    synchronized void nAdapter1DData(int ad, int[] d) {
-        rsnAdapter1DData(mContext, ad, d);
-    }
-    native void rsnAdapter1DData(int con, int ad, float[] d);
-    synchronized void nAdapter1DData(int ad, float[] d) {
-        rsnAdapter1DData(mContext, ad, d);
-    }
-    native void rsnAdapter1DSubData(int con, int ad, int off, int count, int[] d);
-    synchronized void nAdapter1DSubData(int ad, int off, int count, int[] d) {
-        rsnAdapter1DSubData(mContext, ad, off, count, d);
-    }
-    native void rsnAdapter1DSubData(int con, int ad, int off, int count, float[] d);
-    synchronized void nAdapter1DSubData(int ad, int off, int count, float[] d) {
-        rsnAdapter1DSubData(mContext, ad, off, count, d);
-    }
-    native int  rsnAdapter1DCreate(int con);
-    synchronized int nAdapter1DCreate() {
-        return rsnAdapter1DCreate(mContext);
+    native int  rsnFontCreateFromAsset(int con, AssetManager mgr, String path, float size, int dpi);
+    synchronized int nFontCreateFromAsset(AssetManager mgr, String path, float size, int dpi) {
+        return rsnFontCreateFromAsset(mContext, mgr, path, size, dpi);
     }
 
-    native void rsnAdapter2DBindAllocation(int con, int ad, int alloc);
-    synchronized void nAdapter2DBindAllocation(int ad, int alloc) {
-        rsnAdapter2DBindAllocation(mContext, ad, alloc);
-    }
-    native void rsnAdapter2DSetConstraint(int con, int ad, int dim, int value);
-    synchronized void nAdapter2DSetConstraint(int ad, int dim, int value) {
-        rsnAdapter2DSetConstraint(mContext, ad, dim, value);
-    }
-    native void rsnAdapter2DData(int con, int ad, int[] d);
-    synchronized void nAdapter2DData(int ad, int[] d) {
-        rsnAdapter2DData(mContext, ad, d);
-    }
-    native void rsnAdapter2DData(int con, int ad, float[] d);
-    synchronized void nAdapter2DData(int ad, float[] d) {
-        rsnAdapter2DData(mContext, ad, d);
-    }
-    native void rsnAdapter2DSubData(int con, int ad, int xoff, int yoff, int w, int h, int[] d);
-    synchronized void nAdapter2DSubData(int ad, int xoff, int yoff, int w, int h, int[] d) {
-        rsnAdapter2DSubData(mContext, ad, xoff, yoff, w, h, d);
-    }
-    native void rsnAdapter2DSubData(int con, int ad, int xoff, int yoff, int w, int h, float[] d);
-    synchronized void nAdapter2DSubData(int ad, int xoff, int yoff, int w, int h, float[] d) {
-        rsnAdapter2DSubData(mContext, ad, xoff, yoff, w, h, d);
-    }
-    native int  rsnAdapter2DCreate(int con);
-    synchronized int nAdapter2DCreate() {
-        return rsnAdapter2DCreate(mContext);
-    }
 
     native void rsnScriptBindAllocation(int con, int script, int alloc, int slot);
     synchronized void nScriptBindAllocation(int script, int alloc, int slot) {
@@ -417,9 +394,9 @@
     synchronized void nScriptCSetScript(byte[] script, int offset, int length) {
         rsnScriptCSetScript(mContext, script, offset, length);
     }
-    native int  rsnScriptCCreate(int con, String val, String cacheDir);
-    synchronized int nScriptCCreate(String resName, String cacheDir) {
-      return rsnScriptCCreate(mContext, resName, cacheDir);
+    native int  rsnScriptCCreate(int con, String packageName, String resName, String cacheDir);
+    synchronized int nScriptCCreate(String packageName, String resName, String cacheDir) {
+        return rsnScriptCCreate(mContext, packageName, resName, cacheDir);
     }
 
     native void rsnSamplerBegin(int con);
@@ -589,16 +566,8 @@
 
     ProgramStore mProgramStore_BLEND_NONE_DEPTH_TEST;
     ProgramStore mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH;
-    ProgramStore mProgramStore_BLEND_NONE_DEPTH_NO_TEST;
-    ProgramStore mProgramStore_BLEND_NONE_DEPTH_NO_WRITE;
     ProgramStore mProgramStore_BLEND_ALPHA_DEPTH_TEST;
     ProgramStore mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH;
-    ProgramStore mProgramStore_BLEND_ALPHA_DEPTH_NO_TEST;
-    ProgramStore mProgramStore_BLEND_ALPHA_DEPTH_NO_WRITE;
-    ProgramStore mProgramStore_BLEND_ADD_DEPTH_TEST;
-    ProgramStore mProgramStore_BLEND_ADD_DEPTH_NO_DEPTH;
-    ProgramStore mProgramStore_BLEND_ADD_DEPTH_NO_TEST;
-    ProgramStore mProgramStore_BLEND_ADD_DEPTH_NO_WRITE;
 
     ProgramRaster mProgramRaster_CULL_BACK;
     ProgramRaster mProgramRaster_CULL_FRONT;
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java
index 5adb682..58cc739 100644
--- a/graphics/java/android/renderscript/RenderScriptGL.java
+++ b/graphics/java/android/renderscript/RenderScriptGL.java
@@ -29,8 +29,6 @@
 import android.view.SurfaceView;
 
 /**
- * @hide
- *
  * The Graphics derivitive of RenderScript.  Extends the basic context to add a
  * root script which is the display window for graphical output.  When the
  * system needs to update the display the currently bound root script will be
@@ -152,19 +150,6 @@
     };
 
     SurfaceConfig mSurfaceConfig;
-/*
-    // Keep?
-    public void configureSurface(SurfaceHolder sh) {
-        if (mSurfaceConfig.mAlphaMin > 1) {
-            sh.setFormat(PixelFormat.RGBA_8888);
-        } else {
-            sh.setFormat(PixelFormat.RGBX_8888);
-        }
-    }
-
-    public void checkSurface(SurfaceHolder sh) {
-    }
-*/
 
     /**
      * Construct a new RenderScriptGL context.
diff --git a/graphics/java/android/renderscript/Sampler.java b/graphics/java/android/renderscript/Sampler.java
index 45a3949..c656d75 100644
--- a/graphics/java/android/renderscript/Sampler.java
+++ b/graphics/java/android/renderscript/Sampler.java
@@ -29,8 +29,6 @@
 import android.graphics.BitmapFactory;
 
 /**
- * @hide
- *
  * Sampler object which defines how data is extracted from textures.  Samplers
  * are attached to Program objects (currently only fragment) when those objects
  * need to access texture data.
@@ -58,15 +56,15 @@
      * Retrieve a sampler with min and mag set to nearest and wrap modes set to
      * clamp.
      *
-     * @param rs
+     * @param rs Context to which the sampler will belong.
      *
      * @return Sampler
      */
     public static Sampler CLAMP_NEAREST(RenderScript rs) {
         if(rs.mSampler_CLAMP_NEAREST == null) {
             Builder b = new Builder(rs);
-            b.setMin(Value.NEAREST);
-            b.setMag(Value.NEAREST);
+            b.setMinification(Value.NEAREST);
+            b.setMagnification(Value.NEAREST);
             b.setWrapS(Value.CLAMP);
             b.setWrapT(Value.CLAMP);
             rs.mSampler_CLAMP_NEAREST = b.create();
@@ -78,15 +76,15 @@
      * Retrieve a sampler with min and mag set to linear and wrap modes set to
      * clamp.
      *
-     * @param rs
+     * @param rs Context to which the sampler will belong.
      *
      * @return Sampler
      */
     public static Sampler CLAMP_LINEAR(RenderScript rs) {
         if(rs.mSampler_CLAMP_LINEAR == null) {
             Builder b = new Builder(rs);
-            b.setMin(Value.LINEAR);
-            b.setMag(Value.LINEAR);
+            b.setMinification(Value.LINEAR);
+            b.setMagnification(Value.LINEAR);
             b.setWrapS(Value.CLAMP);
             b.setWrapT(Value.CLAMP);
             rs.mSampler_CLAMP_LINEAR = b.create();
@@ -98,15 +96,15 @@
      * Retrieve a sampler with ag set to linear, min linear mipmap linear, and
      * to and wrap modes set to clamp.
      *
-     * @param rs
+     * @param rs Context to which the sampler will belong.
      *
      * @return Sampler
      */
     public static Sampler CLAMP_LINEAR_MIP_LINEAR(RenderScript rs) {
         if(rs.mSampler_CLAMP_LINEAR_MIP_LINEAR == null) {
             Builder b = new Builder(rs);
-            b.setMin(Value.LINEAR_MIP_LINEAR);
-            b.setMag(Value.LINEAR);
+            b.setMinification(Value.LINEAR_MIP_LINEAR);
+            b.setMagnification(Value.LINEAR);
             b.setWrapS(Value.CLAMP);
             b.setWrapT(Value.CLAMP);
             rs.mSampler_CLAMP_LINEAR_MIP_LINEAR = b.create();
@@ -118,15 +116,15 @@
      * Retrieve a sampler with min and mag set to nearest and wrap modes set to
      * wrap.
      *
-     * @param rs
+     * @param rs Context to which the sampler will belong.
      *
      * @return Sampler
      */
     public static Sampler WRAP_NEAREST(RenderScript rs) {
         if(rs.mSampler_WRAP_NEAREST == null) {
             Builder b = new Builder(rs);
-            b.setMin(Value.NEAREST);
-            b.setMag(Value.NEAREST);
+            b.setMinification(Value.NEAREST);
+            b.setMagnification(Value.NEAREST);
             b.setWrapS(Value.WRAP);
             b.setWrapT(Value.WRAP);
             rs.mSampler_WRAP_NEAREST = b.create();
@@ -138,15 +136,15 @@
      * Retrieve a sampler with min and mag set to nearest and wrap modes set to
      * wrap.
      *
-     * @param rs
+     * @param rs Context to which the sampler will belong.
      *
      * @return Sampler
      */
     public static Sampler WRAP_LINEAR(RenderScript rs) {
         if(rs.mSampler_WRAP_LINEAR == null) {
             Builder b = new Builder(rs);
-            b.setMin(Value.LINEAR);
-            b.setMag(Value.LINEAR);
+            b.setMinification(Value.LINEAR);
+            b.setMagnification(Value.LINEAR);
             b.setWrapS(Value.WRAP);
             b.setWrapT(Value.WRAP);
             rs.mSampler_WRAP_LINEAR = b.create();
@@ -158,15 +156,15 @@
      * Retrieve a sampler with ag set to linear, min linear mipmap linear, and
      * to and wrap modes set to wrap.
      *
-     * @param rs
+     * @param rs Context to which the sampler will belong.
      *
      * @return Sampler
      */
     public static Sampler WRAP_LINEAR_MIP_LINEAR(RenderScript rs) {
         if(rs.mSampler_WRAP_LINEAR_MIP_LINEAR == null) {
             Builder b = new Builder(rs);
-            b.setMin(Value.LINEAR_MIP_LINEAR);
-            b.setMag(Value.LINEAR);
+            b.setMinification(Value.LINEAR_MIP_LINEAR);
+            b.setMagnification(Value.LINEAR);
             b.setWrapS(Value.WRAP);
             b.setWrapT(Value.WRAP);
             rs.mSampler_WRAP_LINEAR_MIP_LINEAR = b.create();
@@ -199,7 +197,7 @@
             mAniso = 1.0f;
         }
 
-        public void setMin(Value v) {
+        public void setMinification(Value v) {
             if (v == Value.NEAREST ||
                 v == Value.LINEAR ||
                 v == Value.LINEAR_MIP_LINEAR ||
@@ -210,7 +208,7 @@
             }
         }
 
-        public void setMag(Value v) {
+        public void setMagnification(Value v) {
             if (v == Value.NEAREST || v == Value.LINEAR) {
                 mMag = v;
             } else {
@@ -234,14 +232,6 @@
             }
         }
 
-        public void setWrapR(Value v) {
-            if (v == Value.WRAP || v == Value.CLAMP) {
-                mWrapR = v;
-            } else {
-                throw new IllegalArgumentException("Invalid value");
-            }
-        }
-
         public void setAnisotropy(float v) {
             if(v >= 0.0f) {
                 mAniso = v;
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index aaf5475..b3ad20a 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -17,35 +17,28 @@
 package android.renderscript;
 
 /**
- * @hide
+ *
  **/
 public class Script extends BaseObj {
-    public static final int MAX_SLOT = 16;
-
-    boolean mIsRoot;
-    Type[] mTypes;
-    boolean[] mWritable;
-    Invokable[] mInvokables;
-
-    public static class Invokable {
-        RenderScript mRS;
-        Script mScript;
-        int mSlot;
-        String mName;
-
-        Invokable() {
-            mSlot = -1;
-        }
-
-        public void execute() {
-            mRS.nScriptInvoke(mScript.getID(), mSlot);
-        }
-    }
-
+    /**
+     * @hide
+     *
+     * Only intended for use by generated reflected code.
+     *
+     * @param slot
+     */
     protected void invoke(int slot) {
         mRS.nScriptInvoke(getID(), slot);
     }
 
+    /**
+     * @hide
+     *
+     * Only intended for use by generated reflected code.
+     *
+     * @param slot
+     * @param v
+     */
     protected void invoke(int slot, FieldPacker v) {
         if (v != null) {
             mRS.nScriptInvokeV(getID(), slot, v.getData());
@@ -59,6 +52,15 @@
         super(id, rs);
     }
 
+
+    /**
+     * @hide
+     *
+     * Only intended for use by generated reflected code.
+     *
+     * @param va
+     * @param slot
+     */
     public void bindAllocation(Allocation va, int slot) {
         mRS.validate();
         if (va != null) {
@@ -68,30 +70,86 @@
         }
     }
 
+    /**
+     * @hide
+     *
+     * Only intended for use by generated reflected code.
+     *
+     * @param index
+     * @param v
+     */
     public void setVar(int index, float v) {
         mRS.nScriptSetVarF(getID(), index, v);
     }
 
+    /**
+     * @hide
+     *
+     * Only intended for use by generated reflected code.
+     *
+     * @param index
+     * @param v
+     */
     public void setVar(int index, double v) {
         mRS.nScriptSetVarD(getID(), index, v);
     }
 
+    /**
+     * @hide
+     *
+     * Only intended for use by generated reflected code.
+     *
+     * @param index
+     * @param v
+     */
     public void setVar(int index, int v) {
         mRS.nScriptSetVarI(getID(), index, v);
     }
 
+    /**
+     * @hide
+     *
+     * Only intended for use by generated reflected code.
+     *
+     * @param index
+     * @param v
+     */
     public void setVar(int index, long v) {
         mRS.nScriptSetVarJ(getID(), index, v);
     }
 
+    /**
+     * @hide
+     *
+     * Only intended for use by generated reflected code.
+     *
+     * @param index
+     * @param v
+     */
     public void setVar(int index, boolean v) {
         mRS.nScriptSetVarI(getID(), index, v ? 1 : 0);
     }
 
+    /**
+     * @hide
+     *
+     * Only intended for use by generated reflected code.
+     *
+     * @param index
+     * @param o
+     */
     public void setVar(int index, BaseObj o) {
         mRS.nScriptSetVarObj(getID(), index, (o == null) ? 0 : o.getID());
     }
 
+    /**
+     * @hide
+     *
+     * Only intended for use by generated reflected code.
+     *
+     * @param index
+     * @param v
+     */
     public void setVar(int index, FieldPacker v) {
         mRS.nScriptSetVarV(getID(), index, v.getData());
     }
diff --git a/graphics/java/android/renderscript/ScriptC.java b/graphics/java/android/renderscript/ScriptC.java
index b10247c..14e4ab5 100644
--- a/graphics/java/android/renderscript/ScriptC.java
+++ b/graphics/java/android/renderscript/ScriptC.java
@@ -30,15 +30,33 @@
 import java.lang.reflect.Modifier;
 
 /**
- * @hide
+ *
  **/
 public class ScriptC extends Script {
     private static final String TAG = "ScriptC";
 
+    /**
+     * @hide
+     *
+     * Only intended for use by the generated derived classes.
+     *
+     * @param id
+     * @param rs
+     */
     protected ScriptC(int id, RenderScript rs) {
         super(id, rs);
     }
 
+    /**
+     * @hide
+     *
+     * Only intended for use by the generated derived classes.
+     *
+     *
+     * @param rs
+     * @param resources
+     * @param resourceID
+     */
     protected ScriptC(RenderScript rs, Resources resources, int resourceID) {
         super(0, rs);
         int id = internalCreate(rs, resources, resourceID);
@@ -77,8 +95,14 @@
 
         rs.nScriptCBegin();
         rs.nScriptCSetScript(pgm, 0, pgmLength);
-        Log.v(TAG, "Create script for resource = " + resources.getResourceName(resourceID));
+
+        // E.g, /system/apps/Fountain.apk
+        String packageName = rs.getApplicationContext().getPackageResourcePath();
+        // For res/raw/fountain.bc, it wil be /com.android.fountain:raw/fountain
+        String resName = resources.getResourceName(resourceID);
         String cacheDir = rs.getApplicationContext().getCacheDir().toString();
-        return rs.nScriptCCreate(resources.getResourceName(resourceID), cacheDir);
+
+        Log.v(TAG, "Create script for resource = " + resName);
+        return rs.nScriptCCreate(packageName, resName, cacheDir);
     }
 }
diff --git a/graphics/java/android/renderscript/Short2.java b/graphics/java/android/renderscript/Short2.java
index 426801f..82d897e 100644
--- a/graphics/java/android/renderscript/Short2.java
+++ b/graphics/java/android/renderscript/Short2.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs short2 type back to java applications.
  *
  **/
 public class Short2 {
diff --git a/graphics/java/android/renderscript/Short3.java b/graphics/java/android/renderscript/Short3.java
index 7b9c305..00da574 100644
--- a/graphics/java/android/renderscript/Short3.java
+++ b/graphics/java/android/renderscript/Short3.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs short3 type back to java applications.
  *
  **/
 public class Short3 {
diff --git a/graphics/java/android/renderscript/Short4.java b/graphics/java/android/renderscript/Short4.java
index 9a474e2..450258d 100644
--- a/graphics/java/android/renderscript/Short4.java
+++ b/graphics/java/android/renderscript/Short4.java
@@ -21,7 +21,7 @@
 
 
 /**
- * @hide
+ * Class for exposing the rs short4 type back to java applications.
  *
  **/
 public class Short4 {
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index 859369c..bec76d0 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -21,8 +21,6 @@
 import android.util.Log;
 
 /**
- * @hide
- *
  * Type is an allocation template.  It consists of an Element and one or more
  * dimensions.  It describes only the layout of memory but does not allocate and
  * storage for the data thus described.
@@ -47,6 +45,20 @@
     int mElementCount;
     Element mElement;
 
+    public enum CubemapFace {
+        POSITVE_X (0),
+        NEGATIVE_X (1),
+        POSITVE_Y (2),
+        NEGATIVE_Y (3),
+        POSITVE_Z (4),
+        NEGATIVE_Z (5);
+
+        int mID;
+        CubemapFace(int id) {
+            mID = id;
+        }
+    }
+
     /**
      * Return the element associated with this Type.
      *
@@ -202,7 +214,6 @@
          * Add a dimension to the Type.
          *
          *
-         * @param d
          * @param value
          */
         public Builder setX(int value) {
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index a8343b3..35db786 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -32,12 +32,14 @@
 #include <images/SkImageDecoder.h>
 
 #include <utils/Asset.h>
+#include <utils/AssetManager.h>
 #include <utils/ResourceTypes.h>
 
 #include "jni.h"
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/android_view_Surface.h"
+#include "android_runtime/android_util_AssetManager.h"
 
 #include <RenderScript.h>
 #include <RenderScriptEnv.h>
@@ -47,6 +49,27 @@
 
 using namespace android;
 
+class AutoJavaStringToUTF8 {
+public:
+    AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str)
+    {
+        fCStr = env->GetStringUTFChars(str, NULL);
+        fLength = env->GetStringUTFLength(str);
+    }
+    ~AutoJavaStringToUTF8()
+    {
+        fEnv->ReleaseStringUTFChars(fJStr, fCStr);
+    }
+    const char* c_str() const { return fCStr; }
+    jsize length() const { return fLength; }
+
+private:
+    JNIEnv*     fEnv;
+    jstring     fJStr;
+    const char* fCStr;
+    jsize       fLength;
+};
+
 // ---------------------------------------------------------------------------
 
 static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
@@ -382,26 +405,19 @@
 }
 
 static void
-nAllocationUploadToTexture(JNIEnv *_env, jobject _this, RsContext con, jint a, jboolean genMip, jint mip)
-{
-    LOG_API("nAllocationUploadToTexture, con(%p), a(%p), genMip(%i), mip(%i)", con, (RsAllocation)a, genMip, mip);
-    rsAllocationUploadToTexture(con, (RsAllocation)a, genMip, mip);
-}
-
-static void
-nAllocationUploadToBufferObject(JNIEnv *_env, jobject _this, RsContext con, jint a)
-{
-    LOG_API("nAllocationUploadToBufferObject, con(%p), a(%p)", con, (RsAllocation)a);
-    rsAllocationUploadToBufferObject(con, (RsAllocation)a);
-}
-
-static void
 nAllocationSyncAll(JNIEnv *_env, jobject _this, RsContext con, jint a, jint bits)
 {
     LOG_API("nAllocationSyncAll, con(%p), a(%p), bits(0x%08x)", con, (RsAllocation)a, bits);
     rsAllocationSyncAll(con, (RsAllocation)a, (RsAllocationUsageType)bits);
 }
 
+static void
+nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, RsContext con, jint alloc)
+{
+    LOG_API("nAllocationGenerateMipmaps, con(%p), a(%p)", con, (RsAllocation)alloc);
+    rsAllocationGenerateMipmaps(con, (RsAllocation)alloc);
+}
+
 static int
 nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint type, jint mip, jobject jbitmap, jint usage)
 {
@@ -436,10 +452,14 @@
     SkBitmap const * nativeBitmap =
             (SkBitmap const *)_env->GetIntField(jbitmap, gNativeBitmapID);
     const SkBitmap& bitmap(*nativeBitmap);
+    int w = bitmap.width();
+    int h = bitmap.height();
 
     bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
-    rsAllocationCopyFromBitmap(con, (RsAllocation)alloc, ptr, bitmap.getSize());
+    rsAllocation2DData(con, (RsAllocation)alloc, 0, 0,
+                       0, RS_ALLOCATION_CUBMAP_FACE_POSITVE_X,
+                       w, h, ptr, bitmap.getSize());
     bitmap.unlockPixels();
 }
 
@@ -464,73 +484,97 @@
 
 
 static void
-nAllocationSubData1D_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint count, jintArray data, int sizeBytes)
+nAllocationData1D_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint lod, jint count, jintArray data, int sizeBytes)
 {
     jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation1DSubData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
+    LOG_API("nAllocation1DData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
     jint *ptr = _env->GetIntArrayElements(data, NULL);
-    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
+    rsAllocation1DData(con, (RsAllocation)alloc, offset, lod, count, ptr, sizeBytes);
     _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
 }
 
 static void
-nAllocationSubData1D_s(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint count, jshortArray data, int sizeBytes)
+nAllocationData1D_s(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint lod, jint count, jshortArray data, int sizeBytes)
 {
     jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation1DSubData_s, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
+    LOG_API("nAllocation1DData_s, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
     jshort *ptr = _env->GetShortArrayElements(data, NULL);
-    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
+    rsAllocation1DData(con, (RsAllocation)alloc, offset, lod, count, ptr, sizeBytes);
     _env->ReleaseShortArrayElements(data, ptr, JNI_ABORT);
 }
 
 static void
-nAllocationSubData1D_b(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint count, jbyteArray data, int sizeBytes)
+nAllocationData1D_b(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint lod, jint count, jbyteArray data, int sizeBytes)
 {
     jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation1DSubData_b, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
+    LOG_API("nAllocation1DData_b, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
     jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
+    rsAllocation1DData(con, (RsAllocation)alloc, offset, lod, count, ptr, sizeBytes);
     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
 }
 
 static void
-nAllocationSubData1D_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint count, jfloatArray data, int sizeBytes)
+nAllocationData1D_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint lod, jint count, jfloatArray data, int sizeBytes)
 {
     jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation1DSubData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
+    LOG_API("nAllocation1DData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, count, len, sizeBytes);
     jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr, sizeBytes);
+    rsAllocation1DData(con, (RsAllocation)alloc, offset, lod, count, ptr, sizeBytes);
     _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
 }
 
 static void
-//    native void rsnAllocationSubElementData1D(int con, int id, int xoff, int compIdx, byte[] d, int sizeBytes);
-nAllocationSubElementData1D(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint compIdx, jbyteArray data, int sizeBytes)
+//    native void rsnAllocationElementData1D(int con, int id, int xoff, int compIdx, byte[] d, int sizeBytes);
+nAllocationElementData1D(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint lod, jint compIdx, jbyteArray data, int sizeBytes)
 {
     jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationSubElementData1D, con(%p), alloc(%p), offset(%i), comp(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, compIdx, len, sizeBytes);
+    LOG_API("nAllocationElementData1D, con(%p), alloc(%p), offset(%i), comp(%i), len(%i), sizeBytes(%i)", con, (RsAllocation)alloc, offset, compIdx, len, sizeBytes);
     jbyte *ptr = _env->GetByteArrayElements(data, NULL);
-    rsAllocation1DSubElementData(con, (RsAllocation)alloc, offset, ptr, compIdx, sizeBytes);
+    rsAllocation1DElementData(con, (RsAllocation)alloc, offset, lod, ptr, compIdx, sizeBytes);
     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
 }
 
 static void
-nAllocationSubData2D_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint w, jint h, jintArray data, int sizeBytes)
+nAllocationData2D_s(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint lod, jint face,
+                    jint w, jint h, jshortArray data, int sizeBytes)
 {
     jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation2DSubData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
+    LOG_API("nAllocation2DData_s, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
+    jshort *ptr = _env->GetShortArrayElements(data, NULL);
+    rsAllocation2DData(con, (RsAllocation)alloc, xoff, yoff, lod, (RsAllocationCubemapFace)face, w, h, ptr, sizeBytes);
+    _env->ReleaseShortArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
+nAllocationData2D_b(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint lod, jint face,
+                    jint w, jint h, jbyteArray data, int sizeBytes)
+{
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocation2DData_b, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
+    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
+    rsAllocation2DData(con, (RsAllocation)alloc, xoff, yoff, lod, (RsAllocationCubemapFace)face, w, h, ptr, sizeBytes);
+    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
+nAllocationData2D_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint lod, jint face,
+                    jint w, jint h, jintArray data, int sizeBytes)
+{
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocation2DData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
     jint *ptr = _env->GetIntArrayElements(data, NULL);
-    rsAllocation2DSubData(con, (RsAllocation)alloc, xoff, yoff, w, h, ptr, sizeBytes);
+    rsAllocation2DData(con, (RsAllocation)alloc, xoff, yoff, lod, (RsAllocationCubemapFace)face, w, h, ptr, sizeBytes);
     _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
 }
 
 static void
-nAllocationSubData2D_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint w, jint h, jfloatArray data, int sizeBytes)
+nAllocationData2D_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint xoff, jint yoff, jint lod, jint face,
+                    jint w, jint h, jfloatArray data, int sizeBytes)
 {
     jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocation2DSubData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
+    LOG_API("nAllocation2DData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
     jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    rsAllocation2DSubData(con, (RsAllocation)alloc, xoff, yoff, w, h, ptr, sizeBytes);
+    rsAllocation2DData(con, (RsAllocation)alloc, xoff, yoff, lod, (RsAllocationCubemapFace)face, w, h, ptr, sizeBytes);
     _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
 }
 
@@ -545,6 +589,26 @@
 }
 
 static void
+nAllocationRead_s(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jshortArray data)
+{
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
+    jshort *ptr = _env->GetShortArrayElements(data, NULL);
+    rsAllocationRead(con, (RsAllocation)alloc, ptr);
+    _env->ReleaseShortArrayElements(data, ptr, 0);
+}
+
+static void
+nAllocationRead_b(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jbyteArray data)
+{
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
+    jbyte *ptr = _env->GetByteArrayElements(data, NULL);
+    rsAllocationRead(con, (RsAllocation)alloc, ptr);
+    _env->ReleaseByteArrayElements(data, ptr, 0);
+}
+
+static void
 nAllocationRead_f(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jfloatArray data)
 {
     jint len = _env->GetArrayLength(data);
@@ -584,7 +648,34 @@
 
     Asset* asset = reinterpret_cast<Asset*>(native_asset);
 
-    jint id = (jint)rsaFileA3DCreateFromAssetStream(con, asset->getBuffer(false), asset->getLength());
+    jint id = (jint)rsaFileA3DCreateFromMemory(con, asset->getBuffer(false), asset->getLength());
+    return id;
+}
+
+static int
+nFileA3DCreateFromAsset(JNIEnv *_env, jobject _this, RsContext con, jobject _assetMgr, jstring _path)
+{
+    AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
+    if (mgr == NULL) {
+        return 0;
+    }
+
+    AutoJavaStringToUTF8 str(_env, _path);
+    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+    if (asset == NULL) {
+        return 0;
+    }
+
+    jint id = (jint)rsaFileA3DCreateFromAsset(con, asset);
+    return id;
+}
+
+static int
+nFileA3DCreateFromFile(JNIEnv *_env, jobject _this, RsContext con, jstring fileName)
+{
+    AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
+    jint id = (jint)rsaFileA3DCreateFromFile(con, fileNameUTF.c_str());
+
     return id;
 }
 
@@ -623,141 +714,46 @@
 // -----------------------------------
 
 static int
-nFontCreateFromFile(JNIEnv *_env, jobject _this, RsContext con, jstring fileName, jint fontSize, jint dpi)
+nFontCreateFromFile(JNIEnv *_env, jobject _this, RsContext con,
+                    jstring fileName, jfloat fontSize, jint dpi)
 {
-    const char* fileNameUTF = _env->GetStringUTFChars(fileName, NULL);
+    AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
+    jint id = (jint)rsFontCreateFromFile(con, fileNameUTF.c_str(), fontSize, dpi);
 
-    jint id = (jint)rsFontCreateFromFile(con, fileNameUTF, fontSize, dpi);
     return id;
 }
 
-
-// -----------------------------------
-
-static void
-nAdapter1DBindAllocation(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint alloc)
+static int
+nFontCreateFromAssetStream(JNIEnv *_env, jobject _this, RsContext con,
+                           jstring name, jfloat fontSize, jint dpi, jint native_asset)
 {
-    LOG_API("nAdapter1DBindAllocation, con(%p), adapter(%p), alloc(%p)", con, (RsAdapter1D)adapter, (RsAllocation)alloc);
-    rsAdapter1DBindAllocation(con, (RsAdapter1D)adapter, (RsAllocation)alloc);
+    Asset* asset = reinterpret_cast<Asset*>(native_asset);
+    AutoJavaStringToUTF8 nameUTF(_env, name);
+
+    jint id = (jint)rsFontCreateFromMemory(con, nameUTF.c_str(), fontSize, dpi,
+                                           asset->getBuffer(false), asset->getLength());
+    return id;
 }
 
-static void
-nAdapter1DSetConstraint(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint dim, jint value)
+static int
+nFontCreateFromAsset(JNIEnv *_env, jobject _this, RsContext con, jobject _assetMgr, jstring _path,
+                     jfloat fontSize, jint dpi)
 {
-    LOG_API("nAdapter1DSetConstraint, con(%p), adapter(%p), dim(%i), value(%i)", con, (RsAdapter1D)adapter, dim, value);
-    rsAdapter1DSetConstraint(con, (RsAdapter1D)adapter, (RsDimension)dim, value);
-}
+    AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
+    if (mgr == NULL) {
+        return 0;
+    }
 
-static void
-nAdapter1DData_i(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jintArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAdapter1DData_i, con(%p), adapter(%p), len(%i)", con, (RsAdapter1D)adapter, len);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    rsAdapter1DData(con, (RsAdapter1D)adapter, ptr);
-    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
-}
+    AutoJavaStringToUTF8 str(_env, _path);
+    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+    if (asset == NULL) {
+        return 0;
+    }
 
-static void
-nAdapter1DSubData_i(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint offset, jint count, jintArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAdapter1DSubData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAdapter1D)adapter, offset, count, len);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    rsAdapter1DSubData(con, (RsAdapter1D)adapter, offset, count, ptr);
-    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
-}
-
-static void
-nAdapter1DData_f(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jfloatArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAdapter1DData_f, con(%p), adapter(%p), len(%i)", con, (RsAdapter1D)adapter, len);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    rsAdapter1DData(con, (RsAdapter1D)adapter, ptr);
-    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
-}
-
-static void
-nAdapter1DSubData_f(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint offset, jint count, jfloatArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAdapter1DSubData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAdapter1D)adapter, offset, count, len);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    rsAdapter1DSubData(con, (RsAdapter1D)adapter, offset, count, ptr);
-    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
-}
-
-static jint
-nAdapter1DCreate(JNIEnv *_env, jobject _this, RsContext con)
-{
-    LOG_API("nAdapter1DCreate, con(%p)", con);
-    return (jint)rsAdapter1DCreate(con);
-}
-
-// -----------------------------------
-
-static void
-nAdapter2DBindAllocation(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint alloc)
-{
-    LOG_API("nAdapter2DBindAllocation, con(%p), adapter(%p), alloc(%p)", con, (RsAdapter2D)adapter, (RsAllocation)alloc);
-    rsAdapter2DBindAllocation(con, (RsAdapter2D)adapter, (RsAllocation)alloc);
-}
-
-static void
-nAdapter2DSetConstraint(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint dim, jint value)
-{
-    LOG_API("nAdapter2DSetConstraint, con(%p), adapter(%p), dim(%i), value(%i)", con, (RsAdapter2D)adapter, dim, value);
-    rsAdapter2DSetConstraint(con, (RsAdapter2D)adapter, (RsDimension)dim, value);
-}
-
-static void
-nAdapter2DData_i(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jintArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAdapter2DData_i, con(%p), adapter(%p), len(%i)", con, (RsAdapter2D)adapter, len);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    rsAdapter2DData(con, (RsAdapter2D)adapter, ptr);
-    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
-}
-
-static void
-nAdapter2DData_f(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jfloatArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAdapter2DData_f, con(%p), adapter(%p), len(%i)", con, (RsAdapter2D)adapter, len);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    rsAdapter2DData(con, (RsAdapter2D)adapter, ptr);
-    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
-}
-
-static void
-nAdapter2DSubData_i(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint xoff, jint yoff, jint w, jint h, jintArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAdapter2DSubData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)",
-            con, (RsAdapter2D)adapter, xoff, yoff, w, h, len);
-    jint *ptr = _env->GetIntArrayElements(data, NULL);
-    rsAdapter2DSubData(con, (RsAdapter2D)adapter, xoff, yoff, w, h, ptr);
-    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
-}
-
-static void
-nAdapter2DSubData_f(JNIEnv *_env, jobject _this, RsContext con, jint adapter, jint xoff, jint yoff, jint w, jint h, jfloatArray data)
-{
-    jint len = _env->GetArrayLength(data);
-    LOG_API("nAdapter2DSubData_f, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)",
-            con, (RsAdapter2D)adapter, xoff, yoff, w, h, len);
-    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    rsAdapter2DSubData(con, (RsAdapter1D)adapter, xoff, yoff, w, h, ptr);
-    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
-}
-
-static jint
-nAdapter2DCreate(JNIEnv *_env, jobject _this, RsContext con)
-{
-    LOG_API("nAdapter2DCreate, con(%p)", con);
-    return (jint)rsAdapter2DCreate(con);
+    jint id = (jint)rsFontCreateFromMemory(con, str.c_str(), fontSize, dpi,
+                                           asset->getBuffer(false), asset->getLength());
+    delete asset;
+    return id;
 }
 
 // -----------------------------------
@@ -902,14 +898,13 @@
 }
 
 static jint
-nScriptCCreate(JNIEnv *_env, jobject _this, RsContext con, jstring resName, jstring cacheDir)
+nScriptCCreate(JNIEnv *_env, jobject _this, RsContext con, jstring packageName, jstring resName, jstring cacheDir)
 {
     LOG_API("nScriptCCreate, con(%p)", con);
-    const char* resNameUTF = _env->GetStringUTFChars(resName, NULL);
-    const char* cacheDirUTF = _env->GetStringUTFChars(cacheDir, NULL);
-    jint i = (jint)rsScriptCCreate(con, resNameUTF, cacheDirUTF);
-    _env->ReleaseStringUTFChars(resName, resNameUTF);
-    _env->ReleaseStringUTFChars(cacheDir, cacheDirUTF);
+    AutoJavaStringToUTF8 packageNameUTF(_env, packageName);
+    AutoJavaStringToUTF8 resNameUTF(_env, resName);
+    AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
+    jint i = (jint)rsScriptCCreate(con, packageNameUTF.c_str(), resNameUTF.c_str(), cacheDirUTF.c_str());
     return i;
 }
 
@@ -992,15 +987,13 @@
 static jint
 nProgramFragmentCreate(JNIEnv *_env, jobject _this, RsContext con, jstring shader, jintArray params)
 {
-    const char* shaderUTF = _env->GetStringUTFChars(shader, NULL);
-    jint shaderLen = _env->GetStringUTFLength(shader);
+    AutoJavaStringToUTF8 shaderUTF(_env, shader);
     jint *paramPtr = _env->GetIntArrayElements(params, NULL);
     jint paramLen = _env->GetArrayLength(params);
 
     LOG_API("nProgramFragmentCreate, con(%p), shaderLen(%i), paramLen(%i)", con, shaderLen, paramLen);
 
-    jint ret = (jint)rsProgramFragmentCreate(con, shaderUTF, shaderLen, (uint32_t *)paramPtr, paramLen);
-    _env->ReleaseStringUTFChars(shader, shaderUTF);
+    jint ret = (jint)rsProgramFragmentCreate(con, shaderUTF.c_str(), shaderUTF.length(), (uint32_t *)paramPtr, paramLen);
     _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
     return ret;
 }
@@ -1011,15 +1004,13 @@
 static jint
 nProgramVertexCreate(JNIEnv *_env, jobject _this, RsContext con, jstring shader, jintArray params)
 {
-    const char* shaderUTF = _env->GetStringUTFChars(shader, NULL);
-    jint shaderLen = _env->GetStringUTFLength(shader);
+    AutoJavaStringToUTF8 shaderUTF(_env, shader);
     jint *paramPtr = _env->GetIntArrayElements(params, NULL);
     jint paramLen = _env->GetArrayLength(params);
 
     LOG_API("nProgramVertexCreate, con(%p), shaderLen(%i), paramLen(%i)", con, shaderLen, paramLen);
 
-    jint ret = (jint)rsProgramVertexCreate(con, shaderUTF, shaderLen, (uint32_t *)paramPtr, paramLen);
-    _env->ReleaseStringUTFChars(shader, shaderUTF);
+    jint ret = (jint)rsProgramVertexCreate(con, shaderUTF.c_str(), shaderUTF.length(), (uint32_t *)paramPtr, paramLen);
     _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
     return ret;
 }
@@ -1234,12 +1225,16 @@
 {"rsnGetName",                       "(II)Ljava/lang/String;",                (void*)nGetName },
 {"rsnObjDestroy",                    "(II)V",                                 (void*)nObjDestroy },
 
+{"rsnFileA3DCreateFromFile",         "(ILjava/lang/String;)I",                (void*)nFileA3DCreateFromFile },
 {"rsnFileA3DCreateFromAssetStream",  "(II)I",                                 (void*)nFileA3DCreateFromAssetStream },
+{"rsnFileA3DCreateFromAsset",        "(ILandroid/content/res/AssetManager;Ljava/lang/String;)I",            (void*)nFileA3DCreateFromAsset },
 {"rsnFileA3DGetNumIndexEntries",     "(II)I",                                 (void*)nFileA3DGetNumIndexEntries },
 {"rsnFileA3DGetIndexEntries",        "(III[I[Ljava/lang/String;)V",           (void*)nFileA3DGetIndexEntries },
 {"rsnFileA3DGetEntryByIndex",        "(III)I",                                (void*)nFileA3DGetEntryByIndex },
 
-{"rsnFontCreateFromFile",            "(ILjava/lang/String;II)I",              (void*)nFontCreateFromFile },
+{"rsnFontCreateFromFile",            "(ILjava/lang/String;FI)I",              (void*)nFontCreateFromFile },
+{"rsnFontCreateFromAssetStream",     "(ILjava/lang/String;FII)I",             (void*)nFontCreateFromAssetStream },
+{"rsnFontCreateFromAsset",        "(ILandroid/content/res/AssetManager;Ljava/lang/String;FI)I",            (void*)nFontCreateFromAsset },
 
 {"rsnElementCreate",                 "(IIIZI)I",                              (void*)nElementCreate },
 {"rsnElementCreate2",                "(I[I[Ljava/lang/String;[I)I",           (void*)nElementCreate2 },
@@ -1256,37 +1251,24 @@
 {"rsnAllocationCopyFromBitmap",      "(IILandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyFromBitmap },
 {"rsnAllocationCopyToBitmap",        "(IILandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyToBitmap },
 
-{"rsnAllocationUploadToTexture",     "(IIZI)V",                               (void*)nAllocationUploadToTexture },
-{"rsnAllocationUploadToBufferObject","(II)V",                                 (void*)nAllocationUploadToBufferObject },
 {"rsnAllocationSyncAll",             "(III)V",                                (void*)nAllocationSyncAll },
-{"rsnAllocationSubData1D",           "(IIII[II)V",                            (void*)nAllocationSubData1D_i },
-{"rsnAllocationSubData1D",           "(IIII[SI)V",                            (void*)nAllocationSubData1D_s },
-{"rsnAllocationSubData1D",           "(IIII[BI)V",                            (void*)nAllocationSubData1D_b },
-{"rsnAllocationSubData1D",           "(IIII[FI)V",                            (void*)nAllocationSubData1D_f },
-{"rsnAllocationSubElementData1D",    "(IIII[BI)V",                            (void*)nAllocationSubElementData1D },
-{"rsnAllocationSubData2D",           "(IIIIII[II)V",                          (void*)nAllocationSubData2D_i },
-{"rsnAllocationSubData2D",           "(IIIIII[FI)V",                          (void*)nAllocationSubData2D_f },
+{"rsnAllocationData1D",              "(IIIII[II)V",                           (void*)nAllocationData1D_i },
+{"rsnAllocationData1D",              "(IIIII[SI)V",                           (void*)nAllocationData1D_s },
+{"rsnAllocationData1D",              "(IIIII[BI)V",                           (void*)nAllocationData1D_b },
+{"rsnAllocationData1D",              "(IIIII[FI)V",                           (void*)nAllocationData1D_f },
+{"rsnAllocationElementData1D",       "(IIIII[BI)V",                           (void*)nAllocationElementData1D },
+{"rsnAllocationData2D",              "(IIIIIIII[II)V",                        (void*)nAllocationData2D_i },
+{"rsnAllocationData2D",              "(IIIIIIII[SI)V",                        (void*)nAllocationData2D_s },
+{"rsnAllocationData2D",              "(IIIIIIII[BI)V",                        (void*)nAllocationData2D_b },
+{"rsnAllocationData2D",              "(IIIIIIII[FI)V",                        (void*)nAllocationData2D_f },
 {"rsnAllocationRead",                "(II[I)V",                               (void*)nAllocationRead_i },
+{"rsnAllocationRead",                "(II[S)V",                               (void*)nAllocationRead_s },
+{"rsnAllocationRead",                "(II[B)V",                               (void*)nAllocationRead_b },
 {"rsnAllocationRead",                "(II[F)V",                               (void*)nAllocationRead_f },
 {"rsnAllocationGetType",             "(II)I",                                 (void*)nAllocationGetType},
 {"rsnAllocationResize1D",            "(III)V",                                (void*)nAllocationResize1D },
 {"rsnAllocationResize2D",            "(IIII)V",                               (void*)nAllocationResize2D },
-
-{"rsnAdapter1DBindAllocation",       "(III)V",                                (void*)nAdapter1DBindAllocation },
-{"rsnAdapter1DSetConstraint",        "(IIII)V",                               (void*)nAdapter1DSetConstraint },
-{"rsnAdapter1DData",                 "(II[I)V",                               (void*)nAdapter1DData_i },
-{"rsnAdapter1DData",                 "(II[F)V",                               (void*)nAdapter1DData_f },
-{"rsnAdapter1DSubData",              "(IIII[I)V",                             (void*)nAdapter1DSubData_i },
-{"rsnAdapter1DSubData",              "(IIII[F)V",                             (void*)nAdapter1DSubData_f },
-{"rsnAdapter1DCreate",               "(I)I",                                  (void*)nAdapter1DCreate },
-
-{"rsnAdapter2DBindAllocation",       "(III)V",                                (void*)nAdapter2DBindAllocation },
-{"rsnAdapter2DSetConstraint",        "(IIII)V",                               (void*)nAdapter2DSetConstraint },
-{"rsnAdapter2DData",                 "(II[I)V",                               (void*)nAdapter2DData_i },
-{"rsnAdapter2DData",                 "(II[F)V",                               (void*)nAdapter2DData_f },
-{"rsnAdapter2DSubData",              "(IIIIII[I)V",                           (void*)nAdapter2DSubData_i },
-{"rsnAdapter2DSubData",              "(IIIIII[F)V",                           (void*)nAdapter2DSubData_f },
-{"rsnAdapter2DCreate",               "(I)I",                                  (void*)nAdapter2DCreate },
+{"rsnAllocationGenerateMipmaps",     "(II)V",                                 (void*)nAllocationGenerateMipmaps },
 
 {"rsnScriptBindAllocation",          "(IIII)V",                               (void*)nScriptBindAllocation },
 {"rsnScriptSetTimeZone",             "(II[B)V",                               (void*)nScriptSetTimeZone },
@@ -1301,7 +1283,7 @@
 
 {"rsnScriptCBegin",                  "(I)V",                                  (void*)nScriptCBegin },
 {"rsnScriptCSetScript",              "(I[BII)V",                              (void*)nScriptCSetScript },
-{"rsnScriptCCreate",                 "(ILjava/lang/String;Ljava/lang/String;)I",  (void*)nScriptCCreate },
+{"rsnScriptCCreate",                 "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",  (void*)nScriptCCreate },
 
 {"rsnProgramStoreBegin",             "(III)V",                                (void*)nProgramStoreBegin },
 {"rsnProgramStoreDepthFunc",         "(II)V",                                 (void*)nProgramStoreDepthFunc },
@@ -1315,13 +1297,13 @@
 {"rsnProgramBindTexture",            "(IIII)V",                               (void*)nProgramBindTexture },
 {"rsnProgramBindSampler",            "(IIII)V",                               (void*)nProgramBindSampler },
 
-{"rsnProgramFragmentCreate",        "(ILjava/lang/String;[I)I",               (void*)nProgramFragmentCreate },
+{"rsnProgramFragmentCreate",         "(ILjava/lang/String;[I)I",              (void*)nProgramFragmentCreate },
 
 {"rsnProgramRasterCreate",           "(IZZZ)I",                               (void*)nProgramRasterCreate },
 {"rsnProgramRasterSetLineWidth",     "(IIF)V",                                (void*)nProgramRasterSetLineWidth },
 {"rsnProgramRasterSetCullMode",      "(III)V",                                (void*)nProgramRasterSetCullMode },
 
-{"rsnProgramVertexCreate",          "(ILjava/lang/String;[I)I",               (void*)nProgramVertexCreate },
+{"rsnProgramVertexCreate",           "(ILjava/lang/String;[I)I",              (void*)nProgramVertexCreate },
 
 {"rsnContextBindRootScript",         "(II)V",                                 (void*)nContextBindRootScript },
 {"rsnContextBindProgramStore",       "(II)V",                                 (void*)nContextBindProgramStore },
diff --git a/graphics/tests/graphicstests/src/android/graphics/drawable/MipmapDrawableTest.java b/graphics/tests/graphicstests/src/android/graphics/drawable/MipmapDrawableTest.java
new file mode 100644
index 0000000..5fcc3bc
--- /dev/null
+++ b/graphics/tests/graphicstests/src/android/graphics/drawable/MipmapDrawableTest.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable;
+
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.MipmapDrawable;
+import android.graphics.drawable.DrawableContainer.DrawableContainerState;
+import android.test.InstrumentationTestCase;
+
+public class MipmapDrawableTest extends InstrumentationTestCase {
+    private MockMipmapDrawable mMipmapDrawable;
+
+    private DrawableContainerState mDrawableContainerState;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mMipmapDrawable = new MockMipmapDrawable();
+        mDrawableContainerState = (DrawableContainerState) mMipmapDrawable.getConstantState();
+    }
+
+    public void testMipmapDrawable() {
+        new MipmapDrawable();
+        // Check the values set in the constructor
+        assertNotNull(new MipmapDrawable().getConstantState());
+        assertTrue(new MockMipmapDrawable().hasCalledOnBoundsChanged());
+    }
+
+    public void testAddDrawable() {
+        assertEquals(0, mDrawableContainerState.getChildCount());
+
+        // nothing happens if drawable is null
+        mMipmapDrawable.reset();
+        mMipmapDrawable.addDrawable(null);
+        assertEquals(0, mDrawableContainerState.getChildCount());
+        assertFalse(mMipmapDrawable.hasCalledOnBoundsChanged());
+
+        mMipmapDrawable.reset();
+        mMipmapDrawable.addDrawable(new MockDrawable());
+        assertEquals(1, mDrawableContainerState.getChildCount());
+        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
+
+        mMipmapDrawable.reset();
+        mMipmapDrawable.addDrawable(new MockDrawable());
+        assertEquals(2, mDrawableContainerState.getChildCount());
+        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
+    }
+
+    public void testSortedByHeight() {
+        Drawable small = new MockDrawable(8);
+        Drawable medium = new MockDrawable(32);
+        Drawable large = new MockDrawable(128);
+
+        mMipmapDrawable.addDrawable(medium);
+        assertSame(medium, mDrawableContainerState.getChildren()[0]);
+
+        mMipmapDrawable.addDrawable(small);
+        assertSame(small, mDrawableContainerState.getChildren()[0]);
+        assertSame(medium, mDrawableContainerState.getChildren()[1]);
+
+        mMipmapDrawable.addDrawable(large);
+        assertSame(small, mDrawableContainerState.getChildren()[0]);
+        assertSame(medium, mDrawableContainerState.getChildren()[1]);
+        assertSame(large, mDrawableContainerState.getChildren()[2]);
+
+        mMipmapDrawable.addDrawable(small);
+        assertSame(small, mDrawableContainerState.getChildren()[0]);
+        assertSame(small, mDrawableContainerState.getChildren()[1]);
+        assertSame(medium, mDrawableContainerState.getChildren()[2]);
+        assertSame(large, mDrawableContainerState.getChildren()[3]);
+
+        mMipmapDrawable.addDrawable(medium);
+        assertSame(small, mDrawableContainerState.getChildren()[0]);
+        assertSame(small, mDrawableContainerState.getChildren()[1]);
+        assertSame(medium, mDrawableContainerState.getChildren()[2]);
+        assertSame(medium, mDrawableContainerState.getChildren()[3]);
+        assertSame(large, mDrawableContainerState.getChildren()[4]);
+
+        mMipmapDrawable.addDrawable(large);
+        assertSame(small, mDrawableContainerState.getChildren()[0]);
+        assertSame(small, mDrawableContainerState.getChildren()[1]);
+        assertSame(medium, mDrawableContainerState.getChildren()[2]);
+        assertSame(medium, mDrawableContainerState.getChildren()[3]);
+        assertSame(large, mDrawableContainerState.getChildren()[4]);
+        assertSame(large, mDrawableContainerState.getChildren()[5]);
+    }
+
+    public void testSetBoundsOneItem() {
+        // the method is not called if same bounds are set
+        mMipmapDrawable.reset();
+        mMipmapDrawable.setBounds(mMipmapDrawable.getBounds());
+        assertFalse(mMipmapDrawable.hasCalledOnBoundsChanged());
+
+        // the method is called if different bounds are set, even without drawables
+        mMipmapDrawable.reset();
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, mMipmapDrawable.getBounds().height() + 1));
+        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
+
+        // adding an item should check bounds to see if new drawable is more appropriate
+        mMipmapDrawable.reset();
+        Drawable item = new MockDrawable(42);
+        mMipmapDrawable.addDrawable(item);
+        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
+
+        // the method is called if different bounds are set
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, mMipmapDrawable.getBounds().height() + 1));
+        assertTrue(mMipmapDrawable.hasCalledOnBoundsChanged());
+
+        // check that correct drawable is selected for any size.
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, item.getIntrinsicHeight() - 1));
+        assertSame(item, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, item.getIntrinsicHeight()));
+        assertSame(item, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, item.getIntrinsicHeight() + 1));
+        assertSame(item, mMipmapDrawable.getCurrent());
+    }
+
+    public void testSetBounds() {
+        Drawable small = new MockDrawable(8);
+        Drawable medium = new MockDrawable(32);
+        Drawable large = new MockDrawable(128);
+
+        mMipmapDrawable.addDrawable(large);
+        mMipmapDrawable.addDrawable(small);
+        mMipmapDrawable.addDrawable(medium);
+
+        // check that correct drawable is selected.
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, small.getIntrinsicHeight() - 1));
+        assertSame(small, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, small.getIntrinsicHeight()));
+        assertSame(small, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, small.getIntrinsicHeight() + 1));
+        assertSame(medium, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, medium.getIntrinsicHeight() - 1));
+        assertSame(medium, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, medium.getIntrinsicHeight()));
+        assertSame(medium, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, medium.getIntrinsicHeight() + 1));
+        assertSame(large, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, large.getIntrinsicHeight() - 1));
+        assertSame(large, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, large.getIntrinsicHeight()));
+        assertSame(large, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, large.getIntrinsicHeight() + 1));
+        assertSame(large, mMipmapDrawable.getCurrent());
+    }
+
+    public void testSizes() {
+        // Check default value with no mipmap defined
+        assertEquals(-1, mMipmapDrawable.getIntrinsicHeight());
+        assertEquals(-1, mMipmapDrawable.getIntrinsicWidth());
+        assertEquals(0, mMipmapDrawable.getMinimumHeight());
+        assertEquals(0, mMipmapDrawable.getMinimumWidth());
+
+        Drawable small = new MockDrawable(8, 4);
+        Drawable medium = new MockDrawable(32, 16);
+        Drawable large = new MockDrawable(128, 64);
+
+        mMipmapDrawable.addDrawable(medium);
+        assertEquals(medium.getIntrinsicHeight(), mMipmapDrawable.getIntrinsicHeight());
+        assertEquals(medium.getMinimumHeight(), mMipmapDrawable.getMinimumHeight());
+
+        mMipmapDrawable.addDrawable(large);
+        assertEquals(large.getIntrinsicHeight(), mMipmapDrawable.getIntrinsicHeight());
+        assertEquals(medium.getMinimumHeight(), mMipmapDrawable.getMinimumHeight());
+
+        mMipmapDrawable.addDrawable(small);
+        assertEquals(large.getIntrinsicHeight(), mMipmapDrawable.getIntrinsicHeight());
+        assertEquals(small.getMinimumHeight(), mMipmapDrawable.getMinimumHeight());
+    }
+
+    public void testReplacementWhenAdded() {
+        Drawable small = new MockDrawable(8);
+        Drawable medium = new MockDrawable(32);
+        Drawable large = new MockDrawable(128);
+
+        // Small bounds, so that the smallest mipmap should always be selected
+        mMipmapDrawable.setBounds(new Rect(0, 0, 0, 0));
+
+        // Providing smaller versions, that should immediately be used as current
+        mMipmapDrawable.addDrawable(large);
+        assertSame(large, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.addDrawable(medium);
+        assertSame(medium, mMipmapDrawable.getCurrent());
+
+        mMipmapDrawable.addDrawable(small);
+        assertSame(small, mMipmapDrawable.getCurrent());
+    }
+
+    private class MockMipmapDrawable extends MipmapDrawable {
+        private boolean mHasCalledOnBoundsChanged;
+
+        public boolean hasCalledOnBoundsChanged() {
+            return mHasCalledOnBoundsChanged;
+        }
+
+        public void reset() {
+            mHasCalledOnBoundsChanged = false;
+        }
+
+        @Override
+        protected void onBoundsChange(Rect bounds) {
+            super.onBoundsChange(bounds);
+            mHasCalledOnBoundsChanged = true;
+        }
+    }
+
+    private class MockDrawable extends Drawable {
+        int mIntrinsicHeight;
+        int mMinimumHeight;
+
+        public MockDrawable() {
+            this(0);
+        }
+
+        public MockDrawable(int intrinsicHeight) {
+            this(intrinsicHeight, intrinsicHeight);
+        }
+
+        public MockDrawable(int intrinsicHeight, int minimumHeight) {
+            mIntrinsicHeight = intrinsicHeight;
+            mMinimumHeight = minimumHeight;
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+        }
+
+        @Override
+        public int getOpacity() {
+            return 0;
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+        }
+
+        @Override
+        public int getIntrinsicHeight() {
+            return mIntrinsicHeight;
+        }
+
+        @Override
+        public int getMinimumHeight() {
+            return mMinimumHeight;
+        }
+    }
+}
diff --git a/include/binder/CursorWindow.h b/include/binder/CursorWindow.h
index 4fbff2a..f0b2909 100644
--- a/include/binder/CursorWindow.h
+++ b/include/binder/CursorWindow.h
@@ -25,7 +25,6 @@
 #include <utils/RefBase.h>
 
 #define DEFAULT_WINDOW_SIZE 4096
-#define MAX_WINDOW_SIZE (1024 * 1024)
 #define WINDOW_ALLOCATION_SIZE 4096
 
 #define ROW_SLOT_CHUNK_NUM_ROWS 16
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index c7f0b15..e5f7e62 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -19,6 +19,7 @@
 
 #include <utils/Timers.h>
 #include <camera/ICameraClient.h>
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
@@ -106,7 +107,7 @@
 
 // camera fatal errors
 enum {
-    CAMERA_ERROR_UKNOWN  = 1,
+    CAMERA_ERROR_UNKNOWN  = 1,
     CAMERA_ERROR_SERVER_DIED = 100
 };
 
@@ -175,6 +176,9 @@
             // pass the buffered Surface to the camera service
             status_t    setPreviewDisplay(const sp<Surface>& surface);
 
+            // pass the buffered ISurfaceTexture to the camera service
+            status_t    setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture);
+
             // start preview mode, must call setPreviewDisplay first
             status_t    startPreview();
 
diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h
index b69e075..b2310a6 100644
--- a/include/camera/ICamera.h
+++ b/include/camera/ICamera.h
@@ -24,6 +24,7 @@
 #include <binder/IMemory.h>
 #include <utils/String8.h>
 #include <camera/Camera.h>
+#include <gui/ISurfaceTexture.h>
 
 namespace android {
 
@@ -48,6 +49,10 @@
     // pass the buffered Surface to the camera service
     virtual status_t        setPreviewDisplay(const sp<Surface>& surface) = 0;
 
+    // pass the buffered ISurfaceTexture to the camera service
+    virtual status_t        setPreviewTexture(
+            const sp<ISurfaceTexture>& surfaceTexture) = 0;
+
     // set the preview callback flag to affect how the received frames from
     // preview are handled.
     virtual void            setPreviewCallbackFlag(int flag) = 0;
diff --git a/include/drm/DrmManagerClient.h b/include/drm/DrmManagerClient.h
index e6ba3c4..085ebf1 100644
--- a/include/drm/DrmManagerClient.h
+++ b/include/drm/DrmManagerClient.h
@@ -49,6 +49,9 @@
     class OnInfoListener: virtual public RefBase {
 
     public:
+        virtual ~OnInfoListener() {}
+
+    public:
         virtual void onInfo(const DrmInfoEvent& event) = 0;
     };
 
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
new file mode 100644
index 0000000..77d37f1
--- /dev/null
+++ b/include/gui/ISurfaceTexture.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_ISURFACETEXTURE_H
+#define ANDROID_GUI_ISURFACETEXTURE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include <binder/IInterface.h>
+
+#include <ui/GraphicBuffer.h>
+#include <ui/Rect.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class ISurfaceTexture : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(SurfaceTexture);
+
+    // requestBuffer requests a new buffer for the given index. The server (i.e.
+    // the ISurfaceTexture implementation) assigns the newly created buffer to
+    // the given slot index, and the client is expected to mirror the
+    // slot->buffer mapping so that it's not necessary to transfer a
+    // GraphicBuffer for every dequeue operation.
+    virtual sp<GraphicBuffer> requestBuffer(int slot, uint32_t w, uint32_t h,
+            uint32_t format, uint32_t usage) = 0;
+
+    // setBufferCount sets the number of buffer slots available. Calling this
+    // will also cause all buffer slots to be emptied. The caller should empty
+    // its mirrored copy of the buffer slots when calling this method.
+    virtual status_t setBufferCount(int bufferCount) = 0;
+
+    // dequeueBuffer requests a new buffer slot for the client to use. Ownership
+    // of the slot is transfered to the client, meaning that the server will not
+    // use the contents of the buffer associated with that slot. The slot index
+    // returned may or may not contain a buffer. If the slot is empty the client
+    // should call requestBuffer to assign a new buffer to that slot. The client
+    // is expected to either call cancelBuffer on the dequeued slot or to fill
+    // in the contents of its associated buffer contents and call queueBuffer.
+    virtual status_t dequeueBuffer(int *slot) = 0;
+
+    // queueBuffer indicates that the client has finished filling in the
+    // contents of the buffer associated with slot and transfers ownership of
+    // that slot back to the server. It is not valid to call queueBuffer on a
+    // slot that is not owned by the client or one for which a buffer associated
+    // via requestBuffer.
+    virtual status_t queueBuffer(int slot) = 0;
+
+    // cancelBuffer indicates that the client does not wish to fill in the
+    // buffer associated with slot and transfers ownership of the slot back to
+    // the server.
+    virtual void cancelBuffer(int slot) = 0;
+
+    virtual status_t setCrop(const Rect& reg) = 0;
+    virtual status_t setTransform(uint32_t transform) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnSurfaceTexture : public BnInterface<ISurfaceTexture>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_ISURFACETEXTURE_H
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
new file mode 100644
index 0000000..002e48b
--- /dev/null
+++ b/include/gui/SurfaceTexture.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_SURFACETEXTURE_H
+#define ANDROID_GUI_SURFACETEXTURE_H
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+
+#include <gui/ISurfaceTexture.h>
+
+#include <ui/GraphicBuffer.h>
+
+#include <utils/threads.h>
+#include <utils/Vector.h>
+
+#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class IGraphicBufferAlloc;
+
+class SurfaceTexture : public BnSurfaceTexture {
+public:
+    enum { MIN_BUFFER_SLOTS = 3 };
+    enum { NUM_BUFFER_SLOTS = 32 };
+
+    // tex indicates the name OpenGL texture to which images are to be streamed.
+    // This texture name cannot be changed once the SurfaceTexture is created.
+    SurfaceTexture(GLuint tex);
+
+    virtual ~SurfaceTexture();
+
+    // setBufferCount updates the number of available buffer slots.  After
+    // calling this all buffer slots are both unallocated and owned by the
+    // SurfaceTexture object (i.e. they are not owned by the client).
+    virtual status_t setBufferCount(int bufferCount);
+
+    virtual sp<GraphicBuffer> requestBuffer(int buf, uint32_t w, uint32_t h,
+            uint32_t format, uint32_t usage);
+
+    // dequeueBuffer gets the next buffer slot index for the client to use. If a
+    // buffer slot is available then that slot index is written to the location
+    // pointed to by the buf argument and a status of OK is returned.  If no
+    // slot is available then a status of -EBUSY is returned and buf is
+    // unmodified.
+    virtual status_t dequeueBuffer(int *buf);
+
+    virtual status_t queueBuffer(int buf);
+    virtual void cancelBuffer(int buf);
+    virtual status_t setCrop(const Rect& reg);
+    virtual status_t setTransform(uint32_t transform);
+
+    // updateTexImage sets the image contents of the target texture to that of
+    // the most recently queued buffer.
+    //
+    // This call may only be made while the OpenGL ES context to which the
+    // target texture belongs is bound to the calling thread.
+    status_t updateTexImage();
+
+    // getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
+    // associated with the texture image set by the most recent call to
+    // updateTexImage.
+    //
+    // This transform matrix maps 2D homogeneous texture coordinates of the form
+    // (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture
+    // coordinate that should be used to sample that location from the texture.
+    // Sampling the texture outside of the range of this transform is undefined.
+    //
+    // This transform is necessary to compensate for transforms that the stream
+    // content producer may implicitly apply to the content. By forcing users of
+    // a SurfaceTexture to apply this transform we avoid performing an extra
+    // copy of the data that would be needed to hide the transform from the
+    // user.
+    //
+    // The matrix is stored in column-major order so that it may be passed
+    // directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv
+    // functions.
+    void getTransformMatrix(float mtx[16]);
+
+private:
+
+    // freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
+    // all slots.
+    void freeAllBuffers();
+
+    // createImage creates a new EGLImage from a GraphicBuffer.
+    EGLImageKHR createImage(EGLDisplay dpy,
+            const sp<GraphicBuffer>& graphicBuffer);
+
+    enum { INVALID_BUFFER_SLOT = -1 };
+
+    struct BufferSlot {
+        // mGraphicBuffer points to the buffer allocated for this slot or is NULL
+        // if no buffer has been allocated.
+        sp<GraphicBuffer> mGraphicBuffer;
+
+        // mEglImage is the EGLImage created from mGraphicBuffer.
+        EGLImageKHR mEglImage;
+
+        // mEglDisplay is the EGLDisplay used to create mEglImage.
+        EGLDisplay mEglDisplay;
+
+        // mOwnedByClient indicates whether the slot is currently accessible to a
+        // client and should not be used by the SurfaceTexture object. It gets
+        // set to true when dequeueBuffer returns the slot and is reset to false
+        // when the client calls either queueBuffer or cancelBuffer on the slot.
+        bool mOwnedByClient;
+    };
+
+    // mSlots is the array of buffer slots that must be mirrored on the client
+    // side. This allows buffer ownership to be transferred between the client
+    // and server without sending a GraphicBuffer over binder. The entire array
+    // is initialized to NULL at construction time, and buffers are allocated
+    // for a slot when requestBuffer is called with that slot's index.
+    BufferSlot mSlots[NUM_BUFFER_SLOTS];
+
+    // mBufferCount is the number of buffer slots that the client and server
+    // must maintain. It defaults to MIN_BUFFER_SLOTS and can be changed by
+    // calling setBufferCount.
+    int mBufferCount;
+
+    // mCurrentTexture is the buffer slot index of the buffer that is currently
+    // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
+    // indicating that no buffer slot is currently bound to the texture. Note,
+    // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
+    // that no buffer is bound to the texture. A call to setBufferCount will
+    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
+    int mCurrentTexture;
+
+    // mCurrentTextureBuf is the graphic buffer of the current texture. It's
+    // possible that this buffer is not associated with any buffer slot, so we
+    // must track it separately in order to properly use
+    // IGraphicBufferAlloc::freeAllGraphicBuffersExcept.
+    sp<GraphicBuffer> mCurrentTextureBuf;
+
+    // mCurrentCrop is the crop rectangle that applies to the current texture.
+    // It gets set to mLastQueuedCrop each time updateTexImage is called.
+    Rect mCurrentCrop;
+
+    // mCurrentTransform is the transform identifier for the current texture. It
+    // gets set to mLastQueuedTransform each time updateTexImage is called.
+    uint32_t mCurrentTransform;
+
+    // mLastQueued is the buffer slot index of the most recently enqueued buffer.
+    // At construction time it is initialized to INVALID_BUFFER_SLOT, and is
+    // updated each time queueBuffer is called.
+    int mLastQueued;
+
+    // mLastQueuedCrop is the crop rectangle for the buffer that was most
+    // recently queued. This gets set to mNextCrop each time queueBuffer gets
+    // called.
+    Rect mLastQueuedCrop;
+
+    // mLastQueuedTransform is the transform identifier for the buffer that was
+    // most recently queued. This gets set to mNextTransform each time
+    // queueBuffer gets called.
+    uint32_t mLastQueuedTransform;
+
+    // mNextCrop is the crop rectangle that will be used for the next buffer
+    // that gets queued. It is set by calling setCrop.
+    Rect mNextCrop;
+
+    // mNextTransform is the transform identifier that will be used for the next
+    // buffer that gets queued. It is set by calling setTransform.
+    uint32_t mNextTransform;
+
+    // mTexName is the name of the OpenGL texture to which streamed images will
+    // be bound when updateTexImage is called. It is set at construction time 
+    // changed with a call to setTexName.
+    const GLuint mTexName;
+
+    // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
+    // allocate new GraphicBuffer objects.
+    sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
+
+    // mAllocdBuffers is mirror of the list of buffers that SurfaceFlinger is
+    // referencing. This is kept so that gralloc implementations do not need to
+    // properly handle the case where SurfaceFlinger no longer holds a reference
+    // to a buffer, but other processes do.
+    Vector<sp<GraphicBuffer> > mAllocdBuffers;
+
+    // mMutex is the mutex used to prevent concurrent access to the member
+    // variables of SurfaceTexture objects. It must be locked whenever the
+    // member variables are accessed.
+    Mutex mMutex;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_SURFACETEXTURE_H
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
new file mode 100644
index 0000000..dd1d490
--- /dev/null
+++ b/include/gui/SurfaceTextureClient.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_SURFACETEXTURECLIENT_H
+#define ANDROID_GUI_SURFACETEXTURECLIENT_H
+
+#include <gui/ISurfaceTexture.h>
+#include <gui/SurfaceTexture.h>
+
+#include <ui/egl/android_natives.h>
+
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class SurfaceTextureClient
+    : public EGLNativeBase<ANativeWindow, SurfaceTextureClient, RefBase>
+{
+public:
+    SurfaceTextureClient(const sp<ISurfaceTexture>& surfaceTexture);
+
+private:
+
+    // can't be copied
+    SurfaceTextureClient& operator = (const SurfaceTextureClient& rhs);
+    SurfaceTextureClient(const SurfaceTextureClient& rhs);
+
+    // ANativeWindow hooks
+    static int setSwapInterval(ANativeWindow* window, int interval);
+    static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer);
+    static int cancelBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int lockBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int query(ANativeWindow* window, int what, int* value);
+    static int perform(ANativeWindow* window, int operation, ...);
+
+    int setSwapInterval(int interval);
+    int dequeueBuffer(android_native_buffer_t** buffer);
+    int lockBuffer(android_native_buffer_t* buffer);
+    int queueBuffer(android_native_buffer_t* buffer);
+    int cancelBuffer(android_native_buffer_t* buffer);
+    int query(int what, int* value);
+    int perform(int operation, va_list args);
+
+    int dispatchSetUsage(va_list args);
+    int dispatchConnect(va_list args);
+    int dispatchDisconnect(va_list args);
+    int dispatchSetCrop(va_list args);
+    int dispatchSetBufferCount(va_list args);
+    int dispatchSetBuffersGeometry(va_list args);
+    int dispatchSetBuffersTransform(va_list args);
+
+    int connect(int api);
+    int disconnect(int api);
+    int setUsage(uint32_t reqUsage);
+    int setCrop(Rect const* rect);
+    int setBufferCount(int bufferCount);
+    int setBuffersGeometry(int w, int h, int format);
+    int setBuffersTransform(int transform);
+
+    void freeAllBuffers();
+
+    enum { MIN_BUFFER_SLOTS = SurfaceTexture::MIN_BUFFER_SLOTS };
+    enum { NUM_BUFFER_SLOTS = SurfaceTexture::NUM_BUFFER_SLOTS };
+    enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
+
+    // mSurfaceTexture is the interface to the surface texture server. All
+    // operations on the surface texture client ultimately translate into
+    // interactions with the server using this interface.
+    sp<ISurfaceTexture> mSurfaceTexture;
+
+    // mSlots stores the buffers that have been allocated for each buffer slot.
+    // It is initialized to null pointers, and gets filled in with the result of
+    // ISurfaceTexture::requestBuffer when the client dequeues a buffer from a
+    // slot that has not yet been used. The buffer allocated to a slot will also
+    // be replaced if the requested buffer usage or geometry differs from that
+    // of the buffer allocated to a slot.
+    sp<GraphicBuffer> mSlots[NUM_BUFFER_SLOTS];
+
+    // mReqWidth is the buffer width that will be requested at the next dequeue
+    // operation. It is initialized to 1.
+    uint32_t mReqWidth;
+
+    // mReqHeight is the buffer height that will be requested at the next deuque
+    // operation. It is initialized to 1.
+    uint32_t mReqHeight;
+
+    // mReqFormat is the buffer pixel format that will be requested at the next
+    // deuque operation. It is initialized to PIXEL_FORMAT_RGBA_8888.
+    uint32_t mReqFormat;
+
+    // mReqUsage is the set of buffer usage flags that will be requested
+    // at the next deuque operation. It is initialized to 0.
+    uint32_t mReqUsage;
+
+    // mMutex is the mutex used to prevent concurrent access to the member
+    // variables of SurfaceTexture objects. It must be locked whenever the
+    // member variables are accessed.
+    Mutex mMutex;
+};
+
+}; // namespace android
+
+#endif  // ANDROID_GUI_SURFACETEXTURECLIENT_H
diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h
index e517cf0..8e3cdbb 100644
--- a/include/media/IMediaMetadataRetriever.h
+++ b/include/media/IMediaMetadataRetriever.h
@@ -32,7 +32,6 @@
     virtual void            disconnect() = 0;
     virtual status_t        setDataSource(const char* srcUrl) = 0;
     virtual status_t        setDataSource(int fd, int64_t offset, int64_t length) = 0;
-    virtual status_t        setMode(int mode) = 0;
     virtual sp<IMemory>     getFrameAtTime(int64_t timeUs, int option) = 0;
     virtual sp<IMemory>     extractAlbumArt() = 0;
     virtual const char*     extractMetadata(int keyCode) = 0;
diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h
index 717849d..0449122 100644
--- a/include/media/MediaMetadataRetrieverInterface.h
+++ b/include/media/MediaMetadataRetrieverInterface.h
@@ -32,7 +32,6 @@
     virtual             ~MediaMetadataRetrieverBase() {}
     virtual status_t    setDataSource(const char *url) = 0;
     virtual status_t    setDataSource(int fd, int64_t offset, int64_t length) = 0;
-    virtual status_t    setMode(int mode) = 0;
     virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) = 0;
     virtual MediaAlbumArt* extractAlbumArt() = 0;
     virtual const char* extractMetadata(int keyCode) = 0;
@@ -42,35 +41,12 @@
 class MediaMetadataRetrieverInterface : public MediaMetadataRetrieverBase
 {
 public:
-    MediaMetadataRetrieverInterface()
-        : mMode(0) {
-    }
+    MediaMetadataRetrieverInterface() {}
 
     virtual             ~MediaMetadataRetrieverInterface() {}
-
-    // @param mode The intended mode of operations:
-    // can be any of the following:
-    // METADATA_MODE_NOOP: Experimental - just add and remove data source.
-    // METADATA_MODE_FRAME_CAPTURE_ONLY: For capture frame/thumbnail only.
-    // METADATA_MODE_METADATA_RETRIEVAL_ONLY: For meta data retrieval only.
-    // METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL: For both frame
-    //     capture and meta data retrieval.
-    virtual status_t    setMode(int mode) {
-                            if (mode < METADATA_MODE_NOOP ||
-                                mode > METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL) {
-                                return BAD_VALUE;
-                            }
-
-                            mMode = mode;
-                            return NO_ERROR;
-                        }
-
-    virtual status_t    getMode(int* mode) const { *mode = mMode; return NO_ERROR; }
     virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) { return NULL; }
     virtual MediaAlbumArt* extractAlbumArt() { return NULL; }
     virtual const char* extractMetadata(int keyCode) { return NULL; }
-
-    uint32_t mMode;
 };
 
 }; // namespace android
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index ed54b37..e905006 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -42,36 +42,14 @@
     METADATA_KEY_YEAR            = 8,
     METADATA_KEY_DURATION        = 9,
     METADATA_KEY_NUM_TRACKS      = 10,
-    METADATA_KEY_IS_DRM_CRIPPLED = 11,
-    METADATA_KEY_CODEC           = 12,
-    METADATA_KEY_RATING          = 13,
-    METADATA_KEY_COMMENT         = 14,
-    METADATA_KEY_COPYRIGHT       = 15,
-    METADATA_KEY_BIT_RATE        = 16,
-    METADATA_KEY_FRAME_RATE      = 17,
-    METADATA_KEY_VIDEO_FORMAT    = 18,
-    METADATA_KEY_VIDEO_HEIGHT    = 19,
-    METADATA_KEY_VIDEO_WIDTH     = 20,
-    METADATA_KEY_WRITER          = 21,
-    METADATA_KEY_MIMETYPE        = 22,
-    METADATA_KEY_DISC_NUMBER     = 23,
-    METADATA_KEY_ALBUMARTIST     = 24,
+    METADATA_KEY_WRITER          = 11,
+    METADATA_KEY_MIMETYPE        = 12,
+    METADATA_KEY_ALBUMARTIST     = 13,
+    METADATA_KEY_DISC_NUMBER     = 14,
+    METADATA_KEY_COMPILATION     = 15,
     // Add more here...
 };
 
-// The intended mode of operations:$
-// METADATA_MODE_NOOP: Experimental - just add and remove data source.$
-// METADATA_MODE_FRAME_CAPTURE_ONLY: For capture frame/thumbnail only.$
-// METADATA_MODE_METADATA_RETRIEVAL_ONLY: For meta data retrieval only.$
-// METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL: For both frame capture
-//   and meta data retrieval.$
-enum {
-    METADATA_MODE_NOOP                                 = 0x00,
-    METADATA_MODE_METADATA_RETRIEVAL_ONLY              = 0x01,
-    METADATA_MODE_FRAME_CAPTURE_ONLY                   = 0x02,
-    METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL = 0x03
-};
-
 class MediaMetadataRetriever: public RefBase
 {
 public:
@@ -80,7 +58,6 @@
     void disconnect();
     status_t setDataSource(const char* dataSourceUrl);
     status_t setDataSource(int fd, int64_t offset, int64_t length);
-    status_t setMode(int mode);
     sp<IMemory> getFrameAtTime(int64_t timeUs, int option);
     sp<IMemory> extractAlbumArt();
     const char* extractMetadata(int keyCode);
diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h
index 74c9d5d..df5be32 100644
--- a/include/media/mediascanner.h
+++ b/include/media/mediascanner.h
@@ -71,7 +71,8 @@
     bool addStringTag(const char* name, const char* value);
     void endFile();
 
-    virtual bool scanFile(const char* path, long long lastModified, long long fileSize) = 0;
+    virtual bool scanFile(const char* path, long long lastModified,
+            long long fileSize, bool isDirectory) = 0;
     virtual bool handleStringTag(const char* name, const char* value) = 0;
     virtual bool setMimeType(const char* mimeType) = 0;
     virtual bool addNoMediaFolder(const char* path) = 0;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 940470d..4599d70 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -14,11 +14,12 @@
 
 struct ACodec : public AHierarchicalStateMachine {
     enum {
-        kWhatFillThisBuffer    = 'fill',
-        kWhatDrainThisBuffer   = 'drai',
-        kWhatEOS               = 'eos ',
-        kWhatShutdownCompleted = 'scom',
-        kWhatFlushCompleted    = 'fcom',
+        kWhatFillThisBuffer      = 'fill',
+        kWhatDrainThisBuffer     = 'drai',
+        kWhatEOS                 = 'eos ',
+        kWhatShutdownCompleted   = 'scom',
+        kWhatFlushCompleted      = 'fcom',
+        kWhatOutputFormatChanged = 'outC',
     };
 
     ACodec();
@@ -100,6 +101,8 @@
 
     List<sp<AMessage> > mDeferredQueue;
 
+    bool mSentFormat;
+
     status_t allocateBuffersOnPort(OMX_U32 portIndex);
     status_t freeBuffersOnPort(OMX_U32 portIndex);
     status_t freeBuffer(OMX_U32 portIndex, size_t i);
@@ -144,6 +147,8 @@
     void deferMessage(const sp<AMessage> &msg);
     void processDeferredMessages();
 
+    void sendFormatChange();
+
     DISALLOW_EVIL_CONSTRUCTORS(ACodec);
 };
 
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index a5cec78..d484d60 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -54,11 +54,11 @@
 
         // After the initial mute, we raise the volume linearly
         // over kAutoRampDurationUs.
-        kAutoRampDurationUs = 300000,
+        kAutoRampDurationUs = 700000,
 
         // This is the initial mute duration to suppress
         // the video recording signal tone
-        kAutoRampStartUs = 700000,
+        kAutoRampStartUs = 1000000,
       };
 
     AudioRecord *mRecord;
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index afe7287..0e5d534 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -182,10 +182,10 @@
     // buffer.
     void fillLastReadBufferCopy(MediaBuffer& sourceBuffer);
 
-    // If the passed in size (width x height) is a supported preview size,
-    // the function sets the camera's preview size to it and returns true.
+    // If the passed in size (width x height) is a supported video/preview size,
+    // the function sets the camera's video/preview size to it and returns true.
     // Otherwise returns false.
-    bool trySettingPreviewSize(int32_t width, int32_t height);
+    bool trySettingVideoSize(int32_t width, int32_t height);
 
     // The still camera may not support the demanded video width and height.
     // We look for the supported picture sizes from the still camera and
diff --git a/include/media/stagefright/ColorConverter.h b/include/media/stagefright/ColorConverter.h
index 2b61f58..2ae8a5b 100644
--- a/include/media/stagefright/ColorConverter.h
+++ b/include/media/stagefright/ColorConverter.h
@@ -21,6 +21,7 @@
 #include <sys/types.h>
 
 #include <stdint.h>
+#include <utils/Errors.h>
 
 #include <OMX_Video.h>
 
@@ -32,7 +33,7 @@
 
     bool isValid() const;
 
-    void convert(
+    status_t convert(
             const void *srcBits,
             size_t srcWidth, size_t srcHeight,
             size_t srcCropLeft, size_t srcCropTop,
@@ -63,16 +64,16 @@
 
     uint8_t *initClip();
 
-    void convertCbYCrY(
+    status_t convertCbYCrY(
             const BitmapParams &src, const BitmapParams &dst);
 
-    void convertYUV420Planar(
+    status_t convertYUV420Planar(
             const BitmapParams &src, const BitmapParams &dst);
 
-    void convertQCOMYUV420SemiPlanar(
+    status_t convertQCOMYUV420SemiPlanar(
             const BitmapParams &src, const BitmapParams &dst);
 
-    void convertYUV420SemiPlanar(
+    status_t convertYUV420SemiPlanar(
             const BitmapParams &src, const BitmapParams &dst);
 
     ColorConverter(const ColorConverter &);
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 5f33739..5170a2c 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -80,6 +80,7 @@
     kKeyDiscNumber        = 'dnum',  // cstring
     kKeyDate              = 'date',  // cstring
     kKeyWriter            = 'writ',  // cstring
+    kKeyCompilation       = 'cpil',  // cstring
     kKeyTimeScale         = 'tmsl',  // int32_t
 
     // video profile and level
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index bba5b53..f8daa4f 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -70,8 +70,6 @@
 
     virtual status_t pause();
 
-    void on_message(const omx_message &msg);
-
     // from MediaBufferObserver
     virtual void signalBufferReturned(MediaBuffer *buffer);
 
@@ -79,6 +77,13 @@
     virtual ~OMXCodec();
 
 private:
+
+    // Make sure mLock is accessible to OMXCodecObserver
+    friend class OMXCodecObserver;
+
+    // Call this with mLock hold
+    void on_message(const omx_message &msg);
+
     enum State {
         DEAD,
         LOADED,
diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h
index 941f6b9..72dc730 100644
--- a/include/media/stagefright/foundation/AMessage.h
+++ b/include/media/stagefright/foundation/AMessage.h
@@ -52,6 +52,10 @@
     void setObject(const char *name, const sp<RefBase> &obj);
     void setMessage(const char *name, const sp<AMessage> &obj);
 
+    void setRect(
+            const char *name,
+            int32_t left, int32_t top, int32_t right, int32_t bottom);
+
     bool findInt32(const char *name, int32_t *value) const;
     bool findInt64(const char *name, int64_t *value) const;
     bool findSize(const char *name, size_t *value) const;
@@ -62,8 +66,15 @@
     bool findObject(const char *name, sp<RefBase> *obj) const;
     bool findMessage(const char *name, sp<AMessage> *obj) const;
 
+    bool findRect(
+            const char *name,
+            int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const;
+
     void post(int64_t delayUs = 0);
 
+    // Performs a deep-copy of "this", contained messages are in turn "dup'ed".
+    // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
+    // their refcount incremented.
     sp<AMessage> dup() const;
 
     AString debugString(int32_t indent = 0) const;
@@ -82,11 +93,16 @@
         kTypeString,
         kTypeObject,
         kTypeMessage,
+        kTypeRect,
     };
 
     uint32_t mWhat;
     ALooper::handler_id mTarget;
 
+    struct Rect {
+        int32_t mLeft, mTop, mRight, mBottom;
+    };
+
     struct Item {
         union {
             int32_t int32Value;
@@ -97,6 +113,7 @@
             void *ptrValue;
             RefBase *refValue;
             AString *stringValue;
+            Rect rectValue;
         } u;
         const char *mName;
         Type mType;
diff --git a/include/storage/IMountService.h b/include/storage/IMountService.h
index 51f9aeb..472d8e5 100644
--- a/include/storage/IMountService.h
+++ b/include/storage/IMountService.h
@@ -66,6 +66,8 @@
             const sp<IObbActionListener>& token, const int32_t nonce) = 0;
     virtual bool isObbMounted(const String16& filename) = 0;
     virtual bool getMountedObbPath(const String16& filename, String16& path) = 0;
+    virtual int32_t decryptStorage(const String16& password) = 0;
+    virtual int32_t encryptStorage(const String16& password) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/surfaceflinger/IGraphicBufferAlloc.h b/include/surfaceflinger/IGraphicBufferAlloc.h
new file mode 100644
index 0000000..d996af7
--- /dev/null
+++ b/include/surfaceflinger/IGraphicBufferAlloc.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H
+#define ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+
+#include <binder/IInterface.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class IGraphicBufferAlloc : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(GraphicBufferAlloc);
+
+    /* Create a new GraphicBuffer for the client to use.  The server will
+     * maintain a reference to the newly created GraphicBuffer until
+     * freeAllGraphicBuffers is called.
+     */
+    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+            PixelFormat format, uint32_t usage) = 0;
+
+    /* Free all but one of the GraphicBuffer objects that the server is
+     * currently referencing. If bufIndex is not a valid index of the buffers
+     * the server is referencing, then all buffers are freed.
+     */
+    virtual void freeAllGraphicBuffersExcept(int bufIndex) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnGraphicBufferAlloc : public BnInterface<IGraphicBufferAlloc>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 693fbfb..56ed3a4 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -28,6 +28,7 @@
 #include <ui/PixelFormat.h>
 
 #include <surfaceflinger/ISurfaceComposerClient.h>
+#include <surfaceflinger/IGraphicBufferAlloc.h>
 
 namespace android {
 // ----------------------------------------------------------------------------
@@ -96,6 +97,10 @@
      */
     virtual sp<ISurfaceComposerClient> createClientConnection() = 0;
 
+    /* create a graphic buffer allocator
+     */
+    virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
+
     /* retrieve the control block */
     virtual sp<IMemoryHeap> getCblk() const = 0;
 
@@ -144,6 +149,7 @@
         BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
         CREATE_CONNECTION,
         CREATE_CLIENT_CONNECTION,
+        CREATE_GRAPHIC_BUFFER_ALLOC,
         GET_CBLK,
         OPEN_GLOBAL_TRANSACTION,
         CLOSE_GLOBAL_TRANSACTION,
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 2df8ca3..5532052 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -233,7 +233,7 @@
      *  private stuff...
      */
     void init();
-    status_t validate() const;
+    status_t validate(bool inCancelBuffer = false) const;
     sp<ISurface> getISurface() const;
 
     inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h
index c419efe..edd28a6 100644
--- a/include/ui/DisplayInfo.h
+++ b/include/ui/DisplayInfo.h
@@ -37,6 +37,15 @@
     float               ydpi;
 };
 
+/* Display orientations as defined in Surface.java and ISurfaceComposer.h. */
+enum {
+    DISPLAY_ORIENTATION_0 = 0,
+    DISPLAY_ORIENTATION_90 = 1,
+    DISPLAY_ORIENTATION_180 = 2,
+    DISPLAY_ORIENTATION_270 = 3
+};
+
+
 }; // namespace android
 
 #endif // ANDROID_COMPOSER_DISPLAY_INFO_H
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
deleted file mode 100644
index 6c6c297..0000000
--- a/include/ui/EventHub.h
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright (C) 2005 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//
-#ifndef _RUNTIME_EVENT_HUB_H
-#define _RUNTIME_EVENT_HUB_H
-
-#include <ui/Input.h>
-#include <ui/Keyboard.h>
-#include <ui/KeyLayoutMap.h>
-#include <ui/KeyCharacterMap.h>
-#include <ui/VirtualKeyMap.h>
-#include <utils/String8.h>
-#include <utils/threads.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <utils/List.h>
-#include <utils/Errors.h>
-#include <utils/PropertyMap.h>
-#include <utils/Vector.h>
-
-#include <linux/input.h>
-
-/* These constants are not defined in linux/input.h but they are part of the multitouch
- * input protocol. */
-
-#define ABS_MT_TOUCH_MAJOR 0x30  /* Major axis of touching ellipse */
-#define ABS_MT_TOUCH_MINOR 0x31  /* Minor axis (omit if circular) */
-#define ABS_MT_WIDTH_MAJOR 0x32  /* Major axis of approaching ellipse */
-#define ABS_MT_WIDTH_MINOR 0x33  /* Minor axis (omit if circular) */
-#define ABS_MT_ORIENTATION 0x34  /* Ellipse orientation */
-#define ABS_MT_POSITION_X 0x35   /* Center X ellipse position */
-#define ABS_MT_POSITION_Y 0x36   /* Center Y ellipse position */
-#define ABS_MT_TOOL_TYPE 0x37    /* Type of touching device (finger, pen, ...) */
-#define ABS_MT_BLOB_ID 0x38      /* Group a set of packets as a blob */
-#define ABS_MT_TRACKING_ID 0x39  /* Unique ID of initiated contact */
-#define ABS_MT_PRESSURE 0x3a     /* Pressure on contact area */
-
-#define MT_TOOL_FINGER 0 /* Identifies a finger */
-#define MT_TOOL_PEN 1    /* Identifies a pen */
-
-#define SYN_MT_REPORT 2
-
-/* Convenience constants. */
-
-#define BTN_FIRST 0x100  // first button scancode
-#define BTN_LAST 0x15f   // last button scancode
-
-struct pollfd;
-
-namespace android {
-
-/*
- * A raw event as retrieved from the EventHub.
- */
-struct RawEvent {
-    nsecs_t when;
-    int32_t deviceId;
-    int32_t type;
-    int32_t scanCode;
-    int32_t keyCode;
-    int32_t value;
-    uint32_t flags;
-};
-
-/* Describes an absolute axis. */
-struct RawAbsoluteAxisInfo {
-    bool valid; // true if the information is valid, false otherwise
-
-    int32_t minValue;  // minimum value
-    int32_t maxValue;  // maximum value
-    int32_t flat;      // center flat position, eg. flat == 8 means center is between -8 and 8
-    int32_t fuzz;      // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
-
-    inline int32_t getRange() { return maxValue - minValue; }
-
-    inline void clear() {
-        valid = false;
-        minValue = 0;
-        maxValue = 0;
-        flat = 0;
-        fuzz = 0;
-    }
-};
-
-/*
- * Input device classes.
- */
-enum {
-    /* The input device is a keyboard. */
-    INPUT_DEVICE_CLASS_KEYBOARD      = 0x00000001,
-
-    /* The input device is an alpha-numeric keyboard (not just a dial pad). */
-    INPUT_DEVICE_CLASS_ALPHAKEY      = 0x00000002,
-
-    /* The input device is a touchscreen (either single-touch or multi-touch). */
-    INPUT_DEVICE_CLASS_TOUCHSCREEN   = 0x00000004,
-
-    /* The input device is a trackball. */
-    INPUT_DEVICE_CLASS_TRACKBALL     = 0x00000008,
-
-    /* The input device is a multi-touch touchscreen. */
-    INPUT_DEVICE_CLASS_TOUCHSCREEN_MT= 0x00000010,
-
-    /* The input device is a directional pad (implies keyboard, has DPAD keys). */
-    INPUT_DEVICE_CLASS_DPAD          = 0x00000020,
-
-    /* The input device is a gamepad (implies keyboard, has BUTTON keys). */
-    INPUT_DEVICE_CLASS_GAMEPAD       = 0x00000040,
-
-    /* The input device has switches. */
-    INPUT_DEVICE_CLASS_SWITCH        = 0x00000080,
-};
-
-/*
- * Grand Central Station for events.
- *
- * The event hub aggregates input events received across all known input
- * devices on the system, including devices that may be emulated by the simulator
- * environment.  In addition, the event hub generates fake input events to indicate
- * when devices are added or removed.
- *
- * The event hub provies a stream of input events (via the getEvent function).
- * It also supports querying the current actual state of input devices such as identifying
- * which keys are currently down.  Finally, the event hub keeps track of the capabilities of
- * individual input devices, such as their class and the set of key codes that they support.
- */
-class EventHubInterface : public virtual RefBase {
-protected:
-    EventHubInterface() { }
-    virtual ~EventHubInterface() { }
-
-public:
-    // Synthetic raw event type codes produced when devices are added or removed.
-    enum {
-        // Sent when a device is added.
-        DEVICE_ADDED = 0x10000000,
-        // Sent when a device is removed.
-        DEVICE_REMOVED = 0x20000000,
-        // Sent when all added/removed devices from the most recent scan have been reported.
-        // This event is always sent at least once.
-        FINISHED_DEVICE_SCAN = 0x30000000,
-    };
-
-    virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
-
-    virtual String8 getDeviceName(int32_t deviceId) const = 0;
-
-    virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const = 0;
-
-    virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
-            RawAbsoluteAxisInfo* outAxisInfo) const = 0;
-
-    virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
-            int32_t* outKeycode, uint32_t* outFlags) const = 0;
-
-    // exclude a particular device from opening
-    // this can be used to ignore input devices for sensors
-    virtual void addExcludedDevice(const char* deviceName) = 0;
-
-    /*
-     * Wait for the next event to become available and return it.
-     * After returning, the EventHub holds onto a wake lock until the next call to getEvent.
-     * This ensures that the device will not go to sleep while the event is being processed.
-     * If the device needs to remain awake longer than that, then the caller is responsible
-     * for taking care of it (say, by poking the power manager user activity timer).
-     */
-    virtual bool getEvent(RawEvent* outEvent) = 0;
-
-    /*
-     * Query current input state.
-     */
-    virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0;
-    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
-    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
-
-    /*
-     * Examine key input devices for specific framework keycode support
-     */
-    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
-            uint8_t* outFlags) const = 0;
-
-    virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
-    virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
-
-    virtual void getVirtualKeyDefinitions(int32_t deviceId,
-            Vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
-
-    virtual void dump(String8& dump) = 0;
-};
-
-class EventHub : public EventHubInterface
-{
-public:
-    EventHub();
-
-    status_t errorCheck() const;
-
-    virtual uint32_t getDeviceClasses(int32_t deviceId) const;
-
-    virtual String8 getDeviceName(int32_t deviceId) const;
-
-    virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const;
-
-    virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
-            RawAbsoluteAxisInfo* outAxisInfo) const;
-
-    virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
-            int32_t* outKeycode, uint32_t* outFlags) const;
-
-    virtual void addExcludedDevice(const char* deviceName);
-
-    virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
-    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const;
-    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const;
-
-    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags) const;
-
-    virtual bool getEvent(RawEvent* outEvent);
-
-    virtual bool hasLed(int32_t deviceId, int32_t led) const;
-    virtual void setLedState(int32_t deviceId, int32_t led, bool on);
-
-    virtual void getVirtualKeyDefinitions(int32_t deviceId,
-            Vector<VirtualKeyDefinition>& outVirtualKeys) const;
-
-    virtual void dump(String8& dump);
-
-protected:
-    virtual ~EventHub();
-    
-private:
-    bool openPlatformInput(void);
-
-    int openDevice(const char *devicePath);
-    int closeDevice(const char *devicePath);
-    int scanDir(const char *dirname);
-    int readNotify(int nfd);
-
-    status_t mError;
-
-    struct Device {
-        Device* next;
-
-        int fd;
-        const int32_t id;
-        const String8 path;
-        const InputDeviceIdentifier identifier;
-
-        uint32_t classes;
-        uint8_t* keyBitmask;
-        String8 configurationFile;
-        PropertyMap* configuration;
-        VirtualKeyMap* virtualKeyMap;
-        KeyMap keyMap;
-
-        Device(int fd, int32_t id, const String8& path, const InputDeviceIdentifier& identifier);
-        ~Device();
-
-        void close();
-    };
-
-    Device* getDeviceLocked(int32_t deviceId) const;
-    bool hasKeycodeLocked(Device* device, int keycode) const;
-
-    int32_t getScanCodeStateLocked(Device* device, int32_t scanCode) const;
-    int32_t getKeyCodeStateLocked(Device* device, int32_t keyCode) const;
-    int32_t getSwitchStateLocked(Device* device, int32_t sw) const;
-    bool markSupportedKeyCodesLocked(Device* device, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags) const;
-
-    void loadConfiguration(Device* device);
-    status_t loadVirtualKeyMap(Device* device);
-    status_t loadKeyMap(Device* device);
-    void setKeyboardProperties(Device* device, bool builtInKeyboard);
-    void clearKeyboardProperties(Device* device, bool builtInKeyboard);
-
-    // Protect all internal state.
-    mutable Mutex mLock;
-
-    // The actual id of the built-in keyboard, or -1 if none.
-    // EventHub remaps the built-in keyboard to id 0 externally as required by the API.
-    int32_t mBuiltInKeyboardId;
-
-    int32_t mNextDeviceId;
-
-    // Parallel arrays of fds and devices.
-    // First index is reserved for inotify.
-    Vector<struct pollfd> mFds;
-    Vector<Device*> mDevices;
-
-    Device *mOpeningDevices;
-    Device *mClosingDevices;
-
-    bool mOpened;
-    bool mNeedToSendFinishedDeviceScan;
-    List<String8> mExcludedDevices;
-
-    // device ids that report particular switches.
-#ifdef EV_SW
-    int32_t mSwitches[SW_MAX + 1];
-#endif
-
-    static const int INPUT_BUFFER_SIZE = 64;
-    struct input_event mInputBufferData[INPUT_BUFFER_SIZE];
-    size_t mInputBufferIndex;
-    size_t mInputBufferCount;
-    size_t mInputFdIndex;
-};
-
-}; // namespace android
-
-#endif // _RUNTIME_EVENT_HUB_H
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index aa65d93..8b256f4 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -121,6 +121,7 @@
     friend class Surface;
     friend class BpSurface;
     friend class BnSurface;
+    friend class SurfaceTextureClient;
     friend class LightRefBase<GraphicBuffer>;
     GraphicBuffer(const GraphicBuffer& rhs);
     GraphicBuffer& operator = (const GraphicBuffer& rhs);
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
deleted file mode 100644
index 7305601..0000000
--- a/include/ui/InputDispatcher.h
+++ /dev/null
@@ -1,1110 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_DISPATCHER_H
-#define _UI_INPUT_DISPATCHER_H
-
-#include <ui/Input.h>
-#include <ui/InputTransport.h>
-#include <utils/KeyedVector.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/Looper.h>
-#include <utils/Pool.h>
-#include <utils/BitSet.h>
-
-#include <stddef.h>
-#include <unistd.h>
-#include <limits.h>
-
-
-namespace android {
-
-/*
- * Constants used to report the outcome of input event injection.
- */
-enum {
-    /* (INTERNAL USE ONLY) Specifies that injection is pending and its outcome is unknown. */
-    INPUT_EVENT_INJECTION_PENDING = -1,
-
-    /* Injection succeeded. */
-    INPUT_EVENT_INJECTION_SUCCEEDED = 0,
-
-    /* Injection failed because the injector did not have permission to inject
-     * into the application with input focus. */
-    INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1,
-
-    /* Injection failed because there were no available input targets. */
-    INPUT_EVENT_INJECTION_FAILED = 2,
-
-    /* Injection failed due to a timeout. */
-    INPUT_EVENT_INJECTION_TIMED_OUT = 3
-};
-
-/*
- * Constants used to determine the input event injection synchronization mode.
- */
-enum {
-    /* Injection is asynchronous and is assumed always to be successful. */
-    INPUT_EVENT_INJECTION_SYNC_NONE = 0,
-
-    /* Waits for previous events to be dispatched so that the input dispatcher can determine
-     * whether input event injection willbe permitted based on the current input focus.
-     * Does not wait for the input event to finish processing. */
-    INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1,
-
-    /* Waits for the input event to be completely processed. */
-    INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED = 2,
-};
-
-
-/*
- * An input target specifies how an input event is to be dispatched to a particular window
- * including the window's input channel, control flags, a timeout, and an X / Y offset to
- * be added to input event coordinates to compensate for the absolute position of the
- * window area.
- */
-struct InputTarget {
-    enum {
-        /* This flag indicates that the event is being delivered to a foreground application. */
-        FLAG_FOREGROUND = 0x01,
-
-        /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
-         * of the area of this target and so should instead be delivered as an
-         * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
-        FLAG_OUTSIDE = 0x02,
-
-        /* This flag indicates that the target of a MotionEvent is partly or wholly
-         * obscured by another visible window above it.  The motion event should be
-         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
-        FLAG_WINDOW_IS_OBSCURED = 0x04,
-
-        /* This flag indicates that a motion event is being split across multiple windows. */
-        FLAG_SPLIT = 0x08,
-    };
-
-    // The input channel to be targeted.
-    sp<InputChannel> inputChannel;
-
-    // Flags for the input target.
-    int32_t flags;
-
-    // The x and y offset to add to a MotionEvent as it is delivered.
-    // (ignored for KeyEvents)
-    float xOffset, yOffset;
-
-    // The subset of pointer ids to include in motion events dispatched to this input target
-    // if FLAG_SPLIT is set.
-    BitSet32 pointerIds;
-};
-
-
-/*
- * An input window describes the bounds of a window that can receive input.
- */
-struct InputWindow {
-    // Window flags from WindowManager.LayoutParams
-    enum {
-        FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001,
-        FLAG_DIM_BEHIND        = 0x00000002,
-        FLAG_BLUR_BEHIND        = 0x00000004,
-        FLAG_NOT_FOCUSABLE      = 0x00000008,
-        FLAG_NOT_TOUCHABLE      = 0x00000010,
-        FLAG_NOT_TOUCH_MODAL    = 0x00000020,
-        FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
-        FLAG_KEEP_SCREEN_ON     = 0x00000080,
-        FLAG_LAYOUT_IN_SCREEN   = 0x00000100,
-        FLAG_LAYOUT_NO_LIMITS   = 0x00000200,
-        FLAG_FULLSCREEN      = 0x00000400,
-        FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800,
-        FLAG_DITHER             = 0x00001000,
-        FLAG_SECURE             = 0x00002000,
-        FLAG_SCALED             = 0x00004000,
-        FLAG_IGNORE_CHEEK_PRESSES    = 0x00008000,
-        FLAG_LAYOUT_INSET_DECOR = 0x00010000,
-        FLAG_ALT_FOCUSABLE_IM = 0x00020000,
-        FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
-        FLAG_SHOW_WHEN_LOCKED = 0x00080000,
-        FLAG_SHOW_WALLPAPER = 0x00100000,
-        FLAG_TURN_SCREEN_ON = 0x00200000,
-        FLAG_DISMISS_KEYGUARD = 0x00400000,
-        FLAG_SPLIT_TOUCH = 0x00800000,
-        FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
-        FLAG_COMPATIBLE_WINDOW = 0x20000000,
-        FLAG_SYSTEM_ERROR = 0x40000000,
-    };
-
-    // Window types from WindowManager.LayoutParams
-    enum {
-        FIRST_APPLICATION_WINDOW = 1,
-        TYPE_BASE_APPLICATION   = 1,
-        TYPE_APPLICATION        = 2,
-        TYPE_APPLICATION_STARTING = 3,
-        LAST_APPLICATION_WINDOW = 99,
-        FIRST_SUB_WINDOW        = 1000,
-        TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW,
-        TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1,
-        TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
-        TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
-        TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW+4,
-        LAST_SUB_WINDOW         = 1999,
-        FIRST_SYSTEM_WINDOW     = 2000,
-        TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW,
-        TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1,
-        TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2,
-        TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3,
-        TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4,
-        TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5,
-        TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6,
-        TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7,
-        TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8,
-        TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9,
-        TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10,
-        TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11,
-        TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
-        TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13,
-        TYPE_STATUS_BAR_SUB_PANEL  = FIRST_SYSTEM_WINDOW+14,
-        TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
-        TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16,
-        TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+17,
-        LAST_SYSTEM_WINDOW      = 2999,
-    };
-
-    sp<InputChannel> inputChannel;
-    String8 name;
-    int32_t layoutParamsFlags;
-    int32_t layoutParamsType;
-    nsecs_t dispatchingTimeout;
-    int32_t frameLeft;
-    int32_t frameTop;
-    int32_t frameRight;
-    int32_t frameBottom;
-    int32_t visibleFrameLeft;
-    int32_t visibleFrameTop;
-    int32_t visibleFrameRight;
-    int32_t visibleFrameBottom;
-    int32_t touchableAreaLeft;
-    int32_t touchableAreaTop;
-    int32_t touchableAreaRight;
-    int32_t touchableAreaBottom;
-    bool visible;
-    bool canReceiveKeys;
-    bool hasFocus;
-    bool hasWallpaper;
-    bool paused;
-    int32_t layer;
-    int32_t ownerPid;
-    int32_t ownerUid;
-
-    bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
-    bool frameContainsPoint(int32_t x, int32_t y) const;
-
-    /* Returns true if the window is of a trusted type that is allowed to silently
-     * overlay other windows for the purpose of implementing the secure views feature.
-     * Trusted overlays, such as IME windows, can partly obscure other windows without causing
-     * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
-     */
-    bool isTrustedOverlay() const;
-
-    bool supportsSplitTouch() const;
-};
-
-
-/*
- * A private handle type used by the input manager to track the window.
- */
-class InputApplicationHandle : public RefBase {
-protected:
-    InputApplicationHandle() { }
-    virtual ~InputApplicationHandle() { }
-};
-
-
-/*
- * An input application describes properties of an application that can receive input.
- */
-struct InputApplication {
-    String8 name;
-    nsecs_t dispatchingTimeout;
-    sp<InputApplicationHandle> handle;
-};
-
-
-/*
- * Input dispatcher policy interface.
- *
- * The input reader policy is used by the input reader to interact with the Window Manager
- * and other system components.
- *
- * The actual implementation is partially supported by callbacks into the DVM
- * via JNI.  This interface is also mocked in the unit tests.
- */
-class InputDispatcherPolicyInterface : public virtual RefBase {
-protected:
-    InputDispatcherPolicyInterface() { }
-    virtual ~InputDispatcherPolicyInterface() { }
-
-public:
-    /* Notifies the system that a configuration change has occurred. */
-    virtual void notifyConfigurationChanged(nsecs_t when) = 0;
-
-    /* Notifies the system that an application is not responding.
-     * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
-    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-            const sp<InputChannel>& inputChannel) = 0;
-
-    /* Notifies the system that an input channel is unrecoverably broken. */
-    virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0;
-
-    /* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */
-    virtual nsecs_t getKeyRepeatTimeout() = 0;
-
-    /* Gets the key repeat inter-key delay. */
-    virtual nsecs_t getKeyRepeatDelay() = 0;
-
-    /* Gets the maximum suggested event delivery rate per second.
-     * This value is used to throttle motion event movement actions on a per-device
-     * basis.  It is not intended to be a hard limit.
-     */
-    virtual int32_t getMaxEventsPerSecond() = 0;
-
-    /* Intercepts a key event immediately before queueing it.
-     * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing such as updating policy flags.
-     *
-     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
-     * should be dispatched to applications.
-     */
-    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;
-
-    /* Intercepts a generic touch, trackball or other event before queueing it.
-     * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing such as updating policy flags.
-     *
-     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
-     * should be dispatched to applications.
-     */
-    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
-
-    /* Allows the policy a chance to intercept a key before dispatching. */
-    virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
-
-    /* Allows the policy a chance to perform default processing for an unhandled key.
-     * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
-    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
-
-    /* Notifies the policy about switch events.
-     */
-    virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
-
-    /* Poke user activity for an event dispatched to a window. */
-    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;
-
-    /* Checks whether a given application pid/uid has permission to inject input events
-     * into other applications.
-     *
-     * This method is special in that its implementation promises to be non-reentrant and
-     * is safe to call while holding other locks.  (Most other methods make no such guarantees!)
-     */
-    virtual bool checkInjectEventsPermissionNonReentrant(
-            int32_t injectorPid, int32_t injectorUid) = 0;
-};
-
-
-/* Notifies the system about input events generated by the input reader.
- * The dispatcher is expected to be mostly asynchronous. */
-class InputDispatcherInterface : public virtual RefBase {
-protected:
-    InputDispatcherInterface() { }
-    virtual ~InputDispatcherInterface() { }
-
-public:
-    /* Dumps the state of the input dispatcher.
-     *
-     * This method may be called on any thread (usually by the input manager). */
-    virtual void dump(String8& dump) = 0;
-
-    /* Runs a single iteration of the dispatch loop.
-     * Nominally processes one queued event, a timeout, or a response from an input consumer.
-     *
-     * This method should only be called on the input dispatcher thread.
-     */
-    virtual void dispatchOnce() = 0;
-
-    /* Notifies the dispatcher about new events.
-     *
-     * These methods should only be called on the input reader thread.
-     */
-    virtual void notifyConfigurationChanged(nsecs_t eventTime) = 0;
-    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
-            int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
-    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t flags,
-            int32_t metaState, int32_t edgeFlags,
-            uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
-            float xPrecision, float yPrecision, nsecs_t downTime) = 0;
-    virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
-
-    /* Injects an input event and optionally waits for sync.
-     * The synchronization mode determines whether the method blocks while waiting for
-     * input injection to proceed.
-     * Returns one of the INPUT_EVENT_INJECTION_XXX constants.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual int32_t injectInputEvent(const InputEvent* event,
-            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) = 0;
-
-    /* Sets the list of input windows.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void setInputWindows(const Vector<InputWindow>& inputWindows) = 0;
-
-    /* Sets the focused application.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void setFocusedApplication(const InputApplication* inputApplication) = 0;
-
-    /* Sets the input dispatching mode.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;
-
-    /* Transfers touch focus from the window associated with one channel to the
-     * window associated with the other channel.
-     *
-     * Returns true on success.  False if the window did not actually have touch focus.
-     */
-    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
-            const sp<InputChannel>& toChannel) = 0;
-
-    /* Registers or unregister input channels that may be used as targets for input events.
-     * If monitor is true, the channel will receive a copy of all input events.
-     *
-     * These methods may be called on any thread (usually by the input manager).
-     */
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) = 0;
-    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
-};
-
-/* Dispatches events to input targets.  Some functions of the input dispatcher, such as
- * identifying input targets, are controlled by a separate policy object.
- *
- * IMPORTANT INVARIANT:
- *     Because the policy can potentially block or cause re-entrance into the input dispatcher,
- *     the input dispatcher never calls into the policy while holding its internal locks.
- *     The implementation is also carefully designed to recover from scenarios such as an
- *     input channel becoming unregistered while identifying input targets or processing timeouts.
- *
- *     Methods marked 'Locked' must be called with the lock acquired.
- *
- *     Methods marked 'LockedInterruptible' must be called with the lock acquired but
- *     may during the course of their execution release the lock, call into the policy, and
- *     then reacquire the lock.  The caller is responsible for recovering gracefully.
- *
- *     A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa.
- */
-class InputDispatcher : public InputDispatcherInterface {
-protected:
-    virtual ~InputDispatcher();
-
-public:
-    explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
-
-    virtual void dump(String8& dump);
-
-    virtual void dispatchOnce();
-
-    virtual void notifyConfigurationChanged(nsecs_t eventTime);
-    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
-            int32_t scanCode, int32_t metaState, nsecs_t downTime);
-    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t flags,
-            int32_t metaState, int32_t edgeFlags,
-            uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
-            float xPrecision, float yPrecision, nsecs_t downTime);
-    virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) ;
-
-    virtual int32_t injectInputEvent(const InputEvent* event,
-            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis);
-
-    virtual void setInputWindows(const Vector<InputWindow>& inputWindows);
-    virtual void setFocusedApplication(const InputApplication* inputApplication);
-    virtual void setInputDispatchMode(bool enabled, bool frozen);
-
-    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
-            const sp<InputChannel>& toChannel);
-
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor);
-    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
-
-private:
-    template <typename T>
-    struct Link {
-        T* next;
-        T* prev;
-    };
-
-    struct InjectionState {
-        mutable int32_t refCount;
-
-        int32_t injectorPid;
-        int32_t injectorUid;
-        int32_t injectionResult;  // initially INPUT_EVENT_INJECTION_PENDING
-        bool injectionIsAsync; // set to true if injection is not waiting for the result
-        int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress
-    };
-
-    struct EventEntry : Link<EventEntry> {
-        enum {
-            TYPE_SENTINEL,
-            TYPE_CONFIGURATION_CHANGED,
-            TYPE_KEY,
-            TYPE_MOTION
-        };
-
-        mutable int32_t refCount;
-        int32_t type;
-        nsecs_t eventTime;
-        uint32_t policyFlags;
-        InjectionState* injectionState;
-
-        bool dispatchInProgress; // initially false, set to true while dispatching
-
-        inline bool isInjected() { return injectionState != NULL; }
-    };
-
-    struct ConfigurationChangedEntry : EventEntry {
-    };
-
-    struct KeyEntry : EventEntry {
-        int32_t deviceId;
-        int32_t source;
-        int32_t action;
-        int32_t flags;
-        int32_t keyCode;
-        int32_t scanCode;
-        int32_t metaState;
-        int32_t repeatCount;
-        nsecs_t downTime;
-
-        bool syntheticRepeat; // set to true for synthetic key repeats
-
-        enum InterceptKeyResult {
-            INTERCEPT_KEY_RESULT_UNKNOWN,
-            INTERCEPT_KEY_RESULT_SKIP,
-            INTERCEPT_KEY_RESULT_CONTINUE,
-        };
-        InterceptKeyResult interceptKeyResult; // set based on the interception result
-    };
-
-    struct MotionSample {
-        MotionSample* next;
-
-        nsecs_t eventTime;
-        PointerCoords pointerCoords[MAX_POINTERS];
-    };
-
-    struct MotionEntry : EventEntry {
-        int32_t deviceId;
-        int32_t source;
-        int32_t action;
-        int32_t flags;
-        int32_t metaState;
-        int32_t edgeFlags;
-        float xPrecision;
-        float yPrecision;
-        nsecs_t downTime;
-        uint32_t pointerCount;
-        int32_t pointerIds[MAX_POINTERS];
-
-        // Linked list of motion samples associated with this motion event.
-        MotionSample firstSample;
-        MotionSample* lastSample;
-
-        uint32_t countSamples() const;
-    };
-
-    // Tracks the progress of dispatching a particular event to a particular connection.
-    struct DispatchEntry : Link<DispatchEntry> {
-        EventEntry* eventEntry; // the event to dispatch
-        int32_t targetFlags;
-        float xOffset;
-        float yOffset;
-
-        // True if dispatch has started.
-        bool inProgress;
-
-        // For motion events:
-        //   Pointer to the first motion sample to dispatch in this cycle.
-        //   Usually NULL to indicate that the list of motion samples begins at
-        //   MotionEntry::firstSample.  Otherwise, some samples were dispatched in a previous
-        //   cycle and this pointer indicates the location of the first remainining sample
-        //   to dispatch during the current cycle.
-        MotionSample* headMotionSample;
-        //   Pointer to a motion sample to dispatch in the next cycle if the dispatcher was
-        //   unable to send all motion samples during this cycle.  On the next cycle,
-        //   headMotionSample will be initialized to tailMotionSample and tailMotionSample
-        //   will be set to NULL.
-        MotionSample* tailMotionSample;
-
-        inline bool hasForegroundTarget() const {
-            return targetFlags & InputTarget::FLAG_FOREGROUND;
-        }
-
-        inline bool isSplit() const {
-            return targetFlags & InputTarget::FLAG_SPLIT;
-        }
-    };
-
-    // A command entry captures state and behavior for an action to be performed in the
-    // dispatch loop after the initial processing has taken place.  It is essentially
-    // a kind of continuation used to postpone sensitive policy interactions to a point
-    // in the dispatch loop where it is safe to release the lock (generally after finishing
-    // the critical parts of the dispatch cycle).
-    //
-    // The special thing about commands is that they can voluntarily release and reacquire
-    // the dispatcher lock at will.  Initially when the command starts running, the
-    // dispatcher lock is held.  However, if the command needs to call into the policy to
-    // do some work, it can release the lock, do the work, then reacquire the lock again
-    // before returning.
-    //
-    // This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch
-    // never calls into the policy while holding its lock.
-    //
-    // Commands are implicitly 'LockedInterruptible'.
-    struct CommandEntry;
-    typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);
-
-    class Connection;
-    struct CommandEntry : Link<CommandEntry> {
-        CommandEntry();
-        ~CommandEntry();
-
-        Command command;
-
-        // parameters for the command (usage varies by command)
-        sp<Connection> connection;
-        nsecs_t eventTime;
-        KeyEntry* keyEntry;
-        sp<InputChannel> inputChannel;
-        sp<InputApplicationHandle> inputApplicationHandle;
-        int32_t userActivityEventType;
-        bool handled;
-    };
-
-    // Generic queue implementation.
-    template <typename T>
-    struct Queue {
-        T headSentinel;
-        T tailSentinel;
-
-        inline Queue() {
-            headSentinel.prev = NULL;
-            headSentinel.next = & tailSentinel;
-            tailSentinel.prev = & headSentinel;
-            tailSentinel.next = NULL;
-        }
-
-        inline bool isEmpty() const {
-            return headSentinel.next == & tailSentinel;
-        }
-
-        inline void enqueueAtTail(T* entry) {
-            T* last = tailSentinel.prev;
-            last->next = entry;
-            entry->prev = last;
-            entry->next = & tailSentinel;
-            tailSentinel.prev = entry;
-        }
-
-        inline void enqueueAtHead(T* entry) {
-            T* first = headSentinel.next;
-            headSentinel.next = entry;
-            entry->prev = & headSentinel;
-            entry->next = first;
-            first->prev = entry;
-        }
-
-        inline void dequeue(T* entry) {
-            entry->prev->next = entry->next;
-            entry->next->prev = entry->prev;
-        }
-
-        inline T* dequeueAtHead() {
-            T* first = headSentinel.next;
-            dequeue(first);
-            return first;
-        }
-
-        uint32_t count() const;
-    };
-
-    /* Allocates queue entries and performs reference counting as needed. */
-    class Allocator {
-    public:
-        Allocator();
-
-        InjectionState* obtainInjectionState(int32_t injectorPid, int32_t injectorUid);
-        ConfigurationChangedEntry* obtainConfigurationChangedEntry(nsecs_t eventTime);
-        KeyEntry* obtainKeyEntry(nsecs_t eventTime,
-                int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
-                int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
-                int32_t repeatCount, nsecs_t downTime);
-        MotionEntry* obtainMotionEntry(nsecs_t eventTime,
-                int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
-                int32_t flags, int32_t metaState, int32_t edgeFlags,
-                float xPrecision, float yPrecision,
-                nsecs_t downTime, uint32_t pointerCount,
-                const int32_t* pointerIds, const PointerCoords* pointerCoords);
-        DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry,
-                int32_t targetFlags, float xOffset, float yOffset);
-        CommandEntry* obtainCommandEntry(Command command);
-
-        void releaseInjectionState(InjectionState* injectionState);
-        void releaseEventEntry(EventEntry* entry);
-        void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry);
-        void releaseKeyEntry(KeyEntry* entry);
-        void releaseMotionEntry(MotionEntry* entry);
-        void releaseDispatchEntry(DispatchEntry* entry);
-        void releaseCommandEntry(CommandEntry* entry);
-
-        void recycleKeyEntry(KeyEntry* entry);
-
-        void appendMotionSample(MotionEntry* motionEntry,
-                nsecs_t eventTime, const PointerCoords* pointerCoords);
-
-    private:
-        Pool<InjectionState> mInjectionStatePool;
-        Pool<ConfigurationChangedEntry> mConfigurationChangeEntryPool;
-        Pool<KeyEntry> mKeyEntryPool;
-        Pool<MotionEntry> mMotionEntryPool;
-        Pool<MotionSample> mMotionSamplePool;
-        Pool<DispatchEntry> mDispatchEntryPool;
-        Pool<CommandEntry> mCommandEntryPool;
-
-        void initializeEventEntry(EventEntry* entry, int32_t type, nsecs_t eventTime,
-                uint32_t policyFlags);
-        void releaseEventEntryInjectionState(EventEntry* entry);
-    };
-
-    /* Tracks dispatched key and motion event state so that cancelation events can be
-     * synthesized when events are dropped. */
-    class InputState {
-    public:
-        // Specifies whether a given event will violate input state consistency.
-        enum Consistency {
-            // The event is consistent with the current input state.
-            CONSISTENT,
-            // The event is inconsistent with the current input state but applications
-            // will tolerate it.  eg. Down followed by another down.
-            TOLERABLE,
-            // The event is inconsistent with the current input state and will probably
-            // cause applications to crash.  eg. Up without prior down, move with
-            // unexpected number of pointers.
-            BROKEN
-        };
-
-        // Specifies the sources to cancel.
-        enum CancelationOptions {
-            CANCEL_ALL_EVENTS = 0,
-            CANCEL_POINTER_EVENTS = 1,
-            CANCEL_NON_POINTER_EVENTS = 2,
-            CANCEL_FALLBACK_EVENTS = 3,
-        };
-
-        InputState();
-        ~InputState();
-
-        // Returns true if there is no state to be canceled.
-        bool isNeutral() const;
-
-        // Records tracking information for an event that has just been published.
-        // Returns whether the event is consistent with the current input state.
-        Consistency trackEvent(const EventEntry* entry);
-
-        // Records tracking information for a key event that has just been published.
-        // Returns whether the event is consistent with the current input state.
-        Consistency trackKey(const KeyEntry* entry);
-
-        // Records tracking information for a motion event that has just been published.
-        // Returns whether the event is consistent with the current input state.
-        Consistency trackMotion(const MotionEntry* entry);
-
-        // Synthesizes cancelation events for the current state and resets the tracked state.
-        void synthesizeCancelationEvents(nsecs_t currentTime, Allocator* allocator,
-                Vector<EventEntry*>& outEvents, CancelationOptions options);
-
-        // Clears the current state.
-        void clear();
-
-        // Copies pointer-related parts of the input state to another instance.
-        void copyPointerStateTo(InputState& other) const;
-
-    private:
-        struct KeyMemento {
-            int32_t deviceId;
-            int32_t source;
-            int32_t keyCode;
-            int32_t scanCode;
-            int32_t flags;
-            nsecs_t downTime;
-        };
-
-        struct MotionMemento {
-            int32_t deviceId;
-            int32_t source;
-            float xPrecision;
-            float yPrecision;
-            nsecs_t downTime;
-            uint32_t pointerCount;
-            int32_t pointerIds[MAX_POINTERS];
-            PointerCoords pointerCoords[MAX_POINTERS];
-
-            void setPointers(const MotionEntry* entry);
-        };
-
-        Vector<KeyMemento> mKeyMementos;
-        Vector<MotionMemento> mMotionMementos;
-
-        static bool shouldCancelKey(const KeyMemento& memento,
-                CancelationOptions options);
-        static bool shouldCancelMotion(const MotionMemento& memento,
-                CancelationOptions options);
-    };
-
-    /* Manages the dispatch state associated with a single input channel. */
-    class Connection : public RefBase {
-    protected:
-        virtual ~Connection();
-
-    public:
-        enum Status {
-            // Everything is peachy.
-            STATUS_NORMAL,
-            // An unrecoverable communication error has occurred.
-            STATUS_BROKEN,
-            // The input channel has been unregistered.
-            STATUS_ZOMBIE
-        };
-
-        Status status;
-        sp<InputChannel> inputChannel;
-        InputPublisher inputPublisher;
-        InputState inputState;
-        Queue<DispatchEntry> outboundQueue;
-
-        nsecs_t lastEventTime; // the time when the event was originally captured
-        nsecs_t lastDispatchTime; // the time when the last event was dispatched
-
-        explicit Connection(const sp<InputChannel>& inputChannel);
-
-        inline const char* getInputChannelName() const { return inputChannel->getName().string(); }
-
-        const char* getStatusLabel() const;
-
-        // Finds a DispatchEntry in the outbound queue associated with the specified event.
-        // Returns NULL if not found.
-        DispatchEntry* findQueuedDispatchEntryForEvent(const EventEntry* eventEntry) const;
-
-        // Gets the time since the current event was originally obtained from the input driver.
-        inline double getEventLatencyMillis(nsecs_t currentTime) const {
-            return (currentTime - lastEventTime) / 1000000.0;
-        }
-
-        // Gets the time since the current event entered the outbound dispatch queue.
-        inline double getDispatchLatencyMillis(nsecs_t currentTime) const {
-            return (currentTime - lastDispatchTime) / 1000000.0;
-        }
-
-        status_t initialize();
-    };
-
-    enum DropReason {
-        DROP_REASON_NOT_DROPPED = 0,
-        DROP_REASON_POLICY = 1,
-        DROP_REASON_APP_SWITCH = 2,
-        DROP_REASON_DISABLED = 3,
-    };
-
-    sp<InputDispatcherPolicyInterface> mPolicy;
-
-    Mutex mLock;
-
-    Allocator mAllocator;
-    sp<Looper> mLooper;
-
-    EventEntry* mPendingEvent;
-    Queue<EventEntry> mInboundQueue;
-    Queue<CommandEntry> mCommandQueue;
-
-    Vector<EventEntry*> mTempCancelationEvents;
-
-    void dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, nsecs_t keyRepeatDelay,
-            nsecs_t* nextWakeupTime);
-
-    // Enqueues an inbound event.  Returns true if mLooper->wake() should be called.
-    bool enqueueInboundEventLocked(EventEntry* entry);
-
-    // Cleans up input state when dropping an inbound event.
-    void dropInboundEventLocked(EventEntry* entry, DropReason dropReason);
-
-    // App switch latency optimization.
-    bool mAppSwitchSawKeyDown;
-    nsecs_t mAppSwitchDueTime;
-
-    static bool isAppSwitchKeyCode(int32_t keyCode);
-    bool isAppSwitchKeyEventLocked(KeyEntry* keyEntry);
-    bool isAppSwitchPendingLocked();
-    void resetPendingAppSwitchLocked(bool handled);
-
-    // All registered connections mapped by receive pipe file descriptor.
-    KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
-
-    ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel);
-
-    // Active connections are connections that have a non-empty outbound queue.
-    // We don't use a ref-counted pointer here because we explicitly abort connections
-    // during unregistration which causes the connection's outbound queue to be cleared
-    // and the connection itself to be deactivated.
-    Vector<Connection*> mActiveConnections;
-
-    // Input channels that will receive a copy of all input events.
-    Vector<sp<InputChannel> > mMonitoringChannels;
-
-    // Event injection and synchronization.
-    Condition mInjectionResultAvailableCondition;
-    bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
-    void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult);
-
-    Condition mInjectionSyncFinishedCondition;
-    void incrementPendingForegroundDispatchesLocked(EventEntry* entry);
-    void decrementPendingForegroundDispatchesLocked(EventEntry* entry);
-
-    // Throttling state.
-    struct ThrottleState {
-        nsecs_t minTimeBetweenEvents;
-
-        nsecs_t lastEventTime;
-        int32_t lastDeviceId;
-        uint32_t lastSource;
-
-        uint32_t originalSampleCount; // only collected during debugging
-    } mThrottleState;
-
-    // Key repeat tracking.
-    struct KeyRepeatState {
-        KeyEntry* lastKeyEntry; // or null if no repeat
-        nsecs_t nextRepeatTime;
-    } mKeyRepeatState;
-
-    void resetKeyRepeatLocked();
-    KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime, nsecs_t keyRepeatTimeout);
-
-    // Deferred command processing.
-    bool runCommandsLockedInterruptible();
-    CommandEntry* postCommandLocked(Command command);
-
-    // Inbound event processing.
-    void drainInboundQueueLocked();
-    void releasePendingEventLocked();
-    void releaseInboundEventLocked(EventEntry* entry);
-
-    // Dispatch state.
-    bool mDispatchEnabled;
-    bool mDispatchFrozen;
-
-    Vector<InputWindow> mWindows;
-
-    const InputWindow* getWindowLocked(const sp<InputChannel>& inputChannel);
-
-    // Focus tracking for keys, trackball, etc.
-    const InputWindow* mFocusedWindow;
-
-    // Focus tracking for touch.
-    struct TouchedWindow {
-        const InputWindow* window;
-        int32_t targetFlags;
-        BitSet32 pointerIds;        // zero unless target flag FLAG_SPLIT is set
-        sp<InputChannel> channel;
-    };
-    struct TouchState {
-        bool down;
-        bool split;
-        Vector<TouchedWindow> windows;
-
-        TouchState();
-        ~TouchState();
-        void reset();
-        void copyFrom(const TouchState& other);
-        void addOrUpdateWindow(const InputWindow* window, int32_t targetFlags, BitSet32 pointerIds);
-        void removeOutsideTouchWindows();
-        const InputWindow* getFirstForegroundWindow();
-    };
-
-    TouchState mTouchState;
-    TouchState mTempTouchState;
-
-    // Focused application.
-    InputApplication* mFocusedApplication;
-    InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
-    void releaseFocusedApplicationLocked();
-
-    // Dispatch inbound events.
-    bool dispatchConfigurationChangedLocked(
-            nsecs_t currentTime, ConfigurationChangedEntry* entry);
-    bool dispatchKeyLocked(
-            nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
-            DropReason* dropReason, nsecs_t* nextWakeupTime);
-    bool dispatchMotionLocked(
-            nsecs_t currentTime, MotionEntry* entry,
-            DropReason* dropReason, nsecs_t* nextWakeupTime);
-    void dispatchEventToCurrentInputTargetsLocked(
-            nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);
-
-    void logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry);
-    void logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry);
-
-    // The input targets that were most recently identified for dispatch.
-    bool mCurrentInputTargetsValid; // false while targets are being recomputed
-    Vector<InputTarget> mCurrentInputTargets;
-
-    enum InputTargetWaitCause {
-        INPUT_TARGET_WAIT_CAUSE_NONE,
-        INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY,
-        INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,
-    };
-
-    InputTargetWaitCause mInputTargetWaitCause;
-    nsecs_t mInputTargetWaitStartTime;
-    nsecs_t mInputTargetWaitTimeoutTime;
-    bool mInputTargetWaitTimeoutExpired;
-
-    // Finding targets for input events.
-    void resetTargetsLocked();
-    void commitTargetsLocked();
-    int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
-            const InputApplication* application, const InputWindow* window,
-            nsecs_t* nextWakeupTime);
-    void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
-            const sp<InputChannel>& inputChannel);
-    nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime);
-    void resetANRTimeoutsLocked();
-
-    int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
-            nsecs_t* nextWakeupTime);
-    int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
-            nsecs_t* nextWakeupTime);
-
-    void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
-            BitSet32 pointerIds);
-    void addMonitoringTargetsLocked();
-    void pokeUserActivityLocked(const EventEntry* eventEntry);
-    bool checkInjectionPermission(const InputWindow* window, const InjectionState* injectionState);
-    bool isWindowObscuredAtPointLocked(const InputWindow* window, int32_t x, int32_t y) const;
-    bool isWindowFinishedWithPreviousInputLocked(const InputWindow* window);
-    String8 getApplicationWindowLabelLocked(const InputApplication* application,
-            const InputWindow* window);
-
-    // Manage the dispatch cycle for a single connection.
-    // These methods are deliberately not Interruptible because doing all of the work
-    // with the mutex held makes it easier to ensure that connection invariants are maintained.
-    // If needed, the methods post commands to run later once the critical bits are done.
-    void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
-            EventEntry* eventEntry, const InputTarget* inputTarget,
-            bool resumeWithAppendedMotionSample);
-    void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
-    void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
-            bool handled);
-    void startNextDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
-    void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
-    void drainOutboundQueueLocked(Connection* connection);
-    static int handleReceiveCallback(int receiveFd, int events, void* data);
-
-    void synthesizeCancelationEventsForAllConnectionsLocked(
-            InputState::CancelationOptions options, const char* reason);
-    void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
-            InputState::CancelationOptions options, const char* reason);
-    void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
-            InputState::CancelationOptions options, const char* reason);
-
-    // Splitting motion events across windows.
-    MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
-
-    // Reset and drop everything the dispatcher is doing.
-    void resetAndDropEverythingLocked(const char* reason);
-
-    // Dump state.
-    void dumpDispatchStateLocked(String8& dump);
-    void logDispatchStateLocked();
-
-    // Add or remove a connection to the mActiveConnections vector.
-    void activateConnectionLocked(Connection* connection);
-    void deactivateConnectionLocked(Connection* connection);
-
-    // Interesting events that we might like to log or tell the framework about.
-    void onDispatchCycleStartedLocked(
-            nsecs_t currentTime, const sp<Connection>& connection);
-    void onDispatchCycleFinishedLocked(
-            nsecs_t currentTime, const sp<Connection>& connection, bool handled);
-    void onDispatchCycleBrokenLocked(
-            nsecs_t currentTime, const sp<Connection>& connection);
-    void onANRLocked(
-            nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
-            nsecs_t eventTime, nsecs_t waitStartTime);
-
-    // Outbound policy interactions.
-    void doNotifyConfigurationChangedInterruptible(CommandEntry* commandEntry);
-    void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);
-    void doNotifyANRLockedInterruptible(CommandEntry* commandEntry);
-    void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry);
-    void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry);
-    void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry);
-    void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);
-
-    // Statistics gathering.
-    void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
-            int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
-};
-
-/* Enqueues and dispatches input events, endlessly. */
-class InputDispatcherThread : public Thread {
-public:
-    explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher);
-    ~InputDispatcherThread();
-
-private:
-    virtual bool threadLoop();
-
-    sp<InputDispatcherInterface> mDispatcher;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_DISPATCHER_H
diff --git a/include/ui/InputManager.h b/include/ui/InputManager.h
deleted file mode 100644
index 568568b..0000000
--- a/include/ui/InputManager.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_MANAGER_H
-#define _UI_INPUT_MANAGER_H
-
-/**
- * Native input manager.
- */
-
-#include <ui/EventHub.h>
-#include <ui/Input.h>
-#include <utils/Errors.h>
-#include <utils/Vector.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-
-namespace android {
-
-class InputChannel;
-
-class InputReaderInterface;
-class InputReaderPolicyInterface;
-class InputReaderThread;
-
-class InputDispatcherInterface;
-class InputDispatcherPolicyInterface;
-class InputDispatcherThread;
-
-/*
- * The input manager is the core of the system event processing.
- *
- * The input manager uses two threads.
- *
- * 1. The InputReaderThread (called "InputReader") reads and preprocesses raw input events,
- *    applies policy, and posts messages to a queue managed by the DispatcherThread.
- * 2. The InputDispatcherThread (called "InputDispatcher") thread waits for new events on the
- *    queue and asynchronously dispatches them to applications.
- *
- * By design, the InputReaderThread class and InputDispatcherThread class do not share any
- * internal state.  Moreover, all communication is done one way from the InputReaderThread
- * into the InputDispatcherThread and never the reverse.  Both classes may interact with the
- * InputDispatchPolicy, however.
- *
- * The InputManager class never makes any calls into Java itself.  Instead, the
- * InputDispatchPolicy is responsible for performing all external interactions with the
- * system, including calling DVM services.
- */
-class InputManagerInterface : public virtual RefBase {
-protected:
-    InputManagerInterface() { }
-    virtual ~InputManagerInterface() { }
-
-public:
-    /* Starts the input manager threads. */
-    virtual status_t start() = 0;
-
-    /* Stops the input manager threads and waits for them to exit. */
-    virtual status_t stop() = 0;
-
-    /* Gets the input reader. */
-    virtual sp<InputReaderInterface> getReader() = 0;
-
-    /* Gets the input dispatcher. */
-    virtual sp<InputDispatcherInterface> getDispatcher() = 0;
-};
-
-class InputManager : public InputManagerInterface {
-protected:
-    virtual ~InputManager();
-
-public:
-    InputManager(
-            const sp<EventHubInterface>& eventHub,
-            const sp<InputReaderPolicyInterface>& readerPolicy,
-            const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);
-
-    // (used for testing purposes)
-    InputManager(
-            const sp<InputReaderInterface>& reader,
-            const sp<InputDispatcherInterface>& dispatcher);
-
-    virtual status_t start();
-    virtual status_t stop();
-
-    virtual sp<InputReaderInterface> getReader();
-    virtual sp<InputDispatcherInterface> getDispatcher();
-
-private:
-    sp<InputReaderInterface> mReader;
-    sp<InputReaderThread> mReaderThread;
-
-    sp<InputDispatcherInterface> mDispatcher;
-    sp<InputDispatcherThread> mDispatcherThread;
-
-    void initialize();
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_MANAGER_H
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
deleted file mode 100644
index b466ff1..0000000
--- a/include/ui/InputReader.h
+++ /dev/null
@@ -1,938 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_READER_H
-#define _UI_INPUT_READER_H
-
-#include <ui/EventHub.h>
-#include <ui/Input.h>
-#include <ui/InputDispatcher.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/BitSet.h>
-
-#include <stddef.h>
-#include <unistd.h>
-
-namespace android {
-
-class InputDevice;
-class InputMapper;
-
-
-/*
- * Input reader policy interface.
- *
- * The input reader policy is used by the input reader to interact with the Window Manager
- * and other system components.
- *
- * The actual implementation is partially supported by callbacks into the DVM
- * via JNI.  This interface is also mocked in the unit tests.
- */
-class InputReaderPolicyInterface : public virtual RefBase {
-protected:
-    InputReaderPolicyInterface() { }
-    virtual ~InputReaderPolicyInterface() { }
-
-public:
-    /* Display orientations. */
-    enum {
-        ROTATION_0 = 0,
-        ROTATION_90 = 1,
-        ROTATION_180 = 2,
-        ROTATION_270 = 3
-    };
-
-    /* Gets information about the display with the specified id.
-     * Returns true if the display info is available, false otherwise.
-     */
-    virtual bool getDisplayInfo(int32_t displayId,
-            int32_t* width, int32_t* height, int32_t* orientation) = 0;
-
-    /* Determines whether to turn on some hacks we have to improve the touch interaction with a
-     * certain device whose screen currently is not all that good.
-     */
-    virtual bool filterTouchEvents() = 0;
-
-    /* Determines whether to turn on some hacks to improve touch interaction with another device
-     * where touch coordinate data can get corrupted.
-     */
-    virtual bool filterJumpyTouchEvents() = 0;
-
-    /* Gets the excluded device names for the platform. */
-    virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0;
-};
-
-
-/* Processes raw input events and sends cooked event data to an input dispatcher. */
-class InputReaderInterface : public virtual RefBase {
-protected:
-    InputReaderInterface() { }
-    virtual ~InputReaderInterface() { }
-
-public:
-    /* Dumps the state of the input reader.
-     *
-     * This method may be called on any thread (usually by the input manager). */
-    virtual void dump(String8& dump) = 0;
-
-    /* Runs a single iteration of the processing loop.
-     * Nominally reads and processes one incoming message from the EventHub.
-     *
-     * This method should be called on the input reader thread.
-     */
-    virtual void loopOnce() = 0;
-
-    /* Gets the current input device configuration.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 0;
-
-    /* Gets information about the specified input device.
-     * Returns OK if the device information was obtained or NAME_NOT_FOUND if there
-     * was no such device.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) = 0;
-
-    /* Gets the list of all registered device ids. */
-    virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds) = 0;
-
-    /* Query current input state. */
-    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
-            int32_t scanCode) = 0;
-    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
-            int32_t keyCode) = 0;
-    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
-            int32_t sw) = 0;
-
-    /* Determine whether physical keys exist for the given framework-domain key codes. */
-    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
-            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
-};
-
-
-/* Internal interface used by individual input devices to access global input device state
- * and parameters maintained by the input reader.
- */
-class InputReaderContext {
-public:
-    InputReaderContext() { }
-    virtual ~InputReaderContext() { }
-
-    virtual void updateGlobalMetaState() = 0;
-    virtual int32_t getGlobalMetaState() = 0;
-
-    virtual InputReaderPolicyInterface* getPolicy() = 0;
-    virtual InputDispatcherInterface* getDispatcher() = 0;
-    virtual EventHubInterface* getEventHub() = 0;
-};
-
-
-/* The input reader reads raw event data from the event hub and processes it into input events
- * that it sends to the input dispatcher.  Some functions of the input reader, such as early
- * event filtering in low power states, are controlled by a separate policy object.
- *
- * IMPORTANT INVARIANT:
- *     Because the policy and dispatcher can potentially block or cause re-entrance into
- *     the input reader, the input reader never calls into other components while holding
- *     an exclusive internal lock whenever re-entrance can happen.
- */
-class InputReader : public InputReaderInterface, protected InputReaderContext {
-public:
-    InputReader(const sp<EventHubInterface>& eventHub,
-            const sp<InputReaderPolicyInterface>& policy,
-            const sp<InputDispatcherInterface>& dispatcher);
-    virtual ~InputReader();
-
-    virtual void dump(String8& dump);
-
-    virtual void loopOnce();
-
-    virtual void getInputConfiguration(InputConfiguration* outConfiguration);
-
-    virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo);
-    virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds);
-
-    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
-            int32_t scanCode);
-    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
-            int32_t keyCode);
-    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
-            int32_t sw);
-
-    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
-            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
-
-protected:
-    // These methods are protected virtual so they can be overridden and instrumented
-    // by test cases.
-    virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes);
-
-private:
-    sp<EventHubInterface> mEventHub;
-    sp<InputReaderPolicyInterface> mPolicy;
-    sp<InputDispatcherInterface> mDispatcher;
-
-    virtual InputReaderPolicyInterface* getPolicy() { return mPolicy.get(); }
-    virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); }
-    virtual EventHubInterface* getEventHub() { return mEventHub.get(); }
-
-    // This reader/writer lock guards the list of input devices.
-    // The writer lock must be held whenever the list of input devices is modified
-    //   and then promptly released.
-    // The reader lock must be held whenever the list of input devices is traversed or an
-    //   input device in the list is accessed.
-    // This lock only protects the registry and prevents inadvertent deletion of device objects
-    // that are in use.  Individual devices are responsible for guarding their own internal state
-    // as needed for concurrent operation.
-    RWLock mDeviceRegistryLock;
-    KeyedVector<int32_t, InputDevice*> mDevices;
-
-    // low-level input event decoding and device management
-    void process(const RawEvent* rawEvent);
-
-    void addDevice(int32_t deviceId);
-    void removeDevice(int32_t deviceId);
-    void configureExcludedDevices();
-
-    void consumeEvent(const RawEvent* rawEvent);
-
-    void handleConfigurationChanged(nsecs_t when);
-
-    // state management for all devices
-    Mutex mStateLock;
-
-    int32_t mGlobalMetaState;
-    virtual void updateGlobalMetaState();
-    virtual int32_t getGlobalMetaState();
-
-    InputConfiguration mInputConfiguration;
-    void updateInputConfiguration();
-
-    // state queries
-    typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
-    int32_t getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
-            GetStateFunc getStateFunc);
-    bool markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags);
-};
-
-
-/* Reads raw events from the event hub and processes them, endlessly. */
-class InputReaderThread : public Thread {
-public:
-    InputReaderThread(const sp<InputReaderInterface>& reader);
-    virtual ~InputReaderThread();
-
-private:
-    sp<InputReaderInterface> mReader;
-
-    virtual bool threadLoop();
-};
-
-
-/* Represents the state of a single input device. */
-class InputDevice {
-public:
-    InputDevice(InputReaderContext* context, int32_t id, const String8& name);
-    ~InputDevice();
-
-    inline InputReaderContext* getContext() { return mContext; }
-    inline int32_t getId() { return mId; }
-    inline const String8& getName() { return mName; }
-    inline uint32_t getSources() { return mSources; }
-
-    inline bool isIgnored() { return mMappers.isEmpty(); }
-
-    void dump(String8& dump);
-    void addMapper(InputMapper* mapper);
-    void configure();
-    void reset();
-    void process(const RawEvent* rawEvent);
-
-    void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
-    int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
-    int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-    int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
-    bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags);
-
-    int32_t getMetaState();
-
-    inline const PropertyMap& getConfiguration() {
-        return mConfiguration;
-    }
-
-private:
-    InputReaderContext* mContext;
-    int32_t mId;
-
-    Vector<InputMapper*> mMappers;
-
-    String8 mName;
-    uint32_t mSources;
-
-    typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
-    int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
-
-    PropertyMap mConfiguration;
-};
-
-
-/* An input mapper transforms raw input events into cooked event data.
- * A single input device can have multiple associated input mappers in order to interpret
- * different classes of events.
- */
-class InputMapper {
-public:
-    InputMapper(InputDevice* device);
-    virtual ~InputMapper();
-
-    inline InputDevice* getDevice() { return mDevice; }
-    inline int32_t getDeviceId() { return mDevice->getId(); }
-    inline const String8 getDeviceName() { return mDevice->getName(); }
-    inline InputReaderContext* getContext() { return mContext; }
-    inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
-    inline InputDispatcherInterface* getDispatcher() { return mContext->getDispatcher(); }
-    inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
-
-    virtual uint32_t getSources() = 0;
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(String8& dump);
-    virtual void configure();
-    virtual void reset();
-    virtual void process(const RawEvent* rawEvent) = 0;
-
-    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
-    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags);
-
-    virtual int32_t getMetaState();
-
-protected:
-    InputDevice* mDevice;
-    InputReaderContext* mContext;
-};
-
-
-class SwitchInputMapper : public InputMapper {
-public:
-    SwitchInputMapper(InputDevice* device);
-    virtual ~SwitchInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void process(const RawEvent* rawEvent);
-
-    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
-
-private:
-    void processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue);
-};
-
-
-class KeyboardInputMapper : public InputMapper {
-public:
-    KeyboardInputMapper(InputDevice* device, uint32_t sources, int32_t keyboardType);
-    virtual ~KeyboardInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(String8& dump);
-    virtual void configure();
-    virtual void reset();
-    virtual void process(const RawEvent* rawEvent);
-
-    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags);
-
-    virtual int32_t getMetaState();
-
-private:
-    Mutex mLock;
-
-    struct KeyDown {
-        int32_t keyCode;
-        int32_t scanCode;
-    };
-
-    uint32_t mSources;
-    int32_t mKeyboardType;
-
-    // Immutable configuration parameters.
-    struct Parameters {
-        int32_t associatedDisplayId;
-        bool orientationAware;
-    } mParameters;
-
-    struct LockedState {
-        Vector<KeyDown> keyDowns; // keys that are down
-        int32_t metaState;
-        nsecs_t downTime; // time of most recent key down
-
-        struct LedState {
-            bool avail; // led is available
-            bool on;    // we think the led is currently on
-        };
-        LedState capsLockLedState;
-        LedState numLockLedState;
-        LedState scrollLockLedState;
-    } mLocked;
-
-    void initializeLocked();
-
-    void configureParameters();
-    void dumpParameters(String8& dump);
-
-    bool isKeyboardOrGamepadKey(int32_t scanCode);
-
-    void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode,
-            uint32_t policyFlags);
-
-    ssize_t findKeyDownLocked(int32_t scanCode);
-
-    void resetLedStateLocked();
-    void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led);
-    void updateLedStateLocked(bool reset);
-    void updateLedStateForModifierLocked(LockedState::LedState& ledState, int32_t led,
-            int32_t modifier, bool reset);
-};
-
-
-class TrackballInputMapper : public InputMapper {
-public:
-    TrackballInputMapper(InputDevice* device);
-    virtual ~TrackballInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(String8& dump);
-    virtual void configure();
-    virtual void reset();
-    virtual void process(const RawEvent* rawEvent);
-
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-
-private:
-    // Amount that trackball needs to move in order to generate a key event.
-    static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
-
-    Mutex mLock;
-
-    // Immutable configuration parameters.
-    struct Parameters {
-        int32_t associatedDisplayId;
-        bool orientationAware;
-    } mParameters;
-
-    struct Accumulator {
-        enum {
-            FIELD_BTN_MOUSE = 1,
-            FIELD_REL_X = 2,
-            FIELD_REL_Y = 4
-        };
-
-        uint32_t fields;
-
-        bool btnMouse;
-        int32_t relX;
-        int32_t relY;
-
-        inline void clear() {
-            fields = 0;
-        }
-    } mAccumulator;
-
-    float mXScale;
-    float mYScale;
-    float mXPrecision;
-    float mYPrecision;
-
-    struct LockedState {
-        bool down;
-        nsecs_t downTime;
-    } mLocked;
-
-    void initializeLocked();
-
-    void configureParameters();
-    void dumpParameters(String8& dump);
-
-    void sync(nsecs_t when);
-};
-
-
-class TouchInputMapper : public InputMapper {
-public:
-    TouchInputMapper(InputDevice* device);
-    virtual ~TouchInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(String8& dump);
-    virtual void configure();
-    virtual void reset();
-
-    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags);
-
-protected:
-    Mutex mLock;
-
-    struct VirtualKey {
-        int32_t keyCode;
-        int32_t scanCode;
-        uint32_t flags;
-
-        // computed hit box, specified in touch screen coords based on known display size
-        int32_t hitLeft;
-        int32_t hitTop;
-        int32_t hitRight;
-        int32_t hitBottom;
-
-        inline bool isHit(int32_t x, int32_t y) const {
-            return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
-        }
-    };
-
-    // Raw data for a single pointer.
-    struct PointerData {
-        uint32_t id;
-        int32_t x;
-        int32_t y;
-        int32_t pressure;
-        int32_t touchMajor;
-        int32_t touchMinor;
-        int32_t toolMajor;
-        int32_t toolMinor;
-        int32_t orientation;
-
-        inline bool operator== (const PointerData& other) const {
-            return id == other.id
-                    && x == other.x
-                    && y == other.y
-                    && pressure == other.pressure
-                    && touchMajor == other.touchMajor
-                    && touchMinor == other.touchMinor
-                    && toolMajor == other.toolMajor
-                    && toolMinor == other.toolMinor
-                    && orientation == other.orientation;
-        }
-        inline bool operator!= (const PointerData& other) const {
-            return !(*this == other);
-        }
-    };
-
-    // Raw data for a collection of pointers including a pointer id mapping table.
-    struct TouchData {
-        uint32_t pointerCount;
-        PointerData pointers[MAX_POINTERS];
-        BitSet32 idBits;
-        uint32_t idToIndex[MAX_POINTER_ID + 1];
-
-        void copyFrom(const TouchData& other) {
-            pointerCount = other.pointerCount;
-            idBits = other.idBits;
-
-            for (uint32_t i = 0; i < pointerCount; i++) {
-                pointers[i] = other.pointers[i];
-
-                int id = pointers[i].id;
-                idToIndex[id] = other.idToIndex[id];
-            }
-        }
-
-        inline void clear() {
-            pointerCount = 0;
-            idBits.clear();
-        }
-    };
-
-    // Immutable configuration parameters.
-    struct Parameters {
-        enum DeviceType {
-            DEVICE_TYPE_TOUCH_SCREEN,
-            DEVICE_TYPE_TOUCH_PAD,
-        };
-
-        DeviceType deviceType;
-        int32_t associatedDisplayId;
-        bool orientationAware;
-
-        bool useBadTouchFilter;
-        bool useJumpyTouchFilter;
-        bool useAveragingTouchFilter;
-    } mParameters;
-
-    // Immutable calibration parameters in parsed form.
-    struct Calibration {
-        // Position
-        bool haveXOrigin;
-        int32_t xOrigin;
-        bool haveYOrigin;
-        int32_t yOrigin;
-        bool haveXScale;
-        float xScale;
-        bool haveYScale;
-        float yScale;
-
-        // Touch Size
-        enum TouchSizeCalibration {
-            TOUCH_SIZE_CALIBRATION_DEFAULT,
-            TOUCH_SIZE_CALIBRATION_NONE,
-            TOUCH_SIZE_CALIBRATION_GEOMETRIC,
-            TOUCH_SIZE_CALIBRATION_PRESSURE,
-        };
-
-        TouchSizeCalibration touchSizeCalibration;
-
-        // Tool Size
-        enum ToolSizeCalibration {
-            TOOL_SIZE_CALIBRATION_DEFAULT,
-            TOOL_SIZE_CALIBRATION_NONE,
-            TOOL_SIZE_CALIBRATION_GEOMETRIC,
-            TOOL_SIZE_CALIBRATION_LINEAR,
-            TOOL_SIZE_CALIBRATION_AREA,
-        };
-
-        ToolSizeCalibration toolSizeCalibration;
-        bool haveToolSizeLinearScale;
-        float toolSizeLinearScale;
-        bool haveToolSizeLinearBias;
-        float toolSizeLinearBias;
-        bool haveToolSizeAreaScale;
-        float toolSizeAreaScale;
-        bool haveToolSizeAreaBias;
-        float toolSizeAreaBias;
-        bool haveToolSizeIsSummed;
-        bool toolSizeIsSummed;
-
-        // Pressure
-        enum PressureCalibration {
-            PRESSURE_CALIBRATION_DEFAULT,
-            PRESSURE_CALIBRATION_NONE,
-            PRESSURE_CALIBRATION_PHYSICAL,
-            PRESSURE_CALIBRATION_AMPLITUDE,
-        };
-        enum PressureSource {
-            PRESSURE_SOURCE_DEFAULT,
-            PRESSURE_SOURCE_PRESSURE,
-            PRESSURE_SOURCE_TOUCH,
-        };
-
-        PressureCalibration pressureCalibration;
-        PressureSource pressureSource;
-        bool havePressureScale;
-        float pressureScale;
-
-        // Size
-        enum SizeCalibration {
-            SIZE_CALIBRATION_DEFAULT,
-            SIZE_CALIBRATION_NONE,
-            SIZE_CALIBRATION_NORMALIZED,
-        };
-
-        SizeCalibration sizeCalibration;
-
-        // Orientation
-        enum OrientationCalibration {
-            ORIENTATION_CALIBRATION_DEFAULT,
-            ORIENTATION_CALIBRATION_NONE,
-            ORIENTATION_CALIBRATION_INTERPOLATED,
-        };
-
-        OrientationCalibration orientationCalibration;
-    } mCalibration;
-
-    // Raw axis information from the driver.
-    struct RawAxes {
-        RawAbsoluteAxisInfo x;
-        RawAbsoluteAxisInfo y;
-        RawAbsoluteAxisInfo pressure;
-        RawAbsoluteAxisInfo touchMajor;
-        RawAbsoluteAxisInfo touchMinor;
-        RawAbsoluteAxisInfo toolMajor;
-        RawAbsoluteAxisInfo toolMinor;
-        RawAbsoluteAxisInfo orientation;
-    } mRawAxes;
-
-    // Current and previous touch sample data.
-    TouchData mCurrentTouch;
-    TouchData mLastTouch;
-
-    // The time the primary pointer last went down.
-    nsecs_t mDownTime;
-
-    struct LockedState {
-        Vector<VirtualKey> virtualKeys;
-
-        // The surface orientation and width and height set by configureSurfaceLocked().
-        int32_t surfaceOrientation;
-        int32_t surfaceWidth, surfaceHeight;
-
-        // Translation and scaling factors, orientation-independent.
-        int32_t xOrigin;
-        float xScale;
-        float xPrecision;
-
-        int32_t yOrigin;
-        float yScale;
-        float yPrecision;
-
-        float geometricScale;
-
-        float toolSizeLinearScale;
-        float toolSizeLinearBias;
-        float toolSizeAreaScale;
-        float toolSizeAreaBias;
-
-        float pressureScale;
-
-        float sizeScale;
-
-        float orientationScale;
-
-        // Oriented motion ranges for input device info.
-        struct OrientedRanges {
-            InputDeviceInfo::MotionRange x;
-            InputDeviceInfo::MotionRange y;
-
-            bool havePressure;
-            InputDeviceInfo::MotionRange pressure;
-
-            bool haveSize;
-            InputDeviceInfo::MotionRange size;
-
-            bool haveTouchSize;
-            InputDeviceInfo::MotionRange touchMajor;
-            InputDeviceInfo::MotionRange touchMinor;
-
-            bool haveToolSize;
-            InputDeviceInfo::MotionRange toolMajor;
-            InputDeviceInfo::MotionRange toolMinor;
-
-            bool haveOrientation;
-            InputDeviceInfo::MotionRange orientation;
-        } orientedRanges;
-
-        // Oriented dimensions and precision.
-        float orientedSurfaceWidth, orientedSurfaceHeight;
-        float orientedXPrecision, orientedYPrecision;
-
-        struct CurrentVirtualKeyState {
-            bool down;
-            nsecs_t downTime;
-            int32_t keyCode;
-            int32_t scanCode;
-        } currentVirtualKey;
-    } mLocked;
-
-    virtual void configureParameters();
-    virtual void dumpParameters(String8& dump);
-    virtual void configureRawAxes();
-    virtual void dumpRawAxes(String8& dump);
-    virtual bool configureSurfaceLocked();
-    virtual void dumpSurfaceLocked(String8& dump);
-    virtual void configureVirtualKeysLocked();
-    virtual void dumpVirtualKeysLocked(String8& dump);
-    virtual void parseCalibration();
-    virtual void resolveCalibration();
-    virtual void dumpCalibration(String8& dump);
-
-    enum TouchResult {
-        // Dispatch the touch normally.
-        DISPATCH_TOUCH,
-        // Do not dispatch the touch, but keep tracking the current stroke.
-        SKIP_TOUCH,
-        // Do not dispatch the touch, and drop all information associated with the current stoke
-        // so the next movement will appear as a new down.
-        DROP_STROKE
-    };
-
-    void syncTouch(nsecs_t when, bool havePointerIds);
-
-private:
-    /* Maximum number of historical samples to average. */
-    static const uint32_t AVERAGING_HISTORY_SIZE = 5;
-
-    /* Slop distance for jumpy pointer detection.
-     * The vertical range of the screen divided by this is our epsilon value. */
-    static const uint32_t JUMPY_EPSILON_DIVISOR = 212;
-
-    /* Number of jumpy points to drop for touchscreens that need it. */
-    static const uint32_t JUMPY_TRANSITION_DROPS = 3;
-    static const uint32_t JUMPY_DROP_LIMIT = 3;
-
-    /* Maximum squared distance for averaging.
-     * If moving farther than this, turn of averaging to avoid lag in response. */
-    static const uint64_t AVERAGING_DISTANCE_LIMIT = 75 * 75;
-
-    struct AveragingTouchFilterState {
-        // Individual history tracks are stored by pointer id
-        uint32_t historyStart[MAX_POINTERS];
-        uint32_t historyEnd[MAX_POINTERS];
-        struct {
-            struct {
-                int32_t x;
-                int32_t y;
-                int32_t pressure;
-            } pointers[MAX_POINTERS];
-        } historyData[AVERAGING_HISTORY_SIZE];
-    } mAveragingTouchFilter;
-
-    struct JumpyTouchFilterState {
-        uint32_t jumpyPointsDropped;
-    } mJumpyTouchFilter;
-
-    struct PointerDistanceHeapElement {
-        uint32_t currentPointerIndex : 8;
-        uint32_t lastPointerIndex : 8;
-        uint64_t distance : 48; // squared distance
-    };
-
-    void initializeLocked();
-
-    TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags);
-    void dispatchTouches(nsecs_t when, uint32_t policyFlags);
-    void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch,
-            BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
-            int32_t motionEventAction);
-
-    bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
-    const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y);
-
-    bool applyBadTouchFilter();
-    bool applyJumpyTouchFilter();
-    void applyAveragingTouchFilter();
-    void calculatePointerIds();
-};
-
-
-class SingleTouchInputMapper : public TouchInputMapper {
-public:
-    SingleTouchInputMapper(InputDevice* device);
-    virtual ~SingleTouchInputMapper();
-
-    virtual void reset();
-    virtual void process(const RawEvent* rawEvent);
-
-protected:
-    virtual void configureRawAxes();
-
-private:
-    struct Accumulator {
-        enum {
-            FIELD_BTN_TOUCH = 1,
-            FIELD_ABS_X = 2,
-            FIELD_ABS_Y = 4,
-            FIELD_ABS_PRESSURE = 8,
-            FIELD_ABS_TOOL_WIDTH = 16
-        };
-
-        uint32_t fields;
-
-        bool btnTouch;
-        int32_t absX;
-        int32_t absY;
-        int32_t absPressure;
-        int32_t absToolWidth;
-
-        inline void clear() {
-            fields = 0;
-        }
-    } mAccumulator;
-
-    bool mDown;
-    int32_t mX;
-    int32_t mY;
-    int32_t mPressure;
-    int32_t mToolWidth;
-
-    void initialize();
-
-    void sync(nsecs_t when);
-};
-
-
-class MultiTouchInputMapper : public TouchInputMapper {
-public:
-    MultiTouchInputMapper(InputDevice* device);
-    virtual ~MultiTouchInputMapper();
-
-    virtual void reset();
-    virtual void process(const RawEvent* rawEvent);
-
-protected:
-    virtual void configureRawAxes();
-
-private:
-    struct Accumulator {
-        enum {
-            FIELD_ABS_MT_POSITION_X = 1,
-            FIELD_ABS_MT_POSITION_Y = 2,
-            FIELD_ABS_MT_TOUCH_MAJOR = 4,
-            FIELD_ABS_MT_TOUCH_MINOR = 8,
-            FIELD_ABS_MT_WIDTH_MAJOR = 16,
-            FIELD_ABS_MT_WIDTH_MINOR = 32,
-            FIELD_ABS_MT_ORIENTATION = 64,
-            FIELD_ABS_MT_TRACKING_ID = 128,
-            FIELD_ABS_MT_PRESSURE = 256,
-        };
-
-        uint32_t pointerCount;
-        struct Pointer {
-            uint32_t fields;
-
-            int32_t absMTPositionX;
-            int32_t absMTPositionY;
-            int32_t absMTTouchMajor;
-            int32_t absMTTouchMinor;
-            int32_t absMTWidthMajor;
-            int32_t absMTWidthMinor;
-            int32_t absMTOrientation;
-            int32_t absMTTrackingId;
-            int32_t absMTPressure;
-
-            inline void clear() {
-                fields = 0;
-            }
-        } pointers[MAX_POINTERS + 1]; // + 1 to remove the need for extra range checks
-
-        inline void clear() {
-            pointerCount = 0;
-            pointers[0].clear();
-        }
-    } mAccumulator;
-
-    void initialize();
-
-    void sync(nsecs_t when);
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_READER_H
diff --git a/include/utils/PropertyMap.h b/include/utils/PropertyMap.h
index a54f819..a9e674f 100644
--- a/include/utils/PropertyMap.h
+++ b/include/utils/PropertyMap.h
@@ -71,6 +71,12 @@
     bool tryGetProperty(const String8& key, int32_t& outValue) const;
     bool tryGetProperty(const String8& key, float& outValue) const;
 
+    /* Adds all values from the specified property map. */
+    void addAll(const PropertyMap* map);
+
+    /* Gets the underlying property map. */
+    inline const KeyedVector<String8, String8>& getProperties() const { return mProperties; }
+
     /* Loads a property map from a file. */
     static status_t load(const String8& filename, PropertyMap** outMap);
 
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index f329ac4..d57f2c9 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -619,7 +619,10 @@
 status_t Parcel::writeString8(const String8& str)
 {
     status_t err = writeInt32(str.bytes());
-    if (err == NO_ERROR) {
+    // only write string if its length is more than zero characters,
+    // as readString8 will only read if the length field is non-zero.
+    // this is slightly different from how writeString16 works.
+    if (str.bytes() > 0 && err == NO_ERROR) {
         err = write(str.string(), str.bytes()+1);
     }
     return err;
diff --git a/libs/camera/Android.mk b/libs/camera/Android.mk
index 03ff229..2f16923 100644
--- a/libs/camera/Android.mk
+++ b/libs/camera/Android.mk
@@ -14,7 +14,8 @@
 	libbinder \
 	libhardware \
 	libsurfaceflinger_client \
-	libui
+	libui \
+	libgui
 
 LOCAL_MODULE:= libcamera_client
 
diff --git a/libs/camera/Camera.cpp b/libs/camera/Camera.cpp
index 450971d..907f119 100644
--- a/libs/camera/Camera.cpp
+++ b/libs/camera/Camera.cpp
@@ -80,8 +80,9 @@
         c->mStatus = NO_ERROR;
         c->mCamera = camera;
         camera->asBinder()->linkToDeath(c);
+        return c;
     }
-    return c;
+    return 0;
 }
 
 void Camera::init()
@@ -181,6 +182,20 @@
     }
 }
 
+// pass the buffered ISurfaceTexture to the camera service
+status_t Camera::setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture)
+{
+    LOGV("setPreviewTexture(%p)", surfaceTexture.get());
+    sp <ICamera> c = mCamera;
+    if (c == 0) return NO_INIT;
+    if (surfaceTexture != 0) {
+        return c->setPreviewTexture(surfaceTexture);
+    } else {
+        LOGD("app passed NULL surface");
+        return c->setPreviewTexture(0);
+    }
+}
+
 // start preview mode
 status_t Camera::startPreview()
 {
diff --git a/libs/camera/ICamera.cpp b/libs/camera/ICamera.cpp
index 7ba8d12..0881d65 100644
--- a/libs/camera/ICamera.cpp
+++ b/libs/camera/ICamera.cpp
@@ -28,6 +28,7 @@
 enum {
     DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
     SET_PREVIEW_DISPLAY,
+    SET_PREVIEW_TEXTURE,
     SET_PREVIEW_CALLBACK_FLAG,
     START_PREVIEW,
     STOP_PREVIEW,
@@ -78,6 +79,18 @@
         return reply.readInt32();
     }
 
+    // pass the buffered SurfaceTexture to the camera service
+    status_t setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture)
+    {
+        LOGV("setPreviewTexture");
+        Parcel data, reply;
+        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+        sp<IBinder> b(surfaceTexture->asBinder());
+        data.writeStrongBinder(b);
+        remote()->transact(SET_PREVIEW_TEXTURE, data, &reply);
+        return reply.readInt32();
+    }
+
     // set the preview callback flag to affect how the received frames from
     // preview are handled. See Camera.h for details.
     void setPreviewCallbackFlag(int flag)
@@ -296,6 +309,13 @@
             reply->writeInt32(setPreviewDisplay(surface));
             return NO_ERROR;
         } break;
+        case SET_PREVIEW_TEXTURE: {
+            LOGV("SET_PREVIEW_TEXTURE");
+            CHECK_INTERFACE(ICamera, data, reply);
+            sp<ISurfaceTexture> st = interface_cast<ISurfaceTexture>(data.readStrongBinder());
+            reply->writeInt32(setPreviewTexture(st));
+            return NO_ERROR;
+        } break;
         case SET_PREVIEW_CALLBACK_FLAG: {
             LOGV("SET_PREVIEW_CALLBACK_TYPE");
             CHECK_INTERFACE(ICamera, data, reply);
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 249558a..d1a6af1 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -4,17 +4,25 @@
 LOCAL_SRC_FILES:= \
 	ISensorEventConnection.cpp \
 	ISensorServer.cpp \
+	ISurfaceTexture.cpp \
 	Sensor.cpp \
 	SensorChannel.cpp \
 	SensorEventQueue.cpp \
-	SensorManager.cpp
+	SensorManager.cpp \
+	SurfaceTexture.cpp \
+	SurfaceTextureClient.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	libutils \
 	libbinder \
 	libhardware \
-	libhardware_legacy
+	libhardware_legacy \
+	libui \
+	libEGL \
+	libGLESv2 \
+	libsurfaceflinger_client
+
 
 LOCAL_MODULE:= libgui
 
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
new file mode 100644
index 0000000..90bca3c
--- /dev/null
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+#include <utils/Timers.h>
+
+#include <binder/Parcel.h>
+#include <binder/IInterface.h>
+
+#include <gui/ISurfaceTexture.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+enum {
+    REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
+    SET_BUFFER_COUNT,
+    DEQUEUE_BUFFER,
+    QUEUE_BUFFER,
+    CANCEL_BUFFER,
+    SET_CROP,
+    SET_TRANSFORM,
+};
+
+
+class BpSurfaceTexture : public BpInterface<ISurfaceTexture>
+{
+public:
+    BpSurfaceTexture(const sp<IBinder>& impl)
+        : BpInterface<ISurfaceTexture>(impl)
+    {
+    }
+
+    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
+            uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(bufferIdx);
+        data.writeInt32(w);
+        data.writeInt32(h);
+        data.writeInt32(format);
+        data.writeInt32(usage);
+        remote()->transact(REQUEST_BUFFER, data, &reply);
+        sp<GraphicBuffer> buffer;
+        bool nonNull = reply.readInt32();
+        if (nonNull) {
+            buffer = new GraphicBuffer();
+            reply.read(*buffer);
+        }
+        return buffer;
+    }
+
+    virtual status_t setBufferCount(int bufferCount)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(bufferCount);
+        remote()->transact(SET_BUFFER_COUNT, data, &reply);
+        status_t err = reply.readInt32();
+        return err;
+    }
+
+    virtual status_t dequeueBuffer(int *buf) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        remote()->transact(DEQUEUE_BUFFER, data, &reply);
+        *buf = reply.readInt32();
+        int result = reply.readInt32();
+        return result;
+    }
+
+    virtual status_t queueBuffer(int buf) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(buf);
+        remote()->transact(QUEUE_BUFFER, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
+
+    virtual void cancelBuffer(int buf) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(buf);
+        remote()->transact(CANCEL_BUFFER, data, &reply);
+    }
+
+    virtual status_t setCrop(const Rect& reg) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeFloat(reg.left);
+        data.writeFloat(reg.top);
+        data.writeFloat(reg.right);
+        data.writeFloat(reg.bottom);
+        remote()->transact(SET_CROP, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
+
+    virtual status_t setTransform(uint32_t transform) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(transform);
+        remote()->transact(SET_TRANSFORM, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture");
+
+// ----------------------------------------------------------------------
+
+status_t BnSurfaceTexture::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case REQUEST_BUFFER: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int bufferIdx   = data.readInt32();
+            uint32_t w      = data.readInt32();
+            uint32_t h      = data.readInt32();
+            uint32_t format = data.readInt32();
+            uint32_t usage  = data.readInt32();
+            sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, w, h, format,
+                    usage));
+            reply->writeInt32(buffer != 0);
+            if (buffer != 0) {
+                reply->write(*buffer);
+            }
+            return NO_ERROR;
+        } break;
+        case SET_BUFFER_COUNT: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int bufferCount = data.readInt32();
+            int result = setBufferCount(bufferCount);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        } break;
+        case DEQUEUE_BUFFER: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int buf;
+            int result = dequeueBuffer(&buf);
+            reply->writeInt32(buf);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        } break;
+        case QUEUE_BUFFER: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int buf = data.readInt32();
+            status_t result = queueBuffer(buf);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        } break;
+        case CANCEL_BUFFER: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int buf = data.readInt32();
+            cancelBuffer(buf);
+            return NO_ERROR;
+        } break;
+        case SET_CROP: {
+            Rect reg;
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            reg.left = data.readFloat();
+            reg.top = data.readFloat();
+            reg.right = data.readFloat();
+            reg.bottom = data.readFloat();
+            status_t result = setCrop(reg);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        } break;
+        case SET_TRANSFORM: {
+            Rect reg;
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            uint32_t transform = data.readInt32();
+            status_t result = setTransform(transform);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        } break;
+    }
+    return BBinder::onTransact(code, data, reply, flags);
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
new file mode 100644
index 0000000..447de76
--- /dev/null
+++ b/libs/gui/SurfaceTexture.cpp
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceTexture"
+//#define LOG_NDEBUG 0
+
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <gui/SurfaceTexture.h>
+
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+#include <surfaceflinger/IGraphicBufferAlloc.h>
+
+#include <utils/Log.h>
+
+namespace android {
+
+// Transform matrices
+static float mtxIdentity[16] = {
+    1, 0, 0, 0,
+    0, 1, 0, 0,
+    0, 0, 1, 0,
+    0, 0, 0, 1,
+};
+static float mtxFlipH[16] = {
+    -1, 0, 0, 0,
+    0, 1, 0, 0,
+    0, 0, 1, 0,
+    1, 0, 0, 1,
+};
+static float mtxFlipV[16] = {
+    1, 0, 0, 0,
+    0, -1, 0, 0,
+    0, 0, 1, 0,
+    0, 1, 0, 1,
+};
+static float mtxRot90[16] = {
+    0, 1, 0, 0,
+    -1, 0, 0, 0,
+    0, 0, 1, 0,
+    1, 0, 0, 1,
+};
+static float mtxRot180[16] = {
+    -1, 0, 0, 0,
+    0, -1, 0, 0,
+    0, 0, 1, 0,
+    1, 1, 0, 1,
+};
+static float mtxRot270[16] = {
+    0, -1, 0, 0,
+    1, 0, 0, 0,
+    0, 0, 1, 0,
+    0, 1, 0, 1,
+};
+
+static void mtxMul(float out[16], const float a[16], const float b[16]);
+
+SurfaceTexture::SurfaceTexture(GLuint tex) :
+    mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT),
+    mLastQueued(INVALID_BUFFER_SLOT), mTexName(tex) {
+    LOGV("SurfaceTexture::SurfaceTexture");
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
+        mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
+        mSlots[i].mOwnedByClient = false;
+    }
+    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
+}
+
+SurfaceTexture::~SurfaceTexture() {
+    LOGV("SurfaceTexture::~SurfaceTexture");
+    freeAllBuffers();
+}
+
+status_t SurfaceTexture::setBufferCount(int bufferCount) {
+    LOGV("SurfaceTexture::setBufferCount");
+    Mutex::Autolock lock(mMutex);
+    freeAllBuffers();
+    mBufferCount = bufferCount;
+    mCurrentTexture = INVALID_BUFFER_SLOT;
+    mLastQueued = INVALID_BUFFER_SLOT;
+    return OK;
+}
+
+sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
+        uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+    LOGV("SurfaceTexture::requestBuffer");
+    Mutex::Autolock lock(mMutex);
+    if (buf < 0 || mBufferCount <= buf) {
+        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
+                mBufferCount, buf);
+        return 0;
+    }
+    usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+    sp<GraphicBuffer> graphicBuffer(
+            mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
+    if (graphicBuffer == 0) {
+        LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed");
+    } else {
+        mSlots[buf].mGraphicBuffer = graphicBuffer;
+        if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
+            eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage);
+            mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
+            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
+        }
+        mAllocdBuffers.add(graphicBuffer);
+    }
+    return graphicBuffer;
+}
+
+status_t SurfaceTexture::dequeueBuffer(int *buf) {
+    LOGV("SurfaceTexture::dequeueBuffer");
+    Mutex::Autolock lock(mMutex);
+    int found = INVALID_BUFFER_SLOT;
+    for (int i = 0; i < mBufferCount; i++) {
+        if (!mSlots[i].mOwnedByClient && i != mCurrentTexture && i != mLastQueued) {
+            mSlots[i].mOwnedByClient = true;
+            found = i;
+            break;
+        }
+    }
+    if (found == INVALID_BUFFER_SLOT) {
+        return -EBUSY;
+    }
+    *buf = found;
+    return OK;
+}
+
+status_t SurfaceTexture::queueBuffer(int buf) {
+    LOGV("SurfaceTexture::queueBuffer");
+    Mutex::Autolock lock(mMutex);
+    if (buf < 0 || mBufferCount <= buf) {
+        LOGE("queueBuffer: slot index out of range [0, %d]: %d",
+                mBufferCount, buf);
+        return -EINVAL;
+    } else if (!mSlots[buf].mOwnedByClient) {
+        LOGE("queueBuffer: slot %d is not owned by the client", buf);
+        return -EINVAL;
+    } else if (mSlots[buf].mGraphicBuffer == 0) {
+        LOGE("queueBuffer: slot %d was enqueued without requesting a buffer",
+                buf);
+        return -EINVAL;
+    }
+    mSlots[buf].mOwnedByClient = false;
+    mLastQueued = buf;
+    mLastQueuedCrop = mNextCrop;
+    mLastQueuedTransform = mNextTransform;
+    return OK;
+}
+
+void SurfaceTexture::cancelBuffer(int buf) {
+    LOGV("SurfaceTexture::cancelBuffer");
+    Mutex::Autolock lock(mMutex);
+    if (buf < 0 || mBufferCount <= buf) {
+        LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount,
+                buf);
+        return;
+    } else if (!mSlots[buf].mOwnedByClient) {
+        LOGE("cancelBuffer: slot %d is not owned by the client", buf);
+        return;
+    }
+    mSlots[buf].mOwnedByClient = false;
+}
+
+status_t SurfaceTexture::setCrop(const Rect& crop) {
+    LOGV("SurfaceTexture::setCrop");
+    Mutex::Autolock lock(mMutex);
+    mNextCrop = crop;
+    return OK;
+}
+
+status_t SurfaceTexture::setTransform(uint32_t transform) {
+    LOGV("SurfaceTexture::setTransform");
+    Mutex::Autolock lock(mMutex);
+    mNextTransform = transform;
+    return OK;
+}
+
+status_t SurfaceTexture::updateTexImage() {
+    LOGV("SurfaceTexture::updateTexImage");
+    Mutex::Autolock lock(mMutex);
+
+    // We always bind the texture even if we don't update its contents.
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
+
+    // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT,
+    // so this check will fail until a buffer gets queued.
+    if (mCurrentTexture != mLastQueued) {
+        // Update the GL texture object.
+        EGLImageKHR image = mSlots[mLastQueued].mEglImage;
+        if (image == EGL_NO_IMAGE_KHR) {
+            EGLDisplay dpy = eglGetCurrentDisplay();
+            sp<GraphicBuffer> graphicBuffer = mSlots[mLastQueued].mGraphicBuffer;
+            image = createImage(dpy, graphicBuffer);
+            mSlots[mLastQueued].mEglImage = image;
+            mSlots[mLastQueued].mEglDisplay = dpy;
+        }
+        glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
+        GLint error = glGetError();
+        if (error != GL_NO_ERROR) {
+            LOGE("error binding external texture image %p (slot %d): %#04x",
+                    image, mLastQueued, error);
+            return -EINVAL;
+        }
+
+        // Update the SurfaceTexture state.
+        mCurrentTexture = mLastQueued;
+        mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
+        mCurrentCrop = mLastQueuedCrop;
+        mCurrentTransform = mLastQueuedTransform;
+    }
+    return OK;
+}
+
+void SurfaceTexture::getTransformMatrix(float mtx[16]) {
+    LOGV("SurfaceTexture::updateTexImage");
+    Mutex::Autolock lock(mMutex);
+
+    float* xform = mtxIdentity;
+    switch (mCurrentTransform) {
+        case 0:
+            xform = mtxIdentity;
+            break;
+        case NATIVE_WINDOW_TRANSFORM_FLIP_H:
+            xform = mtxFlipH;
+            break;
+        case NATIVE_WINDOW_TRANSFORM_FLIP_V:
+            xform = mtxFlipV;
+            break;
+        case NATIVE_WINDOW_TRANSFORM_ROT_90:
+            xform = mtxRot90;
+            break;
+        case NATIVE_WINDOW_TRANSFORM_ROT_180:
+            xform = mtxRot180;
+            break;
+        case NATIVE_WINDOW_TRANSFORM_ROT_270:
+            xform = mtxRot270;
+            break;
+        default:
+            LOGE("getTransformMatrix: unknown transform: %d", mCurrentTransform);
+    }
+
+    sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
+    float tx = float(mCurrentCrop.left) / float(buf->getWidth());
+    float ty = float(mCurrentCrop.bottom) / float(buf->getHeight());
+    float sx = float(mCurrentCrop.width()) / float(buf->getWidth());
+    float sy = float(mCurrentCrop.height()) / float(buf->getHeight());
+    float crop[16] = {
+        sx, 0, 0, sx*tx,
+        0, sy, 0, sy*ty,
+        0, 0, 1, 0,
+        0, 0, 0, 1,
+    };
+
+    mtxMul(mtx, crop, xform);
+}
+
+void SurfaceTexture::freeAllBuffers() {
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        mSlots[i].mGraphicBuffer = 0;
+        mSlots[i].mOwnedByClient = false;
+        if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
+            eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
+            mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
+            mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
+        }
+    }
+
+    int exceptBuf = -1;
+    for (size_t i = 0; i < mAllocdBuffers.size(); i++) {
+        if (mAllocdBuffers[i] == mCurrentTextureBuf) {
+            exceptBuf = i;
+            break;
+        }
+    }
+    mAllocdBuffers.clear();
+    if (exceptBuf >= 0) {
+        mAllocdBuffers.add(mCurrentTextureBuf);
+    }
+    mGraphicBufferAlloc->freeAllGraphicBuffersExcept(exceptBuf);
+}
+
+EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
+        const sp<GraphicBuffer>& graphicBuffer) {
+    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
+    EGLint attrs[] = {
+        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
+        EGL_NONE,
+    };
+    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
+            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
+    EGLint error = eglGetError();
+    if (error != EGL_SUCCESS) {
+        LOGE("error creating EGLImage: %#x", error);
+    } else if (image == EGL_NO_IMAGE_KHR) {
+        LOGE("no error reported, but no image was returned by "
+                "eglCreateImageKHR");
+    }
+    return image;
+}
+
+static void mtxMul(float out[16], const float a[16], const float b[16]) {
+    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
+    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
+    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
+    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
+
+    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
+    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
+    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
+    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
+
+    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
+    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
+    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
+    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
+
+    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
+    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
+    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
+    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
+}
+
+}; // namespace android
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
new file mode 100644
index 0000000..0ed8be5
--- /dev/null
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceTextureClient"
+//#define LOG_NDEBUG 0
+
+#include <gui/SurfaceTextureClient.h>
+
+#include <utils/Log.h>
+
+namespace android {
+
+SurfaceTextureClient::SurfaceTextureClient(
+        const sp<ISurfaceTexture>& surfaceTexture):
+        mSurfaceTexture(surfaceTexture), mReqWidth(1), mReqHeight(1),
+        mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
+    // Initialize the ANativeWindow function pointers.
+    ANativeWindow::setSwapInterval  = setSwapInterval;
+    ANativeWindow::dequeueBuffer    = dequeueBuffer;
+    ANativeWindow::cancelBuffer     = cancelBuffer;
+    ANativeWindow::lockBuffer       = lockBuffer;
+    ANativeWindow::queueBuffer      = queueBuffer;
+    ANativeWindow::query            = query;
+    ANativeWindow::perform          = perform;
+}
+
+int SurfaceTextureClient::setSwapInterval(ANativeWindow* window, int interval) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->setSwapInterval(interval);
+}
+
+int SurfaceTextureClient::dequeueBuffer(ANativeWindow* window,
+        android_native_buffer_t** buffer) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->dequeueBuffer(buffer);
+}
+
+int SurfaceTextureClient::cancelBuffer(ANativeWindow* window,
+        android_native_buffer_t* buffer) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->cancelBuffer(buffer);
+}
+
+int SurfaceTextureClient::lockBuffer(ANativeWindow* window,
+        android_native_buffer_t* buffer) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->lockBuffer(buffer);
+}
+
+int SurfaceTextureClient::queueBuffer(ANativeWindow* window,
+        android_native_buffer_t* buffer) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->queueBuffer(buffer);
+}
+
+int SurfaceTextureClient::query(ANativeWindow* window, int what, int* value) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->query(what, value);
+}
+
+int SurfaceTextureClient::perform(ANativeWindow* window, int operation, ...) {
+    va_list args;
+    va_start(args, operation);
+    SurfaceTextureClient* c = getSelf(window);
+    return c->perform(operation, args);
+}
+
+int SurfaceTextureClient::setSwapInterval(int interval) {
+    return INVALID_OPERATION;
+}
+
+int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
+    LOGV("SurfaceTextureClient::dequeueBuffer");
+    Mutex::Autolock lock(mMutex);
+    int buf = -1;
+    status_t err = mSurfaceTexture->dequeueBuffer(&buf);
+    if (err < 0) {
+        LOGE("dequeueBuffer: ISurfaceTexture::dequeueBuffer failed: %d", err);
+        return err;
+    }
+    sp<GraphicBuffer>& gbuf(mSlots[buf]);
+    if (gbuf == 0 || gbuf->getWidth() != mReqWidth ||
+        gbuf->getHeight() != mReqHeight ||
+        uint32_t(gbuf->getPixelFormat()) != mReqFormat ||
+        (gbuf->getUsage() & mReqUsage) != mReqUsage) {
+        gbuf = mSurfaceTexture->requestBuffer(buf, mReqWidth, mReqHeight,
+                mReqFormat, mReqUsage);
+        if (gbuf == 0) {
+            LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
+            return NO_MEMORY;
+        }
+    }
+    *buffer = gbuf.get();
+    return OK;
+}
+
+int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) {
+    LOGV("SurfaceTextureClient::cancelBuffer");
+    Mutex::Autolock lock(mMutex);
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        if (mSlots[i]->handle == buffer->handle) {
+            mSurfaceTexture->cancelBuffer(i);
+            return OK;
+        }
+    }
+    return BAD_VALUE;
+}
+
+int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) {
+    LOGV("SurfaceTextureClient::lockBuffer");
+    Mutex::Autolock lock(mMutex);
+    return OK;
+}
+
+int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
+    LOGV("SurfaceTextureClient::queueBuffer");
+    Mutex::Autolock lock(mMutex);
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        if (mSlots[i]->handle == buffer->handle) {
+            return mSurfaceTexture->queueBuffer(i);
+        }
+    }
+    LOGE("queueBuffer: unknown buffer queued");
+    return BAD_VALUE;
+}
+
+int SurfaceTextureClient::query(int what, int* value) {
+    LOGV("SurfaceTextureClient::query");
+    Mutex::Autolock lock(mMutex);
+    // XXX: Implement this!
+    return INVALID_OPERATION;
+}
+
+int SurfaceTextureClient::perform(int operation, va_list args)
+{
+    int res = NO_ERROR;
+    switch (operation) {
+    case NATIVE_WINDOW_CONNECT:
+        res = dispatchConnect(args);
+        break;
+    case NATIVE_WINDOW_DISCONNECT:
+        res = dispatchDisconnect(args);
+        break;
+    case NATIVE_WINDOW_SET_USAGE:
+        res = dispatchSetUsage(args);
+        break;
+    case NATIVE_WINDOW_SET_CROP:
+        res = dispatchSetCrop(args);
+        break;
+    case NATIVE_WINDOW_SET_BUFFER_COUNT:
+        res = dispatchSetBufferCount(args);
+        break;
+    case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
+        res = dispatchSetBuffersGeometry(args);
+        break;
+    case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
+        res = dispatchSetBuffersTransform(args);
+        break;
+    default:
+        res = NAME_NOT_FOUND;
+        break;
+    }
+    return res;
+}
+
+int SurfaceTextureClient::dispatchConnect(va_list args) {
+    int api = va_arg(args, int);
+    return connect(api);
+}
+
+int SurfaceTextureClient::dispatchDisconnect(va_list args) {
+    int api = va_arg(args, int);
+    return disconnect(api);
+}
+
+int SurfaceTextureClient::dispatchSetUsage(va_list args) {
+    int usage = va_arg(args, int);
+    return setUsage(usage);
+}
+
+int SurfaceTextureClient::dispatchSetCrop(va_list args) {
+    android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
+    return setCrop(reinterpret_cast<Rect const*>(rect));
+}
+
+int SurfaceTextureClient::dispatchSetBufferCount(va_list args) {
+    size_t bufferCount = va_arg(args, size_t);
+    return setBufferCount(bufferCount);
+}
+
+int SurfaceTextureClient::dispatchSetBuffersGeometry(va_list args) {
+    int w = va_arg(args, int);
+    int h = va_arg(args, int);
+    int f = va_arg(args, int);
+    return setBuffersGeometry(w, h, f);
+}
+
+int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
+    int transform = va_arg(args, int);
+    return setBuffersTransform(transform);
+}
+
+int SurfaceTextureClient::connect(int api) {
+    LOGV("SurfaceTextureClient::connect");
+    // XXX: Implement this!
+    return INVALID_OPERATION;
+}
+
+int SurfaceTextureClient::disconnect(int api) {
+    LOGV("SurfaceTextureClient::disconnect");
+    // XXX: Implement this!
+    return INVALID_OPERATION;
+}
+
+int SurfaceTextureClient::setUsage(uint32_t reqUsage)
+{
+    LOGV("SurfaceTextureClient::setUsage");
+    Mutex::Autolock lock(mMutex);
+    mReqUsage = reqUsage;
+    return OK;
+}
+
+int SurfaceTextureClient::setCrop(Rect const* rect)
+{
+    LOGV("SurfaceTextureClient::setCrop");
+    Mutex::Autolock lock(mMutex);
+
+    // empty/invalid rects are not allowed
+    if (rect->isEmpty())
+        return BAD_VALUE;
+
+    status_t err = mSurfaceTexture->setCrop(*rect);
+    LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s",
+            strerror(-err));
+
+    return err;
+}
+
+int SurfaceTextureClient::setBufferCount(int bufferCount)
+{
+    LOGV("SurfaceTextureClient::setBufferCount");
+    Mutex::Autolock lock(mMutex);
+
+    status_t err = mSurfaceTexture->setBufferCount(bufferCount);
+    LOGE_IF(err, "ISurfaceTexture::setBufferCount(%d) returned %s",
+            bufferCount, strerror(-err));
+
+    if (err == NO_ERROR) {
+        freeAllBuffers();
+    }
+
+    return err;
+}
+
+int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format)
+{
+    LOGV("SurfaceTextureClient::setBuffersGeometry");
+    Mutex::Autolock lock(mMutex);
+
+    if (w<0 || h<0 || format<0)
+        return BAD_VALUE;
+
+    if ((w && !h) || (!w && h))
+        return BAD_VALUE;
+
+    mReqWidth = w;
+    mReqHeight = h;
+    mReqFormat = format;
+
+    return NO_ERROR;
+}
+
+int SurfaceTextureClient::setBuffersTransform(int transform)
+{
+    LOGV("SurfaceTextureClient::setBuffersTransform");
+    Mutex::Autolock lock(mMutex);
+    status_t err = mSurfaceTexture->setTransform(transform);
+    return err;
+}
+
+void SurfaceTextureClient::freeAllBuffers() {
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        mSlots[i] = 0;
+    }
+}
+
+}; // namespace android
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 29158e5..c49be93 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -13,6 +13,7 @@
 		FboCache.cpp \
 		GradientCache.cpp \
 		LayerCache.cpp \
+		LayerRenderer.cpp \
 		Matrix.cpp \
 		OpenGLDebugRenderer.cpp \
 		OpenGLRenderer.cpp \
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 40dd117..fde4f96 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -53,6 +53,10 @@
 
     mDebugLevel = readDebugLevel();
     LOGD("Enabling debug mode %d", mDebugLevel);
+
+#if RENDER_LAYERS_AS_REGIONS
+    LOGD("Layers will be composited as regions");
+#endif
 }
 
 Caches::~Caches() {
@@ -102,6 +106,25 @@
     textureCache.clearGarbage();
     gradientCache.clearGarbage();
     pathCache.clearGarbage();
+
+    Mutex::Autolock _l(mGarbageLock);
+
+    size_t count = mLayerGarbage.size();
+    for (size_t i = 0; i < count; i++) {
+        Layer* layer = mLayerGarbage.itemAt(i);
+        if (layer) {
+            if (layer->fbo) glDeleteFramebuffers(1, &layer->fbo);
+            if (layer->texture) glDeleteTextures(1, &layer->texture);
+
+            delete layer;
+        }
+    }
+    mLayerGarbage.clear();
+}
+
+void Caches::deleteLayerDeferred(Layer* layer) {
+    Mutex::Autolock _l(mGarbageLock);
+    mLayerGarbage.push(layer);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 318c120..a11b6bc 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -90,6 +90,9 @@
     TextureVertex* mRegionMesh;
     GLuint mRegionMeshIndices;
 
+    mutable Mutex mGarbageLock;
+    Vector<Layer*> mLayerGarbage;
+
 public:
     /**
      * Indicates whether the renderer is in debug mode.
@@ -106,6 +109,11 @@
     void clearGarbage();
 
     /**
+     * Can be used to delete a layer from a non EGL thread.
+     */
+    void deleteLayerDeferred(Layer* layer);
+
+    /**
      * Binds the VBO used to render simple textured quads.
      */
     void bindMeshBuffer();
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index ddbfa5e..bdd8e73 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -44,4 +44,10 @@
 // Turn on to display debug info about textures
 #define DEBUG_TEXTURES 0
 
+// Turn on to display debug info about the layer renderer
+#define DEBUG_LAYER_RENDERER 0
+
+// Turn on to dump display list state
+#define DEBUG_DISPLAY_LIST 0
+
 #endif // ANDROID_HWUI_DEBUG_H
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 77d628a..e3593da 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -81,7 +81,77 @@
 // Display list
 ///////////////////////////////////////////////////////////////////////////////
 
+const char* DisplayList::OP_NAMES[] = {
+    "AcquireContext",
+    "ReleaseContext",
+    "Save",
+    "Restore",
+    "RestoreToCount",
+    "SaveLayer",
+    "SaveLayerAlpha",
+    "Translate",
+    "Rotate",
+    "Scale",
+    "SetMatrix",
+    "ConcatMatrix",
+    "ClipRect",
+    "DrawDisplayList",
+    "DrawLayer",
+    "DrawBitmap",
+    "DrawBitmapMatrix",
+    "DrawBitmapRect",
+    "DrawPatch",
+    "DrawColor",
+    "DrawRect",
+    "DrawPath",
+    "DrawLines",
+    "DrawText",
+    "ResetShader",
+    "SetupShader",
+    "ResetColorFilter",
+    "SetupColorFilter",
+    "ResetShadow",
+    "SetupShadow"
+};
+
 DisplayList::DisplayList(const DisplayListRenderer& recorder) {
+    initFromDisplayListRenderer(recorder);
+}
+
+DisplayList::~DisplayList() {
+    sk_free((void*) mReader.base());
+
+    Caches& caches = Caches::getInstance();
+
+    for (size_t i = 0; i < mBitmapResources.size(); i++) {
+        caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i));
+    }
+    mBitmapResources.clear();
+
+    for (size_t i = 0; i < mShaders.size(); i++) {
+        caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
+    }
+    mShaders.clear();
+
+    for (size_t i = 0; i < mPaints.size(); i++) {
+        delete mPaints.itemAt(i);
+    }
+    mPaints.clear();
+
+    for (size_t i = 0; i < mMatrices.size(); i++) {
+        delete mMatrices.itemAt(i);
+    }
+    mMatrices.clear();
+
+    if (mPathHeap) {
+        for (int i = 0; i < mPathHeap->count(); i++) {
+            caches.pathCache.removeDeferred(&(*mPathHeap)[i]);
+        }
+        mPathHeap->safeUnref();
+    }
+}
+
+void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder) {
     const SkWriter32& writer = recorder.writeStream();
     init();
 
@@ -109,11 +179,11 @@
         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();
@@ -132,51 +202,29 @@
     }
 }
 
-DisplayList::~DisplayList() {
-    sk_free((void*) mReader.base());
-
-    Caches& caches = Caches::getInstance();
-
-    for (size_t i = 0; i < mBitmapResources.size(); i++) {
-        caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i));
-    }
-    mBitmapResources.clear();
-
-    for (size_t i = 0; i < mShaderResources.size(); i++) {
-        caches.resourceCache.decrementRefcount(mShaderResources.itemAt(i));
-    }
-    mShaderResources.clear();
-
-    for (size_t i = 0; i < mPaints.size(); i++) {
-        delete mPaints.itemAt(i);
-    }
-    mPaints.clear();
-
-    for (size_t i = 0; i < mMatrices.size(); i++) {
-        delete mMatrices.itemAt(i);
-    }
-    mMatrices.clear();
-
-    if (mPathHeap) {
-        for (int i = 0; i < mPathHeap->count(); i++) {
-            caches.pathCache.removeDeferred(&(*mPathHeap)[i]);
-        }
-        mPathHeap->safeUnref();
-    }
-}
-
 void DisplayList::init() {
     mPathHeap = NULL;
 }
 
-void DisplayList::replay(OpenGLRenderer& renderer) {
+void DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
     TextContainer text;
     mReader.rewind();
 
-    int saveCount = renderer.getSaveCount() - 1;
+#if DEBUG_DISPLAY_LIST
+    uint32_t count = (level + 1) * 2;
+    char indent[count + 1];
+    for (uint32_t i = 0; i < count; i++) {
+        indent[i] = ' ';
+    }
+    indent[count] = '\0';
+    DISPLAY_LIST_LOGD("%sStart display list (%p)", (char*) indent + 2, this);
+#endif
 
+    int saveCount = renderer.getSaveCount() - 1;
     while (!mReader.eof()) {
         int op = mReader.readInt();
+        DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+
         switch (op) {
             case AcquireContext: {
                 renderer.acquireContext();
@@ -234,7 +282,11 @@
             }
             break;
             case DrawDisplayList: {
-                renderer.drawDisplayList(getDisplayList());
+                renderer.drawDisplayList(getDisplayList(), level + 1);
+            }
+            break;
+            case DrawLayer: {
+                renderer.drawLayer((Layer*) getInt(), getFloat(), getFloat(), getPaint());
             }
             break;
             case DrawBitmap: {
@@ -318,6 +370,8 @@
             break;
         }
     }
+
+    DISPLAY_LIST_LOGD("%sDone", (char*) indent + 2);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -327,6 +381,7 @@
 DisplayListRenderer::DisplayListRenderer():
         mHeap(HEAP_BLOCK_SIZE), mWriter(MIN_WRITER_SIZE) {
     mPathHeap = NULL;
+    mDisplayList = NULL;
 }
 
 DisplayListRenderer::~DisplayListRenderer() {
@@ -352,11 +407,11 @@
     }
     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();
@@ -367,6 +422,15 @@
 // Operations
 ///////////////////////////////////////////////////////////////////////////////
 
+DisplayList* DisplayListRenderer::getDisplayList() {
+    if (mDisplayList == NULL) {
+        mDisplayList = new DisplayList(*this);
+    } else {
+        mDisplayList->initFromDisplayListRenderer(*this);
+    }
+    return mDisplayList;
+}
+
 void DisplayListRenderer::setViewport(int width, int height) {
     mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
 
@@ -464,11 +528,18 @@
     return OpenGLRenderer::clipRect(left, top, right, bottom, op);
 }
 
-void DisplayListRenderer::drawDisplayList(DisplayList* displayList) {
+void DisplayListRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
     addOp(DisplayList::DrawDisplayList);
     addDisplayList(displayList);
 }
 
+void DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
+    addOp(DisplayList::DrawLayer);
+    addInt((int) layer);
+    addPoint(x, y);
+    addPaint(paint);
+}
+
 void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
         SkPaint* paint) {
     addOp(DisplayList::DrawBitmap);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index b608381..7152334 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -39,6 +39,13 @@
 #define MIN_WRITER_SIZE 16384
 #define HEAP_BLOCK_SIZE 4096
 
+// Debug
+#if DEBUG_DISPLAY_LIST
+    #define DISPLAY_LIST_LOGD(...) LOGD(__VA_ARGS__)
+#else
+    #define DISPLAY_LIST_LOGD(...)
+#endif
+
 ///////////////////////////////////////////////////////////////////////////////
 // Helpers
 ///////////////////////////////////////////////////////////////////////////////
@@ -78,8 +85,10 @@
     DisplayList(const DisplayListRenderer& recorder);
     ~DisplayList();
 
+    // IMPORTANT: Update the intialization of OP_NAMES in the .cpp file
+    //            when modifying this file
     enum Op {
-        AcquireContext,
+        AcquireContext = 0,
         ReleaseContext,
         Save,
         Restore,
@@ -93,6 +102,7 @@
         ConcatMatrix,
         ClipRect,
         DrawDisplayList,
+        DrawLayer,
         DrawBitmap,
         DrawBitmapMatrix,
         DrawBitmapRect,
@@ -107,10 +117,14 @@
         ResetColorFilter,
         SetupColorFilter,
         ResetShadow,
-        SetupShadow
+        SetupShadow,
     };
 
-    void replay(OpenGLRenderer& renderer);
+    static const char* OP_NAMES[];
+
+    void initFromDisplayListRenderer(const DisplayListRenderer& recorder);
+
+    void replay(OpenGLRenderer& renderer, uint32_t level = 0);
 
 private:
     void init();
@@ -192,11 +206,11 @@
     PathHeap* mPathHeap;
 
     Vector<SkBitmap*> mBitmapResources;
-    Vector<SkiaShader*> mShaderResources;
     Vector<SkiaColorFilter*> mFilterResources;
 
     Vector<SkPaint*> mPaints;
     Vector<SkMatrix*> mMatrices;
+    Vector<SkiaShader*> mShaders;
 
     mutable SkFlattenableReadBuffer mReader;
 
@@ -216,6 +230,8 @@
     DisplayListRenderer();
     ~DisplayListRenderer();
 
+    DisplayList* getDisplayList();
+
     void setViewport(int width, int height);
     void prepare(bool opaque);
 
@@ -240,7 +256,8 @@
 
     bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
 
-    void drawDisplayList(DisplayList* displayList);
+    void drawDisplayList(DisplayList* displayList, uint32_t level = 0);
+    void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
@@ -266,10 +283,6 @@
 
     void reset();
 
-    DisplayList* getDisplayList() const {
-        return new DisplayList(*this);
-    }
-
     const SkWriter32& writeStream() const {
         return mWriter;
     }
@@ -278,8 +291,8 @@
         return mBitmapResources;
     }
 
-    const Vector<SkiaShader*>& getShaderResources() const {
-        return mShaderResources;
+    const Vector<SkiaShader*>& getShaders() const {
+        return mShaders;
     }
 
     const Vector<SkPaint*>& getPaints() const {
@@ -353,12 +366,12 @@
     }
 
     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);
@@ -393,10 +406,21 @@
     }
 
     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) {
@@ -409,11 +433,14 @@
     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;
@@ -422,6 +449,8 @@
     SkRefCntRecorder mRCRecorder;
     SkRefCntRecorder mTFRecorder;
 
+    DisplayList *mDisplayList;
+
     friend class DisplayList;
 
 }; // class DisplayListRenderer
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 5224689..d1fbfba 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -38,8 +38,8 @@
 // Font
 ///////////////////////////////////////////////////////////////////////////////
 
-Font::Font(FontRenderer* state, uint32_t fontId, float fontSize) :
-    mState(state), mFontId(fontId), mFontSize(fontSize) {
+Font::Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags) :
+    mState(state), mFontId(fontId), mFontSize(fontSize), mFlags(flags) {
 }
 
 
@@ -275,17 +275,17 @@
     return newGlyph;
 }
 
-Font* Font::create(FontRenderer* state, uint32_t fontId, float fontSize) {
+Font* Font::create(FontRenderer* state, uint32_t fontId, float fontSize, int flags) {
     Vector<Font*> &activeFonts = state->mActiveFonts;
 
     for (uint32_t i = 0; i < activeFonts.size(); i++) {
         Font* font = activeFonts[i];
-        if (font->mFontId == fontId && font->mFontSize == fontSize) {
+        if (font->mFontId == fontId && font->mFontSize == fontSize && font->mFlags == flags) {
             return font;
         }
     }
 
-    Font* newFont = new Font(state, fontId, fontSize);
+    Font* newFont = new Font(state, fontId, fontSize, flags);
     activeFonts.push(newFont);
     return newFont;
 }
@@ -634,7 +634,11 @@
 
 void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) {
     uint32_t currentNumFonts = mActiveFonts.size();
-    mCurrentFont = Font::create(this, fontId, fontSize);
+    int flags = 0;
+    if (paint->isFakeBoldText()) {
+        flags |= Font::kFakeBold;
+    }
+    mCurrentFont = Font::create(this, fontId, fontSize, flags);
 
     const float maxPrecacheFontSize = 40.0f;
     bool isNewFont = currentNumFonts != mActiveFonts.size();
@@ -720,7 +724,7 @@
     // The larger the radius gets, the more our gaussian blur
     // will resemble a box blur since with large sigma
     // the gaussian curve begins to lose its shape
-    float sigma = 0.3f * (float)radius + 0.6f;
+    float sigma = 0.3f * (float) radius + 0.6f;
 
     // Now compute the coefficints
     // We will store some redundant values to save some math during
@@ -730,7 +734,7 @@
     float coeff2 = - 1.0f / (2.0f * sigma * sigma);
 
     float normalizeFactor = 0.0f;
-    for(int32_t r = -radius; r <= radius; r ++) {
+    for (int32_t r = -radius; r <= radius; r ++) {
         float floatR = (float) r;
         weights[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
         normalizeFactor += weights[r + radius];
@@ -738,7 +742,7 @@
 
     //Now we need to normalize the weights because all our coefficients need to add up to one
     normalizeFactor = 1.0f / normalizeFactor;
-    for(int32_t r = -radius; r <= radius; r ++) {
+    for (int32_t r = -radius; r <= radius; r ++) {
         weights[r + radius] *= normalizeFactor;
     }
 }
@@ -748,35 +752,35 @@
     float blurredPixel = 0.0f;
     float currentPixel = 0.0f;
 
-    for(int32_t y = 0; y < height; y ++) {
+    for (int32_t y = 0; y < height; y ++) {
 
         const uint8_t* input = source + y * width;
         uint8_t* output = dest + y * width;
 
-        for(int32_t x = 0; x < width; x ++) {
+        for (int32_t x = 0; x < width; x ++) {
             blurredPixel = 0.0f;
             const float* gPtr = weights;
             // Optimization for non-border pixels
-            if ((x > radius) && (x < (width - radius))) {
+            if (x > radius && x < (width - radius)) {
                 const uint8_t *i = input + (x - radius);
-                for(int r = -radius; r <= radius; r ++) {
+                for (int r = -radius; r <= radius; r ++) {
                     currentPixel = (float) (*i);
                     blurredPixel += currentPixel * gPtr[0];
                     gPtr++;
                     i++;
                 }
             } else {
-                for(int32_t r = -radius; r <= radius; r ++) {
+                for (int32_t r = -radius; r <= radius; r ++) {
                     // Stepping left and right away from the pixel
                     int validW = x + r;
-                    if(validW < 0) {
+                    if (validW < 0) {
                         validW = 0;
                     }
-                    if(validW > width - 1) {
+                    if (validW > width - 1) {
                         validW = width - 1;
                     }
 
-                    currentPixel = (float)(input[validW]);
+                    currentPixel = (float) input[validW];
                     blurredPixel += currentPixel * gPtr[0];
                     gPtr++;
                 }
@@ -792,41 +796,41 @@
     float blurredPixel = 0.0f;
     float currentPixel = 0.0f;
 
-    for(int32_t y = 0; y < height; y ++) {
+    for (int32_t y = 0; y < height; y ++) {
 
         uint8_t* output = dest + y * width;
 
-        for(int32_t x = 0; x < width; x ++) {
+        for (int32_t x = 0; x < width; x ++) {
             blurredPixel = 0.0f;
             const float* gPtr = weights;
             const uint8_t* input = source + x;
             // Optimization for non-border pixels
-            if ((y > radius) && (y < (height - radius))) {
+            if (y > radius && y < (height - radius)) {
                 const uint8_t *i = input + ((y - radius) * width);
-                for(int32_t r = -radius; r <= radius; r ++) {
+                for (int32_t r = -radius; r <= radius; r ++) {
                     currentPixel = (float)(*i);
                     blurredPixel += currentPixel * gPtr[0];
                     gPtr++;
                     i += width;
                 }
             } else {
-                for(int32_t r = -radius; r <= radius; r ++) {
+                for (int32_t r = -radius; r <= radius; r ++) {
                     int validH = y + r;
                     // Clamp to zero and width
-                    if(validH < 0) {
+                    if (validH < 0) {
                         validH = 0;
                     }
-                    if(validH > height - 1) {
+                    if (validH > height - 1) {
                         validH = height - 1;
                     }
 
                     const uint8_t *i = input + validH * width;
-                    currentPixel = (float)(*i);
+                    currentPixel = (float) (*i);
                     blurredPixel += currentPixel * gPtr[0];
                     gPtr++;
                 }
             }
-            *output = (uint8_t)blurredPixel;
+            *output = (uint8_t) blurredPixel;
             output ++;
         }
     }
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 7e749ca..40572c6 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -41,6 +41,10 @@
  */
 class Font {
 public:
+    enum Style {
+        kFakeBold
+    };
+
     ~Font();
 
     /**
@@ -53,7 +57,7 @@
     /**
      * Creates a new font associated with the specified font state.
      */
-    static Font* create(FontRenderer* state, uint32_t fontId, float fontSize);
+    static Font* create(FontRenderer* state, uint32_t fontId, float fontSize, int flags);
 
 protected:
     friend class FontRenderer;
@@ -99,7 +103,7 @@
         SkFixed mRsbDelta;
     };
 
-    Font(FontRenderer* state, uint32_t fontId, float fontSize);
+    Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags);
 
     DefaultKeyedVector<int32_t, CachedGlyphInfo*> mCachedGlyphs;
 
@@ -117,6 +121,7 @@
     FontRenderer* mState;
     uint32_t mFontId;
     float mFontSize;
+    int mFlags;
 };
 
 class FontRenderer {
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index a780183..7d54d3b 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -26,6 +26,7 @@
 #include <SkXfermode.h>
 
 #include "Rect.h"
+#include "SkiaColorFilter.h"
 
 namespace android {
 namespace uirenderer {
@@ -93,6 +94,11 @@
      * have been drawn.
      */
     Region region;
+
+    /**
+     * Color filter used to draw this layer. Optional.
+     */
+    SkiaColorFilter* colorFilter;
 }; // struct Layer
 
 }; // namespace uirenderer
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 9ce0359..ec186a4 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -102,6 +102,7 @@
         layer->blend = true;
         layer->empty = true;
         layer->fbo = 0;
+        layer->colorFilter = NULL;
 
         glGenTextures(1, &layer->texture);
         glBindTexture(GL_TEXTURE_2D, layer->texture);
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
new file mode 100644
index 0000000..a25c95e
--- /dev/null
+++ b/libs/hwui/LayerRenderer.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include "LayerRenderer.h"
+#include "Properties.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Rendering
+///////////////////////////////////////////////////////////////////////////////
+
+void LayerRenderer::prepare(bool opaque) {
+    LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo);
+
+    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &mPreviousFbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo);
+
+    OpenGLRenderer::prepare(opaque);
+}
+
+void LayerRenderer::finish() {
+    OpenGLRenderer::finish();
+    glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFbo);
+
+    LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->mFbo);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Static functions
+///////////////////////////////////////////////////////////////////////////////
+
+Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
+    LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height);
+
+    Layer* layer = new Layer(width, height);
+
+    GLuint previousFbo;
+    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
+
+    glGenFramebuffers(1, &layer->fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
+
+    if (glGetError() != GL_NO_ERROR) {
+        glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+        glDeleteBuffers(1, &layer->fbo);
+        return 0;
+    }
+
+    glActiveTexture(GL_TEXTURE0);
+    glGenTextures(1, &layer->texture);
+    glBindTexture(GL_TEXTURE_2D, layer->texture);
+
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
+            GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+    if (glGetError() != GL_NO_ERROR) {
+        glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+        glDeleteBuffers(1, &layer->fbo);
+        glDeleteTextures(1, &layer->texture);
+        delete layer;
+        return 0;
+    }
+
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+            layer->texture, 0);
+
+    if (glGetError() != GL_NO_ERROR) {
+        glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+        glDeleteBuffers(1, &layer->fbo);
+        glDeleteTextures(1, &layer->texture);
+        delete layer;
+        return 0;
+    }
+
+    glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+
+    layer->layer.set(0.0f, 0.0f, width, height);
+    layer->texCoords.set(0.0f, 1.0f, 1.0f, 0.0f);
+    layer->alpha = 255;
+    layer->mode = SkXfermode::kSrcOver_Mode;
+    layer->blend = !isOpaque;
+    layer->empty = false;
+    layer->colorFilter = NULL;
+
+    return layer;
+}
+
+bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
+    if (layer) {
+        LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->fbo, width, height);
+
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, layer->texture);
+
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
+                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+        if (glGetError() != GL_NO_ERROR) {
+            glDeleteBuffers(1, &layer->fbo);
+            glDeleteTextures(1, &layer->texture);
+
+            layer->width = 0;
+            layer->height = 0;
+            layer->fbo = 0;
+            layer->texture = 0;
+
+            return false;
+        }
+
+        layer->width = width;
+        layer->height = height;
+    }
+    return true;
+}
+
+void LayerRenderer::destroyLayer(Layer* layer) {
+    if (layer) {
+        LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo);
+
+        if (layer->fbo) glDeleteFramebuffers(1, &layer->fbo);
+        if (layer->texture) glDeleteTextures(1, &layer->texture);
+
+        delete layer;
+    }
+}
+
+void LayerRenderer::destroyLayerDeferred(Layer* layer) {
+    if (layer) {
+        LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->fbo);
+
+        Caches::getInstance().deleteLayerDeferred(layer);
+    }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
new file mode 100644
index 0000000..ed5d960
--- /dev/null
+++ b/libs/hwui/LayerRenderer.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_LAYER_RENDERER_H
+#define ANDROID_HWUI_LAYER_RENDERER_H
+
+#include "OpenGLRenderer.h"
+#include "Layer.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+// Debug
+#if DEBUG_LAYER_RENDERER
+    #define LAYER_RENDERER_LOGD(...) LOGD(__VA_ARGS__)
+#else
+    #define LAYER_RENDERER_LOGD(...)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Renderer
+///////////////////////////////////////////////////////////////////////////////
+
+class LayerRenderer: public OpenGLRenderer {
+public:
+    LayerRenderer(Layer* layer): mLayer(layer) {
+    }
+
+    ~LayerRenderer() {
+    }
+
+    void prepare(bool opaque);
+    void finish();
+
+    static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false);
+    static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
+    static void destroyLayer(Layer* layer);
+    static void destroyLayerDeferred(Layer* layer);
+
+private:
+    Layer* mLayer;
+    GLuint mPreviousFbo;
+
+}; // class LayerRenderer
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_LAYER_RENDERER_H
diff --git a/libs/hwui/OpenGLDebugRenderer.cpp b/libs/hwui/OpenGLDebugRenderer.cpp
index 1cf3d20..29bcde8 100644
--- a/libs/hwui/OpenGLDebugRenderer.cpp
+++ b/libs/hwui/OpenGLDebugRenderer.cpp
@@ -48,12 +48,18 @@
     return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags);
 }
 
-void OpenGLDebugRenderer::drawDisplayList(DisplayList* displayList) {
+void OpenGLDebugRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
     mPrimitivesCount++;
     StopWatch w("drawDisplayList");
     OpenGLRenderer::drawDisplayList(displayList);
 }
 
+void OpenGLDebugRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
+    mPrimitivesCount++;
+    StopWatch w("drawLayer");
+    OpenGLRenderer::drawLayer(layer, x, y, paint);
+}
+
 void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
         SkPaint* paint) {
     mPrimitivesCount++;
diff --git a/libs/hwui/OpenGLDebugRenderer.h b/libs/hwui/OpenGLDebugRenderer.h
index ee34d73..aefa7bf 100644
--- a/libs/hwui/OpenGLDebugRenderer.h
+++ b/libs/hwui/OpenGLDebugRenderer.h
@@ -40,7 +40,8 @@
     int saveLayer(float left, float top, float right, float bottom,
             SkPaint* p, int flags);
 
-    void drawDisplayList(DisplayList* displayList);
+    void drawDisplayList(DisplayList* displayList, uint32_t level = 0);
+    void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 4cca0c8..b933232 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -61,42 +61,42 @@
 // In this array, the index of each Blender equals the value of the first
 // entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
 static const Blender gBlends[] = {
-        { SkXfermode::kClear_Mode,   GL_ZERO,                 GL_ZERO },
-        { SkXfermode::kSrc_Mode,     GL_ONE,                  GL_ZERO },
-        { SkXfermode::kDst_Mode,     GL_ZERO,                 GL_ONE },
-        { SkXfermode::kSrcOver_Mode, GL_ONE,                  GL_ONE_MINUS_SRC_ALPHA },
-        { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA,  GL_ONE },
-        { SkXfermode::kSrcIn_Mode,   GL_DST_ALPHA,            GL_ZERO },
-        { SkXfermode::kDstIn_Mode,   GL_ZERO,                 GL_SRC_ALPHA },
-        { SkXfermode::kSrcOut_Mode,  GL_ONE_MINUS_DST_ALPHA,  GL_ZERO },
-        { SkXfermode::kDstOut_Mode,  GL_ZERO,                 GL_ONE_MINUS_SRC_ALPHA },
-        { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA,            GL_ONE_MINUS_SRC_ALPHA },
-        { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA,  GL_SRC_ALPHA },
-        { SkXfermode::kXor_Mode,     GL_ONE_MINUS_DST_ALPHA,  GL_ONE_MINUS_SRC_ALPHA }
+    { SkXfermode::kClear_Mode,   GL_ZERO,                 GL_ZERO },
+    { SkXfermode::kSrc_Mode,     GL_ONE,                  GL_ZERO },
+    { SkXfermode::kDst_Mode,     GL_ZERO,                 GL_ONE },
+    { SkXfermode::kSrcOver_Mode, GL_ONE,                  GL_ONE_MINUS_SRC_ALPHA },
+    { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA,  GL_ONE },
+    { SkXfermode::kSrcIn_Mode,   GL_DST_ALPHA,            GL_ZERO },
+    { SkXfermode::kDstIn_Mode,   GL_ZERO,                 GL_SRC_ALPHA },
+    { SkXfermode::kSrcOut_Mode,  GL_ONE_MINUS_DST_ALPHA,  GL_ZERO },
+    { SkXfermode::kDstOut_Mode,  GL_ZERO,                 GL_ONE_MINUS_SRC_ALPHA },
+    { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA,            GL_ONE_MINUS_SRC_ALPHA },
+    { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA,  GL_SRC_ALPHA },
+    { SkXfermode::kXor_Mode,     GL_ONE_MINUS_DST_ALPHA,  GL_ONE_MINUS_SRC_ALPHA }
 };
 
 // This array contains the swapped version of each SkXfermode. For instance
 // this array's SrcOver blending mode is actually DstOver. You can refer to
 // createLayer() for more information on the purpose of this array.
 static const Blender gBlendsSwap[] = {
-        { SkXfermode::kClear_Mode,   GL_ZERO,                 GL_ZERO },
-        { SkXfermode::kSrc_Mode,     GL_ZERO,                 GL_ONE },
-        { SkXfermode::kDst_Mode,     GL_ONE,                  GL_ZERO },
-        { SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA,  GL_ONE },
-        { SkXfermode::kDstOver_Mode, GL_ONE,                  GL_ONE_MINUS_SRC_ALPHA },
-        { SkXfermode::kSrcIn_Mode,   GL_ZERO,                 GL_SRC_ALPHA },
-        { SkXfermode::kDstIn_Mode,   GL_DST_ALPHA,            GL_ZERO },
-        { SkXfermode::kSrcOut_Mode,  GL_ZERO,                 GL_ONE_MINUS_SRC_ALPHA },
-        { SkXfermode::kDstOut_Mode,  GL_ONE_MINUS_DST_ALPHA,  GL_ZERO },
-        { SkXfermode::kSrcATop_Mode, GL_ONE_MINUS_DST_ALPHA,  GL_SRC_ALPHA },
-        { SkXfermode::kDstATop_Mode, GL_DST_ALPHA,            GL_ONE_MINUS_SRC_ALPHA },
-        { SkXfermode::kXor_Mode,     GL_ONE_MINUS_DST_ALPHA,  GL_ONE_MINUS_SRC_ALPHA }
+    { SkXfermode::kClear_Mode,   GL_ZERO,                 GL_ZERO },
+    { SkXfermode::kSrc_Mode,     GL_ZERO,                 GL_ONE },
+    { SkXfermode::kDst_Mode,     GL_ONE,                  GL_ZERO },
+    { SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA,  GL_ONE },
+    { SkXfermode::kDstOver_Mode, GL_ONE,                  GL_ONE_MINUS_SRC_ALPHA },
+    { SkXfermode::kSrcIn_Mode,   GL_ZERO,                 GL_SRC_ALPHA },
+    { SkXfermode::kDstIn_Mode,   GL_DST_ALPHA,            GL_ZERO },
+    { SkXfermode::kSrcOut_Mode,  GL_ZERO,                 GL_ONE_MINUS_SRC_ALPHA },
+    { SkXfermode::kDstOut_Mode,  GL_ONE_MINUS_DST_ALPHA,  GL_ZERO },
+    { SkXfermode::kSrcATop_Mode, GL_ONE_MINUS_DST_ALPHA,  GL_SRC_ALPHA },
+    { SkXfermode::kDstATop_Mode, GL_DST_ALPHA,            GL_ONE_MINUS_SRC_ALPHA },
+    { SkXfermode::kXor_Mode,     GL_ONE_MINUS_DST_ALPHA,  GL_ONE_MINUS_SRC_ALPHA }
 };
 
 static const GLenum gTextureUnits[] = {
-        GL_TEXTURE0,
-        GL_TEXTURE1,
-        GL_TEXTURE2
+    GL_TEXTURE0,
+    GL_TEXTURE1,
+    GL_TEXTURE2
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -162,6 +162,11 @@
     GLenum status = GL_NO_ERROR;
     while ((status = glGetError()) != GL_NO_ERROR) {
         LOGD("GL error from OpenGLRenderer: 0x%x", status);
+        switch (status) {
+            case GL_OUT_OF_MEMORY:
+                LOGE("  OpenGLRenderer is out of memory!");
+                break;
+        }
     }
 #endif
 #if DEBUG_MEMORY_USAGE
@@ -173,7 +178,7 @@
 #endif
 }
 
-void OpenGLRenderer::acquireContext() {
+void OpenGLRenderer::interrupt() {
     if (mCaches.currentProgram) {
         if (mCaches.currentProgram->isInUse()) {
             mCaches.currentProgram->remove();
@@ -183,7 +188,11 @@
     mCaches.unbindMeshBuffer();
 }
 
-void OpenGLRenderer::releaseContext() {
+void OpenGLRenderer::acquireContext() {
+    interrupt();
+}
+
+void OpenGLRenderer::resume() {
     glViewport(0, 0, mSnapshot->viewport.getWidth(), mSnapshot->viewport.getHeight());
 
     glEnable(GL_SCISSOR_TEST);
@@ -200,6 +209,10 @@
     glBlendEquation(GL_FUNC_ADD);
 }
 
+void OpenGLRenderer::releaseContext() {
+    resume();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // State management
 ///////////////////////////////////////////////////////////////////////////////
@@ -406,6 +419,7 @@
     layer->layer.set(bounds);
     layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->height),
             bounds.getWidth() / float(layer->width), 0.0f);
+    layer->colorFilter = mColorFilter;
 
     // Save the layer in the snapshot
     snapshot->flags |= Snapshot::kFlagIsLayer;
@@ -459,7 +473,6 @@
     snapshot->flags |= Snapshot::kFlagIsFboLayer;
     snapshot->fbo = layer->fbo;
     snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
-    //snapshot->resetClip(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
     snapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
     snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
     snapshot->height = bounds.getHeight();
@@ -544,7 +557,13 @@
     // drawing only the dirty region
     if (fboLayer) {
         dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *previous->transform);
+        if (layer->colorFilter) {
+            setupColorFilter(layer->colorFilter);
+        }
         composeLayerRegion(layer, rect);
+        if (layer->colorFilter) {
+            resetColorFilter();
+        }
     } else {
         dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
         composeLayerRect(layer, rect, true);
@@ -593,43 +612,25 @@
         size_t count;
         const android::Rect* rects = layer->region.getArray(&count);
 
-        setupDraw();
-
-        ProgramDescription description;
-        description.hasTexture = true;
-
         const float alpha = layer->alpha / 255.0f;
-        const bool setColor = description.setColor(alpha, alpha, alpha, alpha);
-        chooseBlending(layer->blend || layer->alpha < 255, layer->mode, description, false);
-
-        useProgram(mCaches.programCache.get(description));
-
-        // Texture
-        bindTexture(layer->texture);
-        glUniform1i(mCaches.currentProgram->getUniform("sampler"), 0);
-
-        // Always premultiplied
-        if (setColor) {
-            mCaches.currentProgram->setColor(alpha, alpha, alpha, alpha);
-        }
-
-        // Mesh
-        int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
-        glEnableVertexAttribArray(texCoordsSlot);
-
-        mModelView.loadIdentity();
-        mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
-
         const float texX = 1.0f / float(layer->width);
         const float texY = 1.0f / float(layer->height);
 
         TextureVertex* mesh = mCaches.getRegionMesh();
         GLsizei numQuads = 0;
 
-        glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
-                gMeshStride, &mesh[0].position[0]);
-        glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE,
-                gMeshStride, &mesh[0].texture[0]);
+        setupDraw();
+        setupDrawWithTexture();
+        setupDrawColor(alpha, alpha, alpha, alpha);
+        setupDrawColorFilter();
+        setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false);
+        setupDrawProgram();
+        setupDrawDirtyRegionsDisabled();
+        setupDrawPureColorUniforms();
+        setupDrawColorFilterUniforms();
+        setupDrawTexture(layer->texture);
+        setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom);
+        setupDrawMesh(&mesh[0].position[0], &mesh[0].texture[0]);
 
         for (size_t i = 0; i < count; i++) {
             const android::Rect* r = &rects[i];
@@ -659,7 +660,7 @@
         }
 
         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-        glDisableVertexAttribArray(texCoordsSlot);
+        finishDrawTexture();
 
 #if DEBUG_LAYERS_AS_REGIONS
         uint32_t colors[] = {
@@ -696,13 +697,7 @@
     if ((mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region) {
         Rect bounds(left, top, right, bottom);
         transform.mapRect(bounds);
-        bounds.intersect(*mSnapshot->clipRect);
-        bounds.snapToPixelBoundaries();
-
-        android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
-        if (!dirty.isEmpty()) {
-            mSnapshot->region->orSelf(dirty);
-        }
+        dirtyLayerUnchecked(bounds, mSnapshot->region);
     }
 #endif
 }
@@ -712,12 +707,18 @@
 #if RENDER_LAYERS_AS_REGIONS
     if ((mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region) {
         Rect bounds(left, top, right, bottom);
-        bounds.intersect(*mSnapshot->clipRect);
-        bounds.snapToPixelBoundaries();
+        dirtyLayerUnchecked(bounds, mSnapshot->region);
+    }
+#endif
+}
 
+void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) {
+#if RENDER_LAYERS_AS_REGIONS
+    if (bounds.intersect(*mSnapshot->clipRect)) {
+        bounds.snapToPixelBoundaries();
         android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
         if (!dirty.isEmpty()) {
-            mSnapshot->region->orSelf(dirty);
+            region->orSelf(dirty);
         }
     }
 #endif
@@ -1023,11 +1024,11 @@
 // Drawing
 ///////////////////////////////////////////////////////////////////////////////
 
-void OpenGLRenderer::drawDisplayList(DisplayList* displayList) {
+void OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
     // All the usual checks and setup operations (quickReject, setupDraw, etc.)
     // will be performed by the display list itself
     if (displayList) {
-        displayList->replay(*this);
+        displayList->replay(*this, level);
     }
 }
 
@@ -1175,7 +1176,6 @@
 }
 
 void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
-    // TODO: Should do quickReject for each line
     if (mSnapshot->isIgnored()) return;
 
     const bool isAA = paint->isAntiAlias();
@@ -1189,6 +1189,7 @@
     getAlphaAndMode(paint, &alpha, &mode);
 
     int verticesCount = count >> 2;
+    int generatedVerticesCount = 0;
     if (!isHairLine) {
         // TODO: AA needs more vertices
         verticesCount *= 6;
@@ -1235,31 +1236,55 @@
             vec2 p3 = b + n;
             vec2 p4 = b - n;
 
-            // Draw the line as 2 triangles, could be optimized
-            // by using only 4 vertices and the correct indices
-            // Also we should probably used non textured vertices
-            // when line AA is disabled to save on bandwidth
-            TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
-            TextureVertex::set(vertex++, p2.x, p2.y, 0.0f, 0.0f);
-            TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
-            TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
-            TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
-            TextureVertex::set(vertex++, p4.x, p4.y, 0.0f, 0.0f);
+            const float left = fmin(p1.x, fmin(p2.x, fmin(p3.x, p4.x)));
+            const float right = fmax(p1.x, fmax(p2.x, fmax(p3.x, p4.x)));
+            const float top = fmin(p1.y, fmin(p2.y, fmin(p3.y, p4.y)));
+            const float bottom = fmax(p1.y, fmax(p2.y, fmax(p3.y, p4.y)));
 
-            // TODO: Mark the dirty regions when RENDER_LAYERS_AS_REGIONS is set
+            if (!quickReject(left, top, right, bottom)) {
+                // Draw the line as 2 triangles, could be optimized
+                // by using only 4 vertices and the correct indices
+                // Also we should probably used non textured vertices
+                // when line AA is disabled to save on bandwidth
+                TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
+                TextureVertex::set(vertex++, p2.x, p2.y, 0.0f, 0.0f);
+                TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
+                TextureVertex::set(vertex++, p1.x, p1.y, 0.0f, 0.0f);
+                TextureVertex::set(vertex++, p3.x, p3.y, 0.0f, 0.0f);
+                TextureVertex::set(vertex++, p4.x, p4.y, 0.0f, 0.0f);
+
+                generatedVerticesCount += 6;
+
+                dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+            }
         }
 
-        // GL_LINE does not give the result we want to match Skia
-        glDrawArrays(GL_TRIANGLES, 0, verticesCount);
+        if (generatedVerticesCount > 0) {
+            // GL_LINE does not give the result we want to match Skia
+            glDrawArrays(GL_TRIANGLES, 0, generatedVerticesCount);
+        }
     } else {
         // TODO: Handle the AA case
         for (int i = 0; i < count; i += 4) {
-            TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
-            TextureVertex::set(vertex++, points[i + 2], points[i + 3], 0.0f, 0.0f);
+            const float left = fmin(points[i], points[i + 1]);
+            const float right = fmax(points[i], points[i + 1]);
+            const float top = fmin(points[i + 2], points[i + 3]);
+            const float bottom = fmax(points[i + 2], points[i + 3]);
+
+            if (!quickReject(left, top, right, bottom)) {
+                TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
+                TextureVertex::set(vertex++, points[i + 2], points[i + 3], 0.0f, 0.0f);
+
+                generatedVerticesCount += 2;
+
+                dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
+            }
         }
 
-        glLineWidth(1.0f);
-        glDrawArrays(GL_LINES, 0, verticesCount);
+        if (generatedVerticesCount > 0) {
+            glLineWidth(1.0f);
+            glDrawArrays(GL_LINES, 0, generatedVerticesCount);
+        }
     }
 }
 
@@ -1301,7 +1326,7 @@
 
 void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
         float x, float y, SkPaint* paint) {
-    if (text == NULL || count == 0 || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) {
+    if (text == NULL || count == 0) {
         return;
     }
     if (mSnapshot->isIgnored()) return;
@@ -1365,6 +1390,10 @@
         finishDrawTexture();
     }
 
+    if (paint->getAlpha() == 0 && paint->getXfermode() == NULL) {
+        return;
+    }
+
     // Pick the appropriate texture filtering
     bool linearFilter = mSnapshot->transform->changesBounds();
     if (pureTranslate && !linearFilter) {
@@ -1458,6 +1487,24 @@
     finishDrawTexture();
 }
 
+void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
+    if (!layer || quickReject(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight())) {
+        return;
+    }
+
+    glActiveTexture(gTextureUnits[0]);
+
+    int alpha;
+    SkXfermode::Mode mode;
+    getAlphaAndMode(paint, &alpha, &mode);
+
+    layer->alpha = alpha;
+    layer->mode = mode;
+
+    const Rect r(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight());
+    composeLayerRect(layer, r);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Shaders
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 8f93f5b..56be134 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -64,6 +64,10 @@
     virtual void prepare(bool opaque);
     virtual void finish();
 
+    // These two calls must not be recorded in display lists
+    void interrupt();
+    void resume();
+
     virtual void acquireContext();
     virtual void releaseContext();
 
@@ -90,7 +94,8 @@
     bool quickReject(float left, float top, float right, float bottom);
     virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
 
-    virtual void drawDisplayList(DisplayList* displayList);
+    virtual void drawDisplayList(DisplayList* displayList, uint32_t level = 0);
+    virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
@@ -127,6 +132,21 @@
      */
     virtual void composeLayer(sp<Snapshot> current, sp<Snapshot> previous);
 
+    /**
+     * Mark the layer as dirty at the specified coordinates. The coordinates
+     * are transformed with the supplied matrix.
+     */
+    virtual void dirtyLayer(const float left, const float top,
+            const float right, const float bottom, const mat4 transform);
+
+    /**
+     * Mark the layer as dirty at the specified coordinates.
+     */
+    virtual void dirtyLayer(const float left, const float top,
+            const float right, const float bottom);
+
+    void dirtyLayerUnchecked(Rect& bounds, Region* region);
+
 private:
     /**
      * Saves the current state of the renderer as a new snapshot.
@@ -396,18 +416,6 @@
         mDirtyClip = true;
     }
 
-    /**
-     * Mark the layer as dirty at the specified coordinates. The coordinates
-     * are transformed with the supplied matrix.
-     */
-    void dirtyLayer(const float left, const float top, const float right, const float bottom,
-            const mat4 transform);
-
-    /**
-     * Mark the layer as dirty at the specified coordinates.
-     */
-    void dirtyLayer(const float left, const float top, const float right, const float bottom);
-
     // Dimensions of the drawing surface
     int mWidth, mHeight;
 
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 8740a64..3184598 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -197,10 +197,16 @@
     bitmap.eraseColor(0);
 
     SkPaint pathPaint(*paint);
-    if (!pathPaint.getXfermode()) {
-        SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
-        pathPaint.setXfermode(mode)->safeUnref();
-    }
+
+    // Make sure the paint is opaque, color, alpha, filter, etc.
+    // will be applied later when compositing the alpha8 texture
+    pathPaint.setColor(0xff000000);
+    pathPaint.setAlpha(255);
+    pathPaint.setColorFilter(NULL);
+    pathPaint.setMaskFilter(NULL);
+    pathPaint.setShader(NULL);
+    SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
+    pathPaint.setXfermode(mode)->safeUnref();
 
     SkCanvas canvas(bitmap);
     canvas.translate(-bounds.fLeft + offset, -bounds.fTop + offset);
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index c474936..6a0d7ea 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -26,7 +26,7 @@
  */
 
 // If turned on, layers drawn inside FBOs are optimized with regions
-#define RENDER_LAYERS_AS_REGIONS 0
+#define RENDER_LAYERS_AS_REGIONS 1
 
 /**
  * Debug level for app developers.
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 1c93ea6..70d117a 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -60,21 +60,19 @@
 }
 
 void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
-    SkPixelRef* pixref = bitmapResource->pixelRef();
-    if (pixref) pixref->globalRef();
-
+    bitmapResource->pixelRef()->safeRef();
     bitmapResource->getColorTable()->safeRef();
     incrementRefcount((void*)bitmapResource, kBitmap);
 }
 
 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,21 +89,19 @@
 }
 
 void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
-    SkPixelRef* pixref = bitmapResource->pixelRef();
-    if (pixref) pixref->globalUnref();
-
+    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 590a9d7..8878c70 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -47,10 +47,22 @@
 // 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 @@
     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 @@
     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 @@
     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 @@
     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 @@
 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 6702129..89dd131 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -56,6 +56,9 @@
             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 @@
             const Snapshot& snapshot) {
     }
 
+    uint32_t getGenerationId() {
+        return mGenerationId;
+    }
+
     void setMatrix(SkMatrix* matrix) {
         updateLocalMatrix(matrix);
+        mGenerationId++;
     }
 
     void updateLocalMatrix(const SkMatrix* matrix) {
@@ -97,6 +105,9 @@
     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 @@
 
     mat4 mUnitMatrix;
     mat4 mShaderMatrix;
+
+private:
+    uint32_t mGenerationId;
 }; // struct SkiaShader
 
 
@@ -127,6 +141,7 @@
 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 @@
     void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
 
 private:
+    SkiaBitmapShader() {
+    }
+
     /**
      * This method does not work for n == 0.
      */
@@ -154,6 +172,7 @@
     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 @@
     void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
 
 private:
+    SkiaLinearGradientShader() {
+    }
+
     float* mBounds;
     uint32_t* mColors;
     float* mPositions;
@@ -174,6 +196,7 @@
     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 @@
 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 @@
 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 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 @@
             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/libs/rs/Android.mk b/libs/rs/Android.mk
index 2ec003f..3835852 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -23,13 +23,17 @@
 # TODO: This should go into build/core/config.mk
 RSG_GENERATOR:=$(LOCAL_BUILT_MODULE)
 
-include $(CLEAR_VARS)
-input_data_file := $(LOCAL_PATH)/rslib.bc
-slangdata_output_var_name := rs_runtime_lib_bc
-LOCAL_MODULE := librslib_rt
-LOCAL_MODULE_TAGS := optional
-include frameworks/compile/slang/SlangData.mk
-include $(BUILD_STATIC_LIBRARY)
+# include $(CLEAR_VARS)
+# input_data_file := $(LOCAL_PATH)/rslib.bc
+# slangdata_output_var_name := rs_runtime_lib_bc
+# LOCAL_MODULE := librslib_rt
+
+# LOCAL_PRELINK_MODULE := false
+# LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+
+# LOCAL_MODULE_TAGS := optional
+# include frameworks/compile/slang/SlangData.mk
+# include $(BUILD_STATIC_LIBRARY)
 
 # Build render script lib ====================
 
@@ -113,11 +117,12 @@
 	rsVertexArray.cpp
 
 
-LOCAL_SHARED_LIBRARIES += libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc
+LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc
 
-LOCAL_STATIC_LIBRARIES := libft2 librslib_rt
+LOCAL_STATIC_LIBRARIES := libdex libft2
 
-LOCAL_C_INCLUDES += external/freetype/include
+LOCAL_C_INCLUDES += external/freetype/include external/zlib dalvik
+LOCAL_C_INCLUDES += frameworks/compile/libbcc/include
 
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libRS
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 3ad453f..f160ef1 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -111,6 +111,15 @@
     RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE = 2
 };
 
+enum RsAllocationCubemapFace {
+    RS_ALLOCATION_CUBMAP_FACE_POSITVE_X = 0,
+    RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_X = 1,
+    RS_ALLOCATION_CUBMAP_FACE_POSITVE_Y = 2,
+    RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_Y = 3,
+    RS_ALLOCATION_CUBMAP_FACE_POSITVE_Z = 4,
+    RS_ALLOCATION_CUBMAP_FACE_NEGATIVE_Z = 5
+};
+
 enum RsDataType {
     RS_TYPE_NONE,
     RS_TYPE_FLOAT_16,
@@ -325,7 +334,9 @@
 // A3D loading and object update code.
 // Should only be called at object creation, not thread safe
 RsObjectBase rsaFileA3DGetEntryByIndex(RsContext, uint32_t idx, RsFile);
-RsFile rsaFileA3DCreateFromAssetStream(RsContext, const void *data, uint32_t len);
+RsFile rsaFileA3DCreateFromMemory(RsContext, const void *data, uint32_t len);
+RsFile rsaFileA3DCreateFromAsset(RsContext, void *asset);
+RsFile rsaFileA3DCreateFromFile(RsContext, const char *path);
 void rsaFileA3DGetNumIndexEntries(RsContext, int32_t *numEntries, RsFile);
 void rsaFileA3DGetIndexEntries(RsContext, RsFileIndexEntry *fileEntries,uint32_t numEntries, RsFile);
 void rsaGetName(RsContext, void * obj, const char **name);
diff --git a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
index 0a06394..50ee921 100644
--- a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
+++ b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
@@ -50,7 +50,7 @@
     private void createProgramVertex() {
         updateProjectionMatrices();
 
-        ProgramVertex.ShaderBuilder sb = new ProgramVertex.ShaderBuilder(mRS);
+        ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);
         String t =  "varying vec4 varColor;\n" +
                     "void main() {\n" +
                     "  vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n" +
@@ -75,18 +75,27 @@
         return allocation;
     }
 
+    ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) {
+        ProgramStore.Builder builder = new ProgramStore.Builder(rs);
+        builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
+        builder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ONE);
+        builder.setDitherEnabled(false);
+        builder.setDepthMaskEnabled(false);
+        return builder.create();
+    }
+
     public void init(RenderScriptGL rs, Resources res, int width, int height) {
         mRS = rs;
         mRes = res;
 
-        ProgramFragment.Builder pfb = new ProgramFragment.Builder(rs);
+        ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs);
         pfb.setPointSpriteTexCoordinateReplacement(true);
-        pfb.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
-                           ProgramFragment.Builder.Format.RGBA, 0);
+        pfb.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
+                           ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
         pfb.setVaryingColor(true);
         mPFPoints = pfb.create();
 
-        pfb = new ProgramFragment.Builder(rs);
+        pfb = new ProgramFragmentFixedFunction.Builder(rs);
         pfb.setVaryingColor(true);
         mPFLines = pfb.create();
 
@@ -97,7 +106,7 @@
 
         Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
         smb.addVertexAllocation(mPoints.getAllocation());
-        smb.addIndexType(Primitive.POINT);
+        smb.addIndexSetType(Mesh.Primitive.POINT);
         Mesh smP = smb.create();
 
         mPhysicsScript = new ScriptC_ball_physics(mRS, mRes, R.raw.ball_physics);
@@ -113,7 +122,7 @@
         mScript.set_gPFPoints(mPFPoints);
         createProgramVertex();
 
-        mRS.bindProgramStore(ProgramStore.BLEND_ADD_DEPTH_NO_DEPTH(mRS));
+        mRS.bindProgramStore(BLEND_ADD_DEPTH_NONE(mRS));
 
         mPhysicsScript.set_gMinPos(new Float2(5, 5));
         mPhysicsScript.set_gMaxPos(new Float2(width - 5, height - 5));
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
index a5d06e9..be2f9ca 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
@@ -34,7 +34,7 @@
         mRS = rs;
         mRes = res;
 
-        ProgramFragment.Builder pfb = new ProgramFragment.Builder(rs);
+        ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs);
         pfb.setVaryingColor(true);
         rs.bindProgramFragment(pfb.create());
 
@@ -43,7 +43,7 @@
 
         Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
         smb.addVertexAllocation(points.getAllocation());
-        smb.addIndexType(Primitive.POINT);
+        smb.addIndexSetType(Mesh.Primitive.POINT);
         Mesh sm = smb.create();
 
         mScript = new ScriptC_fountain(mRS, mRes, R.raw.fountain);
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
index e5900fd..aa4cf2d 100644
--- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
@@ -55,6 +55,9 @@
     gamma = (float3)g;
 }
 
+//sliao
+uchar3 convert2uchar3(float3 xyz);
+
 void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
     uchar4 *output = (uchar4 *)v_out;
     const FilterStruct *fs = (const FilterStruct *)usrData;
@@ -84,7 +87,7 @@
         temp = pow(temp, (float3)gamma);
     temp = clamp(temp * outWMinOutB + outBlack, 0.f, 255.f);
 
-    output->xyz = convert_uchar3(temp);
+    output->xyz = convert2uchar3(temp);
     //output->w = input->w;
 }
 
diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SceneGraphRS.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SceneGraphRS.java
index 6cb50b8..f91f31e 100644
--- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SceneGraphRS.java
+++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SceneGraphRS.java
@@ -23,6 +23,7 @@
 import android.content.res.Resources;
 import android.renderscript.*;
 import android.renderscript.Element.Builder;
+import android.renderscript.Font.Style;
 import android.renderscript.ProgramStore.DepthFunc;
 import android.util.Log;
 
@@ -53,7 +54,7 @@
     private ProgramStore mPSBackground;
     private ProgramFragment mPFBackground;
     private ProgramVertex mPVBackground;
-    private ProgramVertex.MatrixAllocation mPVA;
+    private ProgramVertexFixedFunction.Constants mPVA;
 
     private Allocation mGridImage;
     private Allocation mAllocPV;
@@ -93,8 +94,8 @@
         ProgramStore.Builder b = new ProgramStore.Builder(mRS);
 
         b.setDepthFunc(ProgramStore.DepthFunc.LESS);
-        b.setDitherEnable(false);
-        b.setDepthMask(true);
+        b.setDitherEnabled(false);
+        b.setDepthMaskEnabled(true);
         mPSBackground = b.create();
 
         mScript.set_gPFSBackground(mPSBackground);
@@ -102,15 +103,15 @@
 
     private void initPF() {
         Sampler.Builder bs = new Sampler.Builder(mRS);
-        bs.setMin(Sampler.Value.LINEAR);
-        bs.setMag(Sampler.Value.LINEAR);
+        bs.setMinification(Sampler.Value.LINEAR);
+        bs.setMagnification(Sampler.Value.LINEAR);
         bs.setWrapS(Sampler.Value.CLAMP);
         bs.setWrapT(Sampler.Value.CLAMP);
         mSampler = bs.create();
 
-        ProgramFragment.Builder b = new ProgramFragment.Builder(mRS);
-        b.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
-                     ProgramFragment.Builder.Format.RGBA, 0);
+        ProgramFragmentFixedFunction.Builder b = new ProgramFragmentFixedFunction.Builder(mRS);
+        b.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+                     ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
         mPFBackground = b.create();
         mPFBackground.bindSampler(mSampler, 0);
 
@@ -118,11 +119,11 @@
     }
 
     private void initPV() {
-        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS);
+        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
         mPVBackground = pvb.create();
 
-        mPVA = new ProgramVertex.MatrixAllocation(mRS);
-        mPVBackground.bindAllocation(mPVA);
+        mPVA = new ProgramVertexFixedFunction.Constants(mRS);
+        ((ProgramVertexFixedFunction)mPVBackground).bindConstants(mPVA);
 
         mScript.set_gPVBackground(mPVBackground);
     }
@@ -186,22 +187,20 @@
 
         FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot);
         FileA3D.IndexEntry entry = model.getIndexEntry(0);
-        if (entry == null || entry.getClassID() != FileA3D.ClassID.MESH) {
+        if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) {
             Log.e("rs", "could not load model");
         } else {
             mMesh = (Mesh)entry.getObject();
             mScript.set_gTestMesh(mMesh);
         }
 
-        mItalic = Font.create(mRS, mRes, "DroidSerif-Italic.ttf", 8);
+        mItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8);
         mScript.set_gItalic(mItalic);
 
         initTextAllocation();
 
         initTransformHierarchy();
 
-        Log.v("========SceneGraph========", "transform hierarchy initialized");
-
         mScript.bind_gRootNode(mRootTransform.getField());
 
         mScript.bind_gGroup(mGroup1.mParent.mChildField);
diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java
index 747463a..b18a327 100644
--- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java
+++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/SimpleModelRS.java
@@ -50,7 +50,7 @@
     private ProgramStore mPSBackground;
     private ProgramFragment mPFBackground;
     private ProgramVertex mPVBackground;
-    private ProgramVertex.MatrixAllocation mPVA;
+    private ProgramVertexFixedFunction.Constants mPVA;
 
     private Allocation mGridImage;
     private Allocation mAllocPV;
@@ -89,8 +89,8 @@
         ProgramStore.Builder b = new ProgramStore.Builder(mRS);
 
         b.setDepthFunc(ProgramStore.DepthFunc.LESS);
-        b.setDitherEnable(false);
-        b.setDepthMask(true);
+        b.setDitherEnabled(false);
+        b.setDepthMaskEnabled(true);
         mPSBackground = b.create();
 
         mScript.set_gPFSBackground(mPSBackground);
@@ -98,15 +98,15 @@
 
     private void initPF() {
         Sampler.Builder bs = new Sampler.Builder(mRS);
-        bs.setMin(Sampler.Value.LINEAR);
-        bs.setMag(Sampler.Value.LINEAR);
+        bs.setMinification(Sampler.Value.LINEAR);
+        bs.setMagnification(Sampler.Value.LINEAR);
         bs.setWrapS(Sampler.Value.CLAMP);
         bs.setWrapT(Sampler.Value.CLAMP);
         mSampler = bs.create();
 
-        ProgramFragment.Builder b = new ProgramFragment.Builder(mRS);
-        b.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
-                     ProgramFragment.Builder.Format.RGBA, 0);
+        ProgramFragmentFixedFunction.Builder b = new ProgramFragmentFixedFunction.Builder(mRS);
+        b.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+                     ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
         mPFBackground = b.create();
         mPFBackground.bindSampler(mSampler, 0);
 
@@ -114,11 +114,11 @@
     }
 
     private void initPV() {
-        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS);
+        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
         mPVBackground = pvb.create();
 
-        mPVA = new ProgramVertex.MatrixAllocation(mRS);
-        mPVBackground.bindAllocation(mPVA);
+        mPVA = new ProgramVertexFixedFunction.Constants(mRS);
+        ((ProgramVertexFixedFunction)mPVBackground).bindConstants(mPVA);
 
         mScript.set_gPVBackground(mPVBackground);
     }
@@ -148,14 +148,14 @@
 
         FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot);
         FileA3D.IndexEntry entry = model.getIndexEntry(0);
-        if (entry == null || entry.getClassID() != FileA3D.ClassID.MESH) {
+        if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) {
             Log.e("rs", "could not load model");
         } else {
             mMesh = (Mesh)entry.getObject();
             mScript.set_gTestMesh(mMesh);
         }
 
-        mItalic = Font.create(mRS, mRes, "DroidSerif-Italic.ttf", 8);
+        mItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8);
         mScript.set_gItalic(mItalic);
 
         initTextAllocation();
diff --git a/libs/rs/java/Samples/res/drawable/cubemap_test.png b/libs/rs/java/Samples/res/drawable/cubemap_test.png
index 75ad0a4..baf35d0 100644
--- a/libs/rs/java/Samples/res/drawable/cubemap_test.png
+++ b/libs/rs/java/Samples/res/drawable/cubemap_test.png
Binary files differ
diff --git a/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java b/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java
index ddb05b3..1afcee3 100644
--- a/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java
+++ b/libs/rs/java/Samples/src/com/android/samples/RsBenchRS.java
@@ -22,10 +22,11 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.renderscript.*;
-import android.renderscript.Allocation.CubemapLayout;
 import android.renderscript.Allocation.MipmapControl;
 import android.renderscript.Program.TextureType;
 import android.renderscript.ProgramStore.DepthFunc;
+import android.renderscript.ProgramStore.BlendSrcFunc;
+import android.renderscript.ProgramStore.BlendDstFunc;
 import android.renderscript.Sampler.Value;
 import android.util.Log;
 
@@ -69,7 +70,7 @@
     private ProgramFragment mProgFragmentColor;
 
     private ProgramVertex mProgVertex;
-    private ProgramVertex.MatrixAllocation mPVA;
+    private ProgramVertexFixedFunction.Constants mPVA;
 
     // Custom shaders
     private ProgramVertex mProgVertexCustom;
@@ -122,6 +123,15 @@
         mScript.set_gDisplayMode(mMode);
     }
 
+    ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) {
+        ProgramStore.Builder builder = new ProgramStore.Builder(rs);
+        builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
+        builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
+        builder.setDitherEnabled(false);
+        builder.setDepthMaskEnabled(false);
+        return builder.create();
+    }
+
     private Mesh getMbyNMesh(float width, float height, int wResolution, int hResolution) {
 
         Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
@@ -155,18 +165,18 @@
     private void initProgramStore() {
         // Use stock the stock program store object
         mProgStoreBlendNoneDepth = ProgramStore.BLEND_NONE_DEPTH_TEST(mRS);
-        mProgStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NO_DEPTH(mRS);
+        mProgStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(mRS);
 
         // Create a custom program store
         ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
         builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
         builder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA,
                              ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-        builder.setDitherEnable(false);
-        builder.setDepthMask(false);
+        builder.setDitherEnabled(false);
+        builder.setDepthMaskEnabled(false);
         mProgStoreBlendAlpha = builder.create();
 
-        mProgStoreBlendAdd = ProgramStore.BLEND_ADD_DEPTH_NO_DEPTH(mRS);
+        mProgStoreBlendAdd = BLEND_ADD_DEPTH_NONE(mRS);
 
         mScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
         mScript.set_gProgStoreBlendNone(mProgStoreBlendNone);
@@ -176,13 +186,13 @@
 
     private void initProgramFragment() {
 
-        ProgramFragment.Builder texBuilder = new ProgramFragment.Builder(mRS);
-        texBuilder.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
-                              ProgramFragment.Builder.Format.RGBA, 0);
+        ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
+        texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+                              ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
         mProgFragmentTexture = texBuilder.create();
         mProgFragmentTexture.bindSampler(mLinearClamp, 0);
 
-        ProgramFragment.Builder colBuilder = new ProgramFragment.Builder(mRS);
+        ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
         colBuilder.setVaryingColor(false);
         mProgFragmentColor = colBuilder.create();
 
@@ -191,12 +201,14 @@
     }
 
     private void initProgramVertex() {
-        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS);
+        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
         mProgVertex = pvb.create();
 
-        mPVA = new ProgramVertex.MatrixAllocation(mRS);
-        mProgVertex.bindAllocation(mPVA);
-        mPVA.setupOrthoWindow(mWidth, mHeight);
+        mPVA = new ProgramVertexFixedFunction.Constants(mRS);
+        ((ProgramVertexFixedFunction)mProgVertex).bindConstants(mPVA);
+        Matrix4f proj = new Matrix4f();
+        proj.loadOrthoWindow(mWidth, mHeight);
+        mPVA.setProjection(proj);
 
         mScript.set_gProgVertex(mProgVertex);
     }
@@ -213,7 +225,7 @@
         mScript.bind_gFSConstPixel(mFSConstPixel);
 
         // Initialize the shader builder
-        ProgramVertex.ShaderBuilder pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
+        ProgramVertex.Builder pvbCustom = new ProgramVertex.Builder(mRS);
         // Specify the resource that contains the shader string
         pvbCustom.setShader(mRes, R.raw.shaderv);
         // Use a script field to specify the input layout
@@ -224,7 +236,7 @@
         // Bind the source of constant data
         mProgVertexCustom.bindConstants(mVSConst.getAllocation(), 0);
 
-        ProgramFragment.ShaderBuilder pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
+        ProgramFragment.Builder pfbCustom = new ProgramFragment.Builder(mRS);
         // Specify the resource that contains the shader string
         pfbCustom.setShader(mRes, R.raw.shaderf);
         // Tell the builder how many textures we have
@@ -236,42 +248,44 @@
         mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 0);
 
         // Cubemap test shaders
-        pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
+        pvbCustom = new ProgramVertex.Builder(mRS);
         pvbCustom.setShader(mRes, R.raw.shadercubev);
         pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
         pvbCustom.addConstant(mVSConst.getAllocation().getType());
         mProgVertexCube = pvbCustom.create();
         mProgVertexCube.bindConstants(mVSConst.getAllocation(), 0);
 
-        pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
+        pfbCustom = new ProgramFragment.Builder(mRS);
         pfbCustom.setShader(mRes, R.raw.shadercubef);
         pfbCustom.addTexture(Program.TextureType.TEXTURE_CUBE);
         mProgFragmentCube = pfbCustom.create();
 
-        pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
+        pvbCustom = new ProgramVertex.Builder(mRS);
         pvbCustom.setShader(mRes, R.raw.shader2v);
         pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
         pvbCustom.addConstant(mVSConstPixel.getAllocation().getType());
         mProgVertexPixelLight = pvbCustom.create();
         mProgVertexPixelLight.bindConstants(mVSConstPixel.getAllocation(), 0);
 
-        pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
+        pvbCustom = new ProgramVertex.Builder(mRS);
         pvbCustom.setShader(mRes, R.raw.shader2movev);
         pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
         pvbCustom.addConstant(mVSConstPixel.getAllocation().getType());
         mProgVertexPixelLightMove = pvbCustom.create();
         mProgVertexPixelLightMove.bindConstants(mVSConstPixel.getAllocation(), 0);
 
-        pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
+        pfbCustom = new ProgramFragment.Builder(mRS);
         pfbCustom.setShader(mRes, R.raw.shader2f);
         pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
         pfbCustom.addConstant(mFSConstPixel.getAllocation().getType());
         mProgFragmentPixelLight = pfbCustom.create();
         mProgFragmentPixelLight.bindConstants(mFSConstPixel.getAllocation(), 0);
 
-        pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
+        pfbCustom = new ProgramFragment.Builder(mRS);
         pfbCustom.setShader(mRes, R.raw.multitexf);
-        pfbCustom.setTextureCount(3);
+        for (int texCount = 0; texCount < 3; texCount ++) {
+            pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+        }
         mProgFragmentMultitex = pfbCustom.create();
 
         mScript.set_gProgVertexCustom(mProgVertexCustom);
@@ -303,8 +317,7 @@
         mTexTransparent = loadTextureARGB(R.drawable.leaf);
         mTexChecker = loadTextureRGB(R.drawable.checker);
         Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.cubemap_test);
-        mTexCube = Allocation.createCubemapFromBitmap(mRS, b,
-                                                      Allocation.CubemapLayout.VERTICAL_FACE_LIST);
+        mTexCube = Allocation.createCubemapFromBitmap(mRS, b);
 
         mScript.set_gTexTorus(mTexTorus);
         mScript.set_gTexOpaque(mTexOpaque);
@@ -315,22 +328,15 @@
 
     private void initFonts() {
         // Sans font by family name
-        mFontSans = Font.createFromFamily(mRS, mRes, "sans-serif",
-                                          Font.Style.NORMAL, 8);
-        // Create font by file name
-        mFontSerif = Font.create(mRS, mRes, "DroidSerif-Regular.ttf", 8);
+        mFontSans = Font.create(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8);
+        mFontSerif = Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8);
         // Create fonts by family and style
-        mFontSerifBold = Font.createFromFamily(mRS, mRes, "serif",
-                                               Font.Style.BOLD, 8);
-        mFontSerifItalic = Font.createFromFamily(mRS, mRes, "serif",
-                                                 Font.Style.ITALIC, 8);
-        mFontSerifBoldItalic = Font.createFromFamily(mRS, mRes, "serif",
-                                                     Font.Style.BOLD_ITALIC, 8);
-        mFontMono = Font.createFromFamily(mRS, mRes, "mono",
-                                          Font.Style.NORMAL, 8);
+        mFontSerifBold = Font.create(mRS, mRes, "serif", Font.Style.BOLD, 8);
+        mFontSerifItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8);
+        mFontSerifBoldItalic = Font.create(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8);
+        mFontMono = Font.create(mRS, mRes, "mono", Font.Style.NORMAL, 8);
 
-        mTextAlloc = Allocation.createFromString(mRS, "String from allocation",
-                                                 Allocation.USAGE_SCRIPT);
+        mTextAlloc = Allocation.createFromString(mRS, "String from allocation", Allocation.USAGE_SCRIPT);
 
         mScript.set_gFontSans(mFontSans);
         mScript.set_gFontSerif(mFontSerif);
@@ -351,7 +357,7 @@
 
         FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.torus);
         FileA3D.IndexEntry entry = model.getIndexEntry(0);
-        if (entry == null || entry.getClassID() != FileA3D.ClassID.MESH) {
+        if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) {
             Log.e("rs", "could not load model");
         } else {
             mTorus = (Mesh)entry.getObject();
@@ -361,8 +367,8 @@
 
     private void initSamplers() {
         Sampler.Builder bs = new Sampler.Builder(mRS);
-        bs.setMin(Sampler.Value.LINEAR);
-        bs.setMag(Sampler.Value.LINEAR);
+        bs.setMinification(Sampler.Value.LINEAR);
+        bs.setMagnification(Sampler.Value.LINEAR);
         bs.setWrapS(Sampler.Value.WRAP);
         bs.setWrapT(Sampler.Value.WRAP);
         mLinearWrap = bs.create();
@@ -372,8 +378,8 @@
         mMipLinearWrap = Sampler.WRAP_LINEAR_MIP_LINEAR(mRS);
 
         bs = new Sampler.Builder(mRS);
-        bs.setMin(Sampler.Value.LINEAR_MIP_LINEAR);
-        bs.setMag(Sampler.Value.LINEAR);
+        bs.setMinification(Sampler.Value.LINEAR_MIP_LINEAR);
+        bs.setMagnification(Sampler.Value.LINEAR);
         bs.setWrapS(Sampler.Value.WRAP);
         bs.setWrapT(Sampler.Value.WRAP);
         bs.setAnisotropy(8.0f);
diff --git a/libs/rs/java/Samples/src/com/android/samples/RsListRS.java b/libs/rs/java/Samples/src/com/android/samples/RsListRS.java
index 223f552..8e2d51f 100644
--- a/libs/rs/java/Samples/src/com/android/samples/RsListRS.java
+++ b/libs/rs/java/Samples/src/com/android/samples/RsListRS.java
@@ -134,7 +134,7 @@
 
         mScript.bind_gList(mListAllocs);
 
-        mItalic = Font.createFromFamily(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8);
+        mItalic = Font.create(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8);
         mScript.set_gItalic(mItalic);
 
         mRS.bindRootScript(mScript);
diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
index 75e8d99..87840a7 100644
--- a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
+++ b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java
@@ -22,9 +22,11 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.renderscript.*;
-import android.renderscript.Allocation.CubemapLayout;
+import android.renderscript.Font.Style;
 import android.renderscript.Program.TextureType;
 import android.renderscript.ProgramStore.DepthFunc;
+import android.renderscript.ProgramStore.BlendSrcFunc;
+import android.renderscript.ProgramStore.BlendDstFunc;
 import android.renderscript.Sampler.Value;
 import android.util.Log;
 
@@ -68,7 +70,7 @@
     private ProgramFragment mProgFragmentColor;
 
     private ProgramVertex mProgVertex;
-    private ProgramVertex.MatrixAllocation mPVA;
+    private ProgramVertexFixedFunction.Constants mPVA;
 
     // Custom shaders
     private ProgramVertex mProgVertexCustom;
@@ -119,6 +121,15 @@
         mScript.set_gDisplayMode(mMode);
     }
 
+    ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) {
+        ProgramStore.Builder builder = new ProgramStore.Builder(rs);
+        builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
+        builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
+        builder.setDitherEnabled(false);
+        builder.setDepthMaskEnabled(false);
+        return builder.create();
+    }
+
     private Mesh getMbyNMesh(float width, float height, int wResolution, int hResolution) {
 
         Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
@@ -152,18 +163,18 @@
     private void initProgramStore() {
         // Use stock the stock program store object
         mProgStoreBlendNoneDepth = ProgramStore.BLEND_NONE_DEPTH_TEST(mRS);
-        mProgStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NO_DEPTH(mRS);
+        mProgStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(mRS);
 
         // Create a custom program store
         ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
         builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
         builder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA,
                              ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-        builder.setDitherEnable(false);
-        builder.setDepthMask(false);
+        builder.setDitherEnabled(false);
+        builder.setDepthMaskEnabled(false);
         mProgStoreBlendAlpha = builder.create();
 
-        mProgStoreBlendAdd = ProgramStore.BLEND_ADD_DEPTH_NO_DEPTH(mRS);
+        mProgStoreBlendAdd = BLEND_ADD_DEPTH_NONE(mRS);
 
         mScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
         mScript.set_gProgStoreBlendNone(mProgStoreBlendNone);
@@ -173,13 +184,13 @@
 
     private void initProgramFragment() {
 
-        ProgramFragment.Builder texBuilder = new ProgramFragment.Builder(mRS);
-        texBuilder.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
-                              ProgramFragment.Builder.Format.RGBA, 0);
+        ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
+        texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+                              ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
         mProgFragmentTexture = texBuilder.create();
         mProgFragmentTexture.bindSampler(mLinearClamp, 0);
 
-        ProgramFragment.Builder colBuilder = new ProgramFragment.Builder(mRS);
+        ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
         colBuilder.setVaryingColor(false);
         mProgFragmentColor = colBuilder.create();
 
@@ -188,12 +199,14 @@
     }
 
     private void initProgramVertex() {
-        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS);
+        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
         mProgVertex = pvb.create();
 
-        mPVA = new ProgramVertex.MatrixAllocation(mRS);
-        mProgVertex.bindAllocation(mPVA);
-        mPVA.setupOrthoWindow(mWidth, mHeight);
+        mPVA = new ProgramVertexFixedFunction.Constants(mRS);
+        ((ProgramVertexFixedFunction)mProgVertex).bindConstants(mPVA);
+        Matrix4f proj = new Matrix4f();
+        proj.loadOrthoWindow(mWidth, mHeight);
+        mPVA.setProjection(proj);
 
         mScript.set_gProgVertex(mProgVertex);
     }
@@ -210,7 +223,7 @@
         mScript.bind_gFSConstants2(mFSConst2);
 
         // Initialize the shader builder
-        ProgramVertex.ShaderBuilder pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
+        ProgramVertex.Builder pvbCustom = new ProgramVertex.Builder(mRS);
         // Specify the resource that contains the shader string
         pvbCustom.setShader(mRes, R.raw.shaderv);
         // Use a script field to spcify the input layout
@@ -221,47 +234,49 @@
         // Bind the source of constant data
         mProgVertexCustom.bindConstants(mVSConst.getAllocation(), 0);
 
-        ProgramFragment.ShaderBuilder pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
+        ProgramFragment.Builder pfbCustom = new ProgramFragment.Builder(mRS);
         // Specify the resource that contains the shader string
         pfbCustom.setShader(mRes, R.raw.shaderf);
         //Tell the builder how many textures we have
-        pfbCustom.setTextureCount(1);
+        pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
         // Define the constant input layout
         pfbCustom.addConstant(mFSConst.getAllocation().getType());
         mProgFragmentCustom = pfbCustom.create();
         // Bind the source of constant data
         mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 0);
 
-        pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
+        pvbCustom = new ProgramVertex.Builder(mRS);
         pvbCustom.setShader(mRes, R.raw.shaderarrayv);
         pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
         pvbCustom.addConstant(mVSConst2.getAllocation().getType());
         mProgVertexCustom2 = pvbCustom.create();
         mProgVertexCustom2.bindConstants(mVSConst2.getAllocation(), 0);
 
-        pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
+        pfbCustom = new ProgramFragment.Builder(mRS);
         pfbCustom.setShader(mRes, R.raw.shaderarrayf);
-        pfbCustom.setTextureCount(1);
+        pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
         pfbCustom.addConstant(mFSConst2.getAllocation().getType());
         mProgFragmentCustom2 = pfbCustom.create();
         mProgFragmentCustom2.bindConstants(mFSConst2.getAllocation(), 0);
 
         // Cubemap test shaders
-        pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
+        pvbCustom = new ProgramVertex.Builder(mRS);
         pvbCustom.setShader(mRes, R.raw.shadercubev);
         pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
         pvbCustom.addConstant(mVSConst.getAllocation().getType());
         mProgVertexCube = pvbCustom.create();
         mProgVertexCube.bindConstants(mVSConst.getAllocation(), 0);
 
-        pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
+        pfbCustom = new ProgramFragment.Builder(mRS);
         pfbCustom.setShader(mRes, R.raw.shadercubef);
         pfbCustom.addTexture(Program.TextureType.TEXTURE_CUBE);
         mProgFragmentCube = pfbCustom.create();
 
-        pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
+        pfbCustom = new ProgramFragment.Builder(mRS);
         pfbCustom.setShader(mRes, R.raw.multitexf);
-        pfbCustom.setTextureCount(3);
+        for (int texCount = 0; texCount < 3; texCount ++) {
+            pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+        }
         mProgFragmentMultitex = pfbCustom.create();
 
         mScript.set_gProgVertexCustom(mProgVertexCustom);
@@ -292,8 +307,7 @@
         mTexTransparent = loadTextureARGB(R.drawable.leaf);
         mTexChecker = loadTextureRGB(R.drawable.checker);
         Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.cubemap_test);
-        mTexCube = Allocation.createCubemapFromBitmap(mRS, b,
-                                                      Allocation.CubemapLayout.VERTICAL_FACE_LIST);
+        mTexCube = Allocation.createCubemapFromBitmap(mRS, b);
 
         mScript.set_gTexTorus(mTexTorus);
         mScript.set_gTexOpaque(mTexOpaque);
@@ -304,14 +318,13 @@
 
     private void initFonts() {
         // Sans font by family name
-        mFontSans = Font.createFromFamily(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8);
-        // Create font by file name
-        mFontSerif = Font.create(mRS, mRes, "DroidSerif-Regular.ttf", 8);
+        mFontSans = Font.create(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8);
+        mFontSerif = Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8);
         // Create fonts by family and style
-        mFontSerifBold = Font.createFromFamily(mRS, mRes, "serif", Font.Style.BOLD, 8);
-        mFontSerifItalic = Font.createFromFamily(mRS, mRes, "serif", Font.Style.ITALIC, 8);
-        mFontSerifBoldItalic = Font.createFromFamily(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8);
-        mFontMono = Font.createFromFamily(mRS, mRes, "mono", Font.Style.NORMAL, 8);
+        mFontSerifBold = Font.create(mRS, mRes, "serif", Font.Style.BOLD, 8);
+        mFontSerifItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8);
+        mFontSerifBoldItalic = Font.create(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8);
+        mFontMono = Font.create(mRS, mRes, "mono", Font.Style.NORMAL, 8);
 
         mTextAlloc = Allocation.createFromString(mRS, "String from allocation", Allocation.USAGE_SCRIPT);
 
@@ -330,7 +343,7 @@
 
         FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.torus);
         FileA3D.IndexEntry entry = model.getIndexEntry(0);
-        if (entry == null || entry.getClassID() != FileA3D.ClassID.MESH) {
+        if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) {
             Log.e("rs", "could not load model");
         } else {
             mTorus = (Mesh)entry.getObject();
@@ -340,8 +353,8 @@
 
     private void initSamplers() {
         Sampler.Builder bs = new Sampler.Builder(mRS);
-        bs.setMin(Sampler.Value.LINEAR);
-        bs.setMag(Sampler.Value.LINEAR);
+        bs.setMinification(Sampler.Value.LINEAR);
+        bs.setMagnification(Sampler.Value.LINEAR);
         bs.setWrapS(Sampler.Value.WRAP);
         bs.setWrapT(Sampler.Value.WRAP);
         mLinearWrap = bs.create();
@@ -351,8 +364,8 @@
         mMipLinearWrap = Sampler.WRAP_LINEAR_MIP_LINEAR(mRS);
 
         bs = new Sampler.Builder(mRS);
-        bs.setMin(Sampler.Value.LINEAR_MIP_LINEAR);
-        bs.setMag(Sampler.Value.LINEAR);
+        bs.setMinification(Sampler.Value.LINEAR_MIP_LINEAR);
+        bs.setMagnification(Sampler.Value.LINEAR);
         bs.setWrapS(Sampler.Value.WRAP);
         bs.setWrapT(Sampler.Value.WRAP);
         bs.setAnisotropy(8.0f);
diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
index 265e1d6..fc3a065 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
+++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
@@ -66,6 +66,7 @@
 
         unitTests.add(new UT_primitives(this, mRes, mCtx));
         unitTests.add(new UT_rsdebug(this, mRes, mCtx));
+        unitTests.add(new UT_rstime(this, mRes, mCtx));
         unitTests.add(new UT_rstypes(this, mRes, mCtx));
         unitTests.add(new UT_fp_mad(this, mRes, mCtx));
         /*
@@ -94,7 +95,7 @@
 
         mScript.bind_gList(mListAllocs);
 
-        mFont = Font.createFromFamily(mRS, mRes, "serif", Font.Style.BOLD, 8);
+        mFont = Font.create(mRS, mRes, "serif", Font.Style.BOLD, 8);
         mScript.set_gFont(mFont);
 
         mRS.bindRootScript(mScript);
diff --git a/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java b/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java
new file mode 100644
index 0000000..f302e1a
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/UT_rstime.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_rstime extends UnitTest {
+    private Resources mRes;
+
+    protected UT_rstime(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "rsTime", ctx);
+        mRes = res;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_rstime s = new ScriptC_rstime(pRS, mRes, R.raw.rstime);
+        pRS.setMessageHandler(mRsMessage);
+        s.invoke_test_rstime(0, 0);
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/rstime.rs b/libs/rs/java/tests/src/com/android/rs/test/rstime.rs
new file mode 100644
index 0000000..5e3e078
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/rstime.rs
@@ -0,0 +1,52 @@
+#include "shared.rsh"
+
+static bool basic_test(uint32_t index) {
+    bool failed = false;
+
+    rs_time_t curTime = rsTime(0);
+    rs_tm tm;
+    rsDebug("curTime", curTime);
+
+    rsLocaltime(&tm, &curTime);
+
+    rsDebug("tm.tm_sec", tm.tm_sec);
+    rsDebug("tm.tm_min", tm.tm_min);
+    rsDebug("tm.tm_hour", tm.tm_hour);
+    rsDebug("tm.tm_mday", tm.tm_mday);
+    rsDebug("tm.tm_mon", tm.tm_mon);
+    rsDebug("tm.tm_year", tm.tm_year);
+    rsDebug("tm.tm_wday", tm.tm_wday);
+    rsDebug("tm.tm_yday", tm.tm_yday);
+    rsDebug("tm.tm_isdst", tm.tm_isdst);
+
+    // Test a specific time (only valid for PST localtime)
+    curTime = 1294438893;
+    rsLocaltime(&tm, &curTime);
+
+    _RS_ASSERT(tm.tm_sec == 33);
+    _RS_ASSERT(tm.tm_min == 21);
+    _RS_ASSERT(tm.tm_hour == 14);
+    _RS_ASSERT(tm.tm_mday == 7);
+    _RS_ASSERT(tm.tm_mon == 0);
+    _RS_ASSERT(tm.tm_year == 111);
+    _RS_ASSERT(tm.tm_wday == 5);
+    _RS_ASSERT(tm.tm_yday == 6);
+    _RS_ASSERT(tm.tm_isdst == 0);
+
+    return failed;
+}
+
+void test_rstime(uint32_t index, int test_num) {
+    bool failed = false;
+    failed |= basic_test(index);
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+        rsDebug("rstime_test FAILED", -1);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+        rsDebug("rstime_test PASSED", 0);
+    }
+}
+
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 5daba08..7e23cec 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -47,7 +47,7 @@
 	param int32_t priority
 	}
 
-ContextDestroy {
+ContextDestroyWorker {
 }
 
 AssignName {
@@ -77,40 +77,17 @@
 	ret RsElement
 	}
 
-AllocationCopyFromBitmap {
-	param RsAllocation alloc
-	param const void * data
-	param size_t dataLen
-	}
-
 AllocationCopyToBitmap {
 	param RsAllocation alloc
 	param void * data
 	param size_t dataLen
 	}
 
-AllocationUploadToTexture {
-	param RsAllocation alloc
-	param bool genMipMaps
-	param uint32_t baseMipLevel
-	}
 
-AllocationUploadToBufferObject {
-	param RsAllocation alloc
-	}
-
-
-AllocationData {
-	param RsAllocation va
-	param const void * data
-	param uint32_t bytes
-	handcodeApi
-	togglePlay
-	}
-
-Allocation1DSubData {
+Allocation1DData {
 	param RsAllocation va
 	param uint32_t xoff
+	param uint32_t lod
 	param uint32_t count
 	param const void *data
 	param uint32_t bytes
@@ -118,9 +95,10 @@
 	togglePlay
 	}
 
-Allocation1DSubElementData {
+Allocation1DElementData {
 	param RsAllocation va
 	param uint32_t x
+	param uint32_t lod
 	param const void *data
 	param uint32_t comp_offset
 	param uint32_t bytes
@@ -128,25 +106,33 @@
 	togglePlay
 	}
 
-Allocation2DSubData {
+Allocation2DData {
 	param RsAllocation va
 	param uint32_t xoff
 	param uint32_t yoff
+	param uint32_t lod
+	param RsAllocationCubemapFace face
 	param uint32_t w
 	param uint32_t h
 	param const void *data
 	param uint32_t bytes
 	}
 
-Allocation2DSubElementData {
+Allocation2DElementData {
 	param RsAllocation va
 	param uint32_t x
 	param uint32_t y
+	param uint32_t lod
+	param RsAllocationCubemapFace face
 	param const void *data
 	param uint32_t element_offset
 	param uint32_t bytes
 	}
 
+AllocationGenerateMipmaps {
+	param RsAllocation va
+}
+
 AllocationRead {
 	param RsAllocation va
 	param void * data
@@ -157,61 +143,6 @@
 	param RsAllocationUsageType src
 }
 
-Adapter1DCreate {
-	ret RsAdapter1D
-	}
-
-Adapter1DBindAllocation {
-	param RsAdapter1D adapt
-	param RsAllocation alloc
-	}
-
-Adapter1DSetConstraint {
-	param RsAdapter1D adapter
-	param RsDimension dim
-	param uint32_t value
-	}
-
-Adapter1DData {
-	param RsAdapter1D adapter
-	param const void * data
-	}
-
-Adapter1DSubData {
-	param RsAdapter1D adapter
-	param uint32_t xoff
-	param uint32_t count
-	param const void *data
-	}
-
-Adapter2DCreate {
-	ret RsAdapter2D
-	}
-
-Adapter2DBindAllocation {
-	param RsAdapter2D adapt
-	param RsAllocation alloc
-	}
-
-Adapter2DSetConstraint {
-	param RsAdapter2D adapter
-	param RsDimension dim
-	param uint32_t value
-	}
-
-Adapter2DData {
-	param RsAdapter2D adapter
-	param const void *data
-	}
-
-Adapter2DSubData {
-	param RsAdapter2D adapter
-	param uint32_t xoff
-	param uint32_t yoff
-	param uint32_t w
-	param uint32_t h
-	param const void *data
-	}
 
 AllocationResize1D {
 	param RsAllocation va
@@ -321,6 +252,7 @@
 	}
 
 ScriptCCreate {
+        param const char * packageName
         param const char * resName
         param const char * cacheDir
 	ret RsScript
@@ -412,19 +344,22 @@
 	ret RsProgramVertex
 	}
 
-FileOpen {
-	ret RsFile
-	param const char *name
-	param size_t len
-	}
-
 FontCreateFromFile {
 	param const char *name
-	param uint32_t fontSize
+	param float fontSize
 	param uint32_t dpi
 	ret RsFont
 	}
 
+FontCreateFromMemory {
+	param const char *name
+	param float fontSize
+	param uint32_t dpi
+    param const void *data
+    param uint32_t dataLen
+	ret RsFont
+	}
+
 MeshCreate {
 	ret RsMesh
 	param uint32_t vtxCount
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 77e8032..2ed7774 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -28,6 +28,8 @@
 
 #include "utils/StopWatch.h"
 
+static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va);
+
 using namespace android;
 using namespace android::renderscript;
 
@@ -135,7 +137,6 @@
 }
 
 void Allocation::freeScriptMemory() {
-    rsAssert(!(mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT));
     if (mPtr) {
         free(mPtr);
         mPtr = NULL;
@@ -201,6 +202,17 @@
     rsc->checkError("Allocation::uploadToTexture");
 }
 
+void Allocation::update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
+                                 uint32_t lod, RsAllocationCubemapFace face,
+                                 uint32_t w, uint32_t h) {
+    GLenum type = mType->getElement()->getComponent().getGLType();
+    GLenum format = mType->getElement()->getComponent().getGLFormat();
+    GLenum target = (GLenum)getGLTarget();
+    glBindTexture(target, mTextureID);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    glTexSubImage2D(GL_TEXTURE_2D, lod, xoff, yoff, w, h, format, type, ptr);
+}
+
 void Allocation::upload2DTexture(bool isFirstUpload, const void *ptr) {
     GLenum type = mType->getElement()->getComponent().getGLType();
     GLenum format = mType->getElement()->getComponent().getGLFormat();
@@ -308,29 +320,12 @@
     }
 }
 
-
-void Allocation::data(Context *rsc, const void *data, uint32_t sizeBytes) {
-    uint32_t size = mType->getSizeBytes();
-    if (size != sizeBytes) {
-        LOGE("Allocation::data called with mismatched size expected %i, got %i", size, sizeBytes);
-        return;
-    }
-
-    if (mType->getElement()->getHasReferences()) {
-        incRefs(data, sizeBytes / mType->getElement()->getSizeBytes());
-        decRefs(mPtr, sizeBytes / mType->getElement()->getSizeBytes());
-    }
-
-    memcpy(mPtr, data, size);
-    sendDirty();
-    mUploadDefered = true;
-}
-
 void Allocation::read(void *data) {
     memcpy(data, mPtr, mType->getSizeBytes());
 }
 
-void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes) {
+void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod,
+                         uint32_t count, const void *data, uint32_t sizeBytes) {
     uint32_t eSize = mType->getElementSizeBytes();
     uint8_t * ptr = static_cast<uint8_t *>(mPtr);
     ptr += eSize * xoff;
@@ -352,39 +347,48 @@
     mUploadDefered = true;
 }
 
-void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t yoff,
+void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
              uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
     uint32_t eSize = mType->getElementSizeBytes();
     uint32_t lineSize = eSize * w;
     uint32_t destW = mType->getDimX();
 
-    const uint8_t *src = static_cast<const uint8_t *>(data);
-    uint8_t *dst = static_cast<uint8_t *>(mPtr);
-    dst += eSize * (xoff + yoff * destW);
+    //LOGE("data2d %p,  %i %i %i %i %i %i %p %i", this, xoff, yoff, lod, face, w, h, data, sizeBytes);
 
-    if ((lineSize * eSize * h) != sizeBytes) {
+    if ((lineSize * h) != sizeBytes) {
+        LOGE("Allocation size mismatch, expected %i, got %i", (lineSize * h), sizeBytes);
         rsAssert(!"Allocation::subData called with mismatched size");
         return;
     }
 
-    for (uint32_t line=yoff; line < (yoff+h); line++) {
-        if (mType->getElement()->getHasReferences()) {
-            incRefs(src, w);
-            decRefs(dst, w);
+    if (mPtr) {
+        const uint8_t *src = static_cast<const uint8_t *>(data);
+        uint8_t *dst = static_cast<uint8_t *>(mPtr);
+        dst += mType->getLODOffset(lod, xoff, yoff);
+
+        //LOGE("            %p  %p  %i  ", dst, src, eSize);
+        for (uint32_t line=yoff; line < (yoff+h); line++) {
+            if (mType->getElement()->getHasReferences()) {
+                incRefs(src, w);
+                decRefs(dst, w);
+            }
+            memcpy(dst, src, lineSize);
+            src += lineSize;
+            dst += destW * eSize;
         }
-        memcpy(dst, src, lineSize);
-        src += lineSize;
-        dst += destW * eSize;
+        sendDirty();
+        mUploadDefered = true;
+    } else {
+        update2DTexture(data, xoff, yoff, lod, face, w, h);
     }
-    sendDirty();
-    mUploadDefered = true;
 }
 
-void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
-             uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
+void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
+                      uint32_t lod, RsAllocationCubemapFace face,
+                      uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
 }
 
-void Allocation::subElementData(Context *rsc, uint32_t x, const void *data,
+void Allocation::elementData(Context *rsc, uint32_t x, const void *data,
                                 uint32_t cIdx, uint32_t sizeBytes) {
     uint32_t eSize = mType->getElementSizeBytes();
     uint8_t * ptr = static_cast<uint8_t *>(mPtr);
@@ -421,7 +425,7 @@
     mUploadDefered = true;
 }
 
-void Allocation::subElementData(Context *rsc, uint32_t x, uint32_t y,
+void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y,
                                 const void *data, uint32_t cIdx, uint32_t sizeBytes) {
     uint32_t eSize = mType->getElementSizeBytes();
     uint8_t * ptr = static_cast<uint8_t *>(mPtr);
@@ -540,8 +544,10 @@
     Allocation *alloc = new Allocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT);
     alloc->setName(name.string(), name.size());
 
+    uint32_t count = dataSize / type->getElementSizeBytes();
+
     // Read in all of our allocation data
-    alloc->data(rsc, stream->getPtr() + stream->getPos(), dataSize);
+    alloc->data(rsc, 0, 0, count, stream->getPtr() + stream->getPos(), dataSize);
     stream->reset(stream->getPos() + dataSize);
 
     return alloc;
@@ -699,34 +705,9 @@
     a->syncAll(rsc, src);
 }
 
-void rsi_AllocationCopyFromBitmap(Context *rsc, RsAllocation va, const void *data, size_t dataLen) {
+void rsi_AllocationGenerateMipmaps(Context *rsc, RsAllocation va) {
     Allocation *texAlloc = static_cast<Allocation *>(va);
-    const Type * t = texAlloc->getType();
-
-    uint32_t w = t->getDimX();
-    uint32_t h = t->getDimY();
-    bool genMips = t->getDimLOD();
-    size_t s = w * h * t->getElementSizeBytes();
-    if (s != dataLen) {
-        rsc->setError(RS_ERROR_BAD_VALUE, "Bitmap size didn't match allocation size");
-        return;
-    }
-
-    if (texAlloc->getIsScript()) {
-        memcpy(texAlloc->getPtr(), data, s);
-        if (genMips) {
-            Adapter2D adapt(rsc, texAlloc);
-            Adapter2D adapt2(rsc, texAlloc);
-            for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
-                adapt.setLOD(lod);
-                adapt2.setLOD(lod + 1);
-                mip(adapt2, adapt);
-            }
-        }
-    } else {
-        texAlloc->upload2DTexture(false, data);
-    }
-
+    rsaAllocationGenerateScriptMips(rsc, texAlloc);
 }
 
 void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t dataLen) {
@@ -742,29 +723,28 @@
     memcpy(data, texAlloc->getPtr(), s);
 }
 
-void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes) {
+void rsi_Allocation1DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t lod,
+                          uint32_t count, const void *data, uint32_t sizeBytes) {
     Allocation *a = static_cast<Allocation *>(va);
-    a->data(rsc, data, sizeBytes);
+    a->data(rsc, xoff, lod, count, data, sizeBytes);
 }
 
-void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes) {
+void rsi_Allocation2DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, uint32_t lod, RsAllocationCubemapFace face,
+                                 const void *data, uint32_t eoff, uint32_t sizeBytes) {
     Allocation *a = static_cast<Allocation *>(va);
-    a->subData(rsc, xoff, count, data, sizeBytes);
+    a->elementData(rsc, x, y, data, eoff, sizeBytes);
 }
 
-void rsi_Allocation2DSubElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, const void *data, uint32_t eoff, uint32_t sizeBytes) {
+void rsi_Allocation1DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t lod,
+                                 const void *data, uint32_t eoff, uint32_t sizeBytes) {
     Allocation *a = static_cast<Allocation *>(va);
-    a->subElementData(rsc, x, y, data, eoff, sizeBytes);
+    a->elementData(rsc, x, data, eoff, sizeBytes);
 }
 
-void rsi_Allocation1DSubElementData(Context *rsc, RsAllocation va, uint32_t x, const void *data, uint32_t eoff, uint32_t sizeBytes) {
+void rsi_Allocation2DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
+                          uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
     Allocation *a = static_cast<Allocation *>(va);
-    a->subElementData(rsc, x, data, eoff, sizeBytes);
-}
-
-void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) {
-    Allocation *a = static_cast<Allocation *>(va);
-    a->subData(rsc, xoff, yoff, w, h, data, sizeBytes);
+    a->data(rsc, xoff, yoff, lod, face, w, h, data, sizeBytes);
 }
 
 void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data) {
@@ -787,6 +767,23 @@
 }
 }
 
+static void rsaAllocationGenerateScriptMips(RsContext con, RsAllocation va) {
+    Context *rsc = static_cast<Context *>(con);
+    Allocation *texAlloc = static_cast<Allocation *>(va);
+    uint32_t numFaces = texAlloc->getType()->getDimFaces() ? 6 : 1;
+    for (uint32_t face = 0; face < numFaces; face ++) {
+        Adapter2D adapt(rsc, texAlloc);
+        Adapter2D adapt2(rsc, texAlloc);
+        adapt.setFace(face);
+        adapt2.setFace(face);
+        for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
+            adapt.setLOD(lod);
+            adapt2.setLOD(lod + 1);
+            mip(adapt2, adapt);
+        }
+    }
+}
+
 const void * rsaAllocationGetType(RsContext con, RsAllocation va) {
     Allocation *a = static_cast<Allocation *>(va);
     a->getType()->incUserRef();
@@ -819,13 +816,7 @@
 
     memcpy(texAlloc->getPtr(), data, t->getDimX() * t->getDimY() * t->getElementSizeBytes());
     if (mips == RS_ALLOCATION_MIPMAP_FULL) {
-        Adapter2D adapt(rsc, texAlloc);
-        Adapter2D adapt2(rsc, texAlloc);
-        for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
-            adapt.setLOD(lod);
-            adapt2.setLOD(lod + 1);
-            mip(adapt2, adapt);
-        }
+        rsaAllocationGenerateScriptMips(rsc, texAlloc);
     }
 
     texAlloc->deferedUploadToTexture(rsc);
@@ -848,28 +839,25 @@
         return NULL;
     }
 
+    uint32_t faceSize = t->getDimX();
+    uint32_t strideBytes = faceSize * 6 * t->getElementSizeBytes();
+    uint32_t copySize = faceSize * t->getElementSizeBytes();
+
     uint8_t *sourcePtr = (uint8_t*)data;
     for (uint32_t face = 0; face < 6; face ++) {
         Adapter2D faceAdapter(rsc, texAlloc);
         faceAdapter.setFace(face);
 
-        size_t cpySize = t->getDimX() * t->getDimX() * t->getElementSizeBytes();
-        memcpy(faceAdapter.getElement(0, 0), sourcePtr, cpySize);
+        for (uint32_t dI = 0; dI < faceSize; dI ++) {
+            memcpy(faceAdapter.getElement(0, dI), sourcePtr + strideBytes * dI, copySize);
+        }
 
         // Move the data pointer to the next cube face
-        sourcePtr += cpySize;
+        sourcePtr += copySize;
+    }
 
-        if (mips == RS_ALLOCATION_MIPMAP_FULL) {
-            Adapter2D adapt(rsc, texAlloc);
-            Adapter2D adapt2(rsc, texAlloc);
-            adapt.setFace(face);
-            adapt2.setFace(face);
-            for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
-                adapt.setLOD(lod);
-                adapt2.setLOD(lod + 1);
-                mip(adapt2, adapt);
-            }
-        }
+    if (mips == RS_ALLOCATION_MIPMAP_FULL) {
+        rsaAllocationGenerateScriptMips(rsc, texAlloc);
     }
 
     texAlloc->deferedUploadToTexture(rsc);
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index 44dce0d..a160765 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -61,16 +61,15 @@
     void resize1D(Context *rsc, uint32_t dimX);
     void resize2D(Context *rsc, uint32_t dimX, uint32_t dimY);
 
-    void data(Context *rsc, const void *data, uint32_t sizeBytes);
-    void subData(Context *rsc, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes);
-    void subData(Context *rsc, uint32_t xoff, uint32_t yoff,
+    void data(Context *rsc, uint32_t xoff, uint32_t lod, uint32_t count, const void *data, uint32_t sizeBytes);
+    void data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
                  uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes);
-    void subData(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff,
+    void data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t lod, RsAllocationCubemapFace face,
                  uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes);
 
-    void subElementData(Context *rsc, uint32_t x,
+    void elementData(Context *rsc, uint32_t x,
                         const void *data, uint32_t elementOff, uint32_t sizeBytes);
-    void subElementData(Context *rsc, uint32_t x, uint32_t y,
+    void elementData(Context *rsc, uint32_t x, uint32_t y,
                         const void *data, uint32_t elementOff, uint32_t sizeBytes);
 
     void read(void *data);
@@ -107,6 +106,8 @@
     }
 
     void upload2DTexture(bool isFirstUpload, const void *ptr);
+    void update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
+                         uint32_t lod, RsAllocationCubemapFace face, uint32_t w, uint32_t h);
 
 protected:
     ObjectBaseRef<const Type> mType;
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 2988950..2e0c491 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -44,6 +44,7 @@
 uint32_t Context::gThreadTLSKeyCount = 0;
 uint32_t Context::gGLContextCount = 0;
 pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t Context::gLibMutex = PTHREAD_MUTEX_INITIALIZER;
 
 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
     if (returnVal != EGL_TRUE) {
@@ -235,6 +236,7 @@
     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGL.mMaxFragmentUniformVectors);
 
     mGL.OES_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_OES_texture_npot");
+    mGL.GL_IMG_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_IMG_texture_npot");
     mGL.GL_NV_texture_npot_2D_mipmap = NULL != strstr((const char *)mGL.mExtensions, "GL_NV_texture_npot_2D_mipmap");
     mGL.EXT_texture_max_aniso = 1.0f;
     bool hasAniso = NULL != strstr((const char *)mGL.mExtensions, "GL_EXT_texture_filter_anisotropic");
@@ -509,20 +511,6 @@
      }
 
      LOGV("%p, RS Thread exiting", rsc);
-     if (rsc->mIsGraphicsContext) {
-         rsc->mRaster.clear();
-         rsc->mFragment.clear();
-         rsc->mVertex.clear();
-         rsc->mFragmentStore.clear();
-         rsc->mFont.clear();
-         rsc->mRootScript.clear();
-         rsc->mStateRaster.deinit(rsc);
-         rsc->mStateVertex.deinit(rsc);
-         rsc->mStateFragment.deinit(rsc);
-         rsc->mStateFragmentStore.deinit(rsc);
-         rsc->mStateFont.deinit(rsc);
-     }
-     ObjectBase::zeroAllUserRef(rsc);
 
      if (rsc->mIsGraphicsContext) {
          pthread_mutex_lock(&gInitMutex);
@@ -535,6 +523,27 @@
      return NULL;
 }
 
+void Context::destroyWorkerThreadResources() {
+    LOGV("destroyWorkerThreadResources 1");
+    if (mIsGraphicsContext) {
+         mRaster.clear();
+         mFragment.clear();
+         mVertex.clear();
+         mFragmentStore.clear();
+         mFont.clear();
+         mRootScript.clear();
+         mStateRaster.deinit(this);
+         mStateVertex.deinit(this);
+         mStateFragment.deinit(this);
+         mStateFragmentStore.deinit(this);
+         mStateFont.deinit(this);
+         mShaderCache.cleanupAll();
+    }
+    ObjectBase::zeroAllUserRef(this);
+    LOGV("destroyWorkerThreadResources 2");
+    mExit = true;
+}
+
 void * Context::helperThreadProc(void *vrsc) {
      Context *rsc = static_cast<Context *>(vrsc);
      uint32_t idx = (uint32_t)android_atomic_inc(&rsc->mWorkers.mLaunchCount);
@@ -707,6 +716,9 @@
 
 Context::~Context() {
     LOGV("Context::~Context");
+
+    mIO.mToCore.flush();
+    rsAssert(mExit);
     mExit = true;
     mPaused = false;
     void *res;
@@ -725,13 +737,16 @@
         mDev = NULL;
     }
     pthread_mutex_unlock(&gInitMutex);
+    LOGV("Context::~Context done");
 }
 
 void Context::setSurface(uint32_t w, uint32_t h, ANativeWindow *sur) {
     rsAssert(mIsGraphicsContext);
 
     EGLBoolean ret;
-    if (mEGL.mSurface != NULL) {
+    // WAR: Some drivers fail to handle 0 size surfaces correcntly.
+    // Use the pbuffer to avoid this pitfall.
+    if ((mEGL.mSurface != NULL) || (w == 0) || (h == 0)) {
         ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurfaceDefault, mEGL.mSurfaceDefault, mEGL.mContext);
         checkEglError("eglMakeCurrent", ret);
 
@@ -1019,14 +1034,23 @@
     ObjectBase::dumpAll(rsc);
 }
 
-void rsi_ContextDestroy(Context *rsc) {
+void rsi_ContextDestroyWorker(Context *rsc) {
+    LOGE("rsi_ContextDestroyWorker 1");
+    rsc->destroyWorkerThreadResources();;
+    LOGE("rsi_ContextDestroyWorker 2");
+}
+
+}
+}
+
+void rsContextDestroy(RsContext vcon) {
+    LOGV("rsContextDestroy %p", vcon);
+    Context *rsc = static_cast<Context *>(vcon);
+    rsContextDestroyWorker(rsc);
     delete rsc;
+    LOGV("rsContextDestroy 2 %p", vcon);
 }
 
-}
-}
-
-
 RsContext rsContextCreate(RsDevice vdev, uint32_t version) {
     LOGV("rsContextCreate %p", vdev);
     Device * dev = static_cast<Device *>(vdev);
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 49ee676..9f94f26 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -75,6 +75,8 @@
     static uint32_t gThreadTLSKeyCount;
     static uint32_t gGLContextCount;
     static pthread_mutex_t gInitMutex;
+    // Library mutex (for providing thread-safe calls from the runtime)
+    static pthread_mutex_t gLibMutex;
 
     struct ScriptTLSStruct {
         Context * mContext;
@@ -137,6 +139,7 @@
     void resume();
     void setSurface(uint32_t w, uint32_t h, ANativeWindow *sur);
     void setPriority(int32_t p);
+    void destroyWorkerThreadResources();
 
     void assignName(ObjectBase *obj, const char *name, uint32_t len);
     void removeName(ObjectBase *obj);
@@ -202,6 +205,7 @@
     mutable const ObjectBase * mObjHead;
 
     bool ext_OES_texture_npot() const {return mGL.OES_texture_npot;}
+    bool ext_GL_IMG_texture_npot() const {return mGL.GL_IMG_texture_npot;}
     bool ext_GL_NV_texture_npot_2D_mipmap() const {return mGL.GL_NV_texture_npot_2D_mipmap;}
     float ext_texture_max_aniso() const {return mGL.EXT_texture_max_aniso; }
     uint32_t getMaxFragmentTextures() const {return mGL.mMaxFragmentTextureImageUnits;}
@@ -246,6 +250,7 @@
         int32_t mMaxVertexTextureUnits;
 
         bool OES_texture_npot;
+        bool GL_IMG_texture_npot;
         bool GL_NV_texture_npot_2D_mipmap;
         float EXT_texture_max_aniso;
     } mGL;
diff --git a/libs/rs/rsContextHostStub.h b/libs/rs/rsContextHostStub.h
index c22647f..8cfb38b 100644
--- a/libs/rs/rsContextHostStub.h
+++ b/libs/rs/rsContextHostStub.h
@@ -119,11 +119,12 @@
     mutable const ObjectBase * mObjHead;
 
     bool ext_OES_texture_npot() const {return mGL.OES_texture_npot;}
-    bool ext_GL_NV_texture_npot_2D_mipmap() const {return false;}
-    float ext_texture_max_aniso() const {return 1.0f;}
+    bool ext_GL_NV_texture_npot_2D_mipmap() const {return mGL.GL_NV_texture_npot_2D_mipmap;}
+    float ext_texture_max_aniso() const {return mGL.EXT_texture_max_aniso; }
     uint32_t getMaxFragmentTextures() const {return mGL.mMaxFragmentTextureImageUnits;}
     uint32_t getMaxFragmentUniformVectors() const {return mGL.mMaxFragmentUniformVectors;}
     uint32_t getMaxVertexUniformVectors() const {return mGL.mMaxVertexUniformVectors;}
+    uint32_t getMaxVertexAttributes() const {return mGL.mMaxVertexAttribs;}
 
 protected:
 
@@ -147,6 +148,8 @@
         int32_t mMaxVertexTextureUnits;
 
         bool OES_texture_npot;
+        bool GL_NV_texture_npot_2D_mipmap;
+        float EXT_texture_max_aniso;
     } mGL;
 
 };
diff --git a/libs/rs/rsFileA3D.cpp b/libs/rs/rsFileA3D.cpp
index 0c8692d..d34ddd6 100644
--- a/libs/rs/rsFileA3D.cpp
+++ b/libs/rs/rsFileA3D.cpp
@@ -35,6 +35,7 @@
     mData = NULL;
     mWriteStream = NULL;
     mReadStream = NULL;
+    mAsset = NULL;
 
     mMajorVersion = 0;
     mMinorVersion = 1;
@@ -57,6 +58,9 @@
     if (mAlloc) {
         free(mAlloc);
     }
+    if (mAsset) {
+        delete mAsset;
+    }
 }
 
 void FileA3D::parseHeader(IStream *headerStream) {
@@ -83,6 +87,11 @@
     }
 }
 
+bool FileA3D::load(Asset *asset) {
+    mAsset = asset;
+    return load(asset->getBuffer(false), asset->getLength());
+}
+
 bool FileA3D::load(const void *data, size_t length) {
     const uint8_t *localData = (const uint8_t *)data;
 
@@ -357,26 +366,6 @@
     mWriteStream->align(4);
 }
 
-namespace android {
-namespace renderscript {
-
-RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len) {
-    FileA3D *fa3d = new FileA3D(rsc);
-
-    FILE *f = fopen("/sdcard/test.a3d", "rb");
-    if (f) {
-        fa3d->load(f);
-        fclose(f);
-        fa3d->incUserRef();
-        return fa3d;
-    }
-    delete fa3d;
-    return NULL;
-}
-
-}
-}
-
 RsObjectBase rsaFileA3DGetEntryByIndex(RsContext con, uint32_t index, RsFile file) {
     FileA3D *fa3d = static_cast<FileA3D *>(file);
     if (!fa3d) {
@@ -422,7 +411,7 @@
     }
 }
 
-RsFile rsaFileA3DCreateFromAssetStream(RsContext con, const void *data, uint32_t len) {
+RsFile rsaFileA3DCreateFromMemory(RsContext con, const void *data, uint32_t len) {
     if (data == NULL) {
         LOGE("File load failed. Asset stream is NULL");
         return NULL;
@@ -435,3 +424,35 @@
     fa3d->load(data, len);
     return fa3d;
 }
+
+RsFile rsaFileA3DCreateFromAsset(RsContext con, void *_asset) {
+    Context *rsc = static_cast<Context *>(con);
+    Asset *asset = static_cast<Asset *>(_asset);
+    FileA3D *fa3d = new FileA3D(rsc);
+    fa3d->incUserRef();
+
+    fa3d->load(asset);
+    return fa3d;
+}
+
+RsFile rsaFileA3DCreateFromFile(RsContext con, const char *path) {
+    if (path == NULL) {
+        LOGE("File load failed. Path is NULL");
+        return NULL;
+    }
+
+    Context *rsc = static_cast<Context *>(con);
+    FileA3D *fa3d = NULL;
+
+    FILE *f = fopen(path, "rb");
+    if (f) {
+        fa3d = new FileA3D(rsc);
+        fa3d->incUserRef();
+        fa3d->load(f);
+        fclose(f);
+    } else {
+        LOGE("Could not open file %s", path);
+    }
+
+    return fa3d;
+}
diff --git a/libs/rs/rsFileA3D.h b/libs/rs/rsFileA3D.h
index 3ece4c9..056b5af 100644
--- a/libs/rs/rsFileA3D.h
+++ b/libs/rs/rsFileA3D.h
@@ -21,6 +21,7 @@
 #include "rsMesh.h"
 
 #include <utils/String8.h>
+#include <utils/Asset.h>
 #include "rsStream.h"
 #include <stdio.h>
 
@@ -59,6 +60,7 @@
     };
 
     bool load(FILE *f);
+    bool load(Asset *asset);
     bool load(const void *data, size_t length);
 
     size_t getNumIndexEntries() const;
@@ -83,6 +85,7 @@
     const uint8_t * mData;
     void * mAlloc;
     uint64_t mDataSize;
+    Asset *mAsset;
 
     OStream *mWriteStream;
     Vector<A3DIndexEntry*> mWriteIndex;
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index 2fa1f0a..8571c32 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -40,20 +40,21 @@
     mFace = NULL;
 }
 
-bool Font::init(const char *name, uint32_t fontSize, uint32_t dpi) {
+bool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) {
     if (mInitialized) {
         LOGE("Reinitialization of fonts not supported");
         return false;
     }
 
-    String8 fontsDir("/fonts/");
-    String8 fullPath(getenv("ANDROID_ROOT"));
-    fullPath += fontsDir;
-    fullPath += name;
+    FT_Error error = 0;
+    if (data != NULL && dataLen > 0) {
+        error = FT_New_Memory_Face(mRSC->mStateFont.getLib(), (const FT_Byte*)data, dataLen, 0, &mFace);
+    } else {
+        error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace);
+    }
 
-    FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), fullPath.string(), 0, &mFace);
     if (error) {
-        LOGE("Unable to initialize font %s", fullPath.string());
+        LOGE("Unable to initialize font %s", name);
         return false;
     }
 
@@ -61,9 +62,9 @@
     mFontSize = fontSize;
     mDpi = dpi;
 
-    error = FT_Set_Char_Size(mFace, fontSize * 64, 0, dpi, 0);
+    error = FT_Set_Char_Size(mFace, (FT_F26Dot6)(fontSize * 64.0f), 0, dpi, 0);
     if (error) {
-        LOGE("Unable to set font size on %s", fullPath.string());
+        LOGE("Unable to set font size on %s", name);
         return false;
     }
 
@@ -132,7 +133,8 @@
     int32_t width = (int32_t) glyph->mBitmapWidth;
     int32_t height = (int32_t) glyph->mBitmapHeight;
 
-    if (bounds->bottom > nPenY) {
+    // 0, 0 is top left, so bottom is a positive number
+    if (bounds->bottom < nPenY) {
         bounds->bottom = nPenY;
     }
     if (bounds->left > nPenX) {
@@ -141,8 +143,8 @@
     if (bounds->right < nPenX + width) {
         bounds->right = nPenX + width;
     }
-    if (bounds->top < nPenY + height) {
-        bounds->top = nPenY + height;
+    if (bounds->top > nPenY - height) {
+        bounds->top = nPenY - height;
     }
 }
 
@@ -160,7 +162,7 @@
             return;
         }
         // Reset min and max of the bounding box to something large
-        bounds->set(1e6, -1e6, -1e6, 1e6);
+        bounds->set(1e6, -1e6, 1e6, -1e6);
     }
 
     int32_t penX = x, penY = y;
@@ -278,7 +280,8 @@
     return newGlyph;
 }
 
-Font * Font::create(Context *rsc, const char *name, uint32_t fontSize, uint32_t dpi) {
+Font * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi,
+                    const void *data, uint32_t dataLen) {
     rsc->mStateFont.checkInit();
     Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts;
 
@@ -290,7 +293,7 @@
     }
 
     Font *newFont = new Font(rsc);
-    bool isInitialized = newFont->init(name, fontSize, dpi);
+    bool isInitialized = newFont->init(name, fontSize, dpi, data, dataLen);
     if (isInitialized) {
         activeFonts.push(newFont);
         rsc->mStateFont.precacheLatin(newFont);
@@ -332,31 +335,20 @@
     // Get the gamma
     float gamma = DEFAULT_TEXT_GAMMA;
     if (property_get(PROPERTY_TEXT_GAMMA, property, NULL) > 0) {
-        LOGD("  Setting text gamma to %s", property);
         gamma = atof(property);
-    } else {
-        LOGD("  Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA);
     }
 
     // Get the black gamma threshold
     int32_t blackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD;
     if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, NULL) > 0) {
-        LOGD("  Setting text black gamma threshold to %s", property);
         blackThreshold = atoi(property);
-    } else {
-        LOGD("  Using default text black gamma threshold of %d",
-                DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD);
     }
     mBlackThreshold = (float)(blackThreshold) / 255.0f;
 
     // Get the white gamma threshold
     int32_t whiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD;
     if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, NULL) > 0) {
-        LOGD("  Setting text white gamma threshold to %s", property);
         whiteThreshold = atoi(property);
-    } else {
-        LOGD("  Using default white black gamma threshold of %d",
-                DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD);
     }
     mWhiteThreshold = (float)(whiteThreshold) / 255.0f;
 
@@ -622,7 +614,7 @@
     mRSC->setProgramStore(mFontProgramStore.get());
 
     if (mConstantsDirty) {
-        mFontShaderFConstant->data(mRSC, &mConstants, sizeof(mConstants));
+        mFontShaderFConstant->data(mRSC, 0, 0, 1, &mConstants, sizeof(mConstants));
         mConstantsDirty = false;
     }
 
@@ -735,7 +727,11 @@
     Font *currentFont = mRSC->getFont();
     if (!currentFont) {
         if (!mDefault.get()) {
-            mDefault.set(Font::create(mRSC, "DroidSans.ttf", 16, 96));
+            String8 fontsDir("/fonts/DroidSans.ttf");
+            String8 fullPath(getenv("ANDROID_ROOT"));
+            fullPath += fontsDir;
+
+            mDefault.set(Font::create(mRSC, fullPath.string(), 16, 96));
         }
         currentFont = mDefault.get();
     }
@@ -755,6 +751,8 @@
 
 void FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) {
     renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds);
+    bounds->bottom = - bounds->bottom;
+    bounds->top = - bounds->top;
 }
 
 void FontState::setFontColor(float r, float g, float b, float a) {
@@ -815,7 +813,7 @@
 namespace android {
 namespace renderscript {
 
-RsFont rsi_FontCreateFromFile(Context *rsc, char const *name, uint32_t fontSize, uint32_t dpi) {
+RsFont rsi_FontCreateFromFile(Context *rsc, char const *name, float fontSize, uint32_t dpi) {
     Font *newFont = Font::create(rsc, name, fontSize, dpi);
     if (newFont) {
         newFont->incUserRef();
@@ -823,5 +821,13 @@
     return newFont;
 }
 
+RsFont rsi_FontCreateFromMemory(Context *rsc, char const *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) {
+    Font *newFont = Font::create(rsc, name, fontSize, dpi, data, dataLen);
+    if (newFont) {
+        newFont->incUserRef();
+    }
+    return newFont;
+}
+
 } // renderscript
 } // android
diff --git a/libs/rs/rsFont.h b/libs/rs/rsFont.h
index 0f6815d..00d77c8 100644
--- a/libs/rs/rsFont.h
+++ b/libs/rs/rsFont.h
@@ -73,7 +73,8 @@
         return RS_A3D_CLASS_ID_UNKNOWN;
     }
 
-    static Font * create(Context *rsc, const char *name, uint32_t fontSize, uint32_t dpi);
+    static Font * create(Context *rsc, const char *name, float fontSize, uint32_t dpi,
+                         const void *data = NULL, uint32_t dataLen = 0);
 
 protected:
 
@@ -112,11 +113,11 @@
     };
 
     String8 mFontName;
-    uint32_t mFontSize;
+    float mFontSize;
     uint32_t mDpi;
 
     Font(Context *rsc);
-    bool init(const char *name, uint32_t fontSize, uint32_t dpi);
+    bool init(const char *name, float fontSize, uint32_t dpi, const void *data = NULL, uint32_t dataLen = 0);
 
     FT_Face mFace;
     bool mInitialized;
diff --git a/libs/rs/rsHandcode.h b/libs/rs/rsHandcode.h
index 122a9ed..6f21a35 100644
--- a/libs/rs/rsHandcode.h
+++ b/libs/rs/rsHandcode.h
@@ -49,64 +49,49 @@
     }
 }
 
-static inline void rsHCAPI_AllocationData (RsContext rsc, RsAllocation va, const void * data, uint32_t sizeBytes) {
+static inline void rsHCAPI_Allocation1DData (RsContext rsc, RsAllocation va, uint32_t xoff, uint32_t lod,
+                                             uint32_t count, const void * data, uint32_t sizeBytes) {
     ThreadIO *io = &((Context *)rsc)->mIO;
-    uint32_t size = sizeof(RS_CMD_AllocationData);
+    uint32_t size = sizeof(RS_CMD_Allocation1DData);
     if (sizeBytes < DATA_SYNC_SIZE) {
         size += (sizeBytes + 3) & ~3;
     }
-    RS_CMD_AllocationData *cmd = static_cast<RS_CMD_AllocationData *>(io->mToCore.reserve(size));
-    cmd->va = va;
-    cmd->bytes = sizeBytes;
-    cmd->data = data;
-    if (sizeBytes < DATA_SYNC_SIZE) {
-        cmd->data = (void *)(cmd+1);
-        memcpy(cmd+1, data, sizeBytes);
-        io->mToCore.commit(RS_CMD_ID_AllocationData, size);
-    } else {
-        io->mToCore.commitSync(RS_CMD_ID_AllocationData, size);
-    }
-}
-
-static inline void rsHCAPI_Allocation1DSubData (RsContext rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void * data, uint32_t sizeBytes) {
-    ThreadIO *io = &((Context *)rsc)->mIO;
-    uint32_t size = sizeof(RS_CMD_Allocation1DSubData);
-    if (sizeBytes < DATA_SYNC_SIZE) {
-        size += (sizeBytes + 3) & ~3;
-    }
-    RS_CMD_Allocation1DSubData *cmd = static_cast<RS_CMD_Allocation1DSubData *>(io->mToCore.reserve(size));
+    RS_CMD_Allocation1DData *cmd = static_cast<RS_CMD_Allocation1DData *>(io->mToCore.reserve(size));
     cmd->va = va;
     cmd->xoff = xoff;
+    cmd->lod = lod;
     cmd->count = count;
     cmd->data = data;
     cmd->bytes = sizeBytes;
     if (sizeBytes < DATA_SYNC_SIZE) {
         cmd->data = (void *)(cmd+1);
         memcpy(cmd+1, data, sizeBytes);
-        io->mToCore.commit(RS_CMD_ID_Allocation1DSubData, size);
+        io->mToCore.commit(RS_CMD_ID_Allocation1DData, size);
     } else {
-        io->mToCore.commitSync(RS_CMD_ID_Allocation1DSubData, size);
+        io->mToCore.commitSync(RS_CMD_ID_Allocation1DData, size);
     }
 }
 
-static inline void rsHCAPI_Allocation1DSubElementData (RsContext rsc, RsAllocation va, uint32_t x, const void * data, uint32_t comp_offset, uint32_t sizeBytes) {
+static inline void rsHCAPI_Allocation1DElementData (RsContext rsc, RsAllocation va, uint32_t x, uint32_t lod,
+                                                    const void * data, uint32_t comp_offset, uint32_t sizeBytes) {
     ThreadIO *io = &((Context *)rsc)->mIO;
-    uint32_t size = sizeof(RS_CMD_Allocation1DSubElementData);
+    uint32_t size = sizeof(RS_CMD_Allocation1DElementData);
     if (sizeBytes < DATA_SYNC_SIZE) {
         size += (sizeBytes + 3) & ~3;
     }
-    RS_CMD_Allocation1DSubElementData *cmd = static_cast<RS_CMD_Allocation1DSubElementData *>(io->mToCore.reserve(size));
+    RS_CMD_Allocation1DElementData *cmd = static_cast<RS_CMD_Allocation1DElementData *>(io->mToCore.reserve(size));
     cmd->va = va;
     cmd->x = x;
+    cmd->lod = lod;
     cmd->data = data;
     cmd->comp_offset = comp_offset;
     cmd->bytes = sizeBytes;
     if (sizeBytes < DATA_SYNC_SIZE) {
         cmd->data = (void *)(cmd+1);
         memcpy(cmd+1, data, sizeBytes);
-        io->mToCore.commit(RS_CMD_ID_Allocation1DSubElementData, size);
+        io->mToCore.commit(RS_CMD_ID_Allocation1DElementData, size);
     } else {
-        io->mToCore.commitSync(RS_CMD_ID_Allocation1DSubElementData, size);
+        io->mToCore.commitSync(RS_CMD_ID_Allocation1DElementData, size);
     }
 }
 
diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp
index e2757df..c80aecc 100644
--- a/libs/rs/rsSampler.cpp
+++ b/libs/rs/rsSampler.cpp
@@ -77,8 +77,20 @@
     GLenum target = (GLenum)tex->getGLTarget();
 
     if (!rsc->ext_OES_texture_npot() && tex->getType()->getIsNp2()) {
-        if (tex->getHasGraphicsMipmaps() && rsc->ext_GL_NV_texture_npot_2D_mipmap()) {
-            glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
+        if (tex->getHasGraphicsMipmaps() &&
+            (rsc->ext_GL_NV_texture_npot_2D_mipmap() || rsc->ext_GL_IMG_texture_npot())) {
+            if (rsc->ext_GL_NV_texture_npot_2D_mipmap()) {
+                glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
+            } else {
+                switch (trans[mMinFilter]) {
+                case GL_LINEAR_MIPMAP_LINEAR:
+                    glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+                    break;
+                default:
+                    glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
+                    break;
+                }
+            }
         } else {
             glTexParameteri(target, GL_TEXTURE_MIN_FILTER, transNP[mMinFilter]);
         }
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 507430d..0ecb18a 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -17,9 +17,11 @@
 #include "rsContext.h"
 #include "rsScriptC.h"
 #include "rsMatrix.h"
-#include "../../compile/libbcc/include/bcc/bcc.h"
 #include "utils/Timers.h"
 #include "utils/StopWatch.h"
+extern "C" {
+#include "libdex/ZipArchive.h"
+}
 
 #include <GLES/gl.h>
 #include <GLES/glext.h>
@@ -32,15 +34,76 @@
     Context * rsc = tls->mContext; \
     ScriptC * sc = (ScriptC *) tls->mScript
 
+// Input: cacheDir
+// Input: resName
+// Input: extName
+//
+// Note: cacheFile = resName + extName
+//
+// Output: Returns cachePath == cacheDir + cacheFile
+char *genCacheFileName(const char *cacheDir,
+                       const char *resName,
+                       const char *extName) {
+    char cachePath[512];
+    char cacheFile[sizeof(cachePath)];
+    const size_t kBufLen = sizeof(cachePath) - 1;
+
+    cacheFile[0] = '\0';
+    // Note: resName today is usually something like
+    //       "/com.android.fountain:raw/fountain"
+    if (resName[0] != '/') {
+        // Get the absolute path of the raw/***.bc file.
+
+        // Generate the absolute path.  This doesn't do everything it
+        // should, e.g. if resName is "./out/whatever" it doesn't crunch
+        // the leading "./" out because this if-block is not triggered,
+        // but it'll make do.
+        //
+        if (getcwd(cacheFile, kBufLen) == NULL) {
+            LOGE("Can't get CWD while opening raw/***.bc file\n");
+            return NULL;
+        }
+        // Append "/" at the end of cacheFile so far.
+        strncat(cacheFile, "/", kBufLen);
+    }
+
+    // cacheFile = resName + extName
+    //
+    strncat(cacheFile, resName, kBufLen);
+    if (extName != NULL) {
+        // TODO(srhines): strncat() is a bit dangerous
+        strncat(cacheFile, extName, kBufLen);
+    }
+
+    // Turn the path into a flat filename by replacing
+    // any slashes after the first one with '@' characters.
+    char *cp = cacheFile + 1;
+    while (*cp != '\0') {
+        if (*cp == '/') {
+            *cp = '@';
+        }
+        cp++;
+    }
+
+    // Tack on the file name for the actual cache file path.
+    strncpy(cachePath, cacheDir, kBufLen);
+    strncat(cachePath, cacheFile, kBufLen);
+
+    LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath);
+    return strdup(cachePath);
+}
 
 ScriptC::ScriptC(Context *rsc) : Script(rsc) {
+    LOGD(">>>> ScriptC ctor called, obj=%p", this);
     mBccScript = NULL;
     memset(&mProgram, 0, sizeof(mProgram));
 }
 
 ScriptC::~ScriptC() {
+    LOGD(">>>> ~ScriptC() mBccScript = %p", mBccScript);
     if (mBccScript) {
-        bccDeleteScript(mBccScript);
+        bccDisposeScript(mBccScript);
+        LOGD(">>>> ~ScriptC(mBCCScript)");
     }
     free(mEnviroment.mScriptText);
     mEnviroment.mScriptText = NULL;
@@ -375,11 +438,11 @@
     mScript.set(new ScriptC(rsc));
 }
 
-static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name) {
+static void* symbolLookup(void* pContext, char const* name) {
     const ScriptCState::SymbolTable_t *sym;
     ScriptC *s = (ScriptC *)pContext;
     if (!strcmp(name, "__isThreadable")) {
-      return (BCCvoid*) s->mEnviroment.mIsThreadable;
+      return (void*) s->mEnviroment.mIsThreadable;
     } else if (!strcmp(name, "__clearThreadable")) {
       s->mEnviroment.mIsThreadable = false;
       return NULL;
@@ -399,31 +462,51 @@
     return NULL;
 }
 
+#if 0
 extern const char rs_runtime_lib_bc[];
 extern unsigned rs_runtime_lib_bc_size;
+#endif
 
-void ScriptCState::runCompiler(Context *rsc, ScriptC *s, const char *resName, const char *cacheDir) {
+void ScriptCState::runCompiler(Context *rsc,
+                               ScriptC *s,
+                               const char *resName,
+                               const char *cacheDir) {
     {
         s->mBccScript = bccCreateScript();
+
         s->mEnviroment.mIsThreadable = true;
+
         bccRegisterSymbolCallback(s->mBccScript, symbolLookup, s);
-        // bccReadBC() reads in the BitCode, if no cache file corresponding to
-        // the resName is found. Otherwise, bccReadBC() returns a negative value
-        // and the "else" branch will be taken.
+
         if (bccReadBC(s->mBccScript,
-                      s->mEnviroment.mScriptText,
-                      s->mEnviroment.mScriptTextLength,
                       resName,
-                      cacheDir) >= 0) {
-          //bccLinkBC(s->mBccScript, rs_runtime_lib_bc, rs_runtime_lib_bc_size);
-          bccCompileBC(s->mBccScript);
-        } else {
-          // bccReadBC returns a neagative value: Didn't read any script,
-          // So, use cached binary instead
-          bccLoadBinary(s->mBccScript);
+                      s->mEnviroment.mScriptText,
+                      s->mEnviroment.mScriptTextLength, 0) != 0) {
+            LOGE("bcc: FAILS to read bitcode");
+            // Handle Fatal Error
         }
-        bccGetScriptLabel(s->mBccScript, "root", (BCCvoid**) &s->mProgram.mRoot);
-        bccGetScriptLabel(s->mBccScript, "init", (BCCvoid**) &s->mProgram.mInit);
+
+#if 1
+        if (bccLinkBC(s->mBccScript,
+                      resName,
+                      NULL /*rs_runtime_lib_bc*/,
+                      0 /*rs_runtime_lib_bc_size*/,
+                      0) != 0) {
+            LOGE("bcc: FAILS to link bitcode");
+            // Handle Fatal Error
+        }
+#endif
+        char *cachePath = genCacheFileName(cacheDir, resName, ".oBCC");
+
+        if (bccPrepareExecutable(s->mBccScript, cachePath, 0) != 0) {
+            LOGE("bcc: FAILS to prepare executable");
+            // Handle Fatal Error
+        }
+
+        free(cachePath);
+
+        s->mProgram.mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(s->mBccScript, "root"));
+        s->mProgram.mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(s->mBccScript, "init"));
     }
     LOGV("%p ScriptCState::runCompiler root %p,  init %p", rsc, s->mProgram.mRoot, s->mProgram.mInit);
 
@@ -431,20 +514,20 @@
         s->mProgram.mInit();
     }
 
-    bccGetExportFuncs(s->mBccScript, (BCCsizei*) &s->mEnviroment.mInvokeFunctionCount, 0, NULL);
+    s->mEnviroment.mInvokeFunctionCount = bccGetExportFuncCount(s->mBccScript);
     if (s->mEnviroment.mInvokeFunctionCount <= 0)
         s->mEnviroment.mInvokeFunctions = NULL;
     else {
         s->mEnviroment.mInvokeFunctions = (Script::InvokeFunc_t*) calloc(s->mEnviroment.mInvokeFunctionCount, sizeof(Script::InvokeFunc_t));
-        bccGetExportFuncs(s->mBccScript, NULL, s->mEnviroment.mInvokeFunctionCount, (BCCvoid **) s->mEnviroment.mInvokeFunctions);
+        bccGetExportFuncList(s->mBccScript, s->mEnviroment.mInvokeFunctionCount, (void **) s->mEnviroment.mInvokeFunctions);
     }
 
-    bccGetExportVars(s->mBccScript, (BCCsizei*) &s->mEnviroment.mFieldCount, 0, NULL);
+    s->mEnviroment.mFieldCount = bccGetExportVarCount(s->mBccScript);
     if (s->mEnviroment.mFieldCount <= 0)
         s->mEnviroment.mFieldAddress = NULL;
     else {
         s->mEnviroment.mFieldAddress = (void **) calloc(s->mEnviroment.mFieldCount, sizeof(void *));
-        bccGetExportVars(s->mBccScript, NULL, s->mEnviroment.mFieldCount, (BCCvoid **) s->mEnviroment.mFieldAddress);
+        bccGetExportVarList(s->mBccScript, s->mEnviroment.mFieldCount, (void **) s->mEnviroment.mFieldAddress);
         s->initSlots();
     }
 
@@ -455,65 +538,64 @@
 
     if (s->mProgram.mRoot) {
         const static int pragmaMax = 16;
-        BCCsizei pragmaCount;
-        BCCchar * str[pragmaMax];
-        bccGetPragmas(s->mBccScript, &pragmaCount, pragmaMax, &str[0]);
+        size_t pragmaCount = bccGetPragmaCount(s->mBccScript);
+        char const *keys[pragmaMax];
+        char const *values[pragmaMax];
+        bccGetPragmaList(s->mBccScript, pragmaMax, keys, values);
 
-        for (int ct=0; ct < pragmaCount; ct+=2) {
-            //LOGE("pragme %s %s", str[ct], str[ct+1]);
-            if (!strcmp(str[ct], "version")) {
+        for (size_t i=0; i < pragmaCount; ++i) {
+            //LOGE("pragma %s %s", keys[i], values[i]);
+            if (!strcmp(keys[i], "version")) {
                 continue;
             }
 
-            if (!strcmp(str[ct], "stateVertex")) {
-                if (!strcmp(str[ct+1], "default")) {
+            if (!strcmp(keys[i], "stateVertex")) {
+                if (!strcmp(values[i], "default")) {
                     continue;
                 }
-                if (!strcmp(str[ct+1], "parent")) {
+                if (!strcmp(values[i], "parent")) {
                     s->mEnviroment.mVertex.clear();
                     continue;
                 }
-                LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
+                LOGE("Unreconized value %s passed to stateVertex", values[i]);
             }
 
-            if (!strcmp(str[ct], "stateRaster")) {
-                if (!strcmp(str[ct+1], "default")) {
+            if (!strcmp(keys[i], "stateRaster")) {
+                if (!strcmp(values[i], "default")) {
                     continue;
                 }
-                if (!strcmp(str[ct+1], "parent")) {
+                if (!strcmp(values[i], "parent")) {
                     s->mEnviroment.mRaster.clear();
                     continue;
                 }
-                LOGE("Unreconized value %s passed to stateRaster", str[ct+1]);
+                LOGE("Unreconized value %s passed to stateRaster", values[i]);
             }
 
-            if (!strcmp(str[ct], "stateFragment")) {
-                if (!strcmp(str[ct+1], "default")) {
+            if (!strcmp(keys[i], "stateFragment")) {
+                if (!strcmp(values[i], "default")) {
                     continue;
                 }
-                if (!strcmp(str[ct+1], "parent")) {
+                if (!strcmp(values[i], "parent")) {
                     s->mEnviroment.mFragment.clear();
                     continue;
                 }
-                LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
+                LOGE("Unreconized value %s passed to stateFragment", values[i]);
             }
 
-            if (!strcmp(str[ct], "stateStore")) {
-                if (!strcmp(str[ct+1], "default")) {
+            if (!strcmp(keys[i], "stateStore")) {
+                if (!strcmp(values[i], "default")) {
                     continue;
                 }
-                if (!strcmp(str[ct+1], "parent")) {
+                if (!strcmp(values[i], "parent")) {
                     s->mEnviroment.mFragmentStore.clear();
                     continue;
                 }
-                LOGE("Unreconized value %s passed to stateStore", str[ct+1]);
+                LOGE("Unreconized value %s passed to stateStore", values[i]);
             }
-
         }
-
-
     } else {
-        // Deal with an error.
+        LOGE("bcc: FAILS to prepare executable");
+        // Handle Fatal Error
     }
 }
 
@@ -535,7 +617,11 @@
     ss->mScript->mEnviroment.mScriptTextLength = len;
 }
 
-RsScript rsi_ScriptCCreate(Context * rsc, const char *resName, const char *cacheDir)
+
+RsScript rsi_ScriptCCreate(Context *rsc,
+                           const char *packageName /* deprecated */,
+                           const char *resName,
+                           const char *cacheDir)
 {
     ScriptCState *ss = &rsc->mScriptC;
 
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index a714132..483481e8 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -21,9 +21,7 @@
 
 #include "RenderScriptEnv.h"
 
-namespace bcc {
-class BCCscript;
-}
+#include <bcc/bcc.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -48,7 +46,7 @@
 
     Program_t mProgram;
 
-    bcc::BCCscript* mBccScript;
+    BCCScriptRef mBccScript;
 
     const Allocation *ptrToAllocation(const void *) const;
 
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index f61b983..0b21669 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -100,70 +100,24 @@
 // Time routines
 //////////////////////////////////////////////////////////////////////////////
 
-static int32_t SC_second() {
+static time_t SC_time(time_t *timer) {
     GET_TLS();
-
-    time_t rawtime;
-    time(&rawtime);
-
-    struct tm *timeinfo;
-    timeinfo = localtime(&rawtime);
-    return timeinfo->tm_sec;
+    return time(timer);
 }
 
-static int32_t SC_minute() {
+static tm* SC_localtime(tm *local, time_t *timer) {
     GET_TLS();
+    if (!local) {
+      return NULL;
+    }
 
-    time_t rawtime;
-    time(&rawtime);
-
-    struct tm *timeinfo;
-    timeinfo = localtime(&rawtime);
-    return timeinfo->tm_min;
-}
-
-static int32_t SC_hour() {
-    GET_TLS();
-
-    time_t rawtime;
-    time(&rawtime);
-
-    struct tm *timeinfo;
-    timeinfo = localtime(&rawtime);
-    return timeinfo->tm_hour;
-}
-
-static int32_t SC_day() {
-    GET_TLS();
-
-    time_t rawtime;
-    time(&rawtime);
-
-    struct tm *timeinfo;
-    timeinfo = localtime(&rawtime);
-    return timeinfo->tm_mday;
-}
-
-static int32_t SC_month() {
-    GET_TLS();
-
-    time_t rawtime;
-    time(&rawtime);
-
-    struct tm *timeinfo;
-    timeinfo = localtime(&rawtime);
-    return timeinfo->tm_mon;
-}
-
-static int32_t SC_year() {
-    GET_TLS();
-
-    time_t rawtime;
-    time(&rawtime);
-
-    struct tm *timeinfo;
-    timeinfo = localtime(&rawtime);
-    return timeinfo->tm_year;
+    // The native localtime function is not thread-safe, so we
+    // have to apply locking for proper behavior in RenderScript.
+    pthread_mutex_lock(&rsc->gLibMutex);
+    tm *tmp = localtime(timer);
+    memcpy(local, tmp, sizeof(*tmp));
+    pthread_mutex_unlock(&rsc->gLibMutex);
+    return local;
 }
 
 static int64_t SC_uptimeMillis() {
@@ -498,12 +452,8 @@
     { "_Z6rsFracf", (void *)&SC_frac, true },
 
     // time
-    { "_Z8rsSecondv", (void *)&SC_second, true },
-    { "_Z8rsMinutev", (void *)&SC_minute, true },
-    { "_Z6rsHourv", (void *)&SC_hour, true },
-    { "_Z5rsDayv", (void *)&SC_day, true },
-    { "_Z7rsMonthv", (void *)&SC_month, true },
-    { "_Z6rsYearv", (void *)&SC_year, true },
+    { "_Z6rsTimePi", (void *)&SC_time, true },
+    { "_Z11rsLocaltimeP5rs_tmPKi", (void *)&SC_localtime, true },
     { "_Z14rsUptimeMillisv", (void*)&SC_uptimeMillis, true },
     { "_Z13rsUptimeNanosv", (void*)&SC_uptimeNanos, true },
     { "_Z7rsGetDtv", (void*)&SC_getDt, false },
diff --git a/libs/rs/rsScriptC_LibGL.cpp b/libs/rs/rsScriptC_LibGL.cpp
index fb5980a..48a0969 100644
--- a/libs/rs/rsScriptC_LibGL.cpp
+++ b/libs/rs/rsScriptC_LibGL.cpp
@@ -287,24 +287,6 @@
     static_cast<Allocation *>(va)->syncAll(rsc, source);
 }
 
-static void SC_uploadToTexture2(RsAllocation va, uint32_t baseMipLevel) {
-    CHECK_OBJ(va);
-    GET_TLS();
-    rsi_AllocationUploadToTexture(rsc, va, false, baseMipLevel);
-}
-
-static void SC_uploadToTexture(RsAllocation va) {
-    CHECK_OBJ(va);
-    GET_TLS();
-    rsi_AllocationUploadToTexture(rsc, va, false, 0);
-}
-
-static void SC_uploadToBufferObject(RsAllocation va) {
-    CHECK_OBJ(va);
-    GET_TLS();
-    rsi_AllocationUploadToBufferObject(rsc, va);
-}
-
 static void SC_ClearColor(float r, float g, float b, float a) {
     GET_TLS();
     rsc->setupProgramStore();
@@ -439,10 +421,6 @@
 
     { "_Z20rsgAllocationSyncAll13rs_allocation", (void *)&SC_allocationSyncAll, false },
 
-    { "_Z18rsgUploadToTexture13rs_allocationj", (void *)&SC_uploadToTexture2, false },
-    { "_Z18rsgUploadToTexture13rs_allocation", (void *)&SC_uploadToTexture, false },
-    { "_Z23rsgUploadToBufferObject13rs_allocation", (void *)&SC_uploadToBufferObject, false },
-
     { "_Z11rsgDrawRectfffff", (void *)&SC_drawRect, false },
     { "_Z11rsgDrawQuadffffffffffff", (void *)&SC_drawQuad, false },
     { "_Z20rsgDrawQuadTexCoordsffffffffffffffffffff", (void *)&SC_drawQuadTexCoords, false },
diff --git a/libs/rs/rsShaderCache.cpp b/libs/rs/rsShaderCache.cpp
index 45384c9..b958021 100644
--- a/libs/rs/rsShaderCache.cpp
+++ b/libs/rs/rsShaderCache.cpp
@@ -32,10 +32,7 @@
 }
 
 ShaderCache::~ShaderCache() {
-    for (uint32_t ct=0; ct < mEntries.size(); ct++) {
-        glDeleteProgram(mEntries[ct]->program);
-        free(mEntries[ct]);
-    }
+    cleanupAll();
 }
 
 void ShaderCache::updateUniformArrayData(Context *rsc, Program *prog, uint32_t linkedID,
@@ -251,5 +248,10 @@
 }
 
 void ShaderCache::cleanupAll() {
+    for (uint32_t ct=0; ct < mEntries.size(); ct++) {
+        glDeleteProgram(mEntries[ct]->program);
+        free(mEntries[ct]);
+    }
+    mEntries.clear();
 }
 
diff --git a/libs/rs/rslib.bc b/libs/rs/rslib.bc
deleted file mode 100644
index 1897c3b..0000000
--- a/libs/rs/rslib.bc
+++ /dev/null
Binary files differ
diff --git a/libs/rs/scriptc/rs_cl.rsh b/libs/rs/scriptc/rs_cl.rsh
index 64844a4..a5092b3 100644
--- a/libs/rs/scriptc/rs_cl.rsh
+++ b/libs/rs/scriptc/rs_cl.rsh
@@ -23,8 +23,8 @@
                             CVT_FUNC_2(type, char) \
                             CVT_FUNC_2(type, ushort) \
                             CVT_FUNC_2(type, short) \
-                            CVT_FUNC_2(type, int) \
                             CVT_FUNC_2(type, uint) \
+                            CVT_FUNC_2(type, int) \
                             CVT_FUNC_2(type, float)
 
 CVT_FUNC(char)
@@ -62,6 +62,29 @@
     return r; \
 }
 
+#define DEF_FUNC_1_RI(fnc) \
+static int2 __attribute__((overloadable)) fnc(float2 v) { \
+    int2 r; \
+    r.x = fnc(v.x); \
+    r.y = fnc(v.y); \
+    return r; \
+} \
+static int3 __attribute__((overloadable)) fnc(float3 v) { \
+    int3 r; \
+    r.x = fnc(v.x); \
+    r.y = fnc(v.y); \
+    r.z = fnc(v.z); \
+    return r; \
+} \
+static int4 __attribute__((overloadable)) fnc(float4 v) { \
+    int4 r; \
+    r.x = fnc(v.x); \
+    r.y = fnc(v.y); \
+    r.z = fnc(v.z); \
+    r.w = fnc(v.w); \
+    return r; \
+}
+
 #define DEF_FUNC_2(fnc) \
 static float2 __attribute__((overloadable)) fnc(float2 v1, float2 v2) { \
     float2 r; \
@@ -264,7 +287,7 @@
 DEF_FUNC_2(hypot)
 
 extern int __attribute__((overloadable)) ilogb(float);
-DEF_FUNC_1(ilogb)
+DEF_FUNC_1_RI(ilogb)
 
 extern float __attribute__((overloadable)) ldexp(float, int);
 extern float2 __attribute__((overloadable)) ldexp(float2, int2);
@@ -345,10 +368,10 @@
 extern float __attribute__((overloadable)) remainder(float, float);
 DEF_FUNC_2(remainder)
 
-extern float __attribute__((overloadable)) remquo(float, float, float *);
-extern float2 __attribute__((overloadable)) remquo(float2, float2, float2 *);
-extern float3 __attribute__((overloadable)) remquo(float3, float3, float3 *);
-extern float4 __attribute__((overloadable)) remquo(float4, float4, float4 *);
+extern float __attribute__((overloadable)) remquo(float, float, int *);
+extern float2 __attribute__((overloadable)) remquo(float2, float2, int2 *);
+extern float3 __attribute__((overloadable)) remquo(float3, float3, int3 *);
+extern float4 __attribute__((overloadable)) remquo(float4, float4, int4 *);
 
 extern float __attribute__((overloadable)) rint(float);
 DEF_FUNC_1(rint)
@@ -373,10 +396,10 @@
 DEF_FUNC_1(round)
 
 extern float __attribute__((overloadable)) sqrt(float);
-/*static float __attribute__((overloadable)) rsqrt(float v) {
+static float __attribute__((overloadable)) rsqrt(float v) {
     return 1.f / sqrt(v);
 }
-DEF_FUNC_1(rsqrt)*/
+DEF_FUNC_1(rsqrt)
 
 extern float __attribute__((overloadable)) sin(float);
 DEF_FUNC_1(sin)
@@ -781,5 +804,11 @@
     return v / length(v);
 }
 
+#undef CVT_FUNC
+#undef CVT_FUNC_2
+#undef DEF_FUNC_1
+#undef DEF_FUNC_1_RI
+#undef DEF_FUNC_2
+#undef DEF_FUNC_2F
 
 #endif
diff --git a/libs/rs/scriptc/rs_graphics.rsh b/libs/rs/scriptc/rs_graphics.rsh
index 3e708aa..3868f24 100644
--- a/libs/rs/scriptc/rs_graphics.rsh
+++ b/libs/rs/scriptc/rs_graphics.rsh
@@ -38,13 +38,6 @@
     rsgAllocationSyncAll(rs_allocation);
 
 extern void __attribute__((overloadable))
-    rsgUploadToTexture(rs_allocation);
-extern void __attribute__((overloadable))
-    rsgUploadToTexture(rs_allocation, uint mipLevel);
-extern void __attribute__((overloadable))
-    rsgUploadToBufferObject(rs_allocation);
-
-extern void __attribute__((overloadable))
     rsgDrawRect(float x1, float y1, float x2, float y2, float z);
 extern void __attribute__((overloadable))
     rsgDrawQuad(float x1, float y1, float z1,
diff --git a/libs/rs/scriptc/rs_math.rsh b/libs/rs/scriptc/rs_math.rsh
index d059997..a74c0e0 100644
--- a/libs/rs/scriptc/rs_math.rsh
+++ b/libs/rs/scriptc/rs_math.rsh
@@ -118,32 +118,6 @@
 extern float __attribute__((overloadable))
     rsFrac(float);
 
-// time
-extern int32_t __attribute__((overloadable))
-    rsSecond(void);
-extern int32_t __attribute__((overloadable))
-    rsMinute(void);
-extern int32_t __attribute__((overloadable))
-    rsHour(void);
-extern int32_t __attribute__((overloadable))
-    rsDay(void);
-extern int32_t __attribute__((overloadable))
-    rsMonth(void);
-extern int32_t __attribute__((overloadable))
-    rsYear(void);
-
-// Return the current system clock in milliseconds
-extern int64_t __attribute__((overloadable))
-    rsUptimeMillis(void);
-
-// Return the current system clock in nanoseconds
-extern int64_t __attribute__((overloadable))
-    rsUptimeNanos(void);
-
-// Return the time in seconds since function was last called in this script.
-extern float __attribute__((overloadable))
-    rsGetDt(void);
-
 // Send a message back to the client.  Will not block and returns true
 // if the message was sendable and false if the fifo was full.
 // A message ID is required.  Data payload is optional.
diff --git a/libs/rs/scriptc/rs_time.rsh b/libs/rs/scriptc/rs_time.rsh
new file mode 100644
index 0000000..f1abed63
--- /dev/null
+++ b/libs/rs/scriptc/rs_time.rsh
@@ -0,0 +1,36 @@
+#ifndef __RS_TIME_RSH__
+#define __RS_TIME_RSH__
+
+typedef int rs_time_t;
+
+typedef struct {
+    int tm_sec;
+    int tm_min;
+    int tm_hour;
+    int tm_mday;
+    int tm_mon;
+    int tm_year;
+    int tm_wday;
+    int tm_yday;
+    int tm_isdst;
+} rs_tm;
+
+extern rs_time_t __attribute__((overloadable))
+    rsTime(rs_time_t *timer);
+
+extern rs_tm * __attribute__((overloadable))
+    rsLocaltime(rs_tm *local, const rs_time_t *timer);
+
+// Return the current system clock in milliseconds
+extern int64_t __attribute__((overloadable))
+    rsUptimeMillis(void);
+
+// Return the current system clock in nanoseconds
+extern int64_t __attribute__((overloadable))
+    rsUptimeNanos(void);
+
+// Return the time in seconds since function was last called in this script.
+extern float __attribute__((overloadable))
+    rsGetDt(void);
+
+#endif
diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp
index b5f9c47..7fbf67a 100644
--- a/libs/storage/IMountService.cpp
+++ b/libs/storage/IMountService.cpp
@@ -48,6 +48,8 @@
     TRANSACTION_isObbMounted,
     TRANSACTION_getMountedObbPath,
     TRANSACTION_isExternalStorageEmulated,
+    TRANSACTION_decryptStorage,
+    TRANSACTION_encryptStorage,
 };
 
 class BpMountService: public BpInterface<IMountService>
@@ -504,6 +506,40 @@
         path = reply.readString16();
         return true;
     }
+
+    int32_t decryptStorage(const String16& password)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+        data.writeString16(password);
+        if (remote()->transact(TRANSACTION_decryptStorage, data, &reply) != NO_ERROR) {
+            LOGD("decryptStorage could not contact remote\n");
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        if (err < 0) {
+            LOGD("decryptStorage caught exception %d\n", err);
+            return err;
+        }
+        return reply.readInt32();
+    }
+
+    int32_t encryptStorage(const String16& password)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
+        data.writeString16(password);
+        if (remote()->transact(TRANSACTION_encryptStorage, data, &reply) != NO_ERROR) {
+            LOGD("encryptStorage could not contact remote\n");
+            return -1;
+        }
+        int32_t err = reply.readExceptionCode();
+        if (err < 0) {
+            LOGD("encryptStorage caught exception %d\n", err);
+            return err;
+        }
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MountService, "IMountService");
diff --git a/libs/surfaceflinger_client/Android.mk b/libs/surfaceflinger_client/Android.mk
index ce3c71a..4a0faf0 100644
--- a/libs/surfaceflinger_client/Android.mk
+++ b/libs/surfaceflinger_client/Android.mk
@@ -5,6 +5,7 @@
 	ISurfaceComposer.cpp \
 	ISurface.cpp \
 	ISurfaceComposerClient.cpp \
+	IGraphicBufferAlloc.cpp \
 	LayerState.cpp \
 	SharedBufferStack.cpp \
 	Surface.cpp \
diff --git a/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp b/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp
new file mode 100644
index 0000000..e05da72
--- /dev/null
+++ b/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// tag as surfaceflinger
+#define LOG_TAG "SurfaceFlinger"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <ui/GraphicBuffer.h>
+
+#include <surfaceflinger/IGraphicBufferAlloc.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+enum {
+    CREATE_GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
+    FREE_ALL_GRAPHIC_BUFFERS_EXCEPT,
+};
+
+class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>
+{
+public:
+    BpGraphicBufferAlloc(const sp<IBinder>& impl)
+        : BpInterface<IGraphicBufferAlloc>(impl)
+    {
+    }
+
+    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+            PixelFormat format, uint32_t usage) {
+        Parcel data, reply;
+        data.writeInterfaceToken(
+                IGraphicBufferAlloc::getInterfaceDescriptor());
+        data.writeInt32(w);
+        data.writeInt32(h);
+        data.writeInt32(format);
+        data.writeInt32(usage);
+        remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
+        sp<GraphicBuffer> graphicBuffer;
+        bool nonNull = (bool)reply.readInt32();
+        if (nonNull) {
+            graphicBuffer = new GraphicBuffer();
+            reply.read(*graphicBuffer);
+        }
+        return graphicBuffer;
+    }
+
+    virtual void freeAllGraphicBuffersExcept(int bufIdx) {
+        Parcel data, reply;
+        data.writeInterfaceToken(
+                IGraphicBufferAlloc::getInterfaceDescriptor());
+        data.writeInt32(bufIdx);
+        remote()->transact(FREE_ALL_GRAPHIC_BUFFERS_EXCEPT, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc");
+
+// ----------------------------------------------------------------------
+
+status_t BnGraphicBufferAlloc::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    // codes that don't require permission check
+
+    switch(code) {
+        case CREATE_GRAPHIC_BUFFER: {
+            CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
+            uint32_t w = data.readInt32();
+            uint32_t h = data.readInt32();
+            PixelFormat format = data.readInt32();
+            uint32_t usage = data.readInt32();
+            sp<GraphicBuffer> result(createGraphicBuffer(w, h, format, usage));
+            reply->writeInt32(result != 0);
+            if (result != 0) {
+                reply->write(*result);
+            }
+            return NO_ERROR;
+        } break;
+        case FREE_ALL_GRAPHIC_BUFFERS_EXCEPT: {
+            CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
+            int bufIdx = data.readInt32();
+            freeAllGraphicBuffersExcept(bufIdx);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp
index 0c5d1b4..01ae23f 100644
--- a/libs/surfaceflinger_client/ISurfaceComposer.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp
@@ -64,6 +64,15 @@
         return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
     }
 
+    virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
+    {
+        uint32_t n;
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply);
+        return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder());
+    }
+
     virtual sp<IMemoryHeap> getCblk() const
     {
         Parcel data, reply;
@@ -189,6 +198,11 @@
             sp<IBinder> b = createClientConnection()->asBinder();
             reply->writeStrongBinder(b);
         } break;
+        case CREATE_GRAPHIC_BUFFER_ALLOC: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
+            reply->writeStrongBinder(b);
+        } break;
         case OPEN_GLOBAL_TRANSACTION: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             openGlobalTransaction();
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index aa0c2e8..e21bab7 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -466,7 +466,7 @@
     return mInitCheck == NO_ERROR;
 }
 
-status_t Surface::validate() const
+status_t Surface::validate(bool inCancelBuffer) const
 {
     // check that we initialized ourself properly
     if (mInitCheck != NO_ERROR) {
@@ -476,15 +476,6 @@
 
     // verify the identity of this surface
     uint32_t identity = mSharedBufferClient->getIdentity();
-
-    // this is a bit of a (temporary) special case, identity==0 means that
-    // no operation are allowed from the client (eg: dequeue/queue), this
-    // is used with PUSH_BUFFER surfaces for instance
-    if (identity == 0) {
-        LOGE("[Surface] invalid operation (identity=%u)", mIdentity);
-        return INVALID_OPERATION;
-    }
-
     if (mIdentity != identity) {
         LOGE("[Surface] using an invalid surface, "
                 "identity=%u should be %d",
@@ -492,17 +483,19 @@
         CallStack stack;
         stack.update();
         stack.dump("Surface");
-        return NO_INIT;
+        return BAD_INDEX;
     }
 
     // check the surface didn't become invalid
     status_t err = mSharedBufferClient->getStatus();
     if (err != NO_ERROR) {
-        LOGE("surface (identity=%u) is invalid, err=%d (%s)",
-                mIdentity, err, strerror(-err));
-        CallStack stack;
-        stack.update();
-        stack.dump("Surface");
+        if (!inCancelBuffer) {
+            LOGE("surface (identity=%u) is invalid, err=%d (%s)",
+                    mIdentity, err, strerror(-err));
+            CallStack stack;
+            stack.update();
+            stack.dump("Surface");
+        }
         return err;
     }
 
@@ -633,12 +626,12 @@
 
 int Surface::cancelBuffer(android_native_buffer_t* buffer)
 {
-    status_t err = validate();
+    status_t err = validate(true);
     switch (err) {
     case NO_ERROR:
         // no error, common case
         break;
-    case INVALID_OPERATION:
+    case BAD_INDEX:
         // legitimate errors here
         return err;
     default:
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 4ba8b5b..0d55f08 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -43,16 +43,12 @@
 LOCAL_SRC_FILES:= \
 	$(commonSources) \
 	EGLUtils.cpp \
-	EventHub.cpp \
 	EventRecurrence.cpp \
 	FramebufferNativeWindow.cpp \
 	GraphicBuffer.cpp \
 	GraphicBufferAllocator.cpp \
 	GraphicBufferMapper.cpp \
 	GraphicLog.cpp \
-	InputDispatcher.cpp \
-	InputManager.cpp \
-	InputReader.cpp \
 	InputTransport.cpp \
 	PixelFormat.cpp \
 	Rect.cpp \
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
deleted file mode 100644
index 8f4bac6..0000000
--- a/libs/ui/EventHub.cpp
+++ /dev/null
@@ -1,1092 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-// Handle events, like key input and vsync.
-//
-// The goal is to provide an optimized solution for Linux, not an
-// implementation that works well across all platforms.  We expect
-// events to arrive on file descriptors, so that we can use a select()
-// select() call to sleep.
-//
-// We can't select() on anything but network sockets in Windows, so we
-// provide an alternative implementation of waitEvent for that platform.
-//
-#define LOG_TAG "EventHub"
-
-//#define LOG_NDEBUG 0
-
-#include <ui/EventHub.h>
-#include <hardware_legacy/power.h>
-
-#include <cutils/properties.h>
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <utils/threads.h>
-#include <utils/Errors.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <memory.h>
-#include <errno.h>
-#include <assert.h>
-
-#include <ui/KeyLayoutMap.h>
-#include <ui/KeyCharacterMap.h>
-#include <ui/VirtualKeyMap.h>
-
-#include <string.h>
-#include <stdint.h>
-#include <dirent.h>
-#ifdef HAVE_INOTIFY
-# include <sys/inotify.h>
-#endif
-#ifdef HAVE_ANDROID_OS
-# include <sys/limits.h>        /* not part of Linux */
-#endif
-#include <sys/poll.h>
-#include <sys/ioctl.h>
-
-/* this macro is used to tell if "bit" is set in "array"
- * it selects a byte from the array, and does a boolean AND
- * operation with a byte that only has the relevant bit set.
- * eg. to check for the 12th bit, we do (array[1] & 1<<4)
- */
-#define test_bit(bit, array)    (array[bit/8] & (1<<(bit%8)))
-
-/* this macro computes the number of bytes needed to represent a bit array of the specified size */
-#define sizeof_bit_array(bits)  ((bits + 7) / 8)
-
-#ifndef ABS_MT_TOUCH_MAJOR
-#define ABS_MT_TOUCH_MAJOR      0x30    /* Major axis of touching ellipse */
-#endif
-
-#ifndef ABS_MT_POSITION_X
-#define ABS_MT_POSITION_X       0x35    /* Center X ellipse position */
-#endif
-
-#ifndef ABS_MT_POSITION_Y
-#define ABS_MT_POSITION_Y       0x36    /* Center Y ellipse position */
-#endif
-
-// Fd at index 0 is always reserved for inotify
-#define FIRST_ACTUAL_DEVICE_INDEX 1
-
-#define INDENT "  "
-#define INDENT2 "    "
-#define INDENT3 "      "
-
-namespace android {
-
-static const char *WAKE_LOCK_ID = "KeyEvents";
-static const char *DEVICE_PATH = "/dev/input";
-
-/* return the larger integer */
-static inline int max(int v1, int v2)
-{
-    return (v1 > v2) ? v1 : v2;
-}
-
-static inline const char* toString(bool value) {
-    return value ? "true" : "false";
-}
-
-// --- EventHub::Device ---
-
-EventHub::Device::Device(int fd, int32_t id, const String8& path,
-        const InputDeviceIdentifier& identifier) :
-        next(NULL),
-        fd(fd), id(id), path(path), identifier(identifier),
-        classes(0), keyBitmask(NULL), configuration(NULL), virtualKeyMap(NULL) {
-}
-
-EventHub::Device::~Device() {
-    close();
-    delete[] keyBitmask;
-    delete configuration;
-    delete virtualKeyMap;
-}
-
-void EventHub::Device::close() {
-    if (fd >= 0) {
-        ::close(fd);
-        fd = -1;
-    }
-}
-
-
-// --- EventHub ---
-
-EventHub::EventHub(void) :
-        mError(NO_INIT), mBuiltInKeyboardId(-1), mNextDeviceId(1),
-        mOpeningDevices(0), mClosingDevices(0),
-        mOpened(false), mNeedToSendFinishedDeviceScan(false),
-        mInputBufferIndex(0), mInputBufferCount(0), mInputFdIndex(0) {
-    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
-#ifdef EV_SW
-    memset(mSwitches, 0, sizeof(mSwitches));
-#endif
-}
-
-EventHub::~EventHub(void) {
-    release_wake_lock(WAKE_LOCK_ID);
-    // we should free stuff here...
-}
-
-status_t EventHub::errorCheck() const {
-    return mError;
-}
-
-String8 EventHub::getDeviceName(int32_t deviceId) const {
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device == NULL) return String8();
-    return device->identifier.name;
-}
-
-uint32_t EventHub::getDeviceClasses(int32_t deviceId) const {
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device == NULL) return 0;
-    return device->classes;
-}
-
-void EventHub::getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device && device->configuration) {
-        *outConfiguration = *device->configuration;
-    } else {
-        outConfiguration->clear();
-    }
-}
-
-status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
-        RawAbsoluteAxisInfo* outAxisInfo) const {
-    outAxisInfo->clear();
-
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device == NULL) return -1;
-
-    struct input_absinfo info;
-
-    if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
-        LOGW("Error reading absolute controller %d for device %s fd %d\n",
-             axis, device->identifier.name.string(), device->fd);
-        return -errno;
-    }
-
-    if (info.minimum != info.maximum) {
-        outAxisInfo->valid = true;
-        outAxisInfo->minValue = info.minimum;
-        outAxisInfo->maxValue = info.maximum;
-        outAxisInfo->flat = info.flat;
-        outAxisInfo->fuzz = info.fuzz;
-    }
-    return OK;
-}
-
-int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
-    if (scanCode >= 0 && scanCode <= KEY_MAX) {
-        AutoMutex _l(mLock);
-
-        Device* device = getDeviceLocked(deviceId);
-        if (device != NULL) {
-            return getScanCodeStateLocked(device, scanCode);
-        }
-    }
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getScanCodeStateLocked(Device* device, int32_t scanCode) const {
-    uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
-    memset(key_bitmask, 0, sizeof(key_bitmask));
-    if (ioctl(device->fd,
-               EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
-        return test_bit(scanCode, key_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
-    }
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
-    AutoMutex _l(mLock);
-
-    Device* device = getDeviceLocked(deviceId);
-    if (device != NULL) {
-        return getKeyCodeStateLocked(device, keyCode);
-    }
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getKeyCodeStateLocked(Device* device, int32_t keyCode) const {
-    if (!device->keyMap.haveKeyLayout()) {
-        return AKEY_STATE_UNKNOWN;
-    }
-
-    Vector<int32_t> scanCodes;
-    device->keyMap.keyLayoutMap->findScanCodes(keyCode, &scanCodes);
-
-    uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
-    memset(key_bitmask, 0, sizeof(key_bitmask));
-    if (ioctl(device->fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
-        #if 0
-        for (size_t i=0; i<=KEY_MAX; i++) {
-            LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask));
-        }
-        #endif
-        const size_t N = scanCodes.size();
-        for (size_t i=0; i<N && i<=KEY_MAX; i++) {
-            int32_t sc = scanCodes.itemAt(i);
-            //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask));
-            if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) {
-                return AKEY_STATE_DOWN;
-            }
-        }
-        return AKEY_STATE_UP;
-    }
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
-#ifdef EV_SW
-    if (sw >= 0 && sw <= SW_MAX) {
-        AutoMutex _l(mLock);
-
-        Device* device = getDeviceLocked(deviceId);
-        if (device != NULL) {
-            return getSwitchStateLocked(device, sw);
-        }
-    }
-#endif
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getSwitchStateLocked(Device* device, int32_t sw) const {
-    uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
-    memset(sw_bitmask, 0, sizeof(sw_bitmask));
-    if (ioctl(device->fd,
-               EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
-        return test_bit(sw, sw_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
-    }
-    return AKEY_STATE_UNKNOWN;
-}
-
-bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) const {
-    AutoMutex _l(mLock);
-
-    Device* device = getDeviceLocked(deviceId);
-    if (device != NULL) {
-        return markSupportedKeyCodesLocked(device, numCodes, keyCodes, outFlags);
-    }
-    return false;
-}
-
-bool EventHub::markSupportedKeyCodesLocked(Device* device, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) const {
-    if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
-        return false;
-    }
-
-    Vector<int32_t> scanCodes;
-    for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
-        scanCodes.clear();
-
-        status_t err = device->keyMap.keyLayoutMap->findScanCodes(keyCodes[codeIndex], &scanCodes);
-        if (! err) {
-            // check the possible scan codes identified by the layout map against the
-            // map of codes actually emitted by the driver
-            for (size_t sc = 0; sc < scanCodes.size(); sc++) {
-                if (test_bit(scanCodes[sc], device->keyBitmask)) {
-                    outFlags[codeIndex] = 1;
-                    break;
-                }
-            }
-        }
-    }
-    return true;
-}
-
-status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
-        int32_t* outKeycode, uint32_t* outFlags) const
-{
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    
-    if (device && device->keyMap.haveKeyLayout()) {
-        status_t err = device->keyMap.keyLayoutMap->map(scancode, outKeycode, outFlags);
-        if (err == NO_ERROR) {
-            return NO_ERROR;
-        }
-    }
-    
-    if (mBuiltInKeyboardId != -1) {
-        device = getDeviceLocked(mBuiltInKeyboardId);
-        
-        if (device && device->keyMap.haveKeyLayout()) {
-            status_t err = device->keyMap.keyLayoutMap->map(scancode, outKeycode, outFlags);
-            if (err == NO_ERROR) {
-                return NO_ERROR;
-            }
-        }
-    }
-    
-    *outKeycode = 0;
-    *outFlags = 0;
-    return NAME_NOT_FOUND;
-}
-
-void EventHub::addExcludedDevice(const char* deviceName)
-{
-    AutoMutex _l(mLock);
-
-    String8 name(deviceName);
-    mExcludedDevices.push_back(name);
-}
-
-bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device) {
-        uint8_t bitmask[sizeof_bit_array(LED_MAX + 1)];
-        memset(bitmask, 0, sizeof(bitmask));
-        if (ioctl(device->fd, EVIOCGBIT(EV_LED, sizeof(bitmask)), bitmask) >= 0) {
-            if (test_bit(led, bitmask)) {
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
-void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device) {
-        struct input_event ev;
-        ev.time.tv_sec = 0;
-        ev.time.tv_usec = 0;
-        ev.type = EV_LED;
-        ev.code = led;
-        ev.value = on ? 1 : 0;
-
-        ssize_t nWrite;
-        do {
-            nWrite = write(device->fd, &ev, sizeof(struct input_event));
-        } while (nWrite == -1 && errno == EINTR);
-    }
-}
-
-void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
-        Vector<VirtualKeyDefinition>& outVirtualKeys) const {
-    outVirtualKeys.clear();
-
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device && device->virtualKeyMap) {
-        outVirtualKeys.appendVector(device->virtualKeyMap->getVirtualKeys());
-    }
-}
-
-EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
-    if (deviceId == 0) {
-        deviceId = mBuiltInKeyboardId;
-    }
-
-    size_t numDevices = mDevices.size();
-    for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < numDevices; i++) {
-        Device* device = mDevices[i];
-        if (device->id == deviceId) {
-            return device;
-        }
-    }
-    return NULL;
-}
-
-bool EventHub::getEvent(RawEvent* outEvent) {
-    outEvent->deviceId = 0;
-    outEvent->type = 0;
-    outEvent->scanCode = 0;
-    outEvent->keyCode = 0;
-    outEvent->flags = 0;
-    outEvent->value = 0;
-    outEvent->when = 0;
-
-    // Note that we only allow one caller to getEvent(), so don't need
-    // to do locking here...  only when adding/removing devices.
-
-    if (!mOpened) {
-        mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
-        mOpened = true;
-        mNeedToSendFinishedDeviceScan = true;
-    }
-
-    for (;;) {
-        // Report any devices that had last been added/removed.
-        if (mClosingDevices != NULL) {
-            Device* device = mClosingDevices;
-            LOGV("Reporting device closed: id=%d, name=%s\n",
-                 device->id, device->path.string());
-            mClosingDevices = device->next;
-            if (device->id == mBuiltInKeyboardId) {
-                outEvent->deviceId = 0;
-            } else {
-                outEvent->deviceId = device->id;
-            }
-            outEvent->type = DEVICE_REMOVED;
-            outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
-            delete device;
-            mNeedToSendFinishedDeviceScan = true;
-            return true;
-        }
-
-        if (mOpeningDevices != NULL) {
-            Device* device = mOpeningDevices;
-            LOGV("Reporting device opened: id=%d, name=%s\n",
-                 device->id, device->path.string());
-            mOpeningDevices = device->next;
-            if (device->id == mBuiltInKeyboardId) {
-                outEvent->deviceId = 0;
-            } else {
-                outEvent->deviceId = device->id;
-            }
-            outEvent->type = DEVICE_ADDED;
-            outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
-            mNeedToSendFinishedDeviceScan = true;
-            return true;
-        }
-
-        if (mNeedToSendFinishedDeviceScan) {
-            mNeedToSendFinishedDeviceScan = false;
-            outEvent->type = FINISHED_DEVICE_SCAN;
-            outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
-            return true;
-        }
-
-        // Grab the next input event.
-        for (;;) {
-            // Consume buffered input events, if any.
-            if (mInputBufferIndex < mInputBufferCount) {
-                const struct input_event& iev = mInputBufferData[mInputBufferIndex++];
-                const Device* device = mDevices[mInputFdIndex];
-
-                LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d", device->path.string(),
-                     (int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value);
-                if (device->id == mBuiltInKeyboardId) {
-                    outEvent->deviceId = 0;
-                } else {
-                    outEvent->deviceId = device->id;
-                }
-                outEvent->type = iev.type;
-                outEvent->scanCode = iev.code;
-                outEvent->flags = 0;
-                if (iev.type == EV_KEY) {
-                    outEvent->keyCode = AKEYCODE_UNKNOWN;
-                    if (device->keyMap.haveKeyLayout()) {
-                        status_t err = device->keyMap.keyLayoutMap->map(iev.code,
-                                &outEvent->keyCode, &outEvent->flags);
-                        LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n",
-                                iev.code, outEvent->keyCode, outEvent->flags, err);
-                    }
-                } else {
-                    outEvent->keyCode = iev.code;
-                }
-                outEvent->value = iev.value;
-
-                // Use an event timestamp in the same timebase as
-                // java.lang.System.nanoTime() and android.os.SystemClock.uptimeMillis()
-                // as expected by the rest of the system.
-                outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
-                return true;
-            }
-
-            // Finish reading all events from devices identified in previous poll().
-            // This code assumes that mInputDeviceIndex is initially 0 and that the
-            // revents member of pollfd is initialized to 0 when the device is first added.
-            // Since mFds[0] is used for inotify, we process regular events starting at index 1.
-            mInputFdIndex += 1;
-            if (mInputFdIndex >= mFds.size()) {
-                break;
-            }
-
-            const struct pollfd& pfd = mFds[mInputFdIndex];
-            if (pfd.revents & POLLIN) {
-                int32_t readSize = read(pfd.fd, mInputBufferData,
-                        sizeof(struct input_event) * INPUT_BUFFER_SIZE);
-                if (readSize < 0) {
-                    if (errno != EAGAIN && errno != EINTR) {
-                        LOGW("could not get event (errno=%d)", errno);
-                    }
-                } else if ((readSize % sizeof(struct input_event)) != 0) {
-                    LOGE("could not get event (wrong size: %d)", readSize);
-                } else {
-                    mInputBufferCount = size_t(readSize) / sizeof(struct input_event);
-                    mInputBufferIndex = 0;
-                }
-            }
-        }
-
-#if HAVE_INOTIFY
-        // readNotify() will modify mFDs and mFDCount, so this must be done after
-        // processing all other events.
-        if(mFds[0].revents & POLLIN) {
-            readNotify(mFds[0].fd);
-            mFds.editItemAt(0).revents = 0;
-            continue; // report added or removed devices immediately
-        }
-#endif
-
-        mInputFdIndex = 0;
-
-        // Poll for events.  Mind the wake lock dance!
-        // We hold a wake lock at all times except during poll().  This works due to some
-        // subtle choreography.  When a device driver has pending (unread) events, it acquires
-        // a kernel wake lock.  However, once the last pending event has been read, the device
-        // driver will release the kernel wake lock.  To prevent the system from going to sleep
-        // when this happens, the EventHub holds onto its own user wake lock while the client
-        // is processing events.  Thus the system can only sleep if there are no events
-        // pending or currently being processed.
-        release_wake_lock(WAKE_LOCK_ID);
-
-        int pollResult = poll(mFds.editArray(), mFds.size(), -1);
-
-        acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
-
-        if (pollResult <= 0) {
-            if (errno != EINTR) {
-                LOGW("poll failed (errno=%d)\n", errno);
-                usleep(100000);
-            }
-        }
-    }
-}
-
-/*
- * Open the platform-specific input device.
- */
-bool EventHub::openPlatformInput(void) {
-    /*
-     * Open platform-specific input device(s).
-     */
-    int res, fd;
-
-#ifdef HAVE_INOTIFY
-    fd = inotify_init();
-    res = inotify_add_watch(fd, DEVICE_PATH, IN_DELETE | IN_CREATE);
-    if(res < 0) {
-        LOGE("could not add watch for %s, %s\n", DEVICE_PATH, strerror(errno));
-    }
-#else
-    /*
-     * The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd.
-     * We allocate space for it and set it to something invalid.
-     */
-    fd = -1;
-#endif
-
-    // Reserve fd index 0 for inotify.
-    struct pollfd pollfd;
-    pollfd.fd = fd;
-    pollfd.events = POLLIN;
-    pollfd.revents = 0;
-    mFds.push(pollfd);
-    mDevices.push(NULL);
-
-    res = scanDir(DEVICE_PATH);
-    if(res < 0) {
-        LOGE("scan dir failed for %s\n", DEVICE_PATH);
-    }
-
-    return true;
-}
-
-// ----------------------------------------------------------------------------
-
-static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) {
-    const uint8_t* end = array + endIndex;
-    array += startIndex;
-    while (array != end) {
-        if (*(array++) != 0) {
-            return true;
-        }
-    }
-    return false;
-}
-
-static const int32_t GAMEPAD_KEYCODES[] = {
-        AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C,
-        AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z,
-        AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1,
-        AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2,
-        AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR,
-        AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE
-};
-
-int EventHub::openDevice(const char *devicePath) {
-    char buffer[80];
-
-    LOGV("Opening device: %s", devicePath);
-
-    AutoMutex _l(mLock);
-
-    int fd = open(devicePath, O_RDWR);
-    if(fd < 0) {
-        LOGE("could not open %s, %s\n", devicePath, strerror(errno));
-        return -1;
-    }
-
-    InputDeviceIdentifier identifier;
-
-    // Get device name.
-    if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
-        //fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
-    } else {
-        buffer[sizeof(buffer) - 1] = '\0';
-        identifier.name.setTo(buffer);
-    }
-
-    // Check to see if the device is on our excluded list
-    List<String8>::iterator iter = mExcludedDevices.begin();
-    List<String8>::iterator end = mExcludedDevices.end();
-    for ( ; iter != end; iter++) {
-        const char* test = *iter;
-        if (identifier.name == test) {
-            LOGI("ignoring event id %s driver %s\n", devicePath, test);
-            close(fd);
-            return -1;
-        }
-    }
-
-    // Get device driver version.
-    int driverVersion;
-    if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
-        LOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
-        close(fd);
-        return -1;
-    }
-
-    // Get device identifier.
-    struct input_id inputId;
-    if(ioctl(fd, EVIOCGID, &inputId)) {
-        LOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
-        close(fd);
-        return -1;
-    }
-    identifier.bus = inputId.bustype;
-    identifier.product = inputId.product;
-    identifier.vendor = inputId.vendor;
-    identifier.version = inputId.version;
-
-    // Get device physical location.
-    if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
-        //fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
-    } else {
-        buffer[sizeof(buffer) - 1] = '\0';
-        identifier.location.setTo(buffer);
-    }
-
-    // Get device unique id.
-    if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
-        //fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
-    } else {
-        buffer[sizeof(buffer) - 1] = '\0';
-        identifier.uniqueId.setTo(buffer);
-    }
-
-    // Make file descriptor non-blocking for use with poll().
-    if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
-        LOGE("Error %d making device file descriptor non-blocking.", errno);
-        close(fd);
-        return -1;
-    }
-
-    // Allocate device.  (The device object takes ownership of the fd at this point.)
-    int32_t deviceId = mNextDeviceId++;
-    Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
-
-#if 0
-    LOGI("add device %d: %s\n", deviceId, devicePath);
-    LOGI("  bus:       %04x\n"
-         "  vendor     %04x\n"
-         "  product    %04x\n"
-         "  version    %04x\n",
-        identifier.bus, identifier.vendor, identifier.product, identifier.version);
-    LOGI("  name:      \"%s\"\n", identifier.name.string());
-    LOGI("  location:  \"%s\"\n", identifier.location.string());
-    LOGI("  unique id: \"%s\"\n", identifier.uniqueId.string());
-    LOGI("  driver:    v%d.%d.%d\n",
-        driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
-#endif
-
-    // Load the configuration file for the device.
-    loadConfiguration(device);
-
-    // Figure out the kinds of events the device reports.
-    
-    uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
-    memset(key_bitmask, 0, sizeof(key_bitmask));
-
-    LOGV("Getting keys...");
-    if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
-        //LOGI("MAP\n");
-        //for (int i = 0; i < sizeof(key_bitmask); i++) {
-        //    LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
-        //}
-
-        // See if this is a keyboard.  Ignore everything in the button range except for
-        // gamepads which are also considered keyboards.
-        if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
-                || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),
-                        sizeof_bit_array(BTN_DIGI))
-                || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
-                        sizeof_bit_array(KEY_MAX + 1))) {
-            device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
-
-            device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
-            if (device->keyBitmask != NULL) {
-                memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
-            } else {
-                delete device;
-                LOGE("out of memory allocating key bitmask");
-                return -1;
-            }
-        }
-    }
-    
-    // See if this is a trackball (or mouse).
-    if (test_bit(BTN_MOUSE, key_bitmask)) {
-        uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)];
-        memset(rel_bitmask, 0, sizeof(rel_bitmask));
-        LOGV("Getting relative controllers...");
-        if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) {
-            if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
-                device->classes |= INPUT_DEVICE_CLASS_TRACKBALL;
-            }
-        }
-    }
-
-    // See if this is a touch pad.
-    uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];
-    memset(abs_bitmask, 0, sizeof(abs_bitmask));
-    LOGV("Getting absolute controllers...");
-    if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {
-        // Is this a new modern multi-touch driver?
-        if (test_bit(ABS_MT_POSITION_X, abs_bitmask)
-                && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
-            device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT;
-
-        // Is this an old style single-touch driver?
-        } else if (test_bit(BTN_TOUCH, key_bitmask)
-                && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
-            device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN;
-        }
-    }
-
-#ifdef EV_SW
-    // figure out the switches this device reports
-    uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
-    memset(sw_bitmask, 0, sizeof(sw_bitmask));
-    bool hasSwitches = false;
-    if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
-        for (int i=0; i<EV_SW; i++) {
-            //LOGI("Device %d sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
-            if (test_bit(i, sw_bitmask)) {
-                hasSwitches = true;
-                if (mSwitches[i] == 0) {
-                    mSwitches[i] = device->id;
-                }
-            }
-        }
-    }
-    if (hasSwitches) {
-        device->classes |= INPUT_DEVICE_CLASS_SWITCH;
-    }
-#endif
-
-    if ((device->classes & INPUT_DEVICE_CLASS_TOUCHSCREEN)) {
-        // Load the virtual keys for the touch screen, if any.
-        // We do this now so that we can make sure to load the keymap if necessary.
-        status_t status = loadVirtualKeyMap(device);
-        if (!status) {
-            device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
-        }
-    }
-
-    if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
-        // Load the keymap for the device.
-        status_t status = loadKeyMap(device);
-
-        // Set system properties for the keyboard.
-        setKeyboardProperties(device, false);
-
-        // Register the keyboard as a built-in keyboard if it is eligible.
-        if (!status
-                && mBuiltInKeyboardId == -1
-                && isEligibleBuiltInKeyboard(device->identifier,
-                        device->configuration, &device->keyMap)) {
-            mBuiltInKeyboardId = device->id;
-            setKeyboardProperties(device, true);
-        }
-
-        // 'Q' key support = cheap test of whether this is an alpha-capable kbd
-        if (hasKeycodeLocked(device, AKEYCODE_Q)) {
-            device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
-        }
-
-        // See if this device has a DPAD.
-        if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
-                hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
-                hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
-                hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
-                hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
-            device->classes |= INPUT_DEVICE_CLASS_DPAD;
-        }
-
-        // See if this device has a gamepad.
-        for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
-            if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
-                device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
-                break;
-            }
-        }
-    }
-
-    // If the device isn't recognized as something we handle, don't monitor it.
-    if (device->classes == 0) {
-        LOGV("Dropping device: id=%d, path='%s', name='%s'",
-                deviceId, devicePath, device->identifier.name.string());
-        delete device;
-        return -1;
-    }
-
-    LOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
-            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s",
-         deviceId, fd, devicePath, device->identifier.name.string(),
-         device->classes,
-         device->configurationFile.string(),
-         device->keyMap.keyLayoutFile.string(),
-         device->keyMap.keyCharacterMapFile.string(),
-         toString(mBuiltInKeyboardId == deviceId));
-
-    struct pollfd pollfd;
-    pollfd.fd = fd;
-    pollfd.events = POLLIN;
-    pollfd.revents = 0;
-    mFds.push(pollfd);
-    mDevices.push(device);
-
-    device->next = mOpeningDevices;
-    mOpeningDevices = device;
-    return 0;
-}
-
-void EventHub::loadConfiguration(Device* device) {
-    device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
-            device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
-    if (device->configurationFile.isEmpty()) {
-        LOGD("No input device configuration file found for device '%s'.",
-                device->identifier.name.string());
-    } else {
-        status_t status = PropertyMap::load(device->configurationFile,
-                &device->configuration);
-        if (status) {
-            LOGE("Error loading input device configuration file for device '%s'.  "
-                    "Using default configuration.",
-                    device->identifier.name.string());
-        }
-    }
-}
-
-status_t EventHub::loadVirtualKeyMap(Device* device) {
-    // The virtual key map is supplied by the kernel as a system board property file.
-    String8 path;
-    path.append("/sys/board_properties/virtualkeys.");
-    path.append(device->identifier.name);
-    if (access(path.string(), R_OK)) {
-        return NAME_NOT_FOUND;
-    }
-    return VirtualKeyMap::load(path, &device->virtualKeyMap);
-}
-
-status_t EventHub::loadKeyMap(Device* device) {
-    return device->keyMap.load(device->identifier, device->configuration);
-}
-
-void EventHub::setKeyboardProperties(Device* device, bool builtInKeyboard) {
-    int32_t id = builtInKeyboard ? 0 : device->id;
-    android::setKeyboardProperties(id, device->identifier,
-            device->keyMap.keyLayoutFile, device->keyMap.keyCharacterMapFile);
-}
-
-void EventHub::clearKeyboardProperties(Device* device, bool builtInKeyboard) {
-    int32_t id = builtInKeyboard ? 0 : device->id;
-    android::clearKeyboardProperties(id);
-}
-
-bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
-    if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
-        return false;
-    }
-    
-    Vector<int32_t> scanCodes;
-    device->keyMap.keyLayoutMap->findScanCodes(keycode, &scanCodes);
-    const size_t N = scanCodes.size();
-    for (size_t i=0; i<N && i<=KEY_MAX; i++) {
-        int32_t sc = scanCodes.itemAt(i);
-        if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
-            return true;
-        }
-    }
-    
-    return false;
-}
-
-int EventHub::closeDevice(const char *devicePath) {
-    AutoMutex _l(mLock);
-
-    for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < mDevices.size(); i++) {
-        Device* device = mDevices[i];
-        if (device->path == devicePath) {
-            LOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x\n",
-                 device->path.string(), device->identifier.name.string(), device->id,
-                 device->fd, device->classes);
-
-#ifdef EV_SW
-            for (int j=0; j<EV_SW; j++) {
-                if (mSwitches[j] == device->id) {
-                    mSwitches[j] = 0;
-                }
-            }
-#endif
-
-            if (device->id == mBuiltInKeyboardId) {
-                LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
-                        device->path.string(), mBuiltInKeyboardId);
-                mBuiltInKeyboardId = -1;
-                clearKeyboardProperties(device, true);
-            }
-            clearKeyboardProperties(device, false);
-
-            mFds.removeAt(i);
-            mDevices.removeAt(i);
-            device->close();
-
-            device->next = mClosingDevices;
-            mClosingDevices = device;
-            return 0;
-        }
-    }
-    LOGE("remove device: %s not found\n", devicePath);
-    return -1;
-}
-
-int EventHub::readNotify(int nfd) {
-#ifdef HAVE_INOTIFY
-    int res;
-    char devname[PATH_MAX];
-    char *filename;
-    char event_buf[512];
-    int event_size;
-    int event_pos = 0;
-    struct inotify_event *event;
-
-    LOGV("EventHub::readNotify nfd: %d\n", nfd);
-    res = read(nfd, event_buf, sizeof(event_buf));
-    if(res < (int)sizeof(*event)) {
-        if(errno == EINTR)
-            return 0;
-        LOGW("could not get event, %s\n", strerror(errno));
-        return 1;
-    }
-    //printf("got %d bytes of event information\n", res);
-
-    strcpy(devname, DEVICE_PATH);
-    filename = devname + strlen(devname);
-    *filename++ = '/';
-
-    while(res >= (int)sizeof(*event)) {
-        event = (struct inotify_event *)(event_buf + event_pos);
-        //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
-        if(event->len) {
-            strcpy(filename, event->name);
-            if(event->mask & IN_CREATE) {
-                openDevice(devname);
-            }
-            else {
-                closeDevice(devname);
-            }
-        }
-        event_size = sizeof(*event) + event->len;
-        res -= event_size;
-        event_pos += event_size;
-    }
-#endif
-    return 0;
-}
-
-int EventHub::scanDir(const char *dirname)
-{
-    char devname[PATH_MAX];
-    char *filename;
-    DIR *dir;
-    struct dirent *de;
-    dir = opendir(dirname);
-    if(dir == NULL)
-        return -1;
-    strcpy(devname, dirname);
-    filename = devname + strlen(devname);
-    *filename++ = '/';
-    while((de = readdir(dir))) {
-        if(de->d_name[0] == '.' &&
-           (de->d_name[1] == '\0' ||
-            (de->d_name[1] == '.' && de->d_name[2] == '\0')))
-            continue;
-        strcpy(filename, de->d_name);
-        openDevice(devname);
-    }
-    closedir(dir);
-    return 0;
-}
-
-void EventHub::dump(String8& dump) {
-    dump.append("Event Hub State:\n");
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        dump.appendFormat(INDENT "BuiltInKeyboardId: %d\n", mBuiltInKeyboardId);
-
-        dump.append(INDENT "Devices:\n");
-
-        for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < mDevices.size(); i++) {
-            const Device* device = mDevices[i];
-            if (device) {
-                if (mBuiltInKeyboardId == device->id) {
-                    dump.appendFormat(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
-                            device->id, device->identifier.name.string());
-                } else {
-                    dump.appendFormat(INDENT2 "%d: %s\n", device->id,
-                            device->identifier.name.string());
-                }
-                dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
-                dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
-                dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
-                dump.appendFormat(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string());
-                dump.appendFormat(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
-                        "product=0x%04x, version=0x%04x\n",
-                        device->identifier.bus, device->identifier.vendor,
-                        device->identifier.product, device->identifier.version);
-                dump.appendFormat(INDENT3 "KeyLayoutFile: %s\n",
-                        device->keyMap.keyLayoutFile.string());
-                dump.appendFormat(INDENT3 "KeyCharacterMapFile: %s\n",
-                        device->keyMap.keyCharacterMapFile.string());
-                dump.appendFormat(INDENT3 "ConfigurationFile: %s\n",
-                        device->configurationFile.string());
-            }
-        }
-    } // release lock
-}
-
-}; // namespace android
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
deleted file mode 100644
index ed0cb8e..0000000
--- a/libs/ui/InputDispatcher.cpp
+++ /dev/null
@@ -1,3710 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-// The input dispatcher.
-//
-#define LOG_TAG "InputDispatcher"
-
-//#define LOG_NDEBUG 0
-
-// Log detailed debug messages about each inbound event notification to the dispatcher.
-#define DEBUG_INBOUND_EVENT_DETAILS 0
-
-// Log detailed debug messages about each outbound event processed by the dispatcher.
-#define DEBUG_OUTBOUND_EVENT_DETAILS 0
-
-// Log debug messages about batching.
-#define DEBUG_BATCHING 0
-
-// Log debug messages about the dispatch cycle.
-#define DEBUG_DISPATCH_CYCLE 0
-
-// Log debug messages about registrations.
-#define DEBUG_REGISTRATION 0
-
-// Log debug messages about performance statistics.
-#define DEBUG_PERFORMANCE_STATISTICS 0
-
-// Log debug messages about input event injection.
-#define DEBUG_INJECTION 0
-
-// Log debug messages about input event throttling.
-#define DEBUG_THROTTLING 0
-
-// Log debug messages about input focus tracking.
-#define DEBUG_FOCUS 0
-
-// Log debug messages about the app switch latency optimization.
-#define DEBUG_APP_SWITCH 0
-
-#include <cutils/log.h>
-#include <ui/InputDispatcher.h>
-#include <ui/PowerManager.h>
-
-#include <stddef.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-
-#define INDENT "  "
-#define INDENT2 "    "
-
-namespace android {
-
-// Default input dispatching timeout if there is no focused application or paused window
-// from which to determine an appropriate dispatching timeout.
-const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
-
-// Amount of time to allow for all pending events to be processed when an app switch
-// key is on the way.  This is used to preempt input dispatch and drop input events
-// when an application takes too long to respond and the user has pressed an app switch key.
-const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
-
-
-static inline nsecs_t now() {
-    return systemTime(SYSTEM_TIME_MONOTONIC);
-}
-
-static inline const char* toString(bool value) {
-    return value ? "true" : "false";
-}
-
-static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
-    return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
-            >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-}
-
-static bool isValidKeyAction(int32_t action) {
-    switch (action) {
-    case AKEY_EVENT_ACTION_DOWN:
-    case AKEY_EVENT_ACTION_UP:
-        return true;
-    default:
-        return false;
-    }
-}
-
-static bool validateKeyEvent(int32_t action) {
-    if (! isValidKeyAction(action)) {
-        LOGE("Key event has invalid action code 0x%x", action);
-        return false;
-    }
-    return true;
-}
-
-static bool isValidMotionAction(int32_t action, size_t pointerCount) {
-    switch (action & AMOTION_EVENT_ACTION_MASK) {
-    case AMOTION_EVENT_ACTION_DOWN:
-    case AMOTION_EVENT_ACTION_UP:
-    case AMOTION_EVENT_ACTION_CANCEL:
-    case AMOTION_EVENT_ACTION_MOVE:
-    case AMOTION_EVENT_ACTION_OUTSIDE:
-        return true;
-    case AMOTION_EVENT_ACTION_POINTER_DOWN:
-    case AMOTION_EVENT_ACTION_POINTER_UP: {
-        int32_t index = getMotionEventActionPointerIndex(action);
-        return index >= 0 && size_t(index) < pointerCount;
-    }
-    default:
-        return false;
-    }
-}
-
-static bool validateMotionEvent(int32_t action, size_t pointerCount,
-        const int32_t* pointerIds) {
-    if (! isValidMotionAction(action, pointerCount)) {
-        LOGE("Motion event has invalid action code 0x%x", action);
-        return false;
-    }
-    if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
-        LOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.",
-                pointerCount, MAX_POINTERS);
-        return false;
-    }
-    BitSet32 pointerIdBits;
-    for (size_t i = 0; i < pointerCount; i++) {
-        int32_t id = pointerIds[i];
-        if (id < 0 || id > MAX_POINTER_ID) {
-            LOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
-                    id, MAX_POINTER_ID);
-            return false;
-        }
-        if (pointerIdBits.hasBit(id)) {
-            LOGE("Motion event has duplicate pointer id %d", id);
-            return false;
-        }
-        pointerIdBits.markBit(id);
-    }
-    return true;
-}
-
-
-// --- InputWindow ---
-
-bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
-    return x >= touchableAreaLeft && x <= touchableAreaRight
-            && y >= touchableAreaTop && y <= touchableAreaBottom;
-}
-
-bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
-    return x >= frameLeft && x <= frameRight
-            && y >= frameTop && y <= frameBottom;
-}
-
-bool InputWindow::isTrustedOverlay() const {
-    return layoutParamsType == TYPE_INPUT_METHOD
-            || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
-            || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
-}
-
-bool InputWindow::supportsSplitTouch() const {
-    return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
-}
-
-
-// --- InputDispatcher ---
-
-InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
-    mPolicy(policy),
-    mPendingEvent(NULL), mAppSwitchDueTime(LONG_LONG_MAX),
-    mDispatchEnabled(true), mDispatchFrozen(false),
-    mFocusedWindow(NULL),
-    mFocusedApplication(NULL),
-    mCurrentInputTargetsValid(false),
-    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
-    mLooper = new Looper(false);
-
-    mInboundQueue.headSentinel.refCount = -1;
-    mInboundQueue.headSentinel.type = EventEntry::TYPE_SENTINEL;
-    mInboundQueue.headSentinel.eventTime = LONG_LONG_MIN;
-
-    mInboundQueue.tailSentinel.refCount = -1;
-    mInboundQueue.tailSentinel.type = EventEntry::TYPE_SENTINEL;
-    mInboundQueue.tailSentinel.eventTime = LONG_LONG_MAX;
-
-    mKeyRepeatState.lastKeyEntry = NULL;
-
-    int32_t maxEventsPerSecond = policy->getMaxEventsPerSecond();
-    mThrottleState.minTimeBetweenEvents = 1000000000LL / maxEventsPerSecond;
-    mThrottleState.lastDeviceId = -1;
-
-#if DEBUG_THROTTLING
-    mThrottleState.originalSampleCount = 0;
-    LOGD("Throttling - Max events per second = %d", maxEventsPerSecond);
-#endif
-}
-
-InputDispatcher::~InputDispatcher() {
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        resetKeyRepeatLocked();
-        releasePendingEventLocked();
-        drainInboundQueueLocked();
-    }
-
-    while (mConnectionsByReceiveFd.size() != 0) {
-        unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
-    }
-}
-
-void InputDispatcher::dispatchOnce() {
-    nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
-    nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
-
-    nsecs_t nextWakeupTime = LONG_LONG_MAX;
-    { // acquire lock
-        AutoMutex _l(mLock);
-        dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime);
-
-        if (runCommandsLockedInterruptible()) {
-            nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
-        }
-    } // release lock
-
-    // Wait for callback or timeout or wake.  (make sure we round up, not down)
-    nsecs_t currentTime = now();
-    int32_t timeoutMillis;
-    if (nextWakeupTime > currentTime) {
-        uint64_t timeout = uint64_t(nextWakeupTime - currentTime);
-        timeout = (timeout + 999999LL) / 1000000LL;
-        timeoutMillis = timeout > INT_MAX ? -1 : int32_t(timeout);
-    } else {
-        timeoutMillis = 0;
-    }
-
-    mLooper->pollOnce(timeoutMillis);
-}
-
-void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
-        nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime) {
-    nsecs_t currentTime = now();
-
-    // Reset the key repeat timer whenever we disallow key events, even if the next event
-    // is not a key.  This is to ensure that we abort a key repeat if the device is just coming
-    // out of sleep.
-    if (keyRepeatTimeout < 0) {
-        resetKeyRepeatLocked();
-    }
-
-    // If dispatching is frozen, do not process timeouts or try to deliver any new events.
-    if (mDispatchFrozen) {
-#if DEBUG_FOCUS
-        LOGD("Dispatch frozen.  Waiting some more.");
-#endif
-        return;
-    }
-
-    // Optimize latency of app switches.
-    // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
-    // been pressed.  When it expires, we preempt dispatch and drop all other pending events.
-    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
-    if (mAppSwitchDueTime < *nextWakeupTime) {
-        *nextWakeupTime = mAppSwitchDueTime;
-    }
-
-    // Ready to start a new event.
-    // If we don't already have a pending event, go grab one.
-    if (! mPendingEvent) {
-        if (mInboundQueue.isEmpty()) {
-            if (isAppSwitchDue) {
-                // The inbound queue is empty so the app switch key we were waiting
-                // for will never arrive.  Stop waiting for it.
-                resetPendingAppSwitchLocked(false);
-                isAppSwitchDue = false;
-            }
-
-            // Synthesize a key repeat if appropriate.
-            if (mKeyRepeatState.lastKeyEntry) {
-                if (currentTime >= mKeyRepeatState.nextRepeatTime) {
-                    mPendingEvent = synthesizeKeyRepeatLocked(currentTime, keyRepeatDelay);
-                } else {
-                    if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
-                        *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
-                    }
-                }
-            }
-            if (! mPendingEvent) {
-                return;
-            }
-        } else {
-            // Inbound queue has at least one entry.
-            EventEntry* entry = mInboundQueue.headSentinel.next;
-
-            // Throttle the entry if it is a move event and there are no
-            // other events behind it in the queue.  Due to movement batching, additional
-            // samples may be appended to this event by the time the throttling timeout
-            // expires.
-            // TODO Make this smarter and consider throttling per device independently.
-            if (entry->type == EventEntry::TYPE_MOTION
-                    && !isAppSwitchDue
-                    && mDispatchEnabled
-                    && (entry->policyFlags & POLICY_FLAG_PASS_TO_USER)
-                    && !entry->isInjected()) {
-                MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
-                int32_t deviceId = motionEntry->deviceId;
-                uint32_t source = motionEntry->source;
-                if (! isAppSwitchDue
-                        && motionEntry->next == & mInboundQueue.tailSentinel // exactly one event
-                        && motionEntry->action == AMOTION_EVENT_ACTION_MOVE
-                        && deviceId == mThrottleState.lastDeviceId
-                        && source == mThrottleState.lastSource) {
-                    nsecs_t nextTime = mThrottleState.lastEventTime
-                            + mThrottleState.minTimeBetweenEvents;
-                    if (currentTime < nextTime) {
-                        // Throttle it!
-#if DEBUG_THROTTLING
-                        LOGD("Throttling - Delaying motion event for "
-                                "device %d, source 0x%08x by up to %0.3fms.",
-                                deviceId, source, (nextTime - currentTime) * 0.000001);
-#endif
-                        if (nextTime < *nextWakeupTime) {
-                            *nextWakeupTime = nextTime;
-                        }
-                        if (mThrottleState.originalSampleCount == 0) {
-                            mThrottleState.originalSampleCount =
-                                    motionEntry->countSamples();
-                        }
-                        return;
-                    }
-                }
-
-#if DEBUG_THROTTLING
-                if (mThrottleState.originalSampleCount != 0) {
-                    uint32_t count = motionEntry->countSamples();
-                    LOGD("Throttling - Motion event sample count grew by %d from %d to %d.",
-                            count - mThrottleState.originalSampleCount,
-                            mThrottleState.originalSampleCount, count);
-                    mThrottleState.originalSampleCount = 0;
-                }
-#endif
-
-                mThrottleState.lastEventTime = entry->eventTime < currentTime
-                        ? entry->eventTime : currentTime;
-                mThrottleState.lastDeviceId = deviceId;
-                mThrottleState.lastSource = source;
-            }
-
-            mInboundQueue.dequeue(entry);
-            mPendingEvent = entry;
-        }
-
-        // Poke user activity for this event.
-        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
-            pokeUserActivityLocked(mPendingEvent);
-        }
-    }
-
-    // Now we have an event to dispatch.
-    assert(mPendingEvent != NULL);
-    bool done = false;
-    DropReason dropReason = DROP_REASON_NOT_DROPPED;
-    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
-        dropReason = DROP_REASON_POLICY;
-    } else if (!mDispatchEnabled) {
-        dropReason = DROP_REASON_DISABLED;
-    }
-    switch (mPendingEvent->type) {
-    case EventEntry::TYPE_CONFIGURATION_CHANGED: {
-        ConfigurationChangedEntry* typedEntry =
-                static_cast<ConfigurationChangedEntry*>(mPendingEvent);
-        done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
-        dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
-        break;
-    }
-
-    case EventEntry::TYPE_KEY: {
-        KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
-        if (isAppSwitchDue) {
-            if (isAppSwitchKeyEventLocked(typedEntry)) {
-                resetPendingAppSwitchLocked(true);
-                isAppSwitchDue = false;
-            } else if (dropReason == DROP_REASON_NOT_DROPPED) {
-                dropReason = DROP_REASON_APP_SWITCH;
-            }
-        }
-        done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
-                &dropReason, nextWakeupTime);
-        break;
-    }
-
-    case EventEntry::TYPE_MOTION: {
-        MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
-        if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
-            dropReason = DROP_REASON_APP_SWITCH;
-        }
-        done = dispatchMotionLocked(currentTime, typedEntry,
-                &dropReason, nextWakeupTime);
-        break;
-    }
-
-    default:
-        assert(false);
-        break;
-    }
-
-    if (done) {
-        if (dropReason != DROP_REASON_NOT_DROPPED) {
-            dropInboundEventLocked(mPendingEvent, dropReason);
-        }
-
-        releasePendingEventLocked();
-        *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
-    }
-}
-
-bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
-    bool needWake = mInboundQueue.isEmpty();
-    mInboundQueue.enqueueAtTail(entry);
-
-    switch (entry->type) {
-    case EventEntry::TYPE_KEY: {
-        KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
-        if (isAppSwitchKeyEventLocked(keyEntry)) {
-            if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
-                mAppSwitchSawKeyDown = true;
-            } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
-                if (mAppSwitchSawKeyDown) {
-#if DEBUG_APP_SWITCH
-                    LOGD("App switch is pending!");
-#endif
-                    mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
-                    mAppSwitchSawKeyDown = false;
-                    needWake = true;
-                }
-            }
-        }
-        break;
-    }
-    }
-
-    return needWake;
-}
-
-void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
-    const char* reason;
-    switch (dropReason) {
-    case DROP_REASON_POLICY:
-#if DEBUG_INBOUND_EVENT_DETAILS
-        LOGD("Dropped event because policy consumed it.");
-#endif
-        reason = "inbound event was dropped because the policy consumed it";
-        break;
-    case DROP_REASON_DISABLED:
-        LOGI("Dropped event because input dispatch is disabled.");
-        reason = "inbound event was dropped because input dispatch is disabled";
-        break;
-    case DROP_REASON_APP_SWITCH:
-        LOGI("Dropped event because of pending overdue app switch.");
-        reason = "inbound event was dropped because of pending overdue app switch";
-        break;
-    default:
-        assert(false);
-        return;
-    }
-
-    switch (entry->type) {
-    case EventEntry::TYPE_KEY:
-        synthesizeCancelationEventsForAllConnectionsLocked(
-                InputState::CANCEL_NON_POINTER_EVENTS, reason);
-        break;
-    case EventEntry::TYPE_MOTION: {
-        MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
-        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
-            synthesizeCancelationEventsForAllConnectionsLocked(
-                    InputState::CANCEL_POINTER_EVENTS, reason);
-        } else {
-            synthesizeCancelationEventsForAllConnectionsLocked(
-                    InputState::CANCEL_NON_POINTER_EVENTS, reason);
-        }
-        break;
-    }
-    }
-}
-
-bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
-    return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
-}
-
-bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
-    return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
-            && isAppSwitchKeyCode(keyEntry->keyCode)
-            && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
-            && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
-}
-
-bool InputDispatcher::isAppSwitchPendingLocked() {
-    return mAppSwitchDueTime != LONG_LONG_MAX;
-}
-
-void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
-    mAppSwitchDueTime = LONG_LONG_MAX;
-
-#if DEBUG_APP_SWITCH
-    if (handled) {
-        LOGD("App switch has arrived.");
-    } else {
-        LOGD("App switch was abandoned.");
-    }
-#endif
-}
-
-bool InputDispatcher::runCommandsLockedInterruptible() {
-    if (mCommandQueue.isEmpty()) {
-        return false;
-    }
-
-    do {
-        CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
-
-        Command command = commandEntry->command;
-        (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
-
-        commandEntry->connection.clear();
-        mAllocator.releaseCommandEntry(commandEntry);
-    } while (! mCommandQueue.isEmpty());
-    return true;
-}
-
-InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
-    CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
-    mCommandQueue.enqueueAtTail(commandEntry);
-    return commandEntry;
-}
-
-void InputDispatcher::drainInboundQueueLocked() {
-    while (! mInboundQueue.isEmpty()) {
-        EventEntry* entry = mInboundQueue.dequeueAtHead();
-        releaseInboundEventLocked(entry);
-    }
-}
-
-void InputDispatcher::releasePendingEventLocked() {
-    if (mPendingEvent) {
-        releaseInboundEventLocked(mPendingEvent);
-        mPendingEvent = NULL;
-    }
-}
-
-void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
-    InjectionState* injectionState = entry->injectionState;
-    if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
-#if DEBUG_DISPATCH_CYCLE
-        LOGD("Injected inbound event was dropped.");
-#endif
-        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
-    }
-    mAllocator.releaseEventEntry(entry);
-}
-
-void InputDispatcher::resetKeyRepeatLocked() {
-    if (mKeyRepeatState.lastKeyEntry) {
-        mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
-        mKeyRepeatState.lastKeyEntry = NULL;
-    }
-}
-
-InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
-        nsecs_t currentTime, nsecs_t keyRepeatDelay) {
-    KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
-
-    // Reuse the repeated key entry if it is otherwise unreferenced.
-    uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
-            | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
-    if (entry->refCount == 1) {
-        mAllocator.recycleKeyEntry(entry);
-        entry->eventTime = currentTime;
-        entry->policyFlags = policyFlags;
-        entry->repeatCount += 1;
-    } else {
-        KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
-                entry->deviceId, entry->source, policyFlags,
-                entry->action, entry->flags, entry->keyCode, entry->scanCode,
-                entry->metaState, entry->repeatCount + 1, entry->downTime);
-
-        mKeyRepeatState.lastKeyEntry = newEntry;
-        mAllocator.releaseKeyEntry(entry);
-
-        entry = newEntry;
-    }
-    entry->syntheticRepeat = true;
-
-    // Increment reference count since we keep a reference to the event in
-    // mKeyRepeatState.lastKeyEntry in addition to the one we return.
-    entry->refCount += 1;
-
-    if (entry->repeatCount == 1) {
-        entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
-    }
-
-    mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
-    return entry;
-}
-
-bool InputDispatcher::dispatchConfigurationChangedLocked(
-        nsecs_t currentTime, ConfigurationChangedEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-    LOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
-#endif
-
-    // Reset key repeating in case a keyboard device was added or removed or something.
-    resetKeyRepeatLocked();
-
-    // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doNotifyConfigurationChangedInterruptible);
-    commandEntry->eventTime = entry->eventTime;
-    return true;
-}
-
-bool InputDispatcher::dispatchKeyLocked(
-        nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
-        DropReason* dropReason, nsecs_t* nextWakeupTime) {
-    // Preprocessing.
-    if (! entry->dispatchInProgress) {
-        if (entry->repeatCount == 0
-                && entry->action == AKEY_EVENT_ACTION_DOWN
-                && (entry->policyFlags & POLICY_FLAG_TRUSTED)
-                && !entry->isInjected()) {
-            if (mKeyRepeatState.lastKeyEntry
-                    && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
-                // We have seen two identical key downs in a row which indicates that the device
-                // driver is automatically generating key repeats itself.  We take note of the
-                // repeat here, but we disable our own next key repeat timer since it is clear that
-                // we will not need to synthesize key repeats ourselves.
-                entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
-                resetKeyRepeatLocked();
-                mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
-            } else {
-                // Not a repeat.  Save key down state in case we do see a repeat later.
-                resetKeyRepeatLocked();
-                mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
-            }
-            mKeyRepeatState.lastKeyEntry = entry;
-            entry->refCount += 1;
-        } else if (! entry->syntheticRepeat) {
-            resetKeyRepeatLocked();
-        }
-
-        entry->dispatchInProgress = true;
-        resetTargetsLocked();
-
-        logOutboundKeyDetailsLocked("dispatchKey - ", entry);
-    }
-
-    // Give the policy a chance to intercept the key.
-    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
-        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
-            CommandEntry* commandEntry = postCommandLocked(
-                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
-            if (mFocusedWindow) {
-                commandEntry->inputChannel = mFocusedWindow->inputChannel;
-            }
-            commandEntry->keyEntry = entry;
-            entry->refCount += 1;
-            return false; // wait for the command to run
-        } else {
-            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
-        }
-    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
-        if (*dropReason == DROP_REASON_NOT_DROPPED) {
-            *dropReason = DROP_REASON_POLICY;
-        }
-    }
-
-    // Clean up if dropping the event.
-    if (*dropReason != DROP_REASON_NOT_DROPPED) {
-        resetTargetsLocked();
-        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
-                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
-        return true;
-    }
-
-    // Identify targets.
-    if (! mCurrentInputTargetsValid) {
-        int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
-                entry, nextWakeupTime);
-        if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
-            return false;
-        }
-
-        setInjectionResultLocked(entry, injectionResult);
-        if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
-            return true;
-        }
-
-        addMonitoringTargetsLocked();
-        commitTargetsLocked();
-    }
-
-    // Dispatch the key.
-    dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
-    return true;
-}
-
-void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-    LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
-            "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
-            "repeatCount=%d, downTime=%lld",
-            prefix,
-            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
-            entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
-            entry->repeatCount, entry->downTime);
-#endif
-}
-
-bool InputDispatcher::dispatchMotionLocked(
-        nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
-    // Preprocessing.
-    if (! entry->dispatchInProgress) {
-        entry->dispatchInProgress = true;
-        resetTargetsLocked();
-
-        logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
-    }
-
-    // Clean up if dropping the event.
-    if (*dropReason != DROP_REASON_NOT_DROPPED) {
-        resetTargetsLocked();
-        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
-                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
-        return true;
-    }
-
-    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
-
-    // Identify targets.
-    if (! mCurrentInputTargetsValid) {
-        int32_t injectionResult;
-        if (isPointerEvent) {
-            // Pointer event.  (eg. touchscreen)
-            injectionResult = findTouchedWindowTargetsLocked(currentTime,
-                    entry, nextWakeupTime);
-        } else {
-            // Non touch event.  (eg. trackball)
-            injectionResult = findFocusedWindowTargetsLocked(currentTime,
-                    entry, nextWakeupTime);
-        }
-        if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
-            return false;
-        }
-
-        setInjectionResultLocked(entry, injectionResult);
-        if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
-            return true;
-        }
-
-        addMonitoringTargetsLocked();
-        commitTargetsLocked();
-    }
-
-    // Dispatch the motion.
-    dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
-    return true;
-}
-
-
-void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-    LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
-            "action=0x%x, flags=0x%x, "
-            "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
-            prefix,
-            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
-            entry->action, entry->flags,
-            entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
-            entry->downTime);
-
-    // Print the most recent sample that we have available, this may change due to batching.
-    size_t sampleCount = 1;
-    const MotionSample* sample = & entry->firstSample;
-    for (; sample->next != NULL; sample = sample->next) {
-        sampleCount += 1;
-    }
-    for (uint32_t i = 0; i < entry->pointerCount; i++) {
-        LOGD("  Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
-                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
-                "orientation=%f",
-                i, entry->pointerIds[i],
-                sample->pointerCoords[i].x, sample->pointerCoords[i].y,
-                sample->pointerCoords[i].pressure, sample->pointerCoords[i].size,
-                sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor,
-                sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor,
-                sample->pointerCoords[i].orientation);
-    }
-
-    // Keep in mind that due to batching, it is possible for the number of samples actually
-    // dispatched to change before the application finally consumed them.
-    if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
-        LOGD("  ... Total movement samples currently batched %d ...", sampleCount);
-    }
-#endif
-}
-
-void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
-        EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
-#if DEBUG_DISPATCH_CYCLE
-    LOGD("dispatchEventToCurrentInputTargets - "
-            "resumeWithAppendedMotionSample=%s",
-            toString(resumeWithAppendedMotionSample));
-#endif
-
-    assert(eventEntry->dispatchInProgress); // should already have been set to true
-
-    pokeUserActivityLocked(eventEntry);
-
-    for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
-        const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
-
-        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
-        if (connectionIndex >= 0) {
-            sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-            prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
-                    resumeWithAppendedMotionSample);
-        } else {
-#if DEBUG_FOCUS
-            LOGD("Dropping event delivery to target with channel '%s' because it "
-                    "is no longer registered with the input dispatcher.",
-                    inputTarget.inputChannel->getName().string());
-#endif
-        }
-    }
-}
-
-void InputDispatcher::resetTargetsLocked() {
-    mCurrentInputTargetsValid = false;
-    mCurrentInputTargets.clear();
-    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
-}
-
-void InputDispatcher::commitTargetsLocked() {
-    mCurrentInputTargetsValid = true;
-}
-
-int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
-        const EventEntry* entry, const InputApplication* application, const InputWindow* window,
-        nsecs_t* nextWakeupTime) {
-    if (application == NULL && window == NULL) {
-        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
-#if DEBUG_FOCUS
-            LOGD("Waiting for system to become ready for input.");
-#endif
-            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
-            mInputTargetWaitStartTime = currentTime;
-            mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
-            mInputTargetWaitTimeoutExpired = false;
-        }
-    } else {
-        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
-#if DEBUG_FOCUS
-            LOGD("Waiting for application to become ready for input: %s",
-                    getApplicationWindowLabelLocked(application, window).string());
-#endif
-            nsecs_t timeout = window ? window->dispatchingTimeout :
-                application ? application->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
-
-            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
-            mInputTargetWaitStartTime = currentTime;
-            mInputTargetWaitTimeoutTime = currentTime + timeout;
-            mInputTargetWaitTimeoutExpired = false;
-        }
-    }
-
-    if (mInputTargetWaitTimeoutExpired) {
-        return INPUT_EVENT_INJECTION_TIMED_OUT;
-    }
-
-    if (currentTime >= mInputTargetWaitTimeoutTime) {
-        onANRLocked(currentTime, application, window, entry->eventTime, mInputTargetWaitStartTime);
-
-        // Force poll loop to wake up immediately on next iteration once we get the
-        // ANR response back from the policy.
-        *nextWakeupTime = LONG_LONG_MIN;
-        return INPUT_EVENT_INJECTION_PENDING;
-    } else {
-        // Force poll loop to wake up when timeout is due.
-        if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
-            *nextWakeupTime = mInputTargetWaitTimeoutTime;
-        }
-        return INPUT_EVENT_INJECTION_PENDING;
-    }
-}
-
-void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
-        const sp<InputChannel>& inputChannel) {
-    if (newTimeout > 0) {
-        // Extend the timeout.
-        mInputTargetWaitTimeoutTime = now() + newTimeout;
-    } else {
-        // Give up.
-        mInputTargetWaitTimeoutExpired = true;
-
-        // Release the touch targets.
-        mTouchState.reset();
-
-        // Input state will not be realistic.  Mark it out of sync.
-        if (inputChannel.get()) {
-            ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
-            if (connectionIndex >= 0) {
-                sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-                if (connection->status == Connection::STATUS_NORMAL) {
-                    synthesizeCancelationEventsForConnectionLocked(
-                            connection, InputState::CANCEL_ALL_EVENTS,
-                            "application not responding");
-                }
-            }
-        }
-    }
-}
-
-nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
-        nsecs_t currentTime) {
-    if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
-        return currentTime - mInputTargetWaitStartTime;
-    }
-    return 0;
-}
-
-void InputDispatcher::resetANRTimeoutsLocked() {
-#if DEBUG_FOCUS
-        LOGD("Resetting ANR timeouts.");
-#endif
-
-    // Reset input target wait timeout.
-    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
-}
-
-int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
-        const EventEntry* entry, nsecs_t* nextWakeupTime) {
-    mCurrentInputTargets.clear();
-
-    int32_t injectionResult;
-
-    // If there is no currently focused window and no focused application
-    // then drop the event.
-    if (! mFocusedWindow) {
-        if (mFocusedApplication) {
-#if DEBUG_FOCUS
-            LOGD("Waiting because there is no focused window but there is a "
-                    "focused application that may eventually add a window: %s.",
-                    getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
-#endif
-            injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                    mFocusedApplication, NULL, nextWakeupTime);
-            goto Unresponsive;
-        }
-
-        LOGI("Dropping event because there is no focused window or focused application.");
-        injectionResult = INPUT_EVENT_INJECTION_FAILED;
-        goto Failed;
-    }
-
-    // Check permissions.
-    if (! checkInjectionPermission(mFocusedWindow, entry->injectionState)) {
-        injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
-        goto Failed;
-    }
-
-    // If the currently focused window is paused then keep waiting.
-    if (mFocusedWindow->paused) {
-#if DEBUG_FOCUS
-        LOGD("Waiting because focused window is paused.");
-#endif
-        injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                mFocusedApplication, mFocusedWindow, nextWakeupTime);
-        goto Unresponsive;
-    }
-
-    // If the currently focused window is still working on previous events then keep waiting.
-    if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) {
-#if DEBUG_FOCUS
-        LOGD("Waiting because focused window still processing previous input.");
-#endif
-        injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                mFocusedApplication, mFocusedWindow, nextWakeupTime);
-        goto Unresponsive;
-    }
-
-    // Success!  Output targets.
-    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-    addWindowTargetLocked(mFocusedWindow, InputTarget::FLAG_FOREGROUND, BitSet32(0));
-
-    // Done.
-Failed:
-Unresponsive:
-    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
-    updateDispatchStatisticsLocked(currentTime, entry,
-            injectionResult, timeSpentWaitingForApplication);
-#if DEBUG_FOCUS
-    LOGD("findFocusedWindow finished: injectionResult=%d, "
-            "timeSpendWaitingForApplication=%0.1fms",
-            injectionResult, timeSpentWaitingForApplication / 1000000.0);
-#endif
-    return injectionResult;
-}
-
-int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
-        const MotionEntry* entry, nsecs_t* nextWakeupTime) {
-    enum InjectionPermission {
-        INJECTION_PERMISSION_UNKNOWN,
-        INJECTION_PERMISSION_GRANTED,
-        INJECTION_PERMISSION_DENIED
-    };
-
-    mCurrentInputTargets.clear();
-
-    nsecs_t startTime = now();
-
-    // For security reasons, we defer updating the touch state until we are sure that
-    // event injection will be allowed.
-    //
-    // FIXME In the original code, screenWasOff could never be set to true.
-    //       The reason is that the POLICY_FLAG_WOKE_HERE
-    //       and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
-    //       EV_KEY, EV_REL and EV_ABS events.  As it happens, the touch event was
-    //       actually enqueued using the policyFlags that appeared in the final EV_SYN
-    //       events upon which no preprocessing took place.  So policyFlags was always 0.
-    //       In the new native input dispatcher we're a bit more careful about event
-    //       preprocessing so the touches we receive can actually have non-zero policyFlags.
-    //       Unfortunately we obtain undesirable behavior.
-    //
-    //       Here's what happens:
-    //
-    //       When the device dims in anticipation of going to sleep, touches
-    //       in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
-    //       the device to brighten and reset the user activity timer.
-    //       Touches on other windows (such as the launcher window)
-    //       are dropped.  Then after a moment, the device goes to sleep.  Oops.
-    //
-    //       Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
-    //       instead of POLICY_FLAG_WOKE_HERE...
-    //
-    bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
-
-    int32_t action = entry->action;
-    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
-
-    // Update the touch state as needed based on the properties of the touch event.
-    int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
-    InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
-    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-        mTempTouchState.reset();
-        mTempTouchState.down = true;
-    } else {
-        mTempTouchState.copyFrom(mTouchState);
-    }
-
-    bool isSplit = mTempTouchState.split && mTempTouchState.down;
-    if (maskedAction == AMOTION_EVENT_ACTION_DOWN
-            || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
-        /* Case 1: New splittable pointer going down. */
-
-        int32_t pointerIndex = getMotionEventActionPointerIndex(action);
-        int32_t x = int32_t(entry->firstSample.pointerCoords[pointerIndex].x);
-        int32_t y = int32_t(entry->firstSample.pointerCoords[pointerIndex].y);
-        const InputWindow* newTouchedWindow = NULL;
-        const InputWindow* topErrorWindow = NULL;
-
-        // Traverse windows from front to back to find touched window and outside targets.
-        size_t numWindows = mWindows.size();
-        for (size_t i = 0; i < numWindows; i++) {
-            const InputWindow* window = & mWindows.editItemAt(i);
-            int32_t flags = window->layoutParamsFlags;
-
-            if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
-                if (! topErrorWindow) {
-                    topErrorWindow = window;
-                }
-            }
-
-            if (window->visible) {
-                if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
-                    bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
-                            | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
-                    if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
-                        if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
-                            newTouchedWindow = window;
-                        }
-                        break; // found touched window, exit window loop
-                    }
-                }
-
-                if (maskedAction == AMOTION_EVENT_ACTION_DOWN
-                        && (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)) {
-                    int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
-                    if (isWindowObscuredAtPointLocked(window, x, y)) {
-                        outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
-                    }
-
-                    mTempTouchState.addOrUpdateWindow(window, outsideTargetFlags, BitSet32(0));
-                }
-            }
-        }
-
-        // If there is an error window but it is not taking focus (typically because
-        // it is invisible) then wait for it.  Any other focused window may in
-        // fact be in ANR state.
-        if (topErrorWindow && newTouchedWindow != topErrorWindow) {
-#if DEBUG_FOCUS
-            LOGD("Waiting because system error window is pending.");
-#endif
-            injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                    NULL, NULL, nextWakeupTime);
-            injectionPermission = INJECTION_PERMISSION_UNKNOWN;
-            goto Unresponsive;
-        }
-
-        // Figure out whether splitting will be allowed for this window.
-        if (newTouchedWindow && newTouchedWindow->supportsSplitTouch()) {
-            // New window supports splitting.
-            isSplit = true;
-        } else if (isSplit) {
-            // New window does not support splitting but we have already split events.
-            // Assign the pointer to the first foreground window we find.
-            // (May be NULL which is why we put this code block before the next check.)
-            newTouchedWindow = mTempTouchState.getFirstForegroundWindow();
-        }
-
-        // If we did not find a touched window then fail.
-        if (! newTouchedWindow) {
-            if (mFocusedApplication) {
-#if DEBUG_FOCUS
-                LOGD("Waiting because there is no touched window but there is a "
-                        "focused application that may eventually add a new window: %s.",
-                        getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
-#endif
-                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        mFocusedApplication, NULL, nextWakeupTime);
-                goto Unresponsive;
-            }
-
-            LOGI("Dropping event because there is no touched window or focused application.");
-            injectionResult = INPUT_EVENT_INJECTION_FAILED;
-            goto Failed;
-        }
-
-        // Set target flags.
-        int32_t targetFlags = InputTarget::FLAG_FOREGROUND;
-        if (isSplit) {
-            targetFlags |= InputTarget::FLAG_SPLIT;
-        }
-        if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
-            targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
-        }
-
-        // Update the temporary touch state.
-        BitSet32 pointerIds;
-        if (isSplit) {
-            uint32_t pointerId = entry->pointerIds[pointerIndex];
-            pointerIds.markBit(pointerId);
-        }
-        mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
-    } else {
-        /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
-
-        // If the pointer is not currently down, then ignore the event.
-        if (! mTempTouchState.down) {
-#if DEBUG_INPUT_DISPATCHER_POLICY
-            LOGD("Dropping event because the pointer is not down or we previously "
-                    "dropped the pointer down event.");
-#endif
-            injectionResult = INPUT_EVENT_INJECTION_FAILED;
-            goto Failed;
-        }
-    }
-
-    // Check permission to inject into all touched foreground windows and ensure there
-    // is at least one touched foreground window.
-    {
-        bool haveForegroundWindow = false;
-        for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
-            const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
-            if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
-                haveForegroundWindow = true;
-                if (! checkInjectionPermission(touchedWindow.window, entry->injectionState)) {
-                    injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
-                    injectionPermission = INJECTION_PERMISSION_DENIED;
-                    goto Failed;
-                }
-            }
-        }
-        if (! haveForegroundWindow) {
-#if DEBUG_INPUT_DISPATCHER_POLICY
-            LOGD("Dropping event because there is no touched foreground window to receive it.");
-#endif
-            injectionResult = INPUT_EVENT_INJECTION_FAILED;
-            goto Failed;
-        }
-
-        // Permission granted to injection into all touched foreground windows.
-        injectionPermission = INJECTION_PERMISSION_GRANTED;
-    }
-
-    // Ensure all touched foreground windows are ready for new input.
-    for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
-        const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
-        if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
-            // If the touched window is paused then keep waiting.
-            if (touchedWindow.window->paused) {
-#if DEBUG_INPUT_DISPATCHER_POLICY
-                LOGD("Waiting because touched window is paused.");
-#endif
-                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        NULL, touchedWindow.window, nextWakeupTime);
-                goto Unresponsive;
-            }
-
-            // If the touched window is still working on previous events then keep waiting.
-            if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.window)) {
-#if DEBUG_FOCUS
-                LOGD("Waiting because touched window still processing previous input.");
-#endif
-                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        NULL, touchedWindow.window, nextWakeupTime);
-                goto Unresponsive;
-            }
-        }
-    }
-
-    // If this is the first pointer going down and the touched window has a wallpaper
-    // then also add the touched wallpaper windows so they are locked in for the duration
-    // of the touch gesture.
-    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-        const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow();
-        if (foregroundWindow->hasWallpaper) {
-            for (size_t i = 0; i < mWindows.size(); i++) {
-                const InputWindow* window = & mWindows[i];
-                if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) {
-                    mTempTouchState.addOrUpdateWindow(window,
-                            InputTarget::FLAG_WINDOW_IS_OBSCURED, BitSet32(0));
-                }
-            }
-        }
-    }
-
-    // Success!  Output targets.
-    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-
-    for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
-        const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
-        addWindowTargetLocked(touchedWindow.window, touchedWindow.targetFlags,
-                touchedWindow.pointerIds);
-    }
-
-    // Drop the outside touch window since we will not care about them in the next iteration.
-    mTempTouchState.removeOutsideTouchWindows();
-
-Failed:
-    // Check injection permission once and for all.
-    if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
-        if (checkInjectionPermission(NULL, entry->injectionState)) {
-            injectionPermission = INJECTION_PERMISSION_GRANTED;
-        } else {
-            injectionPermission = INJECTION_PERMISSION_DENIED;
-        }
-    }
-
-    // Update final pieces of touch state if the injector had permission.
-    if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
-        if (maskedAction == AMOTION_EVENT_ACTION_UP
-                || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
-            // All pointers up or canceled.
-            mTempTouchState.reset();
-        } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-            // First pointer went down.
-            if (mTouchState.down) {
-#if DEBUG_FOCUS
-                LOGD("Pointer down received while already down.");
-#endif
-            }
-        } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
-            // One pointer went up.
-            if (isSplit) {
-                int32_t pointerIndex = getMotionEventActionPointerIndex(action);
-                uint32_t pointerId = entry->pointerIds[pointerIndex];
-
-                for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
-                    TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
-                    if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
-                        touchedWindow.pointerIds.clearBit(pointerId);
-                        if (touchedWindow.pointerIds.isEmpty()) {
-                            mTempTouchState.windows.removeAt(i);
-                            continue;
-                        }
-                    }
-                    i += 1;
-                }
-            }
-        }
-
-        // Save changes to touch state.
-        mTouchState.copyFrom(mTempTouchState);
-    } else {
-#if DEBUG_FOCUS
-        LOGD("Not updating touch focus because injection was denied.");
-#endif
-    }
-
-Unresponsive:
-    // Reset temporary touch state to ensure we release unnecessary references to input channels.
-    mTempTouchState.reset();
-
-    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
-    updateDispatchStatisticsLocked(currentTime, entry,
-            injectionResult, timeSpentWaitingForApplication);
-#if DEBUG_FOCUS
-    LOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
-            "timeSpentWaitingForApplication=%0.1fms",
-            injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
-#endif
-    return injectionResult;
-}
-
-void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
-        BitSet32 pointerIds) {
-    mCurrentInputTargets.push();
-
-    InputTarget& target = mCurrentInputTargets.editTop();
-    target.inputChannel = window->inputChannel;
-    target.flags = targetFlags;
-    target.xOffset = - window->frameLeft;
-    target.yOffset = - window->frameTop;
-    target.pointerIds = pointerIds;
-}
-
-void InputDispatcher::addMonitoringTargetsLocked() {
-    for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
-        mCurrentInputTargets.push();
-
-        InputTarget& target = mCurrentInputTargets.editTop();
-        target.inputChannel = mMonitoringChannels[i];
-        target.flags = 0;
-        target.xOffset = 0;
-        target.yOffset = 0;
-    }
-}
-
-bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
-        const InjectionState* injectionState) {
-    if (injectionState
-            && (window == NULL || window->ownerUid != injectionState->injectorUid)
-            && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
-        if (window) {
-            LOGW("Permission denied: injecting event from pid %d uid %d to window "
-                    "with input channel %s owned by uid %d",
-                    injectionState->injectorPid, injectionState->injectorUid,
-                    window->inputChannel->getName().string(),
-                    window->ownerUid);
-        } else {
-            LOGW("Permission denied: injecting event from pid %d uid %d",
-                    injectionState->injectorPid, injectionState->injectorUid);
-        }
-        return false;
-    }
-    return true;
-}
-
-bool InputDispatcher::isWindowObscuredAtPointLocked(
-        const InputWindow* window, int32_t x, int32_t y) const {
-    size_t numWindows = mWindows.size();
-    for (size_t i = 0; i < numWindows; i++) {
-        const InputWindow* other = & mWindows.itemAt(i);
-        if (other == window) {
-            break;
-        }
-        if (other->visible && ! other->isTrustedOverlay() && other->frameContainsPoint(x, y)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* window) {
-    ssize_t connectionIndex = getConnectionIndexLocked(window->inputChannel);
-    if (connectionIndex >= 0) {
-        sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-        return connection->outboundQueue.isEmpty();
-    } else {
-        return true;
-    }
-}
-
-String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* application,
-        const InputWindow* window) {
-    if (application) {
-        if (window) {
-            String8 label(application->name);
-            label.append(" - ");
-            label.append(window->name);
-            return label;
-        } else {
-            return application->name;
-        }
-    } else if (window) {
-        return window->name;
-    } else {
-        return String8("<unknown application or window>");
-    }
-}
-
-void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
-    int32_t eventType = POWER_MANAGER_BUTTON_EVENT;
-    switch (eventEntry->type) {
-    case EventEntry::TYPE_MOTION: {
-        const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
-        if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
-            return;
-        }
-
-        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
-            eventType = POWER_MANAGER_TOUCH_EVENT;
-        }
-        break;
-    }
-    case EventEntry::TYPE_KEY: {
-        const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
-        if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
-            return;
-        }
-        break;
-    }
-    }
-
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doPokeUserActivityLockedInterruptible);
-    commandEntry->eventTime = eventEntry->eventTime;
-    commandEntry->userActivityEventType = eventType;
-}
-
-void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
-        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
-        bool resumeWithAppendedMotionSample) {
-#if DEBUG_DISPATCH_CYCLE
-    LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, "
-            "xOffset=%f, yOffset=%f, "
-            "windowType=%d, pointerIds=0x%x, "
-            "resumeWithAppendedMotionSample=%s",
-            connection->getInputChannelName(), inputTarget->flags,
-            inputTarget->xOffset, inputTarget->yOffset,
-            inputTarget->windowType, inputTarget->pointerIds.value,
-            toString(resumeWithAppendedMotionSample));
-#endif
-
-    // Make sure we are never called for streaming when splitting across multiple windows.
-    bool isSplit = inputTarget->flags & InputTarget::FLAG_SPLIT;
-    assert(! (resumeWithAppendedMotionSample && isSplit));
-
-    // Skip this event if the connection status is not normal.
-    // We don't want to enqueue additional outbound events if the connection is broken.
-    if (connection->status != Connection::STATUS_NORMAL) {
-#if DEBUG_DISPATCH_CYCLE
-        LOGD("channel '%s' ~ Dropping event because the channel status is %s",
-                connection->getInputChannelName(), connection->getStatusLabel());
-#endif
-        return;
-    }
-
-    // Split a motion event if needed.
-    if (isSplit) {
-        assert(eventEntry->type == EventEntry::TYPE_MOTION);
-
-        MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
-        if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
-            MotionEntry* splitMotionEntry = splitMotionEvent(
-                    originalMotionEntry, inputTarget->pointerIds);
-#if DEBUG_FOCUS
-            LOGD("channel '%s' ~ Split motion event.",
-                    connection->getInputChannelName());
-            logOutboundMotionDetailsLocked("  ", splitMotionEntry);
-#endif
-            eventEntry = splitMotionEntry;
-        }
-    }
-
-    // Resume the dispatch cycle with a freshly appended motion sample.
-    // First we check that the last dispatch entry in the outbound queue is for the same
-    // motion event to which we appended the motion sample.  If we find such a dispatch
-    // entry, and if it is currently in progress then we try to stream the new sample.
-    bool wasEmpty = connection->outboundQueue.isEmpty();
-
-    if (! wasEmpty && resumeWithAppendedMotionSample) {
-        DispatchEntry* motionEventDispatchEntry =
-                connection->findQueuedDispatchEntryForEvent(eventEntry);
-        if (motionEventDispatchEntry) {
-            // If the dispatch entry is not in progress, then we must be busy dispatching an
-            // earlier event.  Not a problem, the motion event is on the outbound queue and will
-            // be dispatched later.
-            if (! motionEventDispatchEntry->inProgress) {
-#if DEBUG_BATCHING
-                LOGD("channel '%s' ~ Not streaming because the motion event has "
-                        "not yet been dispatched.  "
-                        "(Waiting for earlier events to be consumed.)",
-                        connection->getInputChannelName());
-#endif
-                return;
-            }
-
-            // If the dispatch entry is in progress but it already has a tail of pending
-            // motion samples, then it must mean that the shared memory buffer filled up.
-            // Not a problem, when this dispatch cycle is finished, we will eventually start
-            // a new dispatch cycle to process the tail and that tail includes the newly
-            // appended motion sample.
-            if (motionEventDispatchEntry->tailMotionSample) {
-#if DEBUG_BATCHING
-                LOGD("channel '%s' ~ Not streaming because no new samples can "
-                        "be appended to the motion event in this dispatch cycle.  "
-                        "(Waiting for next dispatch cycle to start.)",
-                        connection->getInputChannelName());
-#endif
-                return;
-            }
-
-            // The dispatch entry is in progress and is still potentially open for streaming.
-            // Try to stream the new motion sample.  This might fail if the consumer has already
-            // consumed the motion event (or if the channel is broken).
-            MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
-            MotionSample* appendedMotionSample = motionEntry->lastSample;
-            status_t status = connection->inputPublisher.appendMotionSample(
-                    appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
-            if (status == OK) {
-#if DEBUG_BATCHING
-                LOGD("channel '%s' ~ Successfully streamed new motion sample.",
-                        connection->getInputChannelName());
-#endif
-                return;
-            }
-
-#if DEBUG_BATCHING
-            if (status == NO_MEMORY) {
-                LOGD("channel '%s' ~ Could not append motion sample to currently "
-                        "dispatched move event because the shared memory buffer is full.  "
-                        "(Waiting for next dispatch cycle to start.)",
-                        connection->getInputChannelName());
-            } else if (status == status_t(FAILED_TRANSACTION)) {
-                LOGD("channel '%s' ~ Could not append motion sample to currently "
-                        "dispatched move event because the event has already been consumed.  "
-                        "(Waiting for next dispatch cycle to start.)",
-                        connection->getInputChannelName());
-            } else {
-                LOGD("channel '%s' ~ Could not append motion sample to currently "
-                        "dispatched move event due to an error, status=%d.  "
-                        "(Waiting for next dispatch cycle to start.)",
-                        connection->getInputChannelName(), status);
-            }
-#endif
-            // Failed to stream.  Start a new tail of pending motion samples to dispatch
-            // in the next cycle.
-            motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
-            return;
-        }
-    }
-
-    // This is a new event.
-    // Enqueue a new dispatch entry onto the outbound queue for this connection.
-    DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref
-            inputTarget->flags, inputTarget->xOffset, inputTarget->yOffset);
-    if (dispatchEntry->hasForegroundTarget()) {
-        incrementPendingForegroundDispatchesLocked(eventEntry);
-    }
-
-    // Handle the case where we could not stream a new motion sample because the consumer has
-    // already consumed the motion event (otherwise the corresponding dispatch entry would
-    // still be in the outbound queue for this connection).  We set the head motion sample
-    // to the list starting with the newly appended motion sample.
-    if (resumeWithAppendedMotionSample) {
-#if DEBUG_BATCHING
-        LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
-                "that cannot be streamed because the motion event has already been consumed.",
-                connection->getInputChannelName());
-#endif
-        MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
-        dispatchEntry->headMotionSample = appendedMotionSample;
-    }
-
-    // Enqueue the dispatch entry.
-    connection->outboundQueue.enqueueAtTail(dispatchEntry);
-
-    // If the outbound queue was previously empty, start the dispatch cycle going.
-    if (wasEmpty) {
-        activateConnectionLocked(connection.get());
-        startDispatchCycleLocked(currentTime, connection);
-    }
-}
-
-void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
-        const sp<Connection>& connection) {
-#if DEBUG_DISPATCH_CYCLE
-    LOGD("channel '%s' ~ startDispatchCycle",
-            connection->getInputChannelName());
-#endif
-
-    assert(connection->status == Connection::STATUS_NORMAL);
-    assert(! connection->outboundQueue.isEmpty());
-
-    DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
-    assert(! dispatchEntry->inProgress);
-
-    // Mark the dispatch entry as in progress.
-    dispatchEntry->inProgress = true;
-
-    // Update the connection's input state.
-    EventEntry* eventEntry = dispatchEntry->eventEntry;
-    InputState::Consistency consistency = connection->inputState.trackEvent(eventEntry);
-
-#if FILTER_INPUT_EVENTS
-    // Filter out inconsistent sequences of input events.
-    // The input system may drop or inject events in a way that could violate implicit
-    // invariants on input state and potentially cause an application to crash
-    // or think that a key or pointer is stuck down.  Technically we make no guarantees
-    // of consistency but it would be nice to improve on this where possible.
-    // XXX: This code is a proof of concept only.  Not ready for prime time.
-    if (consistency == InputState::TOLERABLE) {
-#if DEBUG_DISPATCH_CYCLE
-        LOGD("channel '%s' ~ Sending an event that is inconsistent with the connection's "
-                "current input state but that is likely to be tolerated by the application.",
-                connection->getInputChannelName());
-#endif
-    } else if (consistency == InputState::BROKEN) {
-        LOGI("channel '%s' ~ Dropping an event that is inconsistent with the connection's "
-                "current input state and that is likely to cause the application to crash.",
-                connection->getInputChannelName());
-        startNextDispatchCycleLocked(currentTime, connection);
-        return;
-    }
-#endif
-
-    // Publish the event.
-    status_t status;
-    switch (eventEntry->type) {
-    case EventEntry::TYPE_KEY: {
-        KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
-
-        // Apply target flags.
-        int32_t action = keyEntry->action;
-        int32_t flags = keyEntry->flags;
-
-        // Publish the key event.
-        status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
-                action, flags, keyEntry->keyCode, keyEntry->scanCode,
-                keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
-                keyEntry->eventTime);
-
-        if (status) {
-            LOGE("channel '%s' ~ Could not publish key event, "
-                    "status=%d", connection->getInputChannelName(), status);
-            abortBrokenDispatchCycleLocked(currentTime, connection);
-            return;
-        }
-        break;
-    }
-
-    case EventEntry::TYPE_MOTION: {
-        MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
-
-        // Apply target flags.
-        int32_t action = motionEntry->action;
-        int32_t flags = motionEntry->flags;
-        if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
-            action = AMOTION_EVENT_ACTION_OUTSIDE;
-        }
-        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
-            flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
-        }
-
-        // If headMotionSample is non-NULL, then it points to the first new sample that we
-        // were unable to dispatch during the previous cycle so we resume dispatching from
-        // that point in the list of motion samples.
-        // Otherwise, we just start from the first sample of the motion event.
-        MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
-        if (! firstMotionSample) {
-            firstMotionSample = & motionEntry->firstSample;
-        }
-
-        // Set the X and Y offset depending on the input source.
-        float xOffset, yOffset;
-        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
-            xOffset = dispatchEntry->xOffset;
-            yOffset = dispatchEntry->yOffset;
-        } else {
-            xOffset = 0.0f;
-            yOffset = 0.0f;
-        }
-
-        // Publish the motion event and the first motion sample.
-        status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
-                motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
-                xOffset, yOffset,
-                motionEntry->xPrecision, motionEntry->yPrecision,
-                motionEntry->downTime, firstMotionSample->eventTime,
-                motionEntry->pointerCount, motionEntry->pointerIds,
-                firstMotionSample->pointerCoords);
-
-        if (status) {
-            LOGE("channel '%s' ~ Could not publish motion event, "
-                    "status=%d", connection->getInputChannelName(), status);
-            abortBrokenDispatchCycleLocked(currentTime, connection);
-            return;
-        }
-
-        // Append additional motion samples.
-        MotionSample* nextMotionSample = firstMotionSample->next;
-        for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
-            status = connection->inputPublisher.appendMotionSample(
-                    nextMotionSample->eventTime, nextMotionSample->pointerCoords);
-            if (status == NO_MEMORY) {
-#if DEBUG_DISPATCH_CYCLE
-                    LOGD("channel '%s' ~ Shared memory buffer full.  Some motion samples will "
-                            "be sent in the next dispatch cycle.",
-                            connection->getInputChannelName());
-#endif
-                break;
-            }
-            if (status != OK) {
-                LOGE("channel '%s' ~ Could not append motion sample "
-                        "for a reason other than out of memory, status=%d",
-                        connection->getInputChannelName(), status);
-                abortBrokenDispatchCycleLocked(currentTime, connection);
-                return;
-            }
-        }
-
-        // Remember the next motion sample that we could not dispatch, in case we ran out
-        // of space in the shared memory buffer.
-        dispatchEntry->tailMotionSample = nextMotionSample;
-        break;
-    }
-
-    default: {
-        assert(false);
-    }
-    }
-
-    // Send the dispatch signal.
-    status = connection->inputPublisher.sendDispatchSignal();
-    if (status) {
-        LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
-                connection->getInputChannelName(), status);
-        abortBrokenDispatchCycleLocked(currentTime, connection);
-        return;
-    }
-
-    // Record information about the newly started dispatch cycle.
-    connection->lastEventTime = eventEntry->eventTime;
-    connection->lastDispatchTime = currentTime;
-
-    // Notify other system components.
-    onDispatchCycleStartedLocked(currentTime, connection);
-}
-
-void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
-        const sp<Connection>& connection, bool handled) {
-#if DEBUG_DISPATCH_CYCLE
-    LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
-            "%01.1fms since dispatch, handled=%s",
-            connection->getInputChannelName(),
-            connection->getEventLatencyMillis(currentTime),
-            connection->getDispatchLatencyMillis(currentTime),
-            toString(handled));
-#endif
-
-    if (connection->status == Connection::STATUS_BROKEN
-            || connection->status == Connection::STATUS_ZOMBIE) {
-        return;
-    }
-
-    // Reset the publisher since the event has been consumed.
-    // We do this now so that the publisher can release some of its internal resources
-    // while waiting for the next dispatch cycle to begin.
-    status_t status = connection->inputPublisher.reset();
-    if (status) {
-        LOGE("channel '%s' ~ Could not reset publisher, status=%d",
-                connection->getInputChannelName(), status);
-        abortBrokenDispatchCycleLocked(currentTime, connection);
-        return;
-    }
-
-    // Notify other system components and prepare to start the next dispatch cycle.
-    onDispatchCycleFinishedLocked(currentTime, connection, handled);
-}
-
-void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
-        const sp<Connection>& connection) {
-    // Start the next dispatch cycle for this connection.
-    while (! connection->outboundQueue.isEmpty()) {
-        DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
-        if (dispatchEntry->inProgress) {
-             // Finish or resume current event in progress.
-            if (dispatchEntry->tailMotionSample) {
-                // We have a tail of undispatched motion samples.
-                // Reuse the same DispatchEntry and start a new cycle.
-                dispatchEntry->inProgress = false;
-                dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
-                dispatchEntry->tailMotionSample = NULL;
-                startDispatchCycleLocked(currentTime, connection);
-                return;
-            }
-            // Finished.
-            connection->outboundQueue.dequeueAtHead();
-            if (dispatchEntry->hasForegroundTarget()) {
-                decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
-            }
-            mAllocator.releaseDispatchEntry(dispatchEntry);
-        } else {
-            // If the head is not in progress, then we must have already dequeued the in
-            // progress event, which means we actually aborted it.
-            // So just start the next event for this connection.
-            startDispatchCycleLocked(currentTime, connection);
-            return;
-        }
-    }
-
-    // Outbound queue is empty, deactivate the connection.
-    deactivateConnectionLocked(connection.get());
-}
-
-void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
-        const sp<Connection>& connection) {
-#if DEBUG_DISPATCH_CYCLE
-    LOGD("channel '%s' ~ abortBrokenDispatchCycle - broken=%s",
-            connection->getInputChannelName(), toString(broken));
-#endif
-
-    // Clear the outbound queue.
-    drainOutboundQueueLocked(connection.get());
-
-    // The connection appears to be unrecoverably broken.
-    // Ignore already broken or zombie connections.
-    if (connection->status == Connection::STATUS_NORMAL) {
-        connection->status = Connection::STATUS_BROKEN;
-
-        // Notify other system components.
-        onDispatchCycleBrokenLocked(currentTime, connection);
-    }
-}
-
-void InputDispatcher::drainOutboundQueueLocked(Connection* connection) {
-    while (! connection->outboundQueue.isEmpty()) {
-        DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
-        if (dispatchEntry->hasForegroundTarget()) {
-            decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
-        }
-        mAllocator.releaseDispatchEntry(dispatchEntry);
-    }
-
-    deactivateConnectionLocked(connection);
-}
-
-int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
-    InputDispatcher* d = static_cast<InputDispatcher*>(data);
-
-    { // acquire lock
-        AutoMutex _l(d->mLock);
-
-        ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
-        if (connectionIndex < 0) {
-            LOGE("Received spurious receive callback for unknown input channel.  "
-                    "fd=%d, events=0x%x", receiveFd, events);
-            return 0; // remove the callback
-        }
-
-        nsecs_t currentTime = now();
-
-        sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
-        if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
-            LOGE("channel '%s' ~ Consumer closed input channel or an error occurred.  "
-                    "events=0x%x", connection->getInputChannelName(), events);
-            d->abortBrokenDispatchCycleLocked(currentTime, connection);
-            d->runCommandsLockedInterruptible();
-            return 0; // remove the callback
-        }
-
-        if (! (events & ALOOPER_EVENT_INPUT)) {
-            LOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
-                    "events=0x%x", connection->getInputChannelName(), events);
-            return 1;
-        }
-
-        bool handled = false;
-        status_t status = connection->inputPublisher.receiveFinishedSignal(&handled);
-        if (status) {
-            LOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
-                    connection->getInputChannelName(), status);
-            d->abortBrokenDispatchCycleLocked(currentTime, connection);
-            d->runCommandsLockedInterruptible();
-            return 0; // remove the callback
-        }
-
-        d->finishDispatchCycleLocked(currentTime, connection, handled);
-        d->runCommandsLockedInterruptible();
-        return 1;
-    } // release lock
-}
-
-void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
-        InputState::CancelationOptions options, const char* reason) {
-    for (size_t i = 0; i < mConnectionsByReceiveFd.size(); i++) {
-        synthesizeCancelationEventsForConnectionLocked(
-                mConnectionsByReceiveFd.valueAt(i), options, reason);
-    }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
-        const sp<InputChannel>& channel, InputState::CancelationOptions options,
-        const char* reason) {
-    ssize_t index = getConnectionIndexLocked(channel);
-    if (index >= 0) {
-        synthesizeCancelationEventsForConnectionLocked(
-                mConnectionsByReceiveFd.valueAt(index), options, reason);
-    }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
-        const sp<Connection>& connection, InputState::CancelationOptions options,
-        const char* reason) {
-    nsecs_t currentTime = now();
-
-    mTempCancelationEvents.clear();
-    connection->inputState.synthesizeCancelationEvents(currentTime, & mAllocator,
-            mTempCancelationEvents, options);
-
-    if (! mTempCancelationEvents.isEmpty()
-            && connection->status != Connection::STATUS_BROKEN) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-        LOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
-                "with reality: %s, options=%d.",
-                connection->getInputChannelName(), mTempCancelationEvents.size(), reason, options);
-#endif
-        for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
-            EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
-            switch (cancelationEventEntry->type) {
-            case EventEntry::TYPE_KEY:
-                logOutboundKeyDetailsLocked("cancel - ",
-                        static_cast<KeyEntry*>(cancelationEventEntry));
-                break;
-            case EventEntry::TYPE_MOTION:
-                logOutboundMotionDetailsLocked("cancel - ",
-                        static_cast<MotionEntry*>(cancelationEventEntry));
-                break;
-            }
-
-            int32_t xOffset, yOffset;
-            const InputWindow* window = getWindowLocked(connection->inputChannel);
-            if (window) {
-                xOffset = -window->frameLeft;
-                yOffset = -window->frameTop;
-            } else {
-                xOffset = 0;
-                yOffset = 0;
-            }
-
-            DispatchEntry* cancelationDispatchEntry =
-                    mAllocator.obtainDispatchEntry(cancelationEventEntry, // increments ref
-                    0, xOffset, yOffset);
-            connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
-
-            mAllocator.releaseEventEntry(cancelationEventEntry);
-        }
-
-        if (!connection->outboundQueue.headSentinel.next->inProgress) {
-            startDispatchCycleLocked(currentTime, connection);
-        }
-    }
-}
-
-InputDispatcher::MotionEntry*
-InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
-    assert(pointerIds.value != 0);
-
-    uint32_t splitPointerIndexMap[MAX_POINTERS];
-    int32_t splitPointerIds[MAX_POINTERS];
-    PointerCoords splitPointerCoords[MAX_POINTERS];
-
-    uint32_t originalPointerCount = originalMotionEntry->pointerCount;
-    uint32_t splitPointerCount = 0;
-
-    for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
-            originalPointerIndex++) {
-        int32_t pointerId = uint32_t(originalMotionEntry->pointerIds[originalPointerIndex]);
-        if (pointerIds.hasBit(pointerId)) {
-            splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
-            splitPointerIds[splitPointerCount] = pointerId;
-            splitPointerCoords[splitPointerCount] =
-                    originalMotionEntry->firstSample.pointerCoords[originalPointerIndex];
-            splitPointerCount += 1;
-        }
-    }
-    assert(splitPointerCount == pointerIds.count());
-
-    int32_t action = originalMotionEntry->action;
-    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
-    if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
-            || maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
-        int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
-        int32_t pointerId = originalMotionEntry->pointerIds[originalPointerIndex];
-        if (pointerIds.hasBit(pointerId)) {
-            if (pointerIds.count() == 1) {
-                // The first/last pointer went down/up.
-                action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
-                        ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
-            } else {
-                // A secondary pointer went down/up.
-                uint32_t splitPointerIndex = 0;
-                while (pointerId != splitPointerIds[splitPointerIndex]) {
-                    splitPointerIndex += 1;
-                }
-                action = maskedAction | (splitPointerIndex
-                        << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
-            }
-        } else {
-            // An unrelated pointer changed.
-            action = AMOTION_EVENT_ACTION_MOVE;
-        }
-    }
-
-    MotionEntry* splitMotionEntry = mAllocator.obtainMotionEntry(
-            originalMotionEntry->eventTime,
-            originalMotionEntry->deviceId,
-            originalMotionEntry->source,
-            originalMotionEntry->policyFlags,
-            action,
-            originalMotionEntry->flags,
-            originalMotionEntry->metaState,
-            originalMotionEntry->edgeFlags,
-            originalMotionEntry->xPrecision,
-            originalMotionEntry->yPrecision,
-            originalMotionEntry->downTime,
-            splitPointerCount, splitPointerIds, splitPointerCoords);
-
-    for (MotionSample* originalMotionSample = originalMotionEntry->firstSample.next;
-            originalMotionSample != NULL; originalMotionSample = originalMotionSample->next) {
-        for (uint32_t splitPointerIndex = 0; splitPointerIndex < splitPointerCount;
-                splitPointerIndex++) {
-            uint32_t originalPointerIndex = splitPointerIndexMap[splitPointerIndex];
-            splitPointerCoords[splitPointerIndex] =
-                    originalMotionSample->pointerCoords[originalPointerIndex];
-        }
-
-        mAllocator.appendMotionSample(splitMotionEntry, originalMotionSample->eventTime,
-                splitPointerCoords);
-    }
-
-    return splitMotionEntry;
-}
-
-void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
-#endif
-
-    bool needWake;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
-        needWake = enqueueInboundEventLocked(newEntry);
-    } // release lock
-
-    if (needWake) {
-        mLooper->wake();
-    }
-}
-
-void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
-        uint32_t policyFlags, int32_t action, int32_t flags,
-        int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    LOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
-            "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
-            eventTime, deviceId, source, policyFlags, action, flags,
-            keyCode, scanCode, metaState, downTime);
-#endif
-    if (! validateKeyEvent(action)) {
-        return;
-    }
-
-    if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
-        policyFlags |= POLICY_FLAG_VIRTUAL;
-        flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
-    }
-
-    policyFlags |= POLICY_FLAG_TRUSTED;
-
-    KeyEvent event;
-    event.initialize(deviceId, source, action, flags, keyCode, scanCode,
-            metaState, 0, downTime, eventTime);
-
-    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
-
-    if (policyFlags & POLICY_FLAG_WOKE_HERE) {
-        flags |= AKEY_EVENT_FLAG_WOKE_HERE;
-    }
-
-    bool needWake;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        int32_t repeatCount = 0;
-        KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
-                deviceId, source, policyFlags, action, flags, keyCode, scanCode,
-                metaState, repeatCount, downTime);
-
-        needWake = enqueueInboundEventLocked(newEntry);
-    } // release lock
-
-    if (needWake) {
-        mLooper->wake();
-    }
-}
-
-void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
-        uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
-        uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
-        float xPrecision, float yPrecision, nsecs_t downTime) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    LOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
-            "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
-            "xPrecision=%f, yPrecision=%f, downTime=%lld",
-            eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
-            xPrecision, yPrecision, downTime);
-    for (uint32_t i = 0; i < pointerCount; i++) {
-        LOGD("  Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
-                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
-                "orientation=%f",
-                i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
-                pointerCoords[i].pressure, pointerCoords[i].size,
-                pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
-                pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
-                pointerCoords[i].orientation);
-    }
-#endif
-    if (! validateMotionEvent(action, pointerCount, pointerIds)) {
-        return;
-    }
-
-    policyFlags |= POLICY_FLAG_TRUSTED;
-    mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
-
-    bool needWake;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        // Attempt batching and streaming of move events.
-        if (action == AMOTION_EVENT_ACTION_MOVE) {
-            // BATCHING CASE
-            //
-            // Try to append a move sample to the tail of the inbound queue for this device.
-            // Give up if we encounter a non-move motion event for this device since that
-            // means we cannot append any new samples until a new motion event has started.
-            for (EventEntry* entry = mInboundQueue.tailSentinel.prev;
-                    entry != & mInboundQueue.headSentinel; entry = entry->prev) {
-                if (entry->type != EventEntry::TYPE_MOTION) {
-                    // Keep looking for motion events.
-                    continue;
-                }
-
-                MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
-                if (motionEntry->deviceId != deviceId) {
-                    // Keep looking for this device.
-                    continue;
-                }
-
-                if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
-                        || motionEntry->pointerCount != pointerCount
-                        || motionEntry->isInjected()) {
-                    // Last motion event in the queue for this device is not compatible for
-                    // appending new samples.  Stop here.
-                    goto NoBatchingOrStreaming;
-                }
-
-                // The last motion event is a move and is compatible for appending.
-                // Do the batching magic.
-                mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
-#if DEBUG_BATCHING
-                LOGD("Appended motion sample onto batch for most recent "
-                        "motion event for this device in the inbound queue.");
-#endif
-                return; // done!
-            }
-
-            // STREAMING CASE
-            //
-            // There is no pending motion event (of any kind) for this device in the inbound queue.
-            // Search the outbound queue for the current foreground targets to find a dispatched
-            // motion event that is still in progress.  If found, then, appen the new sample to
-            // that event and push it out to all current targets.  The logic in
-            // prepareDispatchCycleLocked takes care of the case where some targets may
-            // already have consumed the motion event by starting a new dispatch cycle if needed.
-            if (mCurrentInputTargetsValid) {
-                for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
-                    const InputTarget& inputTarget = mCurrentInputTargets[i];
-                    if ((inputTarget.flags & InputTarget::FLAG_FOREGROUND) == 0) {
-                        // Skip non-foreground targets.  We only want to stream if there is at
-                        // least one foreground target whose dispatch is still in progress.
-                        continue;
-                    }
-
-                    ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
-                    if (connectionIndex < 0) {
-                        // Connection must no longer be valid.
-                        continue;
-                    }
-
-                    sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-                    if (connection->outboundQueue.isEmpty()) {
-                        // This foreground target has an empty outbound queue.
-                        continue;
-                    }
-
-                    DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
-                    if (! dispatchEntry->inProgress
-                            || dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION
-                            || dispatchEntry->isSplit()) {
-                        // No motion event is being dispatched, or it is being split across
-                        // windows in which case we cannot stream.
-                        continue;
-                    }
-
-                    MotionEntry* motionEntry = static_cast<MotionEntry*>(
-                            dispatchEntry->eventEntry);
-                    if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
-                            || motionEntry->deviceId != deviceId
-                            || motionEntry->pointerCount != pointerCount
-                            || motionEntry->isInjected()) {
-                        // The motion event is not compatible with this move.
-                        continue;
-                    }
-
-                    // Hurray!  This foreground target is currently dispatching a move event
-                    // that we can stream onto.  Append the motion sample and resume dispatch.
-                    mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
-#if DEBUG_BATCHING
-                    LOGD("Appended motion sample onto batch for most recently dispatched "
-                            "motion event for this device in the outbound queues.  "
-                            "Attempting to stream the motion sample.");
-#endif
-                    nsecs_t currentTime = now();
-                    dispatchEventToCurrentInputTargetsLocked(currentTime, motionEntry,
-                            true /*resumeWithAppendedMotionSample*/);
-
-                    runCommandsLockedInterruptible();
-                    return; // done!
-                }
-            }
-
-NoBatchingOrStreaming:;
-        }
-
-        // Just enqueue a new motion event.
-        MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
-                deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
-                xPrecision, yPrecision, downTime,
-                pointerCount, pointerIds, pointerCoords);
-
-        needWake = enqueueInboundEventLocked(newEntry);
-    } // release lock
-
-    if (needWake) {
-        mLooper->wake();
-    }
-}
-
-void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
-        uint32_t policyFlags) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    LOGD("notifySwitch - switchCode=%d, switchValue=%d, policyFlags=0x%x",
-            switchCode, switchValue, policyFlags);
-#endif
-
-    policyFlags |= POLICY_FLAG_TRUSTED;
-    mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
-}
-
-int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
-        int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
-            "syncMode=%d, timeoutMillis=%d",
-            event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
-#endif
-
-    nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
-
-    uint32_t policyFlags = POLICY_FLAG_INJECTED;
-    if (hasInjectionPermission(injectorPid, injectorUid)) {
-        policyFlags |= POLICY_FLAG_TRUSTED;
-    }
-
-    EventEntry* injectedEntry;
-    switch (event->getType()) {
-    case AINPUT_EVENT_TYPE_KEY: {
-        const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
-        int32_t action = keyEvent->getAction();
-        if (! validateKeyEvent(action)) {
-            return INPUT_EVENT_INJECTION_FAILED;
-        }
-
-        int32_t flags = keyEvent->getFlags();
-        if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
-            policyFlags |= POLICY_FLAG_VIRTUAL;
-        }
-
-        mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
-
-        if (policyFlags & POLICY_FLAG_WOKE_HERE) {
-            flags |= AKEY_EVENT_FLAG_WOKE_HERE;
-        }
-
-        mLock.lock();
-        injectedEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
-                keyEvent->getDeviceId(), keyEvent->getSource(),
-                policyFlags, action, flags,
-                keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
-                keyEvent->getRepeatCount(), keyEvent->getDownTime());
-        break;
-    }
-
-    case AINPUT_EVENT_TYPE_MOTION: {
-        const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
-        int32_t action = motionEvent->getAction();
-        size_t pointerCount = motionEvent->getPointerCount();
-        const int32_t* pointerIds = motionEvent->getPointerIds();
-        if (! validateMotionEvent(action, pointerCount, pointerIds)) {
-            return INPUT_EVENT_INJECTION_FAILED;
-        }
-
-        nsecs_t eventTime = motionEvent->getEventTime();
-        mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
-
-        mLock.lock();
-        const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
-        const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
-        MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
-                motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
-                action, motionEvent->getFlags(),
-                motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
-                motionEvent->getXPrecision(), motionEvent->getYPrecision(),
-                motionEvent->getDownTime(), uint32_t(pointerCount),
-                pointerIds, samplePointerCoords);
-        for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
-            sampleEventTimes += 1;
-            samplePointerCoords += pointerCount;
-            mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
-        }
-        injectedEntry = motionEntry;
-        break;
-    }
-
-    default:
-        LOGW("Cannot inject event of type %d", event->getType());
-        return INPUT_EVENT_INJECTION_FAILED;
-    }
-
-    InjectionState* injectionState = mAllocator.obtainInjectionState(injectorPid, injectorUid);
-    if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
-        injectionState->injectionIsAsync = true;
-    }
-
-    injectionState->refCount += 1;
-    injectedEntry->injectionState = injectionState;
-
-    bool needWake = enqueueInboundEventLocked(injectedEntry);
-    mLock.unlock();
-
-    if (needWake) {
-        mLooper->wake();
-    }
-
-    int32_t injectionResult;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
-            injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-        } else {
-            for (;;) {
-                injectionResult = injectionState->injectionResult;
-                if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
-                    break;
-                }
-
-                nsecs_t remainingTimeout = endTime - now();
-                if (remainingTimeout <= 0) {
-#if DEBUG_INJECTION
-                    LOGD("injectInputEvent - Timed out waiting for injection result "
-                            "to become available.");
-#endif
-                    injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
-                    break;
-                }
-
-                mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
-            }
-
-            if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
-                    && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
-                while (injectionState->pendingForegroundDispatches != 0) {
-#if DEBUG_INJECTION
-                    LOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
-                            injectionState->pendingForegroundDispatches);
-#endif
-                    nsecs_t remainingTimeout = endTime - now();
-                    if (remainingTimeout <= 0) {
-#if DEBUG_INJECTION
-                    LOGD("injectInputEvent - Timed out waiting for pending foreground "
-                            "dispatches to finish.");
-#endif
-                        injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
-                        break;
-                    }
-
-                    mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
-                }
-            }
-        }
-
-        mAllocator.releaseInjectionState(injectionState);
-    } // release lock
-
-#if DEBUG_INJECTION
-    LOGD("injectInputEvent - Finished with result %d.  "
-            "injectorPid=%d, injectorUid=%d",
-            injectionResult, injectorPid, injectorUid);
-#endif
-
-    return injectionResult;
-}
-
-bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
-    return injectorUid == 0
-            || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
-}
-
-void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
-    InjectionState* injectionState = entry->injectionState;
-    if (injectionState) {
-#if DEBUG_INJECTION
-        LOGD("Setting input event injection result to %d.  "
-                "injectorPid=%d, injectorUid=%d",
-                 injectionResult, injectionState->injectorPid, injectionState->injectorUid);
-#endif
-
-        if (injectionState->injectionIsAsync) {
-            // Log the outcome since the injector did not wait for the injection result.
-            switch (injectionResult) {
-            case INPUT_EVENT_INJECTION_SUCCEEDED:
-                LOGV("Asynchronous input event injection succeeded.");
-                break;
-            case INPUT_EVENT_INJECTION_FAILED:
-                LOGW("Asynchronous input event injection failed.");
-                break;
-            case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
-                LOGW("Asynchronous input event injection permission denied.");
-                break;
-            case INPUT_EVENT_INJECTION_TIMED_OUT:
-                LOGW("Asynchronous input event injection timed out.");
-                break;
-            }
-        }
-
-        injectionState->injectionResult = injectionResult;
-        mInjectionResultAvailableCondition.broadcast();
-    }
-}
-
-void InputDispatcher::incrementPendingForegroundDispatchesLocked(EventEntry* entry) {
-    InjectionState* injectionState = entry->injectionState;
-    if (injectionState) {
-        injectionState->pendingForegroundDispatches += 1;
-    }
-}
-
-void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* entry) {
-    InjectionState* injectionState = entry->injectionState;
-    if (injectionState) {
-        injectionState->pendingForegroundDispatches -= 1;
-
-        if (injectionState->pendingForegroundDispatches == 0) {
-            mInjectionSyncFinishedCondition.broadcast();
-        }
-    }
-}
-
-const InputWindow* InputDispatcher::getWindowLocked(const sp<InputChannel>& inputChannel) {
-    for (size_t i = 0; i < mWindows.size(); i++) {
-        const InputWindow* window = & mWindows[i];
-        if (window->inputChannel == inputChannel) {
-            return window;
-        }
-    }
-    return NULL;
-}
-
-void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
-#if DEBUG_FOCUS
-    LOGD("setInputWindows");
-#endif
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        // Clear old window pointers.
-        sp<InputChannel> oldFocusedWindowChannel;
-        if (mFocusedWindow) {
-            oldFocusedWindowChannel = mFocusedWindow->inputChannel;
-            mFocusedWindow = NULL;
-        }
-
-        mWindows.clear();
-
-        // Loop over new windows and rebuild the necessary window pointers for
-        // tracking focus and touch.
-        mWindows.appendVector(inputWindows);
-
-        size_t numWindows = mWindows.size();
-        for (size_t i = 0; i < numWindows; i++) {
-            const InputWindow* window = & mWindows.itemAt(i);
-            if (window->hasFocus) {
-                mFocusedWindow = window;
-                break;
-            }
-        }
-
-        if (oldFocusedWindowChannel != NULL) {
-            if (!mFocusedWindow || oldFocusedWindowChannel != mFocusedWindow->inputChannel) {
-#if DEBUG_FOCUS
-                LOGD("Focus left window: %s",
-                        oldFocusedWindowChannel->getName().string());
-#endif
-                synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel,
-                        InputState::CANCEL_NON_POINTER_EVENTS, "focus left window");
-                oldFocusedWindowChannel.clear();
-            }
-        }
-        if (mFocusedWindow && oldFocusedWindowChannel == NULL) {
-#if DEBUG_FOCUS
-            LOGD("Focus entered window: %s",
-                    mFocusedWindow->inputChannel->getName().string());
-#endif
-        }
-
-        for (size_t i = 0; i < mTouchState.windows.size(); ) {
-            TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
-            const InputWindow* window = getWindowLocked(touchedWindow.channel);
-            if (window) {
-                touchedWindow.window = window;
-                i += 1;
-            } else {
-#if DEBUG_FOCUS
-                LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string());
-#endif
-                synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel,
-                        InputState::CANCEL_POINTER_EVENTS, "touched window was removed");
-                mTouchState.windows.removeAt(i);
-            }
-        }
-
-#if DEBUG_FOCUS
-        //logDispatchStateLocked();
-#endif
-    } // release lock
-
-    // Wake up poll loop since it may need to make new input dispatching choices.
-    mLooper->wake();
-}
-
-void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) {
-#if DEBUG_FOCUS
-    LOGD("setFocusedApplication");
-#endif
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        releaseFocusedApplicationLocked();
-
-        if (inputApplication) {
-            mFocusedApplicationStorage = *inputApplication;
-            mFocusedApplication = & mFocusedApplicationStorage;
-        }
-
-#if DEBUG_FOCUS
-        //logDispatchStateLocked();
-#endif
-    } // release lock
-
-    // Wake up poll loop since it may need to make new input dispatching choices.
-    mLooper->wake();
-}
-
-void InputDispatcher::releaseFocusedApplicationLocked() {
-    if (mFocusedApplication) {
-        mFocusedApplication = NULL;
-        mFocusedApplicationStorage.handle.clear();
-    }
-}
-
-void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
-#if DEBUG_FOCUS
-    LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
-#endif
-
-    bool changed;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
-            if (mDispatchFrozen && !frozen) {
-                resetANRTimeoutsLocked();
-            }
-
-            if (mDispatchEnabled && !enabled) {
-                resetAndDropEverythingLocked("dispatcher is being disabled");
-            }
-
-            mDispatchEnabled = enabled;
-            mDispatchFrozen = frozen;
-            changed = true;
-        } else {
-            changed = false;
-        }
-
-#if DEBUG_FOCUS
-        //logDispatchStateLocked();
-#endif
-    } // release lock
-
-    if (changed) {
-        // Wake up poll loop since it may need to make new input dispatching choices.
-        mLooper->wake();
-    }
-}
-
-bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
-        const sp<InputChannel>& toChannel) {
-#if DEBUG_FOCUS
-    LOGD("transferTouchFocus: fromChannel=%s, toChannel=%s",
-            fromChannel->getName().string(), toChannel->getName().string());
-#endif
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        const InputWindow* fromWindow = getWindowLocked(fromChannel);
-        const InputWindow* toWindow = getWindowLocked(toChannel);
-        if (! fromWindow || ! toWindow) {
-#if DEBUG_FOCUS
-            LOGD("Cannot transfer focus because from or to window not found.");
-#endif
-            return false;
-        }
-        if (fromWindow == toWindow) {
-#if DEBUG_FOCUS
-            LOGD("Trivial transfer to same window.");
-#endif
-            return true;
-        }
-
-        bool found = false;
-        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
-            const TouchedWindow& touchedWindow = mTouchState.windows[i];
-            if (touchedWindow.window == fromWindow) {
-                int32_t oldTargetFlags = touchedWindow.targetFlags;
-                BitSet32 pointerIds = touchedWindow.pointerIds;
-
-                mTouchState.windows.removeAt(i);
-
-                int32_t newTargetFlags = oldTargetFlags
-                        & (InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_SPLIT);
-                mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds);
-
-                found = true;
-                break;
-            }
-        }
-
-        if (! found) {
-#if DEBUG_FOCUS
-            LOGD("Focus transfer failed because from window did not have focus.");
-#endif
-            return false;
-        }
-
-        ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
-        ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel);
-        if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) {
-            sp<Connection> fromConnection = mConnectionsByReceiveFd.valueAt(fromConnectionIndex);
-            sp<Connection> toConnection = mConnectionsByReceiveFd.valueAt(toConnectionIndex);
-
-            fromConnection->inputState.copyPointerStateTo(toConnection->inputState);
-            synthesizeCancelationEventsForConnectionLocked(fromConnection,
-                    InputState::CANCEL_POINTER_EVENTS,
-                    "transferring touch focus from this window to another window");
-        }
-
-#if DEBUG_FOCUS
-        logDispatchStateLocked();
-#endif
-    } // release lock
-
-    // Wake up poll loop since it may need to make new input dispatching choices.
-    mLooper->wake();
-    return true;
-}
-
-void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
-#if DEBUG_FOCUS
-    LOGD("Resetting and dropping all events (%s).", reason);
-#endif
-
-    synthesizeCancelationEventsForAllConnectionsLocked(InputState::CANCEL_ALL_EVENTS, reason);
-
-    resetKeyRepeatLocked();
-    releasePendingEventLocked();
-    drainInboundQueueLocked();
-    resetTargetsLocked();
-
-    mTouchState.reset();
-}
-
-void InputDispatcher::logDispatchStateLocked() {
-    String8 dump;
-    dumpDispatchStateLocked(dump);
-
-    char* text = dump.lockBuffer(dump.size());
-    char* start = text;
-    while (*start != '\0') {
-        char* end = strchr(start, '\n');
-        if (*end == '\n') {
-            *(end++) = '\0';
-        }
-        LOGD("%s", start);
-        start = end;
-    }
-}
-
-void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
-    dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
-    dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
-
-    if (mFocusedApplication) {
-        dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
-                mFocusedApplication->name.string(),
-                mFocusedApplication->dispatchingTimeout / 1000000.0);
-    } else {
-        dump.append(INDENT "FocusedApplication: <null>\n");
-    }
-    dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
-            mFocusedWindow != NULL ? mFocusedWindow->name.string() : "<null>");
-
-    dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
-    dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
-    if (!mTouchState.windows.isEmpty()) {
-        dump.append(INDENT "TouchedWindows:\n");
-        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
-            const TouchedWindow& touchedWindow = mTouchState.windows[i];
-            dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
-                    i, touchedWindow.window->name.string(), touchedWindow.pointerIds.value,
-                    touchedWindow.targetFlags);
-        }
-    } else {
-        dump.append(INDENT "TouchedWindows: <none>\n");
-    }
-
-    if (!mWindows.isEmpty()) {
-        dump.append(INDENT "Windows:\n");
-        for (size_t i = 0; i < mWindows.size(); i++) {
-            const InputWindow& window = mWindows[i];
-            dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
-                    "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
-                    "frame=[%d,%d][%d,%d], "
-                    "visibleFrame=[%d,%d][%d,%d], "
-                    "touchableArea=[%d,%d][%d,%d], "
-                    "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
-                    i, window.name.string(),
-                    toString(window.paused),
-                    toString(window.hasFocus),
-                    toString(window.hasWallpaper),
-                    toString(window.visible),
-                    toString(window.canReceiveKeys),
-                    window.layoutParamsFlags, window.layoutParamsType,
-                    window.layer,
-                    window.frameLeft, window.frameTop,
-                    window.frameRight, window.frameBottom,
-                    window.visibleFrameLeft, window.visibleFrameTop,
-                    window.visibleFrameRight, window.visibleFrameBottom,
-                    window.touchableAreaLeft, window.touchableAreaTop,
-                    window.touchableAreaRight, window.touchableAreaBottom,
-                    window.ownerPid, window.ownerUid,
-                    window.dispatchingTimeout / 1000000.0);
-        }
-    } else {
-        dump.append(INDENT "Windows: <none>\n");
-    }
-
-    if (!mMonitoringChannels.isEmpty()) {
-        dump.append(INDENT "MonitoringChannels:\n");
-        for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
-            const sp<InputChannel>& channel = mMonitoringChannels[i];
-            dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string());
-        }
-    } else {
-        dump.append(INDENT "MonitoringChannels: <none>\n");
-    }
-
-    dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
-
-    if (!mActiveConnections.isEmpty()) {
-        dump.append(INDENT "ActiveConnections:\n");
-        for (size_t i = 0; i < mActiveConnections.size(); i++) {
-            const Connection* connection = mActiveConnections[i];
-            dump.appendFormat(INDENT2 "%d: '%s', status=%s, outboundQueueLength=%u, "
-                    "inputState.isNeutral=%s\n",
-                    i, connection->getInputChannelName(), connection->getStatusLabel(),
-                    connection->outboundQueue.count(),
-                    toString(connection->inputState.isNeutral()));
-        }
-    } else {
-        dump.append(INDENT "ActiveConnections: <none>\n");
-    }
-
-    if (isAppSwitchPendingLocked()) {
-        dump.appendFormat(INDENT "AppSwitch: pending, due in %01.1fms\n",
-                (mAppSwitchDueTime - now()) / 1000000.0);
-    } else {
-        dump.append(INDENT "AppSwitch: not pending\n");
-    }
-}
-
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
-#if DEBUG_REGISTRATION
-    LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
-            toString(monitor));
-#endif
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (getConnectionIndexLocked(inputChannel) >= 0) {
-            LOGW("Attempted to register already registered input channel '%s'",
-                    inputChannel->getName().string());
-            return BAD_VALUE;
-        }
-
-        sp<Connection> connection = new Connection(inputChannel);
-        status_t status = connection->initialize();
-        if (status) {
-            LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
-                    inputChannel->getName().string(), status);
-            return status;
-        }
-
-        int32_t receiveFd = inputChannel->getReceivePipeFd();
-        mConnectionsByReceiveFd.add(receiveFd, connection);
-
-        if (monitor) {
-            mMonitoringChannels.push(inputChannel);
-        }
-
-        mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
-
-        runCommandsLockedInterruptible();
-    } // release lock
-    return OK;
-}
-
-status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
-#if DEBUG_REGISTRATION
-    LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
-#endif
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
-        if (connectionIndex < 0) {
-            LOGW("Attempted to unregister already unregistered input channel '%s'",
-                    inputChannel->getName().string());
-            return BAD_VALUE;
-        }
-
-        sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-        mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
-
-        connection->status = Connection::STATUS_ZOMBIE;
-
-        for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
-            if (mMonitoringChannels[i] == inputChannel) {
-                mMonitoringChannels.removeAt(i);
-                break;
-            }
-        }
-
-        mLooper->removeFd(inputChannel->getReceivePipeFd());
-
-        nsecs_t currentTime = now();
-        abortBrokenDispatchCycleLocked(currentTime, connection);
-
-        runCommandsLockedInterruptible();
-    } // release lock
-
-    // Wake the poll loop because removing the connection may have changed the current
-    // synchronization state.
-    mLooper->wake();
-    return OK;
-}
-
-ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
-    ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
-    if (connectionIndex >= 0) {
-        sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-        if (connection->inputChannel.get() == inputChannel.get()) {
-            return connectionIndex;
-        }
-    }
-
-    return -1;
-}
-
-void InputDispatcher::activateConnectionLocked(Connection* connection) {
-    for (size_t i = 0; i < mActiveConnections.size(); i++) {
-        if (mActiveConnections.itemAt(i) == connection) {
-            return;
-        }
-    }
-    mActiveConnections.add(connection);
-}
-
-void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
-    for (size_t i = 0; i < mActiveConnections.size(); i++) {
-        if (mActiveConnections.itemAt(i) == connection) {
-            mActiveConnections.removeAt(i);
-            return;
-        }
-    }
-}
-
-void InputDispatcher::onDispatchCycleStartedLocked(
-        nsecs_t currentTime, const sp<Connection>& connection) {
-}
-
-void InputDispatcher::onDispatchCycleFinishedLocked(
-        nsecs_t currentTime, const sp<Connection>& connection, bool handled) {
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
-    commandEntry->connection = connection;
-    commandEntry->handled = handled;
-}
-
-void InputDispatcher::onDispatchCycleBrokenLocked(
-        nsecs_t currentTime, const sp<Connection>& connection) {
-    LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
-            connection->getInputChannelName());
-
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
-    commandEntry->connection = connection;
-}
-
-void InputDispatcher::onANRLocked(
-        nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
-        nsecs_t eventTime, nsecs_t waitStartTime) {
-    LOGI("Application is not responding: %s.  "
-            "%01.1fms since event, %01.1fms since wait started",
-            getApplicationWindowLabelLocked(application, window).string(),
-            (currentTime - eventTime) / 1000000.0,
-            (currentTime - waitStartTime) / 1000000.0);
-
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doNotifyANRLockedInterruptible);
-    if (application) {
-        commandEntry->inputApplicationHandle = application->handle;
-    }
-    if (window) {
-        commandEntry->inputChannel = window->inputChannel;
-    }
-}
-
-void InputDispatcher::doNotifyConfigurationChangedInterruptible(
-        CommandEntry* commandEntry) {
-    mLock.unlock();
-
-    mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
-
-    mLock.lock();
-}
-
-void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
-        CommandEntry* commandEntry) {
-    sp<Connection> connection = commandEntry->connection;
-
-    if (connection->status != Connection::STATUS_ZOMBIE) {
-        mLock.unlock();
-
-        mPolicy->notifyInputChannelBroken(connection->inputChannel);
-
-        mLock.lock();
-    }
-}
-
-void InputDispatcher::doNotifyANRLockedInterruptible(
-        CommandEntry* commandEntry) {
-    mLock.unlock();
-
-    nsecs_t newTimeout = mPolicy->notifyANR(
-            commandEntry->inputApplicationHandle, commandEntry->inputChannel);
-
-    mLock.lock();
-
-    resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
-}
-
-void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
-        CommandEntry* commandEntry) {
-    KeyEntry* entry = commandEntry->keyEntry;
-
-    KeyEvent event;
-    initializeKeyEvent(&event, entry);
-
-    mLock.unlock();
-
-    bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputChannel,
-            &event, entry->policyFlags);
-
-    mLock.lock();
-
-    entry->interceptKeyResult = consumed
-            ? KeyEntry::INTERCEPT_KEY_RESULT_SKIP
-            : KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
-    mAllocator.releaseKeyEntry(entry);
-}
-
-void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
-        CommandEntry* commandEntry) {
-    sp<Connection> connection = commandEntry->connection;
-    bool handled = commandEntry->handled;
-
-    if (!connection->outboundQueue.isEmpty()) {
-        DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
-        if (dispatchEntry->inProgress
-                && dispatchEntry->hasForegroundTarget()
-                && dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
-            KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
-            if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
-                if (handled) {
-                    // If the application handled a non-fallback key, then immediately
-                    // cancel all fallback keys previously dispatched to the application.
-                    // This behavior will prevent chording with fallback keys (so they cannot
-                    // be used as modifiers) but it will ensure that fallback keys do not
-                    // get stuck.  This takes care of the case where the application does not handle
-                    // the original DOWN so we generate a fallback DOWN but it does handle
-                    // the original UP in which case we would not generate the fallback UP.
-                    synthesizeCancelationEventsForConnectionLocked(connection,
-                            InputState::CANCEL_FALLBACK_EVENTS,
-                            "application handled a non-fallback event, canceling all fallback events");
-                } else {
-                    // If the application did not handle a non-fallback key, then ask
-                    // the policy what to do with it.  We might generate a fallback key
-                    // event here.
-                    KeyEvent event;
-                    initializeKeyEvent(&event, keyEntry);
-
-                    mLock.unlock();
-
-                    bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel,
-                            &event, keyEntry->policyFlags, &event);
-
-                    mLock.lock();
-
-                    if (connection->status != Connection::STATUS_NORMAL) {
-                        return;
-                    }
-
-                    assert(connection->outboundQueue.headSentinel.next == dispatchEntry);
-
-                    if (fallback) {
-                        // Restart the dispatch cycle using the fallback key.
-                        keyEntry->eventTime = event.getEventTime();
-                        keyEntry->deviceId = event.getDeviceId();
-                        keyEntry->source = event.getSource();
-                        keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
-                        keyEntry->keyCode = event.getKeyCode();
-                        keyEntry->scanCode = event.getScanCode();
-                        keyEntry->metaState = event.getMetaState();
-                        keyEntry->repeatCount = event.getRepeatCount();
-                        keyEntry->downTime = event.getDownTime();
-                        keyEntry->syntheticRepeat = false;
-
-                        dispatchEntry->inProgress = false;
-                        startDispatchCycleLocked(now(), connection);
-                        return;
-                    }
-                }
-            }
-        }
-    }
-
-    startNextDispatchCycleLocked(now(), connection);
-}
-
-void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
-    mLock.unlock();
-
-    mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);
-
-    mLock.lock();
-}
-
-void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) {
-    event->initialize(entry->deviceId, entry->source, entry->action, entry->flags,
-            entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
-            entry->downTime, entry->eventTime);
-}
-
-void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
-        int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
-    // TODO Write some statistics about how long we spend waiting.
-}
-
-void InputDispatcher::dump(String8& dump) {
-    dump.append("Input Dispatcher State:\n");
-    dumpDispatchStateLocked(dump);
-}
-
-
-// --- InputDispatcher::Queue ---
-
-template <typename T>
-uint32_t InputDispatcher::Queue<T>::count() const {
-    uint32_t result = 0;
-    for (const T* entry = headSentinel.next; entry != & tailSentinel; entry = entry->next) {
-        result += 1;
-    }
-    return result;
-}
-
-
-// --- InputDispatcher::Allocator ---
-
-InputDispatcher::Allocator::Allocator() {
-}
-
-InputDispatcher::InjectionState*
-InputDispatcher::Allocator::obtainInjectionState(int32_t injectorPid, int32_t injectorUid) {
-    InjectionState* injectionState = mInjectionStatePool.alloc();
-    injectionState->refCount = 1;
-    injectionState->injectorPid = injectorPid;
-    injectionState->injectorUid = injectorUid;
-    injectionState->injectionIsAsync = false;
-    injectionState->injectionResult = INPUT_EVENT_INJECTION_PENDING;
-    injectionState->pendingForegroundDispatches = 0;
-    return injectionState;
-}
-
-void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
-        nsecs_t eventTime, uint32_t policyFlags) {
-    entry->type = type;
-    entry->refCount = 1;
-    entry->dispatchInProgress = false;
-    entry->eventTime = eventTime;
-    entry->policyFlags = policyFlags;
-    entry->injectionState = NULL;
-}
-
-void InputDispatcher::Allocator::releaseEventEntryInjectionState(EventEntry* entry) {
-    if (entry->injectionState) {
-        releaseInjectionState(entry->injectionState);
-        entry->injectionState = NULL;
-    }
-}
-
-InputDispatcher::ConfigurationChangedEntry*
-InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
-    ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
-    initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime, 0);
-    return entry;
-}
-
-InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
-        int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
-        int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
-        int32_t repeatCount, nsecs_t downTime) {
-    KeyEntry* entry = mKeyEntryPool.alloc();
-    initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime, policyFlags);
-
-    entry->deviceId = deviceId;
-    entry->source = source;
-    entry->action = action;
-    entry->flags = flags;
-    entry->keyCode = keyCode;
-    entry->scanCode = scanCode;
-    entry->metaState = metaState;
-    entry->repeatCount = repeatCount;
-    entry->downTime = downTime;
-    entry->syntheticRepeat = false;
-    entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
-    return entry;
-}
-
-InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
-        int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
-        int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
-        nsecs_t downTime, uint32_t pointerCount,
-        const int32_t* pointerIds, const PointerCoords* pointerCoords) {
-    MotionEntry* entry = mMotionEntryPool.alloc();
-    initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime, policyFlags);
-
-    entry->eventTime = eventTime;
-    entry->deviceId = deviceId;
-    entry->source = source;
-    entry->action = action;
-    entry->flags = flags;
-    entry->metaState = metaState;
-    entry->edgeFlags = edgeFlags;
-    entry->xPrecision = xPrecision;
-    entry->yPrecision = yPrecision;
-    entry->downTime = downTime;
-    entry->pointerCount = pointerCount;
-    entry->firstSample.eventTime = eventTime;
-    entry->firstSample.next = NULL;
-    entry->lastSample = & entry->firstSample;
-    for (uint32_t i = 0; i < pointerCount; i++) {
-        entry->pointerIds[i] = pointerIds[i];
-        entry->firstSample.pointerCoords[i] = pointerCoords[i];
-    }
-    return entry;
-}
-
-InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
-        EventEntry* eventEntry,
-        int32_t targetFlags, float xOffset, float yOffset) {
-    DispatchEntry* entry = mDispatchEntryPool.alloc();
-    entry->eventEntry = eventEntry;
-    eventEntry->refCount += 1;
-    entry->targetFlags = targetFlags;
-    entry->xOffset = xOffset;
-    entry->yOffset = yOffset;
-    entry->inProgress = false;
-    entry->headMotionSample = NULL;
-    entry->tailMotionSample = NULL;
-    return entry;
-}
-
-InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
-    CommandEntry* entry = mCommandEntryPool.alloc();
-    entry->command = command;
-    return entry;
-}
-
-void InputDispatcher::Allocator::releaseInjectionState(InjectionState* injectionState) {
-    injectionState->refCount -= 1;
-    if (injectionState->refCount == 0) {
-        mInjectionStatePool.free(injectionState);
-    } else {
-        assert(injectionState->refCount > 0);
-    }
-}
-
-void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
-    switch (entry->type) {
-    case EventEntry::TYPE_CONFIGURATION_CHANGED:
-        releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
-        break;
-    case EventEntry::TYPE_KEY:
-        releaseKeyEntry(static_cast<KeyEntry*>(entry));
-        break;
-    case EventEntry::TYPE_MOTION:
-        releaseMotionEntry(static_cast<MotionEntry*>(entry));
-        break;
-    default:
-        assert(false);
-        break;
-    }
-}
-
-void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
-        ConfigurationChangedEntry* entry) {
-    entry->refCount -= 1;
-    if (entry->refCount == 0) {
-        releaseEventEntryInjectionState(entry);
-        mConfigurationChangeEntryPool.free(entry);
-    } else {
-        assert(entry->refCount > 0);
-    }
-}
-
-void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
-    entry->refCount -= 1;
-    if (entry->refCount == 0) {
-        releaseEventEntryInjectionState(entry);
-        mKeyEntryPool.free(entry);
-    } else {
-        assert(entry->refCount > 0);
-    }
-}
-
-void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
-    entry->refCount -= 1;
-    if (entry->refCount == 0) {
-        releaseEventEntryInjectionState(entry);
-        for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
-            MotionSample* next = sample->next;
-            mMotionSamplePool.free(sample);
-            sample = next;
-        }
-        mMotionEntryPool.free(entry);
-    } else {
-        assert(entry->refCount > 0);
-    }
-}
-
-void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
-    releaseEventEntry(entry->eventEntry);
-    mDispatchEntryPool.free(entry);
-}
-
-void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
-    mCommandEntryPool.free(entry);
-}
-
-void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
-        nsecs_t eventTime, const PointerCoords* pointerCoords) {
-    MotionSample* sample = mMotionSamplePool.alloc();
-    sample->eventTime = eventTime;
-    uint32_t pointerCount = motionEntry->pointerCount;
-    for (uint32_t i = 0; i < pointerCount; i++) {
-        sample->pointerCoords[i] = pointerCoords[i];
-    }
-
-    sample->next = NULL;
-    motionEntry->lastSample->next = sample;
-    motionEntry->lastSample = sample;
-}
-
-void InputDispatcher::Allocator::recycleKeyEntry(KeyEntry* keyEntry) {
-    releaseEventEntryInjectionState(keyEntry);
-
-    keyEntry->dispatchInProgress = false;
-    keyEntry->syntheticRepeat = false;
-    keyEntry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
-}
-
-
-// --- InputDispatcher::MotionEntry ---
-
-uint32_t InputDispatcher::MotionEntry::countSamples() const {
-    uint32_t count = 1;
-    for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
-        count += 1;
-    }
-    return count;
-}
-
-
-// --- InputDispatcher::InputState ---
-
-InputDispatcher::InputState::InputState() {
-}
-
-InputDispatcher::InputState::~InputState() {
-}
-
-bool InputDispatcher::InputState::isNeutral() const {
-    return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
-}
-
-InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackEvent(
-        const EventEntry* entry) {
-    switch (entry->type) {
-    case EventEntry::TYPE_KEY:
-        return trackKey(static_cast<const KeyEntry*>(entry));
-
-    case EventEntry::TYPE_MOTION:
-        return trackMotion(static_cast<const MotionEntry*>(entry));
-
-    default:
-        return CONSISTENT;
-    }
-}
-
-InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey(
-        const KeyEntry* entry) {
-    int32_t action = entry->action;
-    for (size_t i = 0; i < mKeyMementos.size(); i++) {
-        KeyMemento& memento = mKeyMementos.editItemAt(i);
-        if (memento.deviceId == entry->deviceId
-                && memento.source == entry->source
-                && memento.keyCode == entry->keyCode
-                && memento.scanCode == entry->scanCode) {
-            switch (action) {
-            case AKEY_EVENT_ACTION_UP:
-                mKeyMementos.removeAt(i);
-                return CONSISTENT;
-
-            case AKEY_EVENT_ACTION_DOWN:
-                return TOLERABLE;
-
-            default:
-                return BROKEN;
-            }
-        }
-    }
-
-    switch (action) {
-    case AKEY_EVENT_ACTION_DOWN: {
-        mKeyMementos.push();
-        KeyMemento& memento = mKeyMementos.editTop();
-        memento.deviceId = entry->deviceId;
-        memento.source = entry->source;
-        memento.keyCode = entry->keyCode;
-        memento.scanCode = entry->scanCode;
-        memento.flags = entry->flags;
-        memento.downTime = entry->downTime;
-        return CONSISTENT;
-    }
-
-    default:
-        return BROKEN;
-    }
-}
-
-InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotion(
-        const MotionEntry* entry) {
-    int32_t action = entry->action & AMOTION_EVENT_ACTION_MASK;
-    for (size_t i = 0; i < mMotionMementos.size(); i++) {
-        MotionMemento& memento = mMotionMementos.editItemAt(i);
-        if (memento.deviceId == entry->deviceId
-                && memento.source == entry->source) {
-            switch (action) {
-            case AMOTION_EVENT_ACTION_UP:
-            case AMOTION_EVENT_ACTION_CANCEL:
-                mMotionMementos.removeAt(i);
-                return CONSISTENT;
-
-            case AMOTION_EVENT_ACTION_DOWN:
-                return TOLERABLE;
-
-            case AMOTION_EVENT_ACTION_POINTER_DOWN:
-                if (entry->pointerCount == memento.pointerCount + 1) {
-                    memento.setPointers(entry);
-                    return CONSISTENT;
-                }
-                return BROKEN;
-
-            case AMOTION_EVENT_ACTION_POINTER_UP:
-                if (entry->pointerCount == memento.pointerCount - 1) {
-                    memento.setPointers(entry);
-                    return CONSISTENT;
-                }
-                return BROKEN;
-
-            case AMOTION_EVENT_ACTION_MOVE:
-                if (entry->pointerCount == memento.pointerCount) {
-                    return CONSISTENT;
-                }
-                return BROKEN;
-
-            default:
-                return BROKEN;
-            }
-        }
-    }
-
-    switch (action) {
-    case AMOTION_EVENT_ACTION_DOWN: {
-        mMotionMementos.push();
-        MotionMemento& memento = mMotionMementos.editTop();
-        memento.deviceId = entry->deviceId;
-        memento.source = entry->source;
-        memento.xPrecision = entry->xPrecision;
-        memento.yPrecision = entry->yPrecision;
-        memento.downTime = entry->downTime;
-        memento.setPointers(entry);
-        return CONSISTENT;
-    }
-
-    default:
-        return BROKEN;
-    }
-}
-
-void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
-    pointerCount = entry->pointerCount;
-    for (uint32_t i = 0; i < entry->pointerCount; i++) {
-        pointerIds[i] = entry->pointerIds[i];
-        pointerCoords[i] = entry->lastSample->pointerCoords[i];
-    }
-}
-
-void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
-        Allocator* allocator, Vector<EventEntry*>& outEvents,
-        CancelationOptions options) {
-    for (size_t i = 0; i < mKeyMementos.size(); ) {
-        const KeyMemento& memento = mKeyMementos.itemAt(i);
-        if (shouldCancelKey(memento, options)) {
-            outEvents.push(allocator->obtainKeyEntry(currentTime,
-                    memento.deviceId, memento.source, 0,
-                    AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
-                    memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
-            mKeyMementos.removeAt(i);
-        } else {
-            i += 1;
-        }
-    }
-
-    for (size_t i = 0; i < mMotionMementos.size(); ) {
-        const MotionMemento& memento = mMotionMementos.itemAt(i);
-        if (shouldCancelMotion(memento, options)) {
-            outEvents.push(allocator->obtainMotionEntry(currentTime,
-                    memento.deviceId, memento.source, 0,
-                    AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
-                    memento.xPrecision, memento.yPrecision, memento.downTime,
-                    memento.pointerCount, memento.pointerIds, memento.pointerCoords));
-            mMotionMementos.removeAt(i);
-        } else {
-            i += 1;
-        }
-    }
-}
-
-void InputDispatcher::InputState::clear() {
-    mKeyMementos.clear();
-    mMotionMementos.clear();
-}
-
-void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const {
-    for (size_t i = 0; i < mMotionMementos.size(); i++) {
-        const MotionMemento& memento = mMotionMementos.itemAt(i);
-        if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
-            for (size_t j = 0; j < other.mMotionMementos.size(); ) {
-                const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j);
-                if (memento.deviceId == otherMemento.deviceId
-                        && memento.source == otherMemento.source) {
-                    other.mMotionMementos.removeAt(j);
-                } else {
-                    j += 1;
-                }
-            }
-            other.mMotionMementos.push(memento);
-        }
-    }
-}
-
-bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
-        CancelationOptions options) {
-    switch (options) {
-    case CANCEL_ALL_EVENTS:
-    case CANCEL_NON_POINTER_EVENTS:
-        return true;
-    case CANCEL_FALLBACK_EVENTS:
-        return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
-    default:
-        return false;
-    }
-}
-
-bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
-        CancelationOptions options) {
-    switch (options) {
-    case CANCEL_ALL_EVENTS:
-        return true;
-    case CANCEL_POINTER_EVENTS:
-        return memento.source & AINPUT_SOURCE_CLASS_POINTER;
-    case CANCEL_NON_POINTER_EVENTS:
-        return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
-    default:
-        return false;
-    }
-}
-
-
-// --- InputDispatcher::Connection ---
-
-InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
-        status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
-        lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
-}
-
-InputDispatcher::Connection::~Connection() {
-}
-
-status_t InputDispatcher::Connection::initialize() {
-    return inputPublisher.initialize();
-}
-
-const char* InputDispatcher::Connection::getStatusLabel() const {
-    switch (status) {
-    case STATUS_NORMAL:
-        return "NORMAL";
-
-    case STATUS_BROKEN:
-        return "BROKEN";
-
-    case STATUS_ZOMBIE:
-        return "ZOMBIE";
-
-    default:
-        return "UNKNOWN";
-    }
-}
-
-InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
-        const EventEntry* eventEntry) const {
-    for (DispatchEntry* dispatchEntry = outboundQueue.tailSentinel.prev;
-            dispatchEntry != & outboundQueue.headSentinel; dispatchEntry = dispatchEntry->prev) {
-        if (dispatchEntry->eventEntry == eventEntry) {
-            return dispatchEntry;
-        }
-    }
-    return NULL;
-}
-
-
-// --- InputDispatcher::CommandEntry ---
-
-InputDispatcher::CommandEntry::CommandEntry() :
-    keyEntry(NULL) {
-}
-
-InputDispatcher::CommandEntry::~CommandEntry() {
-}
-
-
-// --- InputDispatcher::TouchState ---
-
-InputDispatcher::TouchState::TouchState() :
-    down(false), split(false) {
-}
-
-InputDispatcher::TouchState::~TouchState() {
-}
-
-void InputDispatcher::TouchState::reset() {
-    down = false;
-    split = false;
-    windows.clear();
-}
-
-void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
-    down = other.down;
-    split = other.split;
-    windows.clear();
-    windows.appendVector(other.windows);
-}
-
-void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
-        int32_t targetFlags, BitSet32 pointerIds) {
-    if (targetFlags & InputTarget::FLAG_SPLIT) {
-        split = true;
-    }
-
-    for (size_t i = 0; i < windows.size(); i++) {
-        TouchedWindow& touchedWindow = windows.editItemAt(i);
-        if (touchedWindow.window == window) {
-            touchedWindow.targetFlags |= targetFlags;
-            touchedWindow.pointerIds.value |= pointerIds.value;
-            return;
-        }
-    }
-
-    windows.push();
-
-    TouchedWindow& touchedWindow = windows.editTop();
-    touchedWindow.window = window;
-    touchedWindow.targetFlags = targetFlags;
-    touchedWindow.pointerIds = pointerIds;
-    touchedWindow.channel = window->inputChannel;
-}
-
-void InputDispatcher::TouchState::removeOutsideTouchWindows() {
-    for (size_t i = 0 ; i < windows.size(); ) {
-        if (windows[i].targetFlags & InputTarget::FLAG_OUTSIDE) {
-            windows.removeAt(i);
-        } else {
-            i += 1;
-        }
-    }
-}
-
-const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() {
-    for (size_t i = 0; i < windows.size(); i++) {
-        if (windows[i].targetFlags & InputTarget::FLAG_FOREGROUND) {
-            return windows[i].window;
-        }
-    }
-    return NULL;
-}
-
-
-// --- InputDispatcherThread ---
-
-InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
-        Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
-}
-
-InputDispatcherThread::~InputDispatcherThread() {
-}
-
-bool InputDispatcherThread::threadLoop() {
-    mDispatcher->dispatchOnce();
-    return true;
-}
-
-} // namespace android
diff --git a/libs/ui/InputManager.cpp b/libs/ui/InputManager.cpp
deleted file mode 100644
index 09fce38..0000000
--- a/libs/ui/InputManager.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-// The input manager.
-//
-#define LOG_TAG "InputManager"
-
-//#define LOG_NDEBUG 0
-
-#include <cutils/log.h>
-#include <ui/InputManager.h>
-#include <ui/InputReader.h>
-#include <ui/InputDispatcher.h>
-
-namespace android {
-
-InputManager::InputManager(
-        const sp<EventHubInterface>& eventHub,
-        const sp<InputReaderPolicyInterface>& readerPolicy,
-        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
-    mDispatcher = new InputDispatcher(dispatcherPolicy);
-    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
-    initialize();
-}
-
-InputManager::InputManager(
-        const sp<InputReaderInterface>& reader,
-        const sp<InputDispatcherInterface>& dispatcher) :
-        mReader(reader),
-        mDispatcher(dispatcher) {
-    initialize();
-}
-
-InputManager::~InputManager() {
-    stop();
-}
-
-void InputManager::initialize() {
-    mReaderThread = new InputReaderThread(mReader);
-    mDispatcherThread = new InputDispatcherThread(mDispatcher);
-}
-
-status_t InputManager::start() {
-    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
-    if (result) {
-        LOGE("Could not start InputDispatcher thread due to error %d.", result);
-        return result;
-    }
-
-    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
-    if (result) {
-        LOGE("Could not start InputReader thread due to error %d.", result);
-
-        mDispatcherThread->requestExit();
-        return result;
-    }
-
-    return OK;
-}
-
-status_t InputManager::stop() {
-    status_t result = mReaderThread->requestExitAndWait();
-    if (result) {
-        LOGW("Could not stop InputReader thread due to error %d.", result);
-    }
-
-    result = mDispatcherThread->requestExitAndWait();
-    if (result) {
-        LOGW("Could not stop InputDispatcher thread due to error %d.", result);
-    }
-
-    return OK;
-}
-
-sp<InputReaderInterface> InputManager::getReader() {
-    return mReader;
-}
-
-sp<InputDispatcherInterface> InputManager::getDispatcher() {
-    return mDispatcher;
-}
-
-} // namespace android
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
deleted file mode 100644
index 51ed09f..0000000
--- a/libs/ui/InputReader.cpp
+++ /dev/null
@@ -1,3549 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-// The input reader.
-//
-#define LOG_TAG "InputReader"
-
-//#define LOG_NDEBUG 0
-
-// Log debug messages for each raw event received from the EventHub.
-#define DEBUG_RAW_EVENTS 0
-
-// Log debug messages about touch screen filtering hacks.
-#define DEBUG_HACKS 0
-
-// Log debug messages about virtual key processing.
-#define DEBUG_VIRTUAL_KEYS 0
-
-// Log debug messages about pointers.
-#define DEBUG_POINTERS 0
-
-// Log debug messages about pointer assignment calculations.
-#define DEBUG_POINTER_ASSIGNMENT 0
-
-#include <cutils/log.h>
-#include <ui/InputReader.h>
-#include <ui/Keyboard.h>
-#include <ui/VirtualKeyMap.h>
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <math.h>
-
-#define INDENT "  "
-#define INDENT2 "    "
-#define INDENT3 "      "
-#define INDENT4 "        "
-
-namespace android {
-
-// --- Static Functions ---
-
-template<typename T>
-inline static T abs(const T& value) {
-    return value < 0 ? - value : value;
-}
-
-template<typename T>
-inline static T min(const T& a, const T& b) {
-    return a < b ? a : b;
-}
-
-template<typename T>
-inline static void swap(T& a, T& b) {
-    T temp = a;
-    a = b;
-    b = temp;
-}
-
-inline static float avg(float x, float y) {
-    return (x + y) / 2;
-}
-
-inline static float pythag(float x, float y) {
-    return sqrtf(x * x + y * y);
-}
-
-static inline const char* toString(bool value) {
-    return value ? "true" : "false";
-}
-
-static const int32_t keyCodeRotationMap[][4] = {
-        // key codes enumerated counter-clockwise with the original (unrotated) key first
-        // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
-        { AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT },
-        { AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN },
-        { AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT },
-        { AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP },
-};
-static const int keyCodeRotationMapSize =
-        sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
-
-int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
-    if (orientation != InputReaderPolicyInterface::ROTATION_0) {
-        for (int i = 0; i < keyCodeRotationMapSize; i++) {
-            if (keyCode == keyCodeRotationMap[i][0]) {
-                return keyCodeRotationMap[i][orientation];
-            }
-        }
-    }
-    return keyCode;
-}
-
-static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
-    return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
-}
-
-
-// --- InputReader ---
-
-InputReader::InputReader(const sp<EventHubInterface>& eventHub,
-        const sp<InputReaderPolicyInterface>& policy,
-        const sp<InputDispatcherInterface>& dispatcher) :
-        mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
-        mGlobalMetaState(0) {
-    configureExcludedDevices();
-    updateGlobalMetaState();
-    updateInputConfiguration();
-}
-
-InputReader::~InputReader() {
-    for (size_t i = 0; i < mDevices.size(); i++) {
-        delete mDevices.valueAt(i);
-    }
-}
-
-void InputReader::loopOnce() {
-    RawEvent rawEvent;
-    mEventHub->getEvent(& rawEvent);
-
-#if DEBUG_RAW_EVENTS
-    LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
-            rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
-            rawEvent.value);
-#endif
-
-    process(& rawEvent);
-}
-
-void InputReader::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EventHubInterface::DEVICE_ADDED:
-        addDevice(rawEvent->deviceId);
-        break;
-
-    case EventHubInterface::DEVICE_REMOVED:
-        removeDevice(rawEvent->deviceId);
-        break;
-
-    case EventHubInterface::FINISHED_DEVICE_SCAN:
-        handleConfigurationChanged(rawEvent->when);
-        break;
-
-    default:
-        consumeEvent(rawEvent);
-        break;
-    }
-}
-
-void InputReader::addDevice(int32_t deviceId) {
-    String8 name = mEventHub->getDeviceName(deviceId);
-    uint32_t classes = mEventHub->getDeviceClasses(deviceId);
-
-    InputDevice* device = createDevice(deviceId, name, classes);
-    device->configure();
-
-    if (device->isIgnored()) {
-        LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
-    } else {
-        LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
-                device->getSources());
-    }
-
-    bool added = false;
-    { // acquire device registry writer lock
-        RWLock::AutoWLock _wl(mDeviceRegistryLock);
-
-        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-        if (deviceIndex < 0) {
-            mDevices.add(deviceId, device);
-            added = true;
-        }
-    } // release device registry writer lock
-
-    if (! added) {
-        LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
-        delete device;
-        return;
-    }
-}
-
-void InputReader::removeDevice(int32_t deviceId) {
-    bool removed = false;
-    InputDevice* device = NULL;
-    { // acquire device registry writer lock
-        RWLock::AutoWLock _wl(mDeviceRegistryLock);
-
-        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-        if (deviceIndex >= 0) {
-            device = mDevices.valueAt(deviceIndex);
-            mDevices.removeItemsAt(deviceIndex, 1);
-            removed = true;
-        }
-    } // release device registry writer lock
-
-    if (! removed) {
-        LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
-        return;
-    }
-
-    if (device->isIgnored()) {
-        LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
-                device->getId(), device->getName().string());
-    } else {
-        LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
-                device->getId(), device->getName().string(), device->getSources());
-    }
-
-    device->reset();
-
-    delete device;
-}
-
-InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
-    InputDevice* device = new InputDevice(this, deviceId, name);
-
-    // Switch-like devices.
-    if (classes & INPUT_DEVICE_CLASS_SWITCH) {
-        device->addMapper(new SwitchInputMapper(device));
-    }
-
-    // Keyboard-like devices.
-    uint32_t keyboardSources = 0;
-    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
-    if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
-        keyboardSources |= AINPUT_SOURCE_KEYBOARD;
-    }
-    if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
-        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
-    }
-    if (classes & INPUT_DEVICE_CLASS_DPAD) {
-        keyboardSources |= AINPUT_SOURCE_DPAD;
-    }
-
-    if (keyboardSources != 0) {
-        device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType));
-    }
-
-    // Trackball-like devices.
-    if (classes & INPUT_DEVICE_CLASS_TRACKBALL) {
-        device->addMapper(new TrackballInputMapper(device));
-    }
-
-    // Touchscreen-like devices.
-    if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
-        device->addMapper(new MultiTouchInputMapper(device));
-    } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
-        device->addMapper(new SingleTouchInputMapper(device));
-    }
-
-    return device;
-}
-
-void InputReader::consumeEvent(const RawEvent* rawEvent) {
-    int32_t deviceId = rawEvent->deviceId;
-
-    { // acquire device registry reader lock
-        RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-        if (deviceIndex < 0) {
-            LOGW("Discarding event for unknown deviceId %d.", deviceId);
-            return;
-        }
-
-        InputDevice* device = mDevices.valueAt(deviceIndex);
-        if (device->isIgnored()) {
-            //LOGD("Discarding event for ignored deviceId %d.", deviceId);
-            return;
-        }
-
-        device->process(rawEvent);
-    } // release device registry reader lock
-}
-
-void InputReader::handleConfigurationChanged(nsecs_t when) {
-    // Reset global meta state because it depends on the list of all configured devices.
-    updateGlobalMetaState();
-
-    // Update input configuration.
-    updateInputConfiguration();
-
-    // Enqueue configuration changed.
-    mDispatcher->notifyConfigurationChanged(when);
-}
-
-void InputReader::configureExcludedDevices() {
-    Vector<String8> excludedDeviceNames;
-    mPolicy->getExcludedDeviceNames(excludedDeviceNames);
-
-    for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
-        mEventHub->addExcludedDevice(excludedDeviceNames[i]);
-    }
-}
-
-void InputReader::updateGlobalMetaState() {
-    { // acquire state lock
-        AutoMutex _l(mStateLock);
-
-        mGlobalMetaState = 0;
-
-        { // acquire device registry reader lock
-            RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-            for (size_t i = 0; i < mDevices.size(); i++) {
-                InputDevice* device = mDevices.valueAt(i);
-                mGlobalMetaState |= device->getMetaState();
-            }
-        } // release device registry reader lock
-    } // release state lock
-}
-
-int32_t InputReader::getGlobalMetaState() {
-    { // acquire state lock
-        AutoMutex _l(mStateLock);
-
-        return mGlobalMetaState;
-    } // release state lock
-}
-
-void InputReader::updateInputConfiguration() {
-    { // acquire state lock
-        AutoMutex _l(mStateLock);
-
-        int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
-        int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
-        int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
-        { // acquire device registry reader lock
-            RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-            InputDeviceInfo deviceInfo;
-            for (size_t i = 0; i < mDevices.size(); i++) {
-                InputDevice* device = mDevices.valueAt(i);
-                device->getDeviceInfo(& deviceInfo);
-                uint32_t sources = deviceInfo.getSources();
-
-                if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
-                    touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
-                }
-                if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
-                    navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
-                } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
-                    navigationConfig = InputConfiguration::NAVIGATION_DPAD;
-                }
-                if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
-                    keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
-                }
-            }
-        } // release device registry reader lock
-
-        mInputConfiguration.touchScreen = touchScreenConfig;
-        mInputConfiguration.keyboard = keyboardConfig;
-        mInputConfiguration.navigation = navigationConfig;
-    } // release state lock
-}
-
-void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
-    { // acquire state lock
-        AutoMutex _l(mStateLock);
-
-        *outConfiguration = mInputConfiguration;
-    } // release state lock
-}
-
-status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
-    { // acquire device registry reader lock
-        RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-        if (deviceIndex < 0) {
-            return NAME_NOT_FOUND;
-        }
-
-        InputDevice* device = mDevices.valueAt(deviceIndex);
-        if (device->isIgnored()) {
-            return NAME_NOT_FOUND;
-        }
-
-        device->getDeviceInfo(outDeviceInfo);
-        return OK;
-    } // release device registy reader lock
-}
-
-void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
-    outDeviceIds.clear();
-
-    { // acquire device registry reader lock
-        RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-        size_t numDevices = mDevices.size();
-        for (size_t i = 0; i < numDevices; i++) {
-            InputDevice* device = mDevices.valueAt(i);
-            if (! device->isIgnored()) {
-                outDeviceIds.add(device->getId());
-            }
-        }
-    } // release device registy reader lock
-}
-
-int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
-        int32_t keyCode) {
-    return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
-}
-
-int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
-        int32_t scanCode) {
-    return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
-}
-
-int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
-    return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
-}
-
-int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
-        GetStateFunc getStateFunc) {
-    { // acquire device registry reader lock
-        RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-        int32_t result = AKEY_STATE_UNKNOWN;
-        if (deviceId >= 0) {
-            ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-            if (deviceIndex >= 0) {
-                InputDevice* device = mDevices.valueAt(deviceIndex);
-                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                    result = (device->*getStateFunc)(sourceMask, code);
-                }
-            }
-        } else {
-            size_t numDevices = mDevices.size();
-            for (size_t i = 0; i < numDevices; i++) {
-                InputDevice* device = mDevices.valueAt(i);
-                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                    result = (device->*getStateFunc)(sourceMask, code);
-                    if (result >= AKEY_STATE_DOWN) {
-                        return result;
-                    }
-                }
-            }
-        }
-        return result;
-    } // release device registy reader lock
-}
-
-bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
-        size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
-    memset(outFlags, 0, numCodes);
-    return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
-}
-
-bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) {
-    { // acquire device registry reader lock
-        RWLock::AutoRLock _rl(mDeviceRegistryLock);
-        bool result = false;
-        if (deviceId >= 0) {
-            ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-            if (deviceIndex >= 0) {
-                InputDevice* device = mDevices.valueAt(deviceIndex);
-                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                    result = device->markSupportedKeyCodes(sourceMask,
-                            numCodes, keyCodes, outFlags);
-                }
-            }
-        } else {
-            size_t numDevices = mDevices.size();
-            for (size_t i = 0; i < numDevices; i++) {
-                InputDevice* device = mDevices.valueAt(i);
-                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                    result |= device->markSupportedKeyCodes(sourceMask,
-                            numCodes, keyCodes, outFlags);
-                }
-            }
-        }
-        return result;
-    } // release device registy reader lock
-}
-
-void InputReader::dump(String8& dump) {
-    mEventHub->dump(dump);
-    dump.append("\n");
-
-    dump.append("Input Reader State:\n");
-
-    { // acquire device registry reader lock
-        RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-        for (size_t i = 0; i < mDevices.size(); i++) {
-            mDevices.valueAt(i)->dump(dump);
-        }
-    } // release device registy reader lock
-}
-
-
-// --- InputReaderThread ---
-
-InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
-        Thread(/*canCallJava*/ true), mReader(reader) {
-}
-
-InputReaderThread::~InputReaderThread() {
-}
-
-bool InputReaderThread::threadLoop() {
-    mReader->loopOnce();
-    return true;
-}
-
-
-// --- InputDevice ---
-
-InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
-        mContext(context), mId(id), mName(name), mSources(0) {
-}
-
-InputDevice::~InputDevice() {
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        delete mMappers[i];
-    }
-    mMappers.clear();
-}
-
-static void dumpMotionRange(String8& dump, const InputDeviceInfo& deviceInfo,
-        int32_t rangeType, const char* name) {
-    const InputDeviceInfo::MotionRange* range = deviceInfo.getMotionRange(rangeType);
-    if (range) {
-        dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
-                name, range->min, range->max, range->flat, range->fuzz);
-    }
-}
-
-void InputDevice::dump(String8& dump) {
-    InputDeviceInfo deviceInfo;
-    getDeviceInfo(& deviceInfo);
-
-    dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
-            deviceInfo.getName().string());
-    dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
-    dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
-    if (!deviceInfo.getMotionRanges().isEmpty()) {
-        dump.append(INDENT2 "Motion Ranges:\n");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_X, "X");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_Y, "Y");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_PRESSURE, "Pressure");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_SIZE, "Size");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MAJOR, "TouchMajor");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MINOR, "TouchMinor");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MAJOR, "ToolMajor");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MINOR, "ToolMinor");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_ORIENTATION, "Orientation");
-    }
-
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        mapper->dump(dump);
-    }
-}
-
-void InputDevice::addMapper(InputMapper* mapper) {
-    mMappers.add(mapper);
-}
-
-void InputDevice::configure() {
-    if (! isIgnored()) {
-        mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
-    }
-
-    mSources = 0;
-
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        mapper->configure();
-        mSources |= mapper->getSources();
-    }
-}
-
-void InputDevice::reset() {
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        mapper->reset();
-    }
-}
-
-void InputDevice::process(const RawEvent* rawEvent) {
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        mapper->process(rawEvent);
-    }
-}
-
-void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
-    outDeviceInfo->initialize(mId, mName);
-
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        mapper->populateDeviceInfo(outDeviceInfo);
-    }
-}
-
-int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-    return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
-}
-
-int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
-}
-
-int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
-    return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
-}
-
-int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
-    int32_t result = AKEY_STATE_UNKNOWN;
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
-            result = (mapper->*getStateFunc)(sourceMask, code);
-            if (result >= AKEY_STATE_DOWN) {
-                return result;
-            }
-        }
-    }
-    return result;
-}
-
-bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) {
-    bool result = false;
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
-            result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
-        }
-    }
-    return result;
-}
-
-int32_t InputDevice::getMetaState() {
-    int32_t result = 0;
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        result |= mapper->getMetaState();
-    }
-    return result;
-}
-
-
-// --- InputMapper ---
-
-InputMapper::InputMapper(InputDevice* device) :
-        mDevice(device), mContext(device->getContext()) {
-}
-
-InputMapper::~InputMapper() {
-}
-
-void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    info->addSource(getSources());
-}
-
-void InputMapper::dump(String8& dump) {
-}
-
-void InputMapper::configure() {
-}
-
-void InputMapper::reset() {
-}
-
-int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
-    return AKEY_STATE_UNKNOWN;
-}
-
-bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) {
-    return false;
-}
-
-int32_t InputMapper::getMetaState() {
-    return 0;
-}
-
-
-// --- SwitchInputMapper ---
-
-SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
-        InputMapper(device) {
-}
-
-SwitchInputMapper::~SwitchInputMapper() {
-}
-
-uint32_t SwitchInputMapper::getSources() {
-    return 0;
-}
-
-void SwitchInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_SW:
-        processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
-        break;
-    }
-}
-
-void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
-    getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
-}
-
-int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
-    return getEventHub()->getSwitchState(getDeviceId(), switchCode);
-}
-
-
-// --- KeyboardInputMapper ---
-
-KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
-        uint32_t sources, int32_t keyboardType) :
-        InputMapper(device), mSources(sources),
-        mKeyboardType(keyboardType) {
-    initializeLocked();
-}
-
-KeyboardInputMapper::~KeyboardInputMapper() {
-}
-
-void KeyboardInputMapper::initializeLocked() {
-    mLocked.metaState = AMETA_NONE;
-    mLocked.downTime = 0;
-}
-
-uint32_t KeyboardInputMapper::getSources() {
-    return mSources;
-}
-
-void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    info->setKeyboardType(mKeyboardType);
-}
-
-void KeyboardInputMapper::dump(String8& dump) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-        dump.append(INDENT2 "Keyboard Input Mapper:\n");
-        dumpParameters(dump);
-        dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
-        dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
-        dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
-        dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
-    } // release lock
-}
-
-
-void KeyboardInputMapper::configure() {
-    InputMapper::configure();
-
-    // Configure basic parameters.
-    configureParameters();
-
-    // Reset LEDs.
-    {
-        AutoMutex _l(mLock);
-        resetLedStateLocked();
-    }
-}
-
-void KeyboardInputMapper::configureParameters() {
-    mParameters.orientationAware = false;
-    getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
-            mParameters.orientationAware);
-
-    mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
-}
-
-void KeyboardInputMapper::dumpParameters(String8& dump) {
-    dump.append(INDENT3 "Parameters:\n");
-    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
-            mParameters.associatedDisplayId);
-    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
-            toString(mParameters.orientationAware));
-}
-
-void KeyboardInputMapper::reset() {
-    for (;;) {
-        int32_t keyCode, scanCode;
-        { // acquire lock
-            AutoMutex _l(mLock);
-
-            // Synthesize key up event on reset if keys are currently down.
-            if (mLocked.keyDowns.isEmpty()) {
-                initializeLocked();
-                resetLedStateLocked();
-                break; // done
-            }
-
-            const KeyDown& keyDown = mLocked.keyDowns.top();
-            keyCode = keyDown.keyCode;
-            scanCode = keyDown.scanCode;
-        } // release lock
-
-        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
-        processKey(when, false, keyCode, scanCode, 0);
-    }
-
-    InputMapper::reset();
-    getContext()->updateGlobalMetaState();
-}
-
-void KeyboardInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_KEY: {
-        int32_t scanCode = rawEvent->scanCode;
-        if (isKeyboardOrGamepadKey(scanCode)) {
-            processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
-                    rawEvent->flags);
-        }
-        break;
-    }
-    }
-}
-
-bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
-    return scanCode < BTN_MOUSE
-        || scanCode >= KEY_OK
-        || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
-}
-
-void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
-        int32_t scanCode, uint32_t policyFlags) {
-    int32_t newMetaState;
-    nsecs_t downTime;
-    bool metaStateChanged = false;
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (down) {
-            // Rotate key codes according to orientation if needed.
-            // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
-            if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
-                int32_t orientation;
-                if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
-                        NULL, NULL, & orientation)) {
-                    orientation = InputReaderPolicyInterface::ROTATION_0;
-                }
-
-                keyCode = rotateKeyCode(keyCode, orientation);
-            }
-
-            // Add key down.
-            ssize_t keyDownIndex = findKeyDownLocked(scanCode);
-            if (keyDownIndex >= 0) {
-                // key repeat, be sure to use same keycode as before in case of rotation
-                keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
-            } else {
-                // key down
-                mLocked.keyDowns.push();
-                KeyDown& keyDown = mLocked.keyDowns.editTop();
-                keyDown.keyCode = keyCode;
-                keyDown.scanCode = scanCode;
-            }
-
-            mLocked.downTime = when;
-        } else {
-            // Remove key down.
-            ssize_t keyDownIndex = findKeyDownLocked(scanCode);
-            if (keyDownIndex >= 0) {
-                // key up, be sure to use same keycode as before in case of rotation
-                keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
-                mLocked.keyDowns.removeAt(size_t(keyDownIndex));
-            } else {
-                // key was not actually down
-                LOGI("Dropping key up from device %s because the key was not down.  "
-                        "keyCode=%d, scanCode=%d",
-                        getDeviceName().string(), keyCode, scanCode);
-                return;
-            }
-        }
-
-        int32_t oldMetaState = mLocked.metaState;
-        newMetaState = updateMetaState(keyCode, down, oldMetaState);
-        if (oldMetaState != newMetaState) {
-            mLocked.metaState = newMetaState;
-            metaStateChanged = true;
-            updateLedStateLocked(false);
-        }
-
-        downTime = mLocked.downTime;
-    } // release lock
-
-    if (metaStateChanged) {
-        getContext()->updateGlobalMetaState();
-    }
-
-    if (policyFlags & POLICY_FLAG_FUNCTION) {
-        newMetaState |= AMETA_FUNCTION_ON;
-    }
-    getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
-            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
-            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
-}
-
-ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
-    size_t n = mLocked.keyDowns.size();
-    for (size_t i = 0; i < n; i++) {
-        if (mLocked.keyDowns[i].scanCode == scanCode) {
-            return i;
-        }
-    }
-    return -1;
-}
-
-int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-    return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
-}
-
-int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
-}
-
-bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) {
-    return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
-}
-
-int32_t KeyboardInputMapper::getMetaState() {
-    { // acquire lock
-        AutoMutex _l(mLock);
-        return mLocked.metaState;
-    } // release lock
-}
-
-void KeyboardInputMapper::resetLedStateLocked() {
-    initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
-    initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
-    initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
-
-    updateLedStateLocked(true);
-}
-
-void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
-    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
-    ledState.on = false;
-}
-
-void KeyboardInputMapper::updateLedStateLocked(bool reset) {
-    updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
-            AMETA_CAPS_LOCK_ON, reset);
-    updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
-            AMETA_NUM_LOCK_ON, reset);
-    updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
-            AMETA_SCROLL_LOCK_ON, reset);
-}
-
-void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
-        int32_t led, int32_t modifier, bool reset) {
-    if (ledState.avail) {
-        bool desiredState = (mLocked.metaState & modifier) != 0;
-        if (reset || ledState.on != desiredState) {
-            getEventHub()->setLedState(getDeviceId(), led, desiredState);
-            ledState.on = desiredState;
-        }
-    }
-}
-
-
-// --- TrackballInputMapper ---
-
-TrackballInputMapper::TrackballInputMapper(InputDevice* device) :
-        InputMapper(device) {
-    mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
-    mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
-    mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
-    mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
-
-    initializeLocked();
-}
-
-TrackballInputMapper::~TrackballInputMapper() {
-}
-
-uint32_t TrackballInputMapper::getSources() {
-    return AINPUT_SOURCE_TRACKBALL;
-}
-
-void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
-    info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
-}
-
-void TrackballInputMapper::dump(String8& dump) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-        dump.append(INDENT2 "Trackball Input Mapper:\n");
-        dumpParameters(dump);
-        dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
-        dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
-        dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
-        dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
-    } // release lock
-}
-
-void TrackballInputMapper::configure() {
-    InputMapper::configure();
-
-    // Configure basic parameters.
-    configureParameters();
-}
-
-void TrackballInputMapper::configureParameters() {
-    mParameters.orientationAware = false;
-    getDevice()->getConfiguration().tryGetProperty(String8("trackball.orientationAware"),
-            mParameters.orientationAware);
-
-    mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
-}
-
-void TrackballInputMapper::dumpParameters(String8& dump) {
-    dump.append(INDENT3 "Parameters:\n");
-    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
-            mParameters.associatedDisplayId);
-    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
-            toString(mParameters.orientationAware));
-}
-
-void TrackballInputMapper::initializeLocked() {
-    mAccumulator.clear();
-
-    mLocked.down = false;
-    mLocked.downTime = 0;
-}
-
-void TrackballInputMapper::reset() {
-    for (;;) {
-        { // acquire lock
-            AutoMutex _l(mLock);
-
-            if (! mLocked.down) {
-                initializeLocked();
-                break; // done
-            }
-        } // release lock
-
-        // Synthesize trackball button up event on reset.
-        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
-        mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
-        mAccumulator.btnMouse = false;
-        sync(when);
-    }
-
-    InputMapper::reset();
-}
-
-void TrackballInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_KEY:
-        switch (rawEvent->scanCode) {
-        case BTN_MOUSE:
-            mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
-            mAccumulator.btnMouse = rawEvent->value != 0;
-            // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
-            // we need to ensure that we report the up/down promptly.
-            sync(rawEvent->when);
-            break;
-        }
-        break;
-
-    case EV_REL:
-        switch (rawEvent->scanCode) {
-        case REL_X:
-            mAccumulator.fields |= Accumulator::FIELD_REL_X;
-            mAccumulator.relX = rawEvent->value;
-            break;
-        case REL_Y:
-            mAccumulator.fields |= Accumulator::FIELD_REL_Y;
-            mAccumulator.relY = rawEvent->value;
-            break;
-        }
-        break;
-
-    case EV_SYN:
-        switch (rawEvent->scanCode) {
-        case SYN_REPORT:
-            sync(rawEvent->when);
-            break;
-        }
-        break;
-    }
-}
-
-void TrackballInputMapper::sync(nsecs_t when) {
-    uint32_t fields = mAccumulator.fields;
-    if (fields == 0) {
-        return; // no new state changes, so nothing to do
-    }
-
-    int motionEventAction;
-    PointerCoords pointerCoords;
-    nsecs_t downTime;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
-
-        if (downChanged) {
-            if (mAccumulator.btnMouse) {
-                mLocked.down = true;
-                mLocked.downTime = when;
-            } else {
-                mLocked.down = false;
-            }
-        }
-
-        downTime = mLocked.downTime;
-        float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
-        float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
-
-        if (downChanged) {
-            motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
-        } else {
-            motionEventAction = AMOTION_EVENT_ACTION_MOVE;
-        }
-
-        pointerCoords.x = x;
-        pointerCoords.y = y;
-        pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
-        pointerCoords.size = 0;
-        pointerCoords.touchMajor = 0;
-        pointerCoords.touchMinor = 0;
-        pointerCoords.toolMajor = 0;
-        pointerCoords.toolMinor = 0;
-        pointerCoords.orientation = 0;
-
-        if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
-                && (x != 0.0f || y != 0.0f)) {
-            // Rotate motion based on display orientation if needed.
-            // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
-            int32_t orientation;
-            if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
-                    NULL, NULL, & orientation)) {
-                orientation = InputReaderPolicyInterface::ROTATION_0;
-            }
-
-            float temp;
-            switch (orientation) {
-            case InputReaderPolicyInterface::ROTATION_90:
-                temp = pointerCoords.x;
-                pointerCoords.x = pointerCoords.y;
-                pointerCoords.y = - temp;
-                break;
-
-            case InputReaderPolicyInterface::ROTATION_180:
-                pointerCoords.x = - pointerCoords.x;
-                pointerCoords.y = - pointerCoords.y;
-                break;
-
-            case InputReaderPolicyInterface::ROTATION_270:
-                temp = pointerCoords.x;
-                pointerCoords.x = - pointerCoords.y;
-                pointerCoords.y = temp;
-                break;
-            }
-        }
-    } // release lock
-
-    int32_t metaState = mContext->getGlobalMetaState();
-    int32_t pointerId = 0;
-    getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, 0,
-            motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
-            1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
-
-    mAccumulator.clear();
-}
-
-int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
-        return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
-    } else {
-        return AKEY_STATE_UNKNOWN;
-    }
-}
-
-
-// --- TouchInputMapper ---
-
-TouchInputMapper::TouchInputMapper(InputDevice* device) :
-        InputMapper(device) {
-    mLocked.surfaceOrientation = -1;
-    mLocked.surfaceWidth = -1;
-    mLocked.surfaceHeight = -1;
-
-    initializeLocked();
-}
-
-TouchInputMapper::~TouchInputMapper() {
-}
-
-uint32_t TouchInputMapper::getSources() {
-    switch (mParameters.deviceType) {
-    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
-        return AINPUT_SOURCE_TOUCHSCREEN;
-    case Parameters::DEVICE_TYPE_TOUCH_PAD:
-        return AINPUT_SOURCE_TOUCHPAD;
-    default:
-        assert(false);
-        return AINPUT_SOURCE_UNKNOWN;
-    }
-}
-
-void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        // Ensure surface information is up to date so that orientation changes are
-        // noticed immediately.
-        configureSurfaceLocked();
-
-        info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
-        info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
-
-        if (mLocked.orientedRanges.havePressure) {
-            info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
-                    mLocked.orientedRanges.pressure);
-        }
-
-        if (mLocked.orientedRanges.haveSize) {
-            info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
-                    mLocked.orientedRanges.size);
-        }
-
-        if (mLocked.orientedRanges.haveTouchSize) {
-            info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
-                    mLocked.orientedRanges.touchMajor);
-            info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
-                    mLocked.orientedRanges.touchMinor);
-        }
-
-        if (mLocked.orientedRanges.haveToolSize) {
-            info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
-                    mLocked.orientedRanges.toolMajor);
-            info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
-                    mLocked.orientedRanges.toolMinor);
-        }
-
-        if (mLocked.orientedRanges.haveOrientation) {
-            info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
-                    mLocked.orientedRanges.orientation);
-        }
-    } // release lock
-}
-
-void TouchInputMapper::dump(String8& dump) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-        dump.append(INDENT2 "Touch Input Mapper:\n");
-        dumpParameters(dump);
-        dumpVirtualKeysLocked(dump);
-        dumpRawAxes(dump);
-        dumpCalibration(dump);
-        dumpSurfaceLocked(dump);
-        dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
-        dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
-        dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
-        dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
-        dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
-        dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
-        dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
-        dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
-        dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
-        dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
-        dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
-        dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
-        dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
-        dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
-        dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
-    } // release lock
-}
-
-void TouchInputMapper::initializeLocked() {
-    mCurrentTouch.clear();
-    mLastTouch.clear();
-    mDownTime = 0;
-
-    for (uint32_t i = 0; i < MAX_POINTERS; i++) {
-        mAveragingTouchFilter.historyStart[i] = 0;
-        mAveragingTouchFilter.historyEnd[i] = 0;
-    }
-
-    mJumpyTouchFilter.jumpyPointsDropped = 0;
-
-    mLocked.currentVirtualKey.down = false;
-
-    mLocked.orientedRanges.havePressure = false;
-    mLocked.orientedRanges.haveSize = false;
-    mLocked.orientedRanges.haveTouchSize = false;
-    mLocked.orientedRanges.haveToolSize = false;
-    mLocked.orientedRanges.haveOrientation = false;
-}
-
-void TouchInputMapper::configure() {
-    InputMapper::configure();
-
-    // Configure basic parameters.
-    configureParameters();
-
-    // Configure absolute axis information.
-    configureRawAxes();
-
-    // Prepare input device calibration.
-    parseCalibration();
-    resolveCalibration();
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-         // Configure surface dimensions and orientation.
-        configureSurfaceLocked();
-    } // release lock
-}
-
-void TouchInputMapper::configureParameters() {
-    mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
-    mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
-    mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
-
-    String8 deviceTypeString;
-    mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
-    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
-            deviceTypeString)) {
-        if (deviceTypeString == "touchPad") {
-            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
-        } else if (deviceTypeString != "touchScreen") {
-            LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
-        }
-    }
-    bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
-
-    mParameters.orientationAware = isTouchScreen;
-    getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
-            mParameters.orientationAware);
-
-    mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
-}
-
-void TouchInputMapper::dumpParameters(String8& dump) {
-    dump.append(INDENT3 "Parameters:\n");
-
-    switch (mParameters.deviceType) {
-    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
-        dump.append(INDENT4 "DeviceType: touchScreen\n");
-        break;
-    case Parameters::DEVICE_TYPE_TOUCH_PAD:
-        dump.append(INDENT4 "DeviceType: touchPad\n");
-        break;
-    default:
-        assert(false);
-    }
-
-    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
-            mParameters.associatedDisplayId);
-    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
-            toString(mParameters.orientationAware));
-
-    dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
-            toString(mParameters.useBadTouchFilter));
-    dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
-            toString(mParameters.useAveragingTouchFilter));
-    dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
-            toString(mParameters.useJumpyTouchFilter));
-}
-
-void TouchInputMapper::configureRawAxes() {
-    mRawAxes.x.clear();
-    mRawAxes.y.clear();
-    mRawAxes.pressure.clear();
-    mRawAxes.touchMajor.clear();
-    mRawAxes.touchMinor.clear();
-    mRawAxes.toolMajor.clear();
-    mRawAxes.toolMinor.clear();
-    mRawAxes.orientation.clear();
-}
-
-static void dumpAxisInfo(String8& dump, RawAbsoluteAxisInfo axis, const char* name) {
-    if (axis.valid) {
-        dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
-                name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
-    } else {
-        dump.appendFormat(INDENT4 "%s: unknown range\n", name);
-    }
-}
-
-void TouchInputMapper::dumpRawAxes(String8& dump) {
-    dump.append(INDENT3 "Raw Axes:\n");
-    dumpAxisInfo(dump, mRawAxes.x, "X");
-    dumpAxisInfo(dump, mRawAxes.y, "Y");
-    dumpAxisInfo(dump, mRawAxes.pressure, "Pressure");
-    dumpAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
-    dumpAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
-    dumpAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
-    dumpAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
-    dumpAxisInfo(dump, mRawAxes.orientation, "Orientation");
-}
-
-bool TouchInputMapper::configureSurfaceLocked() {
-    // Update orientation and dimensions if needed.
-    int32_t orientation = InputReaderPolicyInterface::ROTATION_0;
-    int32_t width = mRawAxes.x.getRange();
-    int32_t height = mRawAxes.y.getRange();
-
-    if (mParameters.associatedDisplayId >= 0) {
-        bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
-        bool wantOrientation = mParameters.orientationAware;
-
-        // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
-        if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
-                wantSize ? &width : NULL, wantSize ? &height : NULL,
-                wantOrientation ? &orientation : NULL)) {
-            return false;
-        }
-    }
-
-    bool orientationChanged = mLocked.surfaceOrientation != orientation;
-    if (orientationChanged) {
-        mLocked.surfaceOrientation = orientation;
-    }
-
-    bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
-    if (sizeChanged) {
-        LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
-                getDeviceId(), getDeviceName().string(), width, height);
-
-        mLocked.surfaceWidth = width;
-        mLocked.surfaceHeight = height;
-
-        // Configure X and Y factors.
-        if (mRawAxes.x.valid && mRawAxes.y.valid) {
-            mLocked.xOrigin = mCalibration.haveXOrigin
-                    ? mCalibration.xOrigin
-                    : mRawAxes.x.minValue;
-            mLocked.yOrigin = mCalibration.haveYOrigin
-                    ? mCalibration.yOrigin
-                    : mRawAxes.y.minValue;
-            mLocked.xScale = mCalibration.haveXScale
-                    ? mCalibration.xScale
-                    : float(width) / mRawAxes.x.getRange();
-            mLocked.yScale = mCalibration.haveYScale
-                    ? mCalibration.yScale
-                    : float(height) / mRawAxes.y.getRange();
-            mLocked.xPrecision = 1.0f / mLocked.xScale;
-            mLocked.yPrecision = 1.0f / mLocked.yScale;
-
-            configureVirtualKeysLocked();
-        } else {
-            LOGW(INDENT "Touch device did not report support for X or Y axis!");
-            mLocked.xOrigin = 0;
-            mLocked.yOrigin = 0;
-            mLocked.xScale = 1.0f;
-            mLocked.yScale = 1.0f;
-            mLocked.xPrecision = 1.0f;
-            mLocked.yPrecision = 1.0f;
-        }
-
-        // Scale factor for terms that are not oriented in a particular axis.
-        // If the pixels are square then xScale == yScale otherwise we fake it
-        // by choosing an average.
-        mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
-
-        // Size of diagonal axis.
-        float diagonalSize = pythag(width, height);
-
-        // TouchMajor and TouchMinor factors.
-        if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
-            mLocked.orientedRanges.haveTouchSize = true;
-            mLocked.orientedRanges.touchMajor.min = 0;
-            mLocked.orientedRanges.touchMajor.max = diagonalSize;
-            mLocked.orientedRanges.touchMajor.flat = 0;
-            mLocked.orientedRanges.touchMajor.fuzz = 0;
-            mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
-        }
-
-        // ToolMajor and ToolMinor factors.
-        mLocked.toolSizeLinearScale = 0;
-        mLocked.toolSizeLinearBias = 0;
-        mLocked.toolSizeAreaScale = 0;
-        mLocked.toolSizeAreaBias = 0;
-        if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
-            if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
-                if (mCalibration.haveToolSizeLinearScale) {
-                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
-                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
-                    mLocked.toolSizeLinearScale = float(min(width, height))
-                            / mRawAxes.toolMajor.maxValue;
-                }
-
-                if (mCalibration.haveToolSizeLinearBias) {
-                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
-                }
-            } else if (mCalibration.toolSizeCalibration ==
-                    Calibration::TOOL_SIZE_CALIBRATION_AREA) {
-                if (mCalibration.haveToolSizeLinearScale) {
-                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
-                } else {
-                    mLocked.toolSizeLinearScale = min(width, height);
-                }
-
-                if (mCalibration.haveToolSizeLinearBias) {
-                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
-                }
-
-                if (mCalibration.haveToolSizeAreaScale) {
-                    mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
-                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
-                    mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
-                }
-
-                if (mCalibration.haveToolSizeAreaBias) {
-                    mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
-                }
-            }
-
-            mLocked.orientedRanges.haveToolSize = true;
-            mLocked.orientedRanges.toolMajor.min = 0;
-            mLocked.orientedRanges.toolMajor.max = diagonalSize;
-            mLocked.orientedRanges.toolMajor.flat = 0;
-            mLocked.orientedRanges.toolMajor.fuzz = 0;
-            mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
-        }
-
-        // Pressure factors.
-        mLocked.pressureScale = 0;
-        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
-            RawAbsoluteAxisInfo rawPressureAxis;
-            switch (mCalibration.pressureSource) {
-            case Calibration::PRESSURE_SOURCE_PRESSURE:
-                rawPressureAxis = mRawAxes.pressure;
-                break;
-            case Calibration::PRESSURE_SOURCE_TOUCH:
-                rawPressureAxis = mRawAxes.touchMajor;
-                break;
-            default:
-                rawPressureAxis.clear();
-            }
-
-            if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
-                    || mCalibration.pressureCalibration
-                            == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
-                if (mCalibration.havePressureScale) {
-                    mLocked.pressureScale = mCalibration.pressureScale;
-                } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
-                    mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
-                }
-            }
-
-            mLocked.orientedRanges.havePressure = true;
-            mLocked.orientedRanges.pressure.min = 0;
-            mLocked.orientedRanges.pressure.max = 1.0;
-            mLocked.orientedRanges.pressure.flat = 0;
-            mLocked.orientedRanges.pressure.fuzz = 0;
-        }
-
-        // Size factors.
-        mLocked.sizeScale = 0;
-        if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
-            if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
-                if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
-                    mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
-                }
-            }
-
-            mLocked.orientedRanges.haveSize = true;
-            mLocked.orientedRanges.size.min = 0;
-            mLocked.orientedRanges.size.max = 1.0;
-            mLocked.orientedRanges.size.flat = 0;
-            mLocked.orientedRanges.size.fuzz = 0;
-        }
-
-        // Orientation
-        mLocked.orientationScale = 0;
-        if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
-            if (mCalibration.orientationCalibration
-                    == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
-                if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
-                    mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
-                }
-            }
-
-            mLocked.orientedRanges.orientation.min = - M_PI_2;
-            mLocked.orientedRanges.orientation.max = M_PI_2;
-            mLocked.orientedRanges.orientation.flat = 0;
-            mLocked.orientedRanges.orientation.fuzz = 0;
-        }
-    }
-
-    if (orientationChanged || sizeChanged) {
-        // Compute oriented surface dimensions, precision, and scales.
-        float orientedXScale, orientedYScale;
-        switch (mLocked.surfaceOrientation) {
-        case InputReaderPolicyInterface::ROTATION_90:
-        case InputReaderPolicyInterface::ROTATION_270:
-            mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
-            mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
-            mLocked.orientedXPrecision = mLocked.yPrecision;
-            mLocked.orientedYPrecision = mLocked.xPrecision;
-            orientedXScale = mLocked.yScale;
-            orientedYScale = mLocked.xScale;
-            break;
-        default:
-            mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
-            mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
-            mLocked.orientedXPrecision = mLocked.xPrecision;
-            mLocked.orientedYPrecision = mLocked.yPrecision;
-            orientedXScale = mLocked.xScale;
-            orientedYScale = mLocked.yScale;
-            break;
-        }
-
-        // Configure position ranges.
-        mLocked.orientedRanges.x.min = 0;
-        mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
-        mLocked.orientedRanges.x.flat = 0;
-        mLocked.orientedRanges.x.fuzz = orientedXScale;
-
-        mLocked.orientedRanges.y.min = 0;
-        mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
-        mLocked.orientedRanges.y.flat = 0;
-        mLocked.orientedRanges.y.fuzz = orientedYScale;
-    }
-
-    return true;
-}
-
-void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
-    dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
-    dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
-    dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
-}
-
-void TouchInputMapper::configureVirtualKeysLocked() {
-    assert(mRawAxes.x.valid && mRawAxes.y.valid);
-
-    Vector<VirtualKeyDefinition> virtualKeyDefinitions;
-    getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
-
-    mLocked.virtualKeys.clear();
-
-    if (virtualKeyDefinitions.size() == 0) {
-        return;
-    }
-
-    mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
-
-    int32_t touchScreenLeft = mRawAxes.x.minValue;
-    int32_t touchScreenTop = mRawAxes.y.minValue;
-    int32_t touchScreenWidth = mRawAxes.x.getRange();
-    int32_t touchScreenHeight = mRawAxes.y.getRange();
-
-    for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
-        const VirtualKeyDefinition& virtualKeyDefinition =
-                virtualKeyDefinitions[i];
-
-        mLocked.virtualKeys.add();
-        VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
-
-        virtualKey.scanCode = virtualKeyDefinition.scanCode;
-        int32_t keyCode;
-        uint32_t flags;
-        if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
-                & keyCode, & flags)) {
-            LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
-                    virtualKey.scanCode);
-            mLocked.virtualKeys.pop(); // drop the key
-            continue;
-        }
-
-        virtualKey.keyCode = keyCode;
-        virtualKey.flags = flags;
-
-        // convert the key definition's display coordinates into touch coordinates for a hit box
-        int32_t halfWidth = virtualKeyDefinition.width / 2;
-        int32_t halfHeight = virtualKeyDefinition.height / 2;
-
-        virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
-                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
-        virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
-                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
-        virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
-                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
-        virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
-                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
-
-    }
-}
-
-void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
-    if (!mLocked.virtualKeys.isEmpty()) {
-        dump.append(INDENT3 "Virtual Keys:\n");
-
-        for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
-            const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
-            dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
-                    "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
-                    i, virtualKey.scanCode, virtualKey.keyCode,
-                    virtualKey.hitLeft, virtualKey.hitRight,
-                    virtualKey.hitTop, virtualKey.hitBottom);
-        }
-    }
-}
-
-void TouchInputMapper::parseCalibration() {
-    const PropertyMap& in = getDevice()->getConfiguration();
-    Calibration& out = mCalibration;
-
-    // Position
-    out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin);
-    out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin);
-    out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale);
-    out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale);
-
-    // Touch Size
-    out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
-    String8 touchSizeCalibrationString;
-    if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
-        if (touchSizeCalibrationString == "none") {
-            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
-        } else if (touchSizeCalibrationString == "geometric") {
-            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
-        } else if (touchSizeCalibrationString == "pressure") {
-            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
-        } else if (touchSizeCalibrationString != "default") {
-            LOGW("Invalid value for touch.touchSize.calibration: '%s'",
-                    touchSizeCalibrationString.string());
-        }
-    }
-
-    // Tool Size
-    out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
-    String8 toolSizeCalibrationString;
-    if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
-        if (toolSizeCalibrationString == "none") {
-            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
-        } else if (toolSizeCalibrationString == "geometric") {
-            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
-        } else if (toolSizeCalibrationString == "linear") {
-            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
-        } else if (toolSizeCalibrationString == "area") {
-            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
-        } else if (toolSizeCalibrationString != "default") {
-            LOGW("Invalid value for touch.toolSize.calibration: '%s'",
-                    toolSizeCalibrationString.string());
-        }
-    }
-
-    out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
-            out.toolSizeLinearScale);
-    out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
-            out.toolSizeLinearBias);
-    out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
-            out.toolSizeAreaScale);
-    out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
-            out.toolSizeAreaBias);
-    out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
-            out.toolSizeIsSummed);
-
-    // Pressure
-    out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
-    String8 pressureCalibrationString;
-    if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
-        if (pressureCalibrationString == "none") {
-            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
-        } else if (pressureCalibrationString == "physical") {
-            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
-        } else if (pressureCalibrationString == "amplitude") {
-            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
-        } else if (pressureCalibrationString != "default") {
-            LOGW("Invalid value for touch.pressure.calibration: '%s'",
-                    pressureCalibrationString.string());
-        }
-    }
-
-    out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
-    String8 pressureSourceString;
-    if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
-        if (pressureSourceString == "pressure") {
-            out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
-        } else if (pressureSourceString == "touch") {
-            out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
-        } else if (pressureSourceString != "default") {
-            LOGW("Invalid value for touch.pressure.source: '%s'",
-                    pressureSourceString.string());
-        }
-    }
-
-    out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
-            out.pressureScale);
-
-    // Size
-    out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
-    String8 sizeCalibrationString;
-    if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
-        if (sizeCalibrationString == "none") {
-            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
-        } else if (sizeCalibrationString == "normalized") {
-            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
-        } else if (sizeCalibrationString != "default") {
-            LOGW("Invalid value for touch.size.calibration: '%s'",
-                    sizeCalibrationString.string());
-        }
-    }
-
-    // Orientation
-    out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
-    String8 orientationCalibrationString;
-    if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
-        if (orientationCalibrationString == "none") {
-            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
-        } else if (orientationCalibrationString == "interpolated") {
-            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
-        } else if (orientationCalibrationString != "default") {
-            LOGW("Invalid value for touch.orientation.calibration: '%s'",
-                    orientationCalibrationString.string());
-        }
-    }
-}
-
-void TouchInputMapper::resolveCalibration() {
-    // Pressure
-    switch (mCalibration.pressureSource) {
-    case Calibration::PRESSURE_SOURCE_DEFAULT:
-        if (mRawAxes.pressure.valid) {
-            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
-        } else if (mRawAxes.touchMajor.valid) {
-            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
-        }
-        break;
-
-    case Calibration::PRESSURE_SOURCE_PRESSURE:
-        if (! mRawAxes.pressure.valid) {
-            LOGW("Calibration property touch.pressure.source is 'pressure' but "
-                    "the pressure axis is not available.");
-        }
-        break;
-
-    case Calibration::PRESSURE_SOURCE_TOUCH:
-        if (! mRawAxes.touchMajor.valid) {
-            LOGW("Calibration property touch.pressure.source is 'touch' but "
-                    "the touchMajor axis is not available.");
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    switch (mCalibration.pressureCalibration) {
-    case Calibration::PRESSURE_CALIBRATION_DEFAULT:
-        if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
-            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
-        } else {
-            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    // Tool Size
-    switch (mCalibration.toolSizeCalibration) {
-    case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
-        if (mRawAxes.toolMajor.valid) {
-            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
-        } else {
-            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    // Touch Size
-    switch (mCalibration.touchSizeCalibration) {
-    case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
-        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
-                && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
-            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
-        } else {
-            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    // Size
-    switch (mCalibration.sizeCalibration) {
-    case Calibration::SIZE_CALIBRATION_DEFAULT:
-        if (mRawAxes.toolMajor.valid) {
-            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
-        } else {
-            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    // Orientation
-    switch (mCalibration.orientationCalibration) {
-    case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
-        if (mRawAxes.orientation.valid) {
-            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
-        } else {
-            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
-        }
-        break;
-
-    default:
-        break;
-    }
-}
-
-void TouchInputMapper::dumpCalibration(String8& dump) {
-    dump.append(INDENT3 "Calibration:\n");
-
-    // Position
-    if (mCalibration.haveXOrigin) {
-        dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin);
-    }
-    if (mCalibration.haveYOrigin) {
-        dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin);
-    }
-    if (mCalibration.haveXScale) {
-        dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale);
-    }
-    if (mCalibration.haveYScale) {
-        dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale);
-    }
-
-    // Touch Size
-    switch (mCalibration.touchSizeCalibration) {
-    case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
-        dump.append(INDENT4 "touch.touchSize.calibration: none\n");
-        break;
-    case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
-        dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
-        break;
-    case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
-        dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
-        break;
-    default:
-        assert(false);
-    }
-
-    // Tool Size
-    switch (mCalibration.toolSizeCalibration) {
-    case Calibration::TOOL_SIZE_CALIBRATION_NONE:
-        dump.append(INDENT4 "touch.toolSize.calibration: none\n");
-        break;
-    case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
-        dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
-        break;
-    case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
-        dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
-        break;
-    case Calibration::TOOL_SIZE_CALIBRATION_AREA:
-        dump.append(INDENT4 "touch.toolSize.calibration: area\n");
-        break;
-    default:
-        assert(false);
-    }
-
-    if (mCalibration.haveToolSizeLinearScale) {
-        dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
-                mCalibration.toolSizeLinearScale);
-    }
-
-    if (mCalibration.haveToolSizeLinearBias) {
-        dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
-                mCalibration.toolSizeLinearBias);
-    }
-
-    if (mCalibration.haveToolSizeAreaScale) {
-        dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
-                mCalibration.toolSizeAreaScale);
-    }
-
-    if (mCalibration.haveToolSizeAreaBias) {
-        dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
-                mCalibration.toolSizeAreaBias);
-    }
-
-    if (mCalibration.haveToolSizeIsSummed) {
-        dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
-                toString(mCalibration.toolSizeIsSummed));
-    }
-
-    // Pressure
-    switch (mCalibration.pressureCalibration) {
-    case Calibration::PRESSURE_CALIBRATION_NONE:
-        dump.append(INDENT4 "touch.pressure.calibration: none\n");
-        break;
-    case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
-        dump.append(INDENT4 "touch.pressure.calibration: physical\n");
-        break;
-    case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
-        dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
-        break;
-    default:
-        assert(false);
-    }
-
-    switch (mCalibration.pressureSource) {
-    case Calibration::PRESSURE_SOURCE_PRESSURE:
-        dump.append(INDENT4 "touch.pressure.source: pressure\n");
-        break;
-    case Calibration::PRESSURE_SOURCE_TOUCH:
-        dump.append(INDENT4 "touch.pressure.source: touch\n");
-        break;
-    case Calibration::PRESSURE_SOURCE_DEFAULT:
-        break;
-    default:
-        assert(false);
-    }
-
-    if (mCalibration.havePressureScale) {
-        dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
-                mCalibration.pressureScale);
-    }
-
-    // Size
-    switch (mCalibration.sizeCalibration) {
-    case Calibration::SIZE_CALIBRATION_NONE:
-        dump.append(INDENT4 "touch.size.calibration: none\n");
-        break;
-    case Calibration::SIZE_CALIBRATION_NORMALIZED:
-        dump.append(INDENT4 "touch.size.calibration: normalized\n");
-        break;
-    default:
-        assert(false);
-    }
-
-    // Orientation
-    switch (mCalibration.orientationCalibration) {
-    case Calibration::ORIENTATION_CALIBRATION_NONE:
-        dump.append(INDENT4 "touch.orientation.calibration: none\n");
-        break;
-    case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
-        dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
-        break;
-    default:
-        assert(false);
-    }
-}
-
-void TouchInputMapper::reset() {
-    // Synthesize touch up event if touch is currently down.
-    // This will also take care of finishing virtual key processing if needed.
-    if (mLastTouch.pointerCount != 0) {
-        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
-        mCurrentTouch.clear();
-        syncTouch(when, true);
-    }
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-        initializeLocked();
-    } // release lock
-
-    InputMapper::reset();
-}
-
-void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
-    uint32_t policyFlags = 0;
-
-    // Preprocess pointer data.
-
-    if (mParameters.useBadTouchFilter) {
-        if (applyBadTouchFilter()) {
-            havePointerIds = false;
-        }
-    }
-
-    if (mParameters.useJumpyTouchFilter) {
-        if (applyJumpyTouchFilter()) {
-            havePointerIds = false;
-        }
-    }
-
-    if (! havePointerIds) {
-        calculatePointerIds();
-    }
-
-    TouchData temp;
-    TouchData* savedTouch;
-    if (mParameters.useAveragingTouchFilter) {
-        temp.copyFrom(mCurrentTouch);
-        savedTouch = & temp;
-
-        applyAveragingTouchFilter();
-    } else {
-        savedTouch = & mCurrentTouch;
-    }
-
-    // Process touches and virtual keys.
-
-    TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
-    if (touchResult == DISPATCH_TOUCH) {
-        dispatchTouches(when, policyFlags);
-    }
-
-    // Copy current touch to last touch in preparation for the next cycle.
-
-    if (touchResult == DROP_STROKE) {
-        mLastTouch.clear();
-    } else {
-        mLastTouch.copyFrom(*savedTouch);
-    }
-}
-
-TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
-        nsecs_t when, uint32_t policyFlags) {
-    int32_t keyEventAction, keyEventFlags;
-    int32_t keyCode, scanCode, downTime;
-    TouchResult touchResult;
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        // Update surface size and orientation, including virtual key positions.
-        if (! configureSurfaceLocked()) {
-            return DROP_STROKE;
-        }
-
-        // Check for virtual key press.
-        if (mLocked.currentVirtualKey.down) {
-            if (mCurrentTouch.pointerCount == 0) {
-                // Pointer went up while virtual key was down.
-                mLocked.currentVirtualKey.down = false;
-#if DEBUG_VIRTUAL_KEYS
-                LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
-                        mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
-#endif
-                keyEventAction = AKEY_EVENT_ACTION_UP;
-                keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
-                touchResult = SKIP_TOUCH;
-                goto DispatchVirtualKey;
-            }
-
-            if (mCurrentTouch.pointerCount == 1) {
-                int32_t x = mCurrentTouch.pointers[0].x;
-                int32_t y = mCurrentTouch.pointers[0].y;
-                const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
-                if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
-                    // Pointer is still within the space of the virtual key.
-                    return SKIP_TOUCH;
-                }
-            }
-
-            // Pointer left virtual key area or another pointer also went down.
-            // Send key cancellation and drop the stroke so subsequent motions will be
-            // considered fresh downs.  This is useful when the user swipes away from the
-            // virtual key area into the main display surface.
-            mLocked.currentVirtualKey.down = false;
-#if DEBUG_VIRTUAL_KEYS
-            LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
-                    mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
-#endif
-            keyEventAction = AKEY_EVENT_ACTION_UP;
-            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
-                    | AKEY_EVENT_FLAG_CANCELED;
-
-            // Check whether the pointer moved inside the display area where we should
-            // start a new stroke.
-            int32_t x = mCurrentTouch.pointers[0].x;
-            int32_t y = mCurrentTouch.pointers[0].y;
-            if (isPointInsideSurfaceLocked(x, y)) {
-                mLastTouch.clear();
-                touchResult = DISPATCH_TOUCH;
-            } else {
-                touchResult = DROP_STROKE;
-            }
-        } else {
-            if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
-                // Pointer just went down.  Handle off-screen touches, if needed.
-                int32_t x = mCurrentTouch.pointers[0].x;
-                int32_t y = mCurrentTouch.pointers[0].y;
-                if (! isPointInsideSurfaceLocked(x, y)) {
-                    // If exactly one pointer went down, check for virtual key hit.
-                    // Otherwise we will drop the entire stroke.
-                    if (mCurrentTouch.pointerCount == 1) {
-                        const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
-                        if (virtualKey) {
-                            mLocked.currentVirtualKey.down = true;
-                            mLocked.currentVirtualKey.downTime = when;
-                            mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
-                            mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
-#if DEBUG_VIRTUAL_KEYS
-                            LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
-                                    mLocked.currentVirtualKey.keyCode,
-                                    mLocked.currentVirtualKey.scanCode);
-#endif
-                            keyEventAction = AKEY_EVENT_ACTION_DOWN;
-                            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
-                                    | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
-                            touchResult = SKIP_TOUCH;
-                            goto DispatchVirtualKey;
-                        }
-                    }
-                    return DROP_STROKE;
-                }
-            }
-            return DISPATCH_TOUCH;
-        }
-
-    DispatchVirtualKey:
-        // Collect remaining state needed to dispatch virtual key.
-        keyCode = mLocked.currentVirtualKey.keyCode;
-        scanCode = mLocked.currentVirtualKey.scanCode;
-        downTime = mLocked.currentVirtualKey.downTime;
-    } // release lock
-
-    // Dispatch virtual key.
-    int32_t metaState = mContext->getGlobalMetaState();
-    policyFlags |= POLICY_FLAG_VIRTUAL;
-    getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
-            keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
-    return touchResult;
-}
-
-void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
-    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
-    uint32_t lastPointerCount = mLastTouch.pointerCount;
-    if (currentPointerCount == 0 && lastPointerCount == 0) {
-        return; // nothing to do!
-    }
-
-    BitSet32 currentIdBits = mCurrentTouch.idBits;
-    BitSet32 lastIdBits = mLastTouch.idBits;
-
-    if (currentIdBits == lastIdBits) {
-        // No pointer id changes so this is a move event.
-        // The dispatcher takes care of batching moves so we don't have to deal with that here.
-        int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
-        dispatchTouch(when, policyFlags, & mCurrentTouch,
-                currentIdBits, -1, currentPointerCount, motionEventAction);
-    } else {
-        // There may be pointers going up and pointers going down and pointers moving
-        // all at the same time.
-        BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
-        BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
-        BitSet32 activeIdBits(lastIdBits.value);
-        uint32_t pointerCount = lastPointerCount;
-
-        // Produce an intermediate representation of the touch data that consists of the
-        // old location of pointers that have just gone up and the new location of pointers that
-        // have just moved but omits the location of pointers that have just gone down.
-        TouchData interimTouch;
-        interimTouch.copyFrom(mLastTouch);
-
-        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
-        bool moveNeeded = false;
-        while (!moveIdBits.isEmpty()) {
-            uint32_t moveId = moveIdBits.firstMarkedBit();
-            moveIdBits.clearBit(moveId);
-
-            int32_t oldIndex = mLastTouch.idToIndex[moveId];
-            int32_t newIndex = mCurrentTouch.idToIndex[moveId];
-            if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
-                interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
-                moveNeeded = true;
-            }
-        }
-
-        // Dispatch pointer up events using the interim pointer locations.
-        while (!upIdBits.isEmpty()) {
-            uint32_t upId = upIdBits.firstMarkedBit();
-            upIdBits.clearBit(upId);
-            BitSet32 oldActiveIdBits = activeIdBits;
-            activeIdBits.clearBit(upId);
-
-            int32_t motionEventAction;
-            if (activeIdBits.isEmpty()) {
-                motionEventAction = AMOTION_EVENT_ACTION_UP;
-            } else {
-                motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
-            }
-
-            dispatchTouch(when, policyFlags, &interimTouch,
-                    oldActiveIdBits, upId, pointerCount, motionEventAction);
-            pointerCount -= 1;
-        }
-
-        // Dispatch move events if any of the remaining pointers moved from their old locations.
-        // Although applications receive new locations as part of individual pointer up
-        // events, they do not generally handle them except when presented in a move event.
-        if (moveNeeded) {
-            dispatchTouch(when, policyFlags, &mCurrentTouch,
-                    activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
-        }
-
-        // Dispatch pointer down events using the new pointer locations.
-        while (!downIdBits.isEmpty()) {
-            uint32_t downId = downIdBits.firstMarkedBit();
-            downIdBits.clearBit(downId);
-            BitSet32 oldActiveIdBits = activeIdBits;
-            activeIdBits.markBit(downId);
-
-            int32_t motionEventAction;
-            if (oldActiveIdBits.isEmpty()) {
-                motionEventAction = AMOTION_EVENT_ACTION_DOWN;
-                mDownTime = when;
-            } else {
-                motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
-            }
-
-            pointerCount += 1;
-            dispatchTouch(when, policyFlags, &mCurrentTouch,
-                    activeIdBits, downId, pointerCount, motionEventAction);
-        }
-    }
-}
-
-void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
-        TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
-        int32_t motionEventAction) {
-    int32_t pointerIds[MAX_POINTERS];
-    PointerCoords pointerCoords[MAX_POINTERS];
-    int32_t motionEventEdgeFlags = 0;
-    float xPrecision, yPrecision;
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        // Walk through the the active pointers and map touch screen coordinates (TouchData) into
-        // display coordinates (PointerCoords) and adjust for display orientation.
-        for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
-            uint32_t id = idBits.firstMarkedBit();
-            idBits.clearBit(id);
-            uint32_t inIndex = touch->idToIndex[id];
-
-            const PointerData& in = touch->pointers[inIndex];
-
-            // X and Y
-            float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
-            float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
-
-            // ToolMajor and ToolMinor
-            float toolMajor, toolMinor;
-            switch (mCalibration.toolSizeCalibration) {
-            case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
-                toolMajor = in.toolMajor * mLocked.geometricScale;
-                if (mRawAxes.toolMinor.valid) {
-                    toolMinor = in.toolMinor * mLocked.geometricScale;
-                } else {
-                    toolMinor = toolMajor;
-                }
-                break;
-            case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
-                toolMajor = in.toolMajor != 0
-                        ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
-                        : 0;
-                if (mRawAxes.toolMinor.valid) {
-                    toolMinor = in.toolMinor != 0
-                            ? in.toolMinor * mLocked.toolSizeLinearScale
-                                    + mLocked.toolSizeLinearBias
-                            : 0;
-                } else {
-                    toolMinor = toolMajor;
-                }
-                break;
-            case Calibration::TOOL_SIZE_CALIBRATION_AREA:
-                if (in.toolMajor != 0) {
-                    float diameter = sqrtf(in.toolMajor
-                            * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
-                    toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
-                } else {
-                    toolMajor = 0;
-                }
-                toolMinor = toolMajor;
-                break;
-            default:
-                toolMajor = 0;
-                toolMinor = 0;
-                break;
-            }
-
-            if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
-                toolMajor /= pointerCount;
-                toolMinor /= pointerCount;
-            }
-
-            // Pressure
-            float rawPressure;
-            switch (mCalibration.pressureSource) {
-            case Calibration::PRESSURE_SOURCE_PRESSURE:
-                rawPressure = in.pressure;
-                break;
-            case Calibration::PRESSURE_SOURCE_TOUCH:
-                rawPressure = in.touchMajor;
-                break;
-            default:
-                rawPressure = 0;
-            }
-
-            float pressure;
-            switch (mCalibration.pressureCalibration) {
-            case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
-            case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
-                pressure = rawPressure * mLocked.pressureScale;
-                break;
-            default:
-                pressure = 1;
-                break;
-            }
-
-            // TouchMajor and TouchMinor
-            float touchMajor, touchMinor;
-            switch (mCalibration.touchSizeCalibration) {
-            case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
-                touchMajor = in.touchMajor * mLocked.geometricScale;
-                if (mRawAxes.touchMinor.valid) {
-                    touchMinor = in.touchMinor * mLocked.geometricScale;
-                } else {
-                    touchMinor = touchMajor;
-                }
-                break;
-            case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
-                touchMajor = toolMajor * pressure;
-                touchMinor = toolMinor * pressure;
-                break;
-            default:
-                touchMajor = 0;
-                touchMinor = 0;
-                break;
-            }
-
-            if (touchMajor > toolMajor) {
-                touchMajor = toolMajor;
-            }
-            if (touchMinor > toolMinor) {
-                touchMinor = toolMinor;
-            }
-
-            // Size
-            float size;
-            switch (mCalibration.sizeCalibration) {
-            case Calibration::SIZE_CALIBRATION_NORMALIZED: {
-                float rawSize = mRawAxes.toolMinor.valid
-                        ? avg(in.toolMajor, in.toolMinor)
-                        : in.toolMajor;
-                size = rawSize * mLocked.sizeScale;
-                break;
-            }
-            default:
-                size = 0;
-                break;
-            }
-
-            // Orientation
-            float orientation;
-            switch (mCalibration.orientationCalibration) {
-            case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
-                orientation = in.orientation * mLocked.orientationScale;
-                break;
-            default:
-                orientation = 0;
-            }
-
-            // Adjust coords for orientation.
-            switch (mLocked.surfaceOrientation) {
-            case InputReaderPolicyInterface::ROTATION_90: {
-                float xTemp = x;
-                x = y;
-                y = mLocked.surfaceWidth - xTemp;
-                orientation -= M_PI_2;
-                if (orientation < - M_PI_2) {
-                    orientation += M_PI;
-                }
-                break;
-            }
-            case InputReaderPolicyInterface::ROTATION_180: {
-                x = mLocked.surfaceWidth - x;
-                y = mLocked.surfaceHeight - y;
-                orientation = - orientation;
-                break;
-            }
-            case InputReaderPolicyInterface::ROTATION_270: {
-                float xTemp = x;
-                x = mLocked.surfaceHeight - y;
-                y = xTemp;
-                orientation += M_PI_2;
-                if (orientation > M_PI_2) {
-                    orientation -= M_PI;
-                }
-                break;
-            }
-            }
-
-            // Write output coords.
-            PointerCoords& out = pointerCoords[outIndex];
-            out.x = x;
-            out.y = y;
-            out.pressure = pressure;
-            out.size = size;
-            out.touchMajor = touchMajor;
-            out.touchMinor = touchMinor;
-            out.toolMajor = toolMajor;
-            out.toolMinor = toolMinor;
-            out.orientation = orientation;
-
-            pointerIds[outIndex] = int32_t(id);
-
-            if (id == changedId) {
-                motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-            }
-        }
-
-        // Check edge flags by looking only at the first pointer since the flags are
-        // global to the event.
-        if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
-            if (pointerCoords[0].x <= 0) {
-                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
-            } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
-                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
-            }
-            if (pointerCoords[0].y <= 0) {
-                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
-            } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
-                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
-            }
-        }
-
-        xPrecision = mLocked.orientedXPrecision;
-        yPrecision = mLocked.orientedYPrecision;
-    } // release lock
-
-    getDispatcher()->notifyMotion(when, getDeviceId(), getSources(), policyFlags,
-            motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
-            pointerCount, pointerIds, pointerCoords,
-            xPrecision, yPrecision, mDownTime);
-}
-
-bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
-    if (mRawAxes.x.valid && mRawAxes.y.valid) {
-        return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
-                && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
-    }
-    return true;
-}
-
-const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
-        int32_t x, int32_t y) {
-    size_t numVirtualKeys = mLocked.virtualKeys.size();
-    for (size_t i = 0; i < numVirtualKeys; i++) {
-        const VirtualKey& virtualKey = mLocked.virtualKeys[i];
-
-#if DEBUG_VIRTUAL_KEYS
-        LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
-                "left=%d, top=%d, right=%d, bottom=%d",
-                x, y,
-                virtualKey.keyCode, virtualKey.scanCode,
-                virtualKey.hitLeft, virtualKey.hitTop,
-                virtualKey.hitRight, virtualKey.hitBottom);
-#endif
-
-        if (virtualKey.isHit(x, y)) {
-            return & virtualKey;
-        }
-    }
-
-    return NULL;
-}
-
-void TouchInputMapper::calculatePointerIds() {
-    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
-    uint32_t lastPointerCount = mLastTouch.pointerCount;
-
-    if (currentPointerCount == 0) {
-        // No pointers to assign.
-        mCurrentTouch.idBits.clear();
-    } else if (lastPointerCount == 0) {
-        // All pointers are new.
-        mCurrentTouch.idBits.clear();
-        for (uint32_t i = 0; i < currentPointerCount; i++) {
-            mCurrentTouch.pointers[i].id = i;
-            mCurrentTouch.idToIndex[i] = i;
-            mCurrentTouch.idBits.markBit(i);
-        }
-    } else if (currentPointerCount == 1 && lastPointerCount == 1) {
-        // Only one pointer and no change in count so it must have the same id as before.
-        uint32_t id = mLastTouch.pointers[0].id;
-        mCurrentTouch.pointers[0].id = id;
-        mCurrentTouch.idToIndex[id] = 0;
-        mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
-    } else {
-        // General case.
-        // We build a heap of squared euclidean distances between current and last pointers
-        // associated with the current and last pointer indices.  Then, we find the best
-        // match (by distance) for each current pointer.
-        PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
-
-        uint32_t heapSize = 0;
-        for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
-                currentPointerIndex++) {
-            for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
-                    lastPointerIndex++) {
-                int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
-                        - mLastTouch.pointers[lastPointerIndex].x;
-                int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
-                        - mLastTouch.pointers[lastPointerIndex].y;
-
-                uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
-
-                // Insert new element into the heap (sift up).
-                heap[heapSize].currentPointerIndex = currentPointerIndex;
-                heap[heapSize].lastPointerIndex = lastPointerIndex;
-                heap[heapSize].distance = distance;
-                heapSize += 1;
-            }
-        }
-
-        // Heapify
-        for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
-            startIndex -= 1;
-            for (uint32_t parentIndex = startIndex; ;) {
-                uint32_t childIndex = parentIndex * 2 + 1;
-                if (childIndex >= heapSize) {
-                    break;
-                }
-
-                if (childIndex + 1 < heapSize
-                        && heap[childIndex + 1].distance < heap[childIndex].distance) {
-                    childIndex += 1;
-                }
-
-                if (heap[parentIndex].distance <= heap[childIndex].distance) {
-                    break;
-                }
-
-                swap(heap[parentIndex], heap[childIndex]);
-                parentIndex = childIndex;
-            }
-        }
-
-#if DEBUG_POINTER_ASSIGNMENT
-        LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
-        for (size_t i = 0; i < heapSize; i++) {
-            LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
-                    i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
-                    heap[i].distance);
-        }
-#endif
-
-        // Pull matches out by increasing order of distance.
-        // To avoid reassigning pointers that have already been matched, the loop keeps track
-        // of which last and current pointers have been matched using the matchedXXXBits variables.
-        // It also tracks the used pointer id bits.
-        BitSet32 matchedLastBits(0);
-        BitSet32 matchedCurrentBits(0);
-        BitSet32 usedIdBits(0);
-        bool first = true;
-        for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
-            for (;;) {
-                if (first) {
-                    // The first time through the loop, we just consume the root element of
-                    // the heap (the one with smallest distance).
-                    first = false;
-                } else {
-                    // Previous iterations consumed the root element of the heap.
-                    // Pop root element off of the heap (sift down).
-                    heapSize -= 1;
-                    assert(heapSize > 0);
-
-                    // Sift down.
-                    heap[0] = heap[heapSize];
-                    for (uint32_t parentIndex = 0; ;) {
-                        uint32_t childIndex = parentIndex * 2 + 1;
-                        if (childIndex >= heapSize) {
-                            break;
-                        }
-
-                        if (childIndex + 1 < heapSize
-                                && heap[childIndex + 1].distance < heap[childIndex].distance) {
-                            childIndex += 1;
-                        }
-
-                        if (heap[parentIndex].distance <= heap[childIndex].distance) {
-                            break;
-                        }
-
-                        swap(heap[parentIndex], heap[childIndex]);
-                        parentIndex = childIndex;
-                    }
-
-#if DEBUG_POINTER_ASSIGNMENT
-                    LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
-                    for (size_t i = 0; i < heapSize; i++) {
-                        LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
-                                i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
-                                heap[i].distance);
-                    }
-#endif
-                }
-
-                uint32_t currentPointerIndex = heap[0].currentPointerIndex;
-                if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
-
-                uint32_t lastPointerIndex = heap[0].lastPointerIndex;
-                if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
-
-                matchedCurrentBits.markBit(currentPointerIndex);
-                matchedLastBits.markBit(lastPointerIndex);
-
-                uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
-                mCurrentTouch.pointers[currentPointerIndex].id = id;
-                mCurrentTouch.idToIndex[id] = currentPointerIndex;
-                usedIdBits.markBit(id);
-
-#if DEBUG_POINTER_ASSIGNMENT
-                LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
-                        lastPointerIndex, currentPointerIndex, id, heap[0].distance);
-#endif
-                break;
-            }
-        }
-
-        // Assign fresh ids to new pointers.
-        if (currentPointerCount > lastPointerCount) {
-            for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
-                uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
-                uint32_t id = usedIdBits.firstUnmarkedBit();
-
-                mCurrentTouch.pointers[currentPointerIndex].id = id;
-                mCurrentTouch.idToIndex[id] = currentPointerIndex;
-                usedIdBits.markBit(id);
-
-#if DEBUG_POINTER_ASSIGNMENT
-                LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
-                        currentPointerIndex, id);
-#endif
-
-                if (--i == 0) break; // done
-                matchedCurrentBits.markBit(currentPointerIndex);
-            }
-        }
-
-        // Fix id bits.
-        mCurrentTouch.idBits = usedIdBits;
-    }
-}
-
-/* Special hack for devices that have bad screen data: if one of the
- * points has moved more than a screen height from the last position,
- * then drop it. */
-bool TouchInputMapper::applyBadTouchFilter() {
-    // This hack requires valid axis parameters.
-    if (! mRawAxes.y.valid) {
-        return false;
-    }
-
-    uint32_t pointerCount = mCurrentTouch.pointerCount;
-
-    // Nothing to do if there are no points.
-    if (pointerCount == 0) {
-        return false;
-    }
-
-    // Don't do anything if a finger is going down or up.  We run
-    // here before assigning pointer IDs, so there isn't a good
-    // way to do per-finger matching.
-    if (pointerCount != mLastTouch.pointerCount) {
-        return false;
-    }
-
-    // We consider a single movement across more than a 7/16 of
-    // the long size of the screen to be bad.  This was a magic value
-    // determined by looking at the maximum distance it is feasible
-    // to actually move in one sample.
-    int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
-
-    // XXX The original code in InputDevice.java included commented out
-    //     code for testing the X axis.  Note that when we drop a point
-    //     we don't actually restore the old X either.  Strange.
-    //     The old code also tries to track when bad points were previously
-    //     detected but it turns out that due to the placement of a "break"
-    //     at the end of the loop, we never set mDroppedBadPoint to true
-    //     so it is effectively dead code.
-    // Need to figure out if the old code is busted or just overcomplicated
-    // but working as intended.
-
-    // Look through all new points and see if any are farther than
-    // acceptable from all previous points.
-    for (uint32_t i = pointerCount; i-- > 0; ) {
-        int32_t y = mCurrentTouch.pointers[i].y;
-        int32_t closestY = INT_MAX;
-        int32_t closestDeltaY = 0;
-
-#if DEBUG_HACKS
-        LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
-#endif
-
-        for (uint32_t j = pointerCount; j-- > 0; ) {
-            int32_t lastY = mLastTouch.pointers[j].y;
-            int32_t deltaY = abs(y - lastY);
-
-#if DEBUG_HACKS
-            LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
-                    j, lastY, deltaY);
-#endif
-
-            if (deltaY < maxDeltaY) {
-                goto SkipSufficientlyClosePoint;
-            }
-            if (deltaY < closestDeltaY) {
-                closestDeltaY = deltaY;
-                closestY = lastY;
-            }
-        }
-
-        // Must not have found a close enough match.
-#if DEBUG_HACKS
-        LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
-                i, y, closestY, closestDeltaY, maxDeltaY);
-#endif
-
-        mCurrentTouch.pointers[i].y = closestY;
-        return true; // XXX original code only corrects one point
-
-    SkipSufficientlyClosePoint: ;
-    }
-
-    // No change.
-    return false;
-}
-
-/* Special hack for devices that have bad screen data: drop points where
- * the coordinate value for one axis has jumped to the other pointer's location.
- */
-bool TouchInputMapper::applyJumpyTouchFilter() {
-    // This hack requires valid axis parameters.
-    if (! mRawAxes.y.valid) {
-        return false;
-    }
-
-    uint32_t pointerCount = mCurrentTouch.pointerCount;
-    if (mLastTouch.pointerCount != pointerCount) {
-#if DEBUG_HACKS
-        LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
-                mLastTouch.pointerCount, pointerCount);
-        for (uint32_t i = 0; i < pointerCount; i++) {
-            LOGD("  Pointer %d (%d, %d)", i,
-                    mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
-        }
-#endif
-
-        if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
-            if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
-                // Just drop the first few events going from 1 to 2 pointers.
-                // They're bad often enough that they're not worth considering.
-                mCurrentTouch.pointerCount = 1;
-                mJumpyTouchFilter.jumpyPointsDropped += 1;
-
-#if DEBUG_HACKS
-                LOGD("JumpyTouchFilter: Pointer 2 dropped");
-#endif
-                return true;
-            } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
-                // The event when we go from 2 -> 1 tends to be messed up too
-                mCurrentTouch.pointerCount = 2;
-                mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
-                mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
-                mJumpyTouchFilter.jumpyPointsDropped += 1;
-
-#if DEBUG_HACKS
-                for (int32_t i = 0; i < 2; i++) {
-                    LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
-                            mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
-                }
-#endif
-                return true;
-            }
-        }
-        // Reset jumpy points dropped on other transitions or if limit exceeded.
-        mJumpyTouchFilter.jumpyPointsDropped = 0;
-
-#if DEBUG_HACKS
-        LOGD("JumpyTouchFilter: Transition - drop limit reset");
-#endif
-        return false;
-    }
-
-    // We have the same number of pointers as last time.
-    // A 'jumpy' point is one where the coordinate value for one axis
-    // has jumped to the other pointer's location. No need to do anything
-    // else if we only have one pointer.
-    if (pointerCount < 2) {
-        return false;
-    }
-
-    if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
-        int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
-
-        // We only replace the single worst jumpy point as characterized by pointer distance
-        // in a single axis.
-        int32_t badPointerIndex = -1;
-        int32_t badPointerReplacementIndex = -1;
-        int32_t badPointerDistance = INT_MIN; // distance to be corrected
-
-        for (uint32_t i = pointerCount; i-- > 0; ) {
-            int32_t x = mCurrentTouch.pointers[i].x;
-            int32_t y = mCurrentTouch.pointers[i].y;
-
-#if DEBUG_HACKS
-            LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
-#endif
-
-            // Check if a touch point is too close to another's coordinates
-            bool dropX = false, dropY = false;
-            for (uint32_t j = 0; j < pointerCount; j++) {
-                if (i == j) {
-                    continue;
-                }
-
-                if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
-                    dropX = true;
-                    break;
-                }
-
-                if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
-                    dropY = true;
-                    break;
-                }
-            }
-            if (! dropX && ! dropY) {
-                continue; // not jumpy
-            }
-
-            // Find a replacement candidate by comparing with older points on the
-            // complementary (non-jumpy) axis.
-            int32_t distance = INT_MIN; // distance to be corrected
-            int32_t replacementIndex = -1;
-
-            if (dropX) {
-                // X looks too close.  Find an older replacement point with a close Y.
-                int32_t smallestDeltaY = INT_MAX;
-                for (uint32_t j = 0; j < pointerCount; j++) {
-                    int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
-                    if (deltaY < smallestDeltaY) {
-                        smallestDeltaY = deltaY;
-                        replacementIndex = j;
-                    }
-                }
-                distance = abs(x - mLastTouch.pointers[replacementIndex].x);
-            } else {
-                // Y looks too close.  Find an older replacement point with a close X.
-                int32_t smallestDeltaX = INT_MAX;
-                for (uint32_t j = 0; j < pointerCount; j++) {
-                    int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
-                    if (deltaX < smallestDeltaX) {
-                        smallestDeltaX = deltaX;
-                        replacementIndex = j;
-                    }
-                }
-                distance = abs(y - mLastTouch.pointers[replacementIndex].y);
-            }
-
-            // If replacing this pointer would correct a worse error than the previous ones
-            // considered, then use this replacement instead.
-            if (distance > badPointerDistance) {
-                badPointerIndex = i;
-                badPointerReplacementIndex = replacementIndex;
-                badPointerDistance = distance;
-            }
-        }
-
-        // Correct the jumpy pointer if one was found.
-        if (badPointerIndex >= 0) {
-#if DEBUG_HACKS
-            LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
-                    badPointerIndex,
-                    mLastTouch.pointers[badPointerReplacementIndex].x,
-                    mLastTouch.pointers[badPointerReplacementIndex].y);
-#endif
-
-            mCurrentTouch.pointers[badPointerIndex].x =
-                    mLastTouch.pointers[badPointerReplacementIndex].x;
-            mCurrentTouch.pointers[badPointerIndex].y =
-                    mLastTouch.pointers[badPointerReplacementIndex].y;
-            mJumpyTouchFilter.jumpyPointsDropped += 1;
-            return true;
-        }
-    }
-
-    mJumpyTouchFilter.jumpyPointsDropped = 0;
-    return false;
-}
-
-/* Special hack for devices that have bad screen data: aggregate and
- * compute averages of the coordinate data, to reduce the amount of
- * jitter seen by applications. */
-void TouchInputMapper::applyAveragingTouchFilter() {
-    for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
-        uint32_t id = mCurrentTouch.pointers[currentIndex].id;
-        int32_t x = mCurrentTouch.pointers[currentIndex].x;
-        int32_t y = mCurrentTouch.pointers[currentIndex].y;
-        int32_t pressure;
-        switch (mCalibration.pressureSource) {
-        case Calibration::PRESSURE_SOURCE_PRESSURE:
-            pressure = mCurrentTouch.pointers[currentIndex].pressure;
-            break;
-        case Calibration::PRESSURE_SOURCE_TOUCH:
-            pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
-            break;
-        default:
-            pressure = 1;
-            break;
-        }
-
-        if (mLastTouch.idBits.hasBit(id)) {
-            // Pointer was down before and is still down now.
-            // Compute average over history trace.
-            uint32_t start = mAveragingTouchFilter.historyStart[id];
-            uint32_t end = mAveragingTouchFilter.historyEnd[id];
-
-            int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
-            int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
-            uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
-
-#if DEBUG_HACKS
-            LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
-                    id, distance);
-#endif
-
-            if (distance < AVERAGING_DISTANCE_LIMIT) {
-                // Increment end index in preparation for recording new historical data.
-                end += 1;
-                if (end > AVERAGING_HISTORY_SIZE) {
-                    end = 0;
-                }
-
-                // If the end index has looped back to the start index then we have filled
-                // the historical trace up to the desired size so we drop the historical
-                // data at the start of the trace.
-                if (end == start) {
-                    start += 1;
-                    if (start > AVERAGING_HISTORY_SIZE) {
-                        start = 0;
-                    }
-                }
-
-                // Add the raw data to the historical trace.
-                mAveragingTouchFilter.historyStart[id] = start;
-                mAveragingTouchFilter.historyEnd[id] = end;
-                mAveragingTouchFilter.historyData[end].pointers[id].x = x;
-                mAveragingTouchFilter.historyData[end].pointers[id].y = y;
-                mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
-
-                // Average over all historical positions in the trace by total pressure.
-                int32_t averagedX = 0;
-                int32_t averagedY = 0;
-                int32_t totalPressure = 0;
-                for (;;) {
-                    int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
-                    int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
-                    int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
-                            .pointers[id].pressure;
-
-                    averagedX += historicalX * historicalPressure;
-                    averagedY += historicalY * historicalPressure;
-                    totalPressure += historicalPressure;
-
-                    if (start == end) {
-                        break;
-                    }
-
-                    start += 1;
-                    if (start > AVERAGING_HISTORY_SIZE) {
-                        start = 0;
-                    }
-                }
-
-                if (totalPressure != 0) {
-                    averagedX /= totalPressure;
-                    averagedY /= totalPressure;
-
-#if DEBUG_HACKS
-                    LOGD("AveragingTouchFilter: Pointer id %d - "
-                            "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
-                            averagedX, averagedY);
-#endif
-
-                    mCurrentTouch.pointers[currentIndex].x = averagedX;
-                    mCurrentTouch.pointers[currentIndex].y = averagedY;
-                }
-            } else {
-#if DEBUG_HACKS
-                LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
-#endif
-            }
-        } else {
-#if DEBUG_HACKS
-            LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
-#endif
-        }
-
-        // Reset pointer history.
-        mAveragingTouchFilter.historyStart[id] = 0;
-        mAveragingTouchFilter.historyEnd[id] = 0;
-        mAveragingTouchFilter.historyData[0].pointers[id].x = x;
-        mAveragingTouchFilter.historyData[0].pointers[id].y = y;
-        mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
-    }
-}
-
-int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
-            return AKEY_STATE_VIRTUAL;
-        }
-
-        size_t numVirtualKeys = mLocked.virtualKeys.size();
-        for (size_t i = 0; i < numVirtualKeys; i++) {
-            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
-            if (virtualKey.keyCode == keyCode) {
-                return AKEY_STATE_UP;
-            }
-        }
-    } // release lock
-
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
-            return AKEY_STATE_VIRTUAL;
-        }
-
-        size_t numVirtualKeys = mLocked.virtualKeys.size();
-        for (size_t i = 0; i < numVirtualKeys; i++) {
-            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
-            if (virtualKey.scanCode == scanCode) {
-                return AKEY_STATE_UP;
-            }
-        }
-    } // release lock
-
-    return AKEY_STATE_UNKNOWN;
-}
-
-bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        size_t numVirtualKeys = mLocked.virtualKeys.size();
-        for (size_t i = 0; i < numVirtualKeys; i++) {
-            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
-
-            for (size_t i = 0; i < numCodes; i++) {
-                if (virtualKey.keyCode == keyCodes[i]) {
-                    outFlags[i] = 1;
-                }
-            }
-        }
-    } // release lock
-
-    return true;
-}
-
-
-// --- SingleTouchInputMapper ---
-
-SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
-        TouchInputMapper(device) {
-    initialize();
-}
-
-SingleTouchInputMapper::~SingleTouchInputMapper() {
-}
-
-void SingleTouchInputMapper::initialize() {
-    mAccumulator.clear();
-
-    mDown = false;
-    mX = 0;
-    mY = 0;
-    mPressure = 0; // default to 0 for devices that don't report pressure
-    mToolWidth = 0; // default to 0 for devices that don't report tool width
-}
-
-void SingleTouchInputMapper::reset() {
-    TouchInputMapper::reset();
-
-    initialize();
- }
-
-void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_KEY:
-        switch (rawEvent->scanCode) {
-        case BTN_TOUCH:
-            mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
-            mAccumulator.btnTouch = rawEvent->value != 0;
-            // Don't sync immediately.  Wait until the next SYN_REPORT since we might
-            // not have received valid position information yet.  This logic assumes that
-            // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
-            break;
-        }
-        break;
-
-    case EV_ABS:
-        switch (rawEvent->scanCode) {
-        case ABS_X:
-            mAccumulator.fields |= Accumulator::FIELD_ABS_X;
-            mAccumulator.absX = rawEvent->value;
-            break;
-        case ABS_Y:
-            mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
-            mAccumulator.absY = rawEvent->value;
-            break;
-        case ABS_PRESSURE:
-            mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
-            mAccumulator.absPressure = rawEvent->value;
-            break;
-        case ABS_TOOL_WIDTH:
-            mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
-            mAccumulator.absToolWidth = rawEvent->value;
-            break;
-        }
-        break;
-
-    case EV_SYN:
-        switch (rawEvent->scanCode) {
-        case SYN_REPORT:
-            sync(rawEvent->when);
-            break;
-        }
-        break;
-    }
-}
-
-void SingleTouchInputMapper::sync(nsecs_t when) {
-    uint32_t fields = mAccumulator.fields;
-    if (fields == 0) {
-        return; // no new state changes, so nothing to do
-    }
-
-    if (fields & Accumulator::FIELD_BTN_TOUCH) {
-        mDown = mAccumulator.btnTouch;
-    }
-
-    if (fields & Accumulator::FIELD_ABS_X) {
-        mX = mAccumulator.absX;
-    }
-
-    if (fields & Accumulator::FIELD_ABS_Y) {
-        mY = mAccumulator.absY;
-    }
-
-    if (fields & Accumulator::FIELD_ABS_PRESSURE) {
-        mPressure = mAccumulator.absPressure;
-    }
-
-    if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
-        mToolWidth = mAccumulator.absToolWidth;
-    }
-
-    mCurrentTouch.clear();
-
-    if (mDown) {
-        mCurrentTouch.pointerCount = 1;
-        mCurrentTouch.pointers[0].id = 0;
-        mCurrentTouch.pointers[0].x = mX;
-        mCurrentTouch.pointers[0].y = mY;
-        mCurrentTouch.pointers[0].pressure = mPressure;
-        mCurrentTouch.pointers[0].touchMajor = 0;
-        mCurrentTouch.pointers[0].touchMinor = 0;
-        mCurrentTouch.pointers[0].toolMajor = mToolWidth;
-        mCurrentTouch.pointers[0].toolMinor = mToolWidth;
-        mCurrentTouch.pointers[0].orientation = 0;
-        mCurrentTouch.idToIndex[0] = 0;
-        mCurrentTouch.idBits.markBit(0);
-    }
-
-    syncTouch(when, true);
-
-    mAccumulator.clear();
-}
-
-void SingleTouchInputMapper::configureRawAxes() {
-    TouchInputMapper::configureRawAxes();
-
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
-}
-
-
-// --- MultiTouchInputMapper ---
-
-MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
-        TouchInputMapper(device) {
-    initialize();
-}
-
-MultiTouchInputMapper::~MultiTouchInputMapper() {
-}
-
-void MultiTouchInputMapper::initialize() {
-    mAccumulator.clear();
-}
-
-void MultiTouchInputMapper::reset() {
-    TouchInputMapper::reset();
-
-    initialize();
-}
-
-void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_ABS: {
-        uint32_t pointerIndex = mAccumulator.pointerCount;
-        Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
-
-        switch (rawEvent->scanCode) {
-        case ABS_MT_POSITION_X:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
-            pointer->absMTPositionX = rawEvent->value;
-            break;
-        case ABS_MT_POSITION_Y:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
-            pointer->absMTPositionY = rawEvent->value;
-            break;
-        case ABS_MT_TOUCH_MAJOR:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
-            pointer->absMTTouchMajor = rawEvent->value;
-            break;
-        case ABS_MT_TOUCH_MINOR:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
-            pointer->absMTTouchMinor = rawEvent->value;
-            break;
-        case ABS_MT_WIDTH_MAJOR:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
-            pointer->absMTWidthMajor = rawEvent->value;
-            break;
-        case ABS_MT_WIDTH_MINOR:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
-            pointer->absMTWidthMinor = rawEvent->value;
-            break;
-        case ABS_MT_ORIENTATION:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
-            pointer->absMTOrientation = rawEvent->value;
-            break;
-        case ABS_MT_TRACKING_ID:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
-            pointer->absMTTrackingId = rawEvent->value;
-            break;
-        case ABS_MT_PRESSURE:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
-            pointer->absMTPressure = rawEvent->value;
-            break;
-        }
-        break;
-    }
-
-    case EV_SYN:
-        switch (rawEvent->scanCode) {
-        case SYN_MT_REPORT: {
-            // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
-            uint32_t pointerIndex = mAccumulator.pointerCount;
-
-            if (mAccumulator.pointers[pointerIndex].fields) {
-                if (pointerIndex == MAX_POINTERS) {
-                    LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
-                            MAX_POINTERS);
-                } else {
-                    pointerIndex += 1;
-                    mAccumulator.pointerCount = pointerIndex;
-                }
-            }
-
-            mAccumulator.pointers[pointerIndex].clear();
-            break;
-        }
-
-        case SYN_REPORT:
-            sync(rawEvent->when);
-            break;
-        }
-        break;
-    }
-}
-
-void MultiTouchInputMapper::sync(nsecs_t when) {
-    static const uint32_t REQUIRED_FIELDS =
-            Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
-
-    uint32_t inCount = mAccumulator.pointerCount;
-    uint32_t outCount = 0;
-    bool havePointerIds = true;
-
-    mCurrentTouch.clear();
-
-    for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
-        const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
-        uint32_t fields = inPointer.fields;
-
-        if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
-            // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
-            // Drop this finger.
-            continue;
-        }
-
-        PointerData& outPointer = mCurrentTouch.pointers[outCount];
-        outPointer.x = inPointer.absMTPositionX;
-        outPointer.y = inPointer.absMTPositionY;
-
-        if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
-            if (inPointer.absMTPressure <= 0) {
-                // Some devices send sync packets with X / Y but with a 0 pressure to indicate
-                // a pointer going up.  Drop this finger.
-                continue;
-            }
-            outPointer.pressure = inPointer.absMTPressure;
-        } else {
-            // Default pressure to 0 if absent.
-            outPointer.pressure = 0;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
-            if (inPointer.absMTTouchMajor <= 0) {
-                // Some devices send sync packets with X / Y but with a 0 touch major to indicate
-                // a pointer going up.  Drop this finger.
-                continue;
-            }
-            outPointer.touchMajor = inPointer.absMTTouchMajor;
-        } else {
-            // Default touch area to 0 if absent.
-            outPointer.touchMajor = 0;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
-            outPointer.touchMinor = inPointer.absMTTouchMinor;
-        } else {
-            // Assume touch area is circular.
-            outPointer.touchMinor = outPointer.touchMajor;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
-            outPointer.toolMajor = inPointer.absMTWidthMajor;
-        } else {
-            // Default tool area to 0 if absent.
-            outPointer.toolMajor = 0;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
-            outPointer.toolMinor = inPointer.absMTWidthMinor;
-        } else {
-            // Assume tool area is circular.
-            outPointer.toolMinor = outPointer.toolMajor;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
-            outPointer.orientation = inPointer.absMTOrientation;
-        } else {
-            // Default orientation to vertical if absent.
-            outPointer.orientation = 0;
-        }
-
-        // Assign pointer id using tracking id if available.
-        if (havePointerIds) {
-            if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
-                uint32_t id = uint32_t(inPointer.absMTTrackingId);
-
-                if (id > MAX_POINTER_ID) {
-#if DEBUG_POINTERS
-                    LOGD("Pointers: Ignoring driver provided pointer id %d because "
-                            "it is larger than max supported id %d",
-                            id, MAX_POINTER_ID);
-#endif
-                    havePointerIds = false;
-                }
-                else {
-                    outPointer.id = id;
-                    mCurrentTouch.idToIndex[id] = outCount;
-                    mCurrentTouch.idBits.markBit(id);
-                }
-            } else {
-                havePointerIds = false;
-            }
-        }
-
-        outCount += 1;
-    }
-
-    mCurrentTouch.pointerCount = outCount;
-
-    syncTouch(when, havePointerIds);
-
-    mAccumulator.clear();
-}
-
-void MultiTouchInputMapper::configureRawAxes() {
-    TouchInputMapper::configureRawAxes();
-
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
-}
-
-
-} // namespace android
diff --git a/libs/ui/KeyCharacterMap.cpp b/libs/ui/KeyCharacterMap.cpp
index 9bfa8f6..2decfe9 100644
--- a/libs/ui/KeyCharacterMap.cpp
+++ b/libs/ui/KeyCharacterMap.cpp
@@ -185,9 +185,11 @@
     const Key* key;
     const Behavior* behavior;
     if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
-        outFallbackAction->keyCode = behavior->fallbackKeyCode;
-        outFallbackAction->metaState = metaState & ~behavior->metaState;
-        result = true;
+        if (behavior->fallbackKeyCode) {
+            outFallbackAction->keyCode = behavior->fallbackKeyCode;
+            outFallbackAction->metaState = metaState & ~behavior->metaState;
+            result = true;
+        }
     }
 #if DEBUG_MAPPING
     LOGD("getFallbackKeyCode: keyCode=%d, metaState=0x%08x ~ Result %s, "
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index aa017b9..580d73c 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -7,8 +7,6 @@
 # Build the unit tests.
 test_src_files := \
     InputChannel_test.cpp \
-    InputReader_test.cpp \
-    InputDispatcher_test.cpp \
     InputPublisherAndConsumer_test.cpp
 
 shared_libraries := \
diff --git a/libs/ui/tests/InputDispatcher_test.cpp b/libs/ui/tests/InputDispatcher_test.cpp
deleted file mode 100644
index 7e17c57..0000000
--- a/libs/ui/tests/InputDispatcher_test.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-
-#include <ui/InputDispatcher.h>
-#include <gtest/gtest.h>
-#include <linux/input.h>
-
-namespace android {
-
-// An arbitrary time value.
-static const nsecs_t ARBITRARY_TIME = 1234;
-
-// An arbitrary device id.
-static const int32_t DEVICE_ID = 1;
-
-// An arbitrary injector pid / uid pair that has permission to inject events.
-static const int32_t INJECTOR_PID = 999;
-static const int32_t INJECTOR_UID = 1001;
-
-
-// --- FakeInputDispatcherPolicy ---
-
-class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
-protected:
-    virtual ~FakeInputDispatcherPolicy() {
-    }
-
-public:
-    FakeInputDispatcherPolicy() {
-    }
-
-private:
-    virtual void notifyConfigurationChanged(nsecs_t when) {
-    }
-
-    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-            const sp<InputChannel>& inputChannel) {
-        return 0;
-    }
-
-    virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
-    }
-
-    virtual nsecs_t getKeyRepeatTimeout() {
-        return 500 * 1000000LL;
-    }
-
-    virtual nsecs_t getKeyRepeatDelay() {
-        return 50 * 1000000LL;
-    }
-
-    virtual int32_t getMaxEventsPerSecond() {
-        return 60;
-    }
-
-    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
-    }
-
-    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
-    }
-
-    virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags) {
-        return false;
-    }
-
-    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
-        return false;
-    }
-
-    virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
-    }
-
-    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
-    }
-
-    virtual bool checkInjectEventsPermissionNonReentrant(
-            int32_t injectorPid, int32_t injectorUid) {
-        return false;
-    }
-};
-
-
-// --- InputDispatcherTest ---
-
-class InputDispatcherTest : public testing::Test {
-protected:
-    sp<FakeInputDispatcherPolicy> mFakePolicy;
-    sp<InputDispatcher> mDispatcher;
-
-    virtual void SetUp() {
-        mFakePolicy = new FakeInputDispatcherPolicy();
-        mDispatcher = new InputDispatcher(mFakePolicy);
-    }
-
-    virtual void TearDown() {
-        mFakePolicy.clear();
-        mDispatcher.clear();
-    }
-};
-
-
-TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
-    KeyEvent event;
-
-    // Rejects undefined key actions.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
-            /*action*/ -1, 0,
-            AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject key events with undefined action.";
-
-    // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
-            AKEY_EVENT_ACTION_MULTIPLE, 0,
-            AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject key events with ACTION_MULTIPLE.";
-}
-
-TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
-    MotionEvent event;
-    int32_t pointerIds[MAX_POINTERS + 1];
-    PointerCoords pointerCoords[MAX_POINTERS + 1];
-    for (int i = 0; i <= MAX_POINTERS; i++) {
-        pointerIds[i] = i;
-    }
-
-    // Rejects undefined motion actions.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with undefined action.";
-
-    // Rejects pointer down with invalid index.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with pointer down index too large.";
-
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with pointer down index too small.";
-
-    // Rejects pointer up with invalid index.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with pointer up index too large.";
-
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with pointer up index too small.";
-
-    // Rejects motion events with invalid number of pointers.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 0, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with 0 pointers.";
-
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ MAX_POINTERS + 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with more than MAX_POINTERS pointers.";
-
-    // Rejects motion events with invalid pointer ids.
-    pointerIds[0] = -1;
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with pointer ids less than 0.";
-
-    pointerIds[0] = MAX_POINTER_ID + 1;
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
-
-    // Rejects motion events with duplicate pointer ids.
-    pointerIds[0] = 1;
-    pointerIds[1] = 1;
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 2, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with duplicate pointer ids.";
-}
-
-} // namespace android
diff --git a/libs/ui/tests/InputReader_test.cpp b/libs/ui/tests/InputReader_test.cpp
deleted file mode 100644
index 97cbc25..0000000
--- a/libs/ui/tests/InputReader_test.cpp
+++ /dev/null
@@ -1,3497 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-
-#include <ui/InputReader.h>
-#include <utils/List.h>
-#include <gtest/gtest.h>
-#include <math.h>
-
-namespace android {
-
-// An arbitrary time value.
-static const nsecs_t ARBITRARY_TIME = 1234;
-
-// Arbitrary display properties.
-static const int32_t DISPLAY_ID = 0;
-static const int32_t DISPLAY_WIDTH = 480;
-static const int32_t DISPLAY_HEIGHT = 800;
-
-// Error tolerance for floating point assertions.
-static const float EPSILON = 0.001f;
-
-template<typename T>
-static inline T min(T a, T b) {
-    return a < b ? a : b;
-}
-
-static inline float avg(float x, float y) {
-    return (x + y) / 2;
-}
-
-
-// --- FakeInputReaderPolicy ---
-
-class FakeInputReaderPolicy : public InputReaderPolicyInterface {
-    struct DisplayInfo {
-        int32_t width;
-        int32_t height;
-        int32_t orientation;
-    };
-
-    KeyedVector<int32_t, DisplayInfo> mDisplayInfos;
-    bool mFilterTouchEvents;
-    bool mFilterJumpyTouchEvents;
-    Vector<String8> mExcludedDeviceNames;
-
-protected:
-    virtual ~FakeInputReaderPolicy() { }
-
-public:
-    FakeInputReaderPolicy() :
-            mFilterTouchEvents(false), mFilterJumpyTouchEvents(false) {
-    }
-
-    void removeDisplayInfo(int32_t displayId) {
-        mDisplayInfos.removeItem(displayId);
-    }
-
-    void setDisplayInfo(int32_t displayId, int32_t width, int32_t height, int32_t orientation) {
-        removeDisplayInfo(displayId);
-
-        DisplayInfo info;
-        info.width = width;
-        info.height = height;
-        info.orientation = orientation;
-        mDisplayInfos.add(displayId, info);
-    }
-
-    void setFilterTouchEvents(bool enabled) {
-        mFilterTouchEvents = enabled;
-    }
-
-    void setFilterJumpyTouchEvents(bool enabled) {
-        mFilterJumpyTouchEvents = enabled;
-    }
-
-    void addExcludedDeviceName(const String8& deviceName) {
-        mExcludedDeviceNames.push(deviceName);
-    }
-
-private:
-    virtual bool getDisplayInfo(int32_t displayId,
-            int32_t* width, int32_t* height, int32_t* orientation) {
-        ssize_t index = mDisplayInfos.indexOfKey(displayId);
-        if (index >= 0) {
-            const DisplayInfo& info = mDisplayInfos.valueAt(index);
-            if (width) {
-                *width = info.width;
-            }
-            if (height) {
-                *height = info.height;
-            }
-            if (orientation) {
-                *orientation = info.orientation;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    virtual bool filterTouchEvents() {
-        return mFilterTouchEvents;
-    }
-
-    virtual bool filterJumpyTouchEvents() {
-        return mFilterJumpyTouchEvents;
-    }
-
-    virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
-        outExcludedDeviceNames.appendVector(mExcludedDeviceNames);
-    }
-};
-
-
-// --- FakeInputDispatcher ---
-
-class FakeInputDispatcher : public InputDispatcherInterface {
-public:
-    struct NotifyConfigurationChangedArgs {
-        nsecs_t eventTime;
-    };
-
-    struct NotifyKeyArgs {
-        nsecs_t eventTime;
-        int32_t deviceId;
-        int32_t source;
-        uint32_t policyFlags;
-        int32_t action;
-        int32_t flags;
-        int32_t keyCode;
-        int32_t scanCode;
-        int32_t metaState;
-        nsecs_t downTime;
-    };
-
-    struct NotifyMotionArgs {
-        nsecs_t eventTime;
-        int32_t deviceId;
-        int32_t source;
-        uint32_t policyFlags;
-        int32_t action;
-        int32_t flags;
-        int32_t metaState;
-        int32_t edgeFlags;
-        uint32_t pointerCount;
-        Vector<int32_t> pointerIds;
-        Vector<PointerCoords> pointerCoords;
-        float xPrecision;
-        float yPrecision;
-        nsecs_t downTime;
-    };
-
-    struct NotifySwitchArgs {
-        nsecs_t when;
-        int32_t switchCode;
-        int32_t switchValue;
-        uint32_t policyFlags;
-    };
-
-private:
-    List<NotifyConfigurationChangedArgs> mNotifyConfigurationChangedArgs;
-    List<NotifyKeyArgs> mNotifyKeyArgs;
-    List<NotifyMotionArgs> mNotifyMotionArgs;
-    List<NotifySwitchArgs> mNotifySwitchArgs;
-
-protected:
-    virtual ~FakeInputDispatcher() { }
-
-public:
-    FakeInputDispatcher() {
-    }
-
-    void assertNotifyConfigurationChangedWasCalled(NotifyConfigurationChangedArgs* outArgs = NULL) {
-        ASSERT_FALSE(mNotifyConfigurationChangedArgs.empty())
-                << "Expected notifyConfigurationChanged() to have been called.";
-        if (outArgs) {
-            *outArgs = *mNotifyConfigurationChangedArgs.begin();
-        }
-        mNotifyConfigurationChangedArgs.erase(mNotifyConfigurationChangedArgs.begin());
-    }
-
-    void assertNotifyKeyWasCalled(NotifyKeyArgs* outArgs = NULL) {
-        ASSERT_FALSE(mNotifyKeyArgs.empty())
-                << "Expected notifyKey() to have been called.";
-        if (outArgs) {
-            *outArgs = *mNotifyKeyArgs.begin();
-        }
-        mNotifyKeyArgs.erase(mNotifyKeyArgs.begin());
-    }
-
-    void assertNotifyKeyWasNotCalled() {
-        ASSERT_TRUE(mNotifyKeyArgs.empty())
-                << "Expected notifyKey() to not have been called.";
-    }
-
-    void assertNotifyMotionWasCalled(NotifyMotionArgs* outArgs = NULL) {
-        ASSERT_FALSE(mNotifyMotionArgs.empty())
-                << "Expected notifyMotion() to have been called.";
-        if (outArgs) {
-            *outArgs = *mNotifyMotionArgs.begin();
-        }
-        mNotifyMotionArgs.erase(mNotifyMotionArgs.begin());
-    }
-
-    void assertNotifyMotionWasNotCalled() {
-        ASSERT_TRUE(mNotifyMotionArgs.empty())
-                << "Expected notifyMotion() to not have been called.";
-    }
-
-    void assertNotifySwitchWasCalled(NotifySwitchArgs* outArgs = NULL) {
-        ASSERT_FALSE(mNotifySwitchArgs.empty())
-                << "Expected notifySwitch() to have been called.";
-        if (outArgs) {
-            *outArgs = *mNotifySwitchArgs.begin();
-        }
-        mNotifySwitchArgs.erase(mNotifySwitchArgs.begin());
-    }
-
-private:
-    virtual void notifyConfigurationChanged(nsecs_t eventTime) {
-        NotifyConfigurationChangedArgs args;
-        args.eventTime = eventTime;
-        mNotifyConfigurationChangedArgs.push_back(args);
-    }
-
-    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
-            int32_t scanCode, int32_t metaState, nsecs_t downTime) {
-        NotifyKeyArgs args;
-        args.eventTime = eventTime;
-        args.deviceId = deviceId;
-        args.source = source;
-        args.policyFlags = policyFlags;
-        args.action = action;
-        args.flags = flags;
-        args.keyCode = keyCode;
-        args.scanCode = scanCode;
-        args.metaState = metaState;
-        args.downTime = downTime;
-        mNotifyKeyArgs.push_back(args);
-    }
-
-    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t flags,
-            int32_t metaState, int32_t edgeFlags,
-            uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
-            float xPrecision, float yPrecision, nsecs_t downTime) {
-        NotifyMotionArgs args;
-        args.eventTime = eventTime;
-        args.deviceId = deviceId;
-        args.source = source;
-        args.policyFlags = policyFlags;
-        args.action = action;
-        args.flags = flags;
-        args.metaState = metaState;
-        args.edgeFlags = edgeFlags;
-        args.pointerCount = pointerCount;
-        args.pointerIds.clear();
-        args.pointerIds.appendArray(pointerIds, pointerCount);
-        args.pointerCoords.clear();
-        args.pointerCoords.appendArray(pointerCoords, pointerCount);
-        args.xPrecision = xPrecision;
-        args.yPrecision = yPrecision;
-        args.downTime = downTime;
-        mNotifyMotionArgs.push_back(args);
-    }
-
-    virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
-        NotifySwitchArgs args;
-        args.when = when;
-        args.switchCode = switchCode;
-        args.switchValue = switchValue;
-        args.policyFlags = policyFlags;
-        mNotifySwitchArgs.push_back(args);
-    }
-
-    virtual void dump(String8& dump) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-    }
-
-    virtual void dispatchOnce() {
-        ADD_FAILURE() << "Should never be called by input reader.";
-    }
-
-    virtual int32_t injectInputEvent(const InputEvent* event,
-            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-        return INPUT_EVENT_INJECTION_FAILED;
-    }
-
-    virtual void setInputWindows(const Vector<InputWindow>& inputWindows) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-    }
-
-    virtual void setFocusedApplication(const InputApplication* inputApplication) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-    }
-
-    virtual void setInputDispatchMode(bool enabled, bool frozen) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-    }
-
-    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
-            const sp<InputChannel>& toChannel) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-        return 0;
-    }
-
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-        return 0;
-    }
-
-    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-        return 0;
-    }
-};
-
-
-// --- FakeEventHub ---
-
-class FakeEventHub : public EventHubInterface {
-    struct KeyInfo {
-        int32_t keyCode;
-        uint32_t flags;
-    };
-
-    struct Device {
-        String8 name;
-        uint32_t classes;
-        PropertyMap configuration;
-        KeyedVector<int, RawAbsoluteAxisInfo> axes;
-        KeyedVector<int32_t, int32_t> keyCodeStates;
-        KeyedVector<int32_t, int32_t> scanCodeStates;
-        KeyedVector<int32_t, int32_t> switchStates;
-        KeyedVector<int32_t, KeyInfo> keys;
-        KeyedVector<int32_t, bool> leds;
-        Vector<VirtualKeyDefinition> virtualKeys;
-
-        Device(const String8& name, uint32_t classes) :
-                name(name), classes(classes) {
-        }
-    };
-
-    KeyedVector<int32_t, Device*> mDevices;
-    Vector<String8> mExcludedDevices;
-    List<RawEvent> mEvents;
-
-protected:
-    virtual ~FakeEventHub() {
-        for (size_t i = 0; i < mDevices.size(); i++) {
-            delete mDevices.valueAt(i);
-        }
-    }
-
-public:
-    FakeEventHub() { }
-
-    void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
-        Device* device = new Device(name, classes);
-        mDevices.add(deviceId, device);
-
-        enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0, 0, 0);
-    }
-
-    void removeDevice(int32_t deviceId) {
-        delete mDevices.valueFor(deviceId);
-        mDevices.removeItem(deviceId);
-
-        enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0, 0, 0);
-    }
-
-    void finishDeviceScan() {
-        enqueueEvent(ARBITRARY_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0, 0, 0);
-    }
-
-    void addConfigurationProperty(int32_t deviceId, const String8& key, const String8& value) {
-        Device* device = getDevice(deviceId);
-        device->configuration.addProperty(key, value);
-    }
-
-    void addAxis(int32_t deviceId, int axis,
-            int32_t minValue, int32_t maxValue, int flat, int fuzz) {
-        Device* device = getDevice(deviceId);
-
-        RawAbsoluteAxisInfo info;
-        info.valid = true;
-        info.minValue = minValue;
-        info.maxValue = maxValue;
-        info.flat = flat;
-        info.fuzz = fuzz;
-        device->axes.add(axis, info);
-    }
-
-    void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state) {
-        Device* device = getDevice(deviceId);
-        device->keyCodeStates.replaceValueFor(keyCode, state);
-    }
-
-    void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) {
-        Device* device = getDevice(deviceId);
-        device->scanCodeStates.replaceValueFor(scanCode, state);
-    }
-
-    void setSwitchState(int32_t deviceId, int32_t switchCode, int32_t state) {
-        Device* device = getDevice(deviceId);
-        device->switchStates.replaceValueFor(switchCode, state);
-    }
-
-    void addKey(int32_t deviceId, int32_t scanCode, int32_t keyCode, uint32_t flags) {
-        Device* device = getDevice(deviceId);
-        KeyInfo info;
-        info.keyCode = keyCode;
-        info.flags = flags;
-        device->keys.add(scanCode, info);
-    }
-
-    void addLed(int32_t deviceId, int32_t led, bool initialState) {
-        Device* device = getDevice(deviceId);
-        device->leds.add(led, initialState);
-    }
-
-    bool getLedState(int32_t deviceId, int32_t led) {
-        Device* device = getDevice(deviceId);
-        return device->leds.valueFor(led);
-    }
-
-    Vector<String8>& getExcludedDevices() {
-        return mExcludedDevices;
-    }
-
-    void addVirtualKeyDefinition(int32_t deviceId, const VirtualKeyDefinition& definition) {
-        Device* device = getDevice(deviceId);
-        device->virtualKeys.push(definition);
-    }
-
-    void enqueueEvent(nsecs_t when, int32_t deviceId, int32_t type,
-            int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) {
-        RawEvent event;
-        event.when = when;
-        event.deviceId = deviceId;
-        event.type = type;
-        event.scanCode = scanCode;
-        event.keyCode = keyCode;
-        event.value = value;
-        event.flags = flags;
-        mEvents.push_back(event);
-    }
-
-    void assertQueueIsEmpty() {
-        ASSERT_EQ(size_t(0), mEvents.size())
-                << "Expected the event queue to be empty (fully consumed).";
-    }
-
-private:
-    Device* getDevice(int32_t deviceId) const {
-        ssize_t index = mDevices.indexOfKey(deviceId);
-        return index >= 0 ? mDevices.valueAt(index) : NULL;
-    }
-
-    virtual uint32_t getDeviceClasses(int32_t deviceId) const {
-        Device* device = getDevice(deviceId);
-        return device ? device->classes : 0;
-    }
-
-    virtual String8 getDeviceName(int32_t deviceId) const {
-        Device* device = getDevice(deviceId);
-        return device ? device->name : String8("unknown");
-    }
-
-    virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            *outConfiguration = device->configuration;
-        }
-    }
-
-    virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
-            RawAbsoluteAxisInfo* outAxisInfo) const {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            ssize_t index = device->axes.indexOfKey(axis);
-            if (index >= 0) {
-                *outAxisInfo = device->axes.valueAt(index);
-                return OK;
-            }
-        }
-        return -1;
-    }
-
-    virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
-            int32_t* outKeycode, uint32_t* outFlags) const {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            ssize_t index = device->keys.indexOfKey(scancode);
-            if (index >= 0) {
-                if (outKeycode) {
-                    *outKeycode = device->keys.valueAt(index).keyCode;
-                }
-                if (outFlags) {
-                    *outFlags = device->keys.valueAt(index).flags;
-                }
-                return OK;
-            }
-        }
-        return NAME_NOT_FOUND;
-    }
-
-    virtual void addExcludedDevice(const char* deviceName) {
-        mExcludedDevices.add(String8(deviceName));
-    }
-
-    virtual bool getEvent(RawEvent* outEvent) {
-        if (mEvents.empty()) {
-            return false;
-        }
-
-        *outEvent = *mEvents.begin();
-        mEvents.erase(mEvents.begin());
-        return true;
-    }
-
-    virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            ssize_t index = device->scanCodeStates.indexOfKey(scanCode);
-            if (index >= 0) {
-                return device->scanCodeStates.valueAt(index);
-            }
-        }
-        return AKEY_STATE_UNKNOWN;
-    }
-
-    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            ssize_t index = device->keyCodeStates.indexOfKey(keyCode);
-            if (index >= 0) {
-                return device->keyCodeStates.valueAt(index);
-            }
-        }
-        return AKEY_STATE_UNKNOWN;
-    }
-
-    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            ssize_t index = device->switchStates.indexOfKey(sw);
-            if (index >= 0) {
-                return device->switchStates.valueAt(index);
-            }
-        }
-        return AKEY_STATE_UNKNOWN;
-    }
-
-    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
-            uint8_t* outFlags) const {
-        bool result = false;
-        Device* device = getDevice(deviceId);
-        if (device) {
-            for (size_t i = 0; i < numCodes; i++) {
-                for (size_t j = 0; j < device->keys.size(); j++) {
-                    if (keyCodes[i] == device->keys.valueAt(j).keyCode) {
-                        outFlags[i] = 1;
-                        result = true;
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
-    virtual bool hasLed(int32_t deviceId, int32_t led) const {
-        Device* device = getDevice(deviceId);
-        return device && device->leds.indexOfKey(led) >= 0;
-    }
-
-    virtual void setLedState(int32_t deviceId, int32_t led, bool on) {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            ssize_t index = device->leds.indexOfKey(led);
-            if (index >= 0) {
-                device->leds.replaceValueAt(led, on);
-            } else {
-                ADD_FAILURE()
-                        << "Attempted to set the state of an LED that the EventHub declared "
-                        "was not present.  led=" << led;
-            }
-        }
-    }
-
-    virtual void getVirtualKeyDefinitions(int32_t deviceId,
-            Vector<VirtualKeyDefinition>& outVirtualKeys) const {
-        outVirtualKeys.clear();
-
-        Device* device = getDevice(deviceId);
-        if (device) {
-            outVirtualKeys.appendVector(device->virtualKeys);
-        }
-    }
-
-    virtual void dump(String8& dump) {
-    }
-};
-
-
-// --- FakeInputReaderContext ---
-
-class FakeInputReaderContext : public InputReaderContext {
-    sp<EventHubInterface> mEventHub;
-    sp<InputReaderPolicyInterface> mPolicy;
-    sp<InputDispatcherInterface> mDispatcher;
-    int32_t mGlobalMetaState;
-    bool mUpdateGlobalMetaStateWasCalled;
-
-public:
-    FakeInputReaderContext(const sp<EventHubInterface>& eventHub,
-            const sp<InputReaderPolicyInterface>& policy,
-            const sp<InputDispatcherInterface>& dispatcher) :
-            mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
-            mGlobalMetaState(0) {
-    }
-
-    virtual ~FakeInputReaderContext() { }
-
-    void assertUpdateGlobalMetaStateWasCalled() {
-        ASSERT_TRUE(mUpdateGlobalMetaStateWasCalled)
-                << "Expected updateGlobalMetaState() to have been called.";
-        mUpdateGlobalMetaStateWasCalled = false;
-    }
-
-    void setGlobalMetaState(int32_t state) {
-        mGlobalMetaState = state;
-    }
-
-private:
-    virtual void updateGlobalMetaState() {
-        mUpdateGlobalMetaStateWasCalled = true;
-    }
-
-    virtual int32_t getGlobalMetaState() {
-        return mGlobalMetaState;
-    }
-
-    virtual EventHubInterface* getEventHub() {
-        return mEventHub.get();
-    }
-
-    virtual InputReaderPolicyInterface* getPolicy() {
-        return mPolicy.get();
-    }
-
-    virtual InputDispatcherInterface* getDispatcher() {
-        return mDispatcher.get();
-    }
-};
-
-
-// --- FakeInputMapper ---
-
-class FakeInputMapper : public InputMapper {
-    uint32_t mSources;
-    int32_t mKeyboardType;
-    int32_t mMetaState;
-    KeyedVector<int32_t, int32_t> mKeyCodeStates;
-    KeyedVector<int32_t, int32_t> mScanCodeStates;
-    KeyedVector<int32_t, int32_t> mSwitchStates;
-    Vector<int32_t> mSupportedKeyCodes;
-    RawEvent mLastEvent;
-
-    bool mConfigureWasCalled;
-    bool mResetWasCalled;
-    bool mProcessWasCalled;
-
-public:
-    FakeInputMapper(InputDevice* device, uint32_t sources) :
-            InputMapper(device),
-            mSources(sources), mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
-            mMetaState(0),
-            mConfigureWasCalled(false), mResetWasCalled(false), mProcessWasCalled(false) {
-    }
-
-    virtual ~FakeInputMapper() { }
-
-    void setKeyboardType(int32_t keyboardType) {
-        mKeyboardType = keyboardType;
-    }
-
-    void setMetaState(int32_t metaState) {
-        mMetaState = metaState;
-    }
-
-    void assertConfigureWasCalled() {
-        ASSERT_TRUE(mConfigureWasCalled)
-                << "Expected configure() to have been called.";
-        mConfigureWasCalled = false;
-    }
-
-    void assertResetWasCalled() {
-        ASSERT_TRUE(mResetWasCalled)
-                << "Expected reset() to have been called.";
-        mResetWasCalled = false;
-    }
-
-    void assertProcessWasCalled(RawEvent* outLastEvent = NULL) {
-        ASSERT_TRUE(mProcessWasCalled)
-                << "Expected process() to have been called.";
-        if (outLastEvent) {
-            *outLastEvent = mLastEvent;
-        }
-        mProcessWasCalled = false;
-    }
-
-    void setKeyCodeState(int32_t keyCode, int32_t state) {
-        mKeyCodeStates.replaceValueFor(keyCode, state);
-    }
-
-    void setScanCodeState(int32_t scanCode, int32_t state) {
-        mScanCodeStates.replaceValueFor(scanCode, state);
-    }
-
-    void setSwitchState(int32_t switchCode, int32_t state) {
-        mSwitchStates.replaceValueFor(switchCode, state);
-    }
-
-    void addSupportedKeyCode(int32_t keyCode) {
-        mSupportedKeyCodes.add(keyCode);
-    }
-
-private:
-    virtual uint32_t getSources() {
-        return mSources;
-    }
-
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo) {
-        InputMapper::populateDeviceInfo(deviceInfo);
-
-        if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
-            deviceInfo->setKeyboardType(mKeyboardType);
-        }
-    }
-
-    virtual void configure() {
-        mConfigureWasCalled = true;
-    }
-
-    virtual void reset() {
-        mResetWasCalled = true;
-    }
-
-    virtual void process(const RawEvent* rawEvent) {
-        mLastEvent = *rawEvent;
-        mProcessWasCalled = true;
-    }
-
-    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-        ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
-        return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
-    }
-
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-        ssize_t index = mScanCodeStates.indexOfKey(scanCode);
-        return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
-    }
-
-    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode) {
-        ssize_t index = mSwitchStates.indexOfKey(switchCode);
-        return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
-    }
-
-    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags) {
-        bool result = false;
-        for (size_t i = 0; i < numCodes; i++) {
-            for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
-                if (keyCodes[i] == mSupportedKeyCodes[j]) {
-                    outFlags[i] = 1;
-                    result = true;
-                }
-            }
-        }
-        return result;
-    }
-
-    virtual int32_t getMetaState() {
-        return mMetaState;
-    }
-};
-
-
-// --- InstrumentedInputReader ---
-
-class InstrumentedInputReader : public InputReader {
-    InputDevice* mNextDevice;
-
-public:
-    InstrumentedInputReader(const sp<EventHubInterface>& eventHub,
-            const sp<InputReaderPolicyInterface>& policy,
-            const sp<InputDispatcherInterface>& dispatcher) :
-            InputReader(eventHub, policy, dispatcher) {
-    }
-
-    virtual ~InstrumentedInputReader() {
-        if (mNextDevice) {
-            delete mNextDevice;
-        }
-    }
-
-    void setNextDevice(InputDevice* device) {
-        mNextDevice = device;
-    }
-
-protected:
-    virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
-        if (mNextDevice) {
-            InputDevice* device = mNextDevice;
-            mNextDevice = NULL;
-            return device;
-        }
-        return InputReader::createDevice(deviceId, name, classes);
-    }
-
-    friend class InputReaderTest;
-};
-
-
-// --- InputReaderTest ---
-
-class InputReaderTest : public testing::Test {
-protected:
-    sp<FakeInputDispatcher> mFakeDispatcher;
-    sp<FakeInputReaderPolicy> mFakePolicy;
-    sp<FakeEventHub> mFakeEventHub;
-    sp<InstrumentedInputReader> mReader;
-
-    virtual void SetUp() {
-        mFakeEventHub = new FakeEventHub();
-        mFakePolicy = new FakeInputReaderPolicy();
-        mFakeDispatcher = new FakeInputDispatcher();
-
-        mReader = new InstrumentedInputReader(mFakeEventHub, mFakePolicy, mFakeDispatcher);
-    }
-
-    virtual void TearDown() {
-        mReader.clear();
-
-        mFakeDispatcher.clear();
-        mFakePolicy.clear();
-        mFakeEventHub.clear();
-    }
-
-    void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
-        mFakeEventHub->addDevice(deviceId, name, classes);
-        mFakeEventHub->finishDeviceScan();
-        mReader->loopOnce();
-        mReader->loopOnce();
-        mFakeEventHub->assertQueueIsEmpty();
-    }
-
-    FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId,
-            const String8& name, uint32_t classes, uint32_t sources) {
-        InputDevice* device = new InputDevice(mReader.get(), deviceId, name);
-        FakeInputMapper* mapper = new FakeInputMapper(device, sources);
-        device->addMapper(mapper);
-        mReader->setNextDevice(device);
-        addDevice(deviceId, name, classes);
-        return mapper;
-    }
-};
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenNoDevices_ReturnsDefaults) {
-    InputConfiguration config;
-    mReader->getInputConfiguration(&config);
-
-    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
-    ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
-    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenAlphabeticKeyboardPresent_ReturnsQwertyKeyboard) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("keyboard"),
-            INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY));
-
-    InputConfiguration config;
-    mReader->getInputConfiguration(&config);
-
-    ASSERT_EQ(InputConfiguration::KEYBOARD_QWERTY, config.keyboard);
-    ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
-    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenTouchScreenPresent_ReturnsFingerTouchScreen) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("touchscreen"),
-            INPUT_DEVICE_CLASS_TOUCHSCREEN));
-
-    InputConfiguration config;
-    mReader->getInputConfiguration(&config);
-
-    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
-    ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
-    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_FINGER, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenTrackballPresent_ReturnsTrackballNavigation) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("trackball"),
-            INPUT_DEVICE_CLASS_TRACKBALL));
-
-    InputConfiguration config;
-    mReader->getInputConfiguration(&config);
-
-    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
-    ASSERT_EQ(InputConfiguration::NAVIGATION_TRACKBALL, config.navigation);
-    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenDPadPresent_ReturnsDPadNavigation) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("dpad"),
-            INPUT_DEVICE_CLASS_DPAD));
-
-    InputConfiguration config;
-    mReader->getInputConfiguration(&config);
-
-    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
-    ASSERT_EQ(InputConfiguration::NAVIGATION_DPAD, config.navigation);
-    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsValid) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
-            INPUT_DEVICE_CLASS_KEYBOARD));
-
-    InputDeviceInfo info;
-    status_t result = mReader->getInputDeviceInfo(1, &info);
-
-    ASSERT_EQ(OK, result);
-    ASSERT_EQ(1, info.getId());
-    ASSERT_STREQ("keyboard", info.getName().string());
-    ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, info.getKeyboardType());
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, info.getSources());
-    ASSERT_EQ(size_t(0), info.getMotionRanges().size());
-}
-
-TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsInvalid) {
-    InputDeviceInfo info;
-    status_t result = mReader->getInputDeviceInfo(-1, &info);
-
-    ASSERT_EQ(NAME_NOT_FOUND, result);
-}
-
-TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsIgnored) {
-    addDevice(1, String8("ignored"), 0); // no classes so device will be ignored
-
-    InputDeviceInfo info;
-    status_t result = mReader->getInputDeviceInfo(1, &info);
-
-    ASSERT_EQ(NAME_NOT_FOUND, result);
-}
-
-TEST_F(InputReaderTest, GetInputDeviceIds) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
-            INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY));
-    ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("trackball"),
-            INPUT_DEVICE_CLASS_TRACKBALL));
-
-    Vector<int32_t> ids;
-    mReader->getInputDeviceIds(ids);
-
-    ASSERT_EQ(size_t(2), ids.size());
-    ASSERT_EQ(1, ids[0]);
-    ASSERT_EQ(2, ids[1]);
-}
-
-TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
-    FakeInputMapper* mapper = NULL;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
-            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
-    mapper->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0,
-            AINPUT_SOURCE_ANY, AKEYCODE_A))
-            << "Should return unknown when the device id is >= 0 but unknown.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(1,
-            AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return unknown when the device id is valid but the sources are not supported by the device.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(1,
-            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
-            AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(-1,
-            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-}
-
-TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
-    FakeInputMapper* mapper = NULL;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
-            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
-    mapper->setScanCodeState(KEY_A, AKEY_STATE_DOWN);
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0,
-            AINPUT_SOURCE_ANY, KEY_A))
-            << "Should return unknown when the device id is >= 0 but unknown.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(1,
-            AINPUT_SOURCE_TRACKBALL, KEY_A))
-            << "Should return unknown when the device id is valid but the sources are not supported by the device.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(1,
-            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
-            << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
-            AINPUT_SOURCE_TRACKBALL, KEY_A))
-            << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(-1,
-            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
-            << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-}
-
-TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
-    FakeInputMapper* mapper = NULL;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
-            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
-    mapper->setSwitchState(SW_LID, AKEY_STATE_DOWN);
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0,
-            AINPUT_SOURCE_ANY, SW_LID))
-            << "Should return unknown when the device id is >= 0 but unknown.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(1,
-            AINPUT_SOURCE_TRACKBALL, SW_LID))
-            << "Should return unknown when the device id is valid but the sources are not supported by the device.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(1,
-            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
-            << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
-            AINPUT_SOURCE_TRACKBALL, SW_LID))
-            << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(-1,
-            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
-            << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-}
-
-TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
-    FakeInputMapper* mapper = NULL;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
-            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
-    mapper->addSupportedKeyCode(AKEYCODE_A);
-    mapper->addSupportedKeyCode(AKEYCODE_B);
-
-    const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
-    uint8_t flags[4] = { 0, 0, 0, 1 };
-
-    ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, 4, keyCodes, flags))
-            << "Should return false when device id is >= 0 but unknown.";
-    ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
-
-    flags[3] = 1;
-    ASSERT_FALSE(mReader->hasKeys(1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
-            << "Should return false when device id is valid but the sources are not supported by the device.";
-    ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
-
-    flags[3] = 1;
-    ASSERT_TRUE(mReader->hasKeys(1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
-            << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-    ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
-
-    flags[3] = 1;
-    ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
-            << "Should return false when the device id is < 0 but the sources are not supported by any device.";
-    ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
-
-    flags[3] = 1;
-    ASSERT_TRUE(mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
-            << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-    ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
-}
-
-TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
-    addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD);
-
-    FakeInputDispatcher::NotifyConfigurationChangedArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyConfigurationChangedWasCalled(&args));
-    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-}
-
-TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
-    FakeInputMapper* mapper = NULL;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
-            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
-
-    mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, AKEYCODE_A, 1, POLICY_FLAG_WAKE);
-    mReader->loopOnce();
-    ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
-
-    RawEvent event;
-    ASSERT_NO_FATAL_FAILURE(mapper->assertProcessWasCalled(&event));
-    ASSERT_EQ(0, event.when);
-    ASSERT_EQ(1, event.deviceId);
-    ASSERT_EQ(EV_KEY, event.type);
-    ASSERT_EQ(KEY_A, event.scanCode);
-    ASSERT_EQ(AKEYCODE_A, event.keyCode);
-    ASSERT_EQ(1, event.value);
-    ASSERT_EQ(POLICY_FLAG_WAKE, event.flags);
-}
-
-
-// --- InputDeviceTest ---
-
-class InputDeviceTest : public testing::Test {
-protected:
-    static const char* DEVICE_NAME;
-    static const int32_t DEVICE_ID;
-
-    sp<FakeEventHub> mFakeEventHub;
-    sp<FakeInputReaderPolicy> mFakePolicy;
-    sp<FakeInputDispatcher> mFakeDispatcher;
-    FakeInputReaderContext* mFakeContext;
-
-    InputDevice* mDevice;
-
-    virtual void SetUp() {
-        mFakeEventHub = new FakeEventHub();
-        mFakePolicy = new FakeInputReaderPolicy();
-        mFakeDispatcher = new FakeInputDispatcher();
-        mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
-
-        mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
-        mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
-    }
-
-    virtual void TearDown() {
-        delete mDevice;
-
-        delete mFakeContext;
-        mFakeDispatcher.clear();
-        mFakePolicy.clear();
-        mFakeEventHub.clear();
-    }
-};
-
-const char* InputDeviceTest::DEVICE_NAME = "device";
-const int32_t InputDeviceTest::DEVICE_ID = 1;
-
-TEST_F(InputDeviceTest, ImmutableProperties) {
-    ASSERT_EQ(DEVICE_ID, mDevice->getId());
-    ASSERT_STREQ(DEVICE_NAME, mDevice->getName());
-}
-
-TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
-    // Configuration.
-    mDevice->configure();
-
-    // Metadata.
-    ASSERT_TRUE(mDevice->isIgnored());
-    ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
-
-    InputDeviceInfo info;
-    mDevice->getDeviceInfo(&info);
-    ASSERT_EQ(DEVICE_ID, info.getId());
-    ASSERT_STREQ(DEVICE_NAME, info.getName().string());
-    ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
-    ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
-
-    // State queries.
-    ASSERT_EQ(0, mDevice->getMetaState());
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
-            << "Ignored device should return unknown key code state.";
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
-            << "Ignored device should return unknown scan code state.";
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
-            << "Ignored device should return unknown switch state.";
-
-    const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
-    uint8_t flags[2] = { 0, 1 };
-    ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 2, keyCodes, flags))
-            << "Ignored device should never mark any key codes.";
-    ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
-    ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
-
-    // Reset.
-    mDevice->reset();
-}
-
-TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
-    // Configuration.
-    mFakeEventHub->addConfigurationProperty(DEVICE_ID, String8("key"), String8("value"));
-
-    FakeInputMapper* mapper1 = new FakeInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD);
-    mapper1->setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    mapper1->setMetaState(AMETA_ALT_ON);
-    mapper1->addSupportedKeyCode(AKEYCODE_A);
-    mapper1->addSupportedKeyCode(AKEYCODE_B);
-    mapper1->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
-    mapper1->setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
-    mapper1->setScanCodeState(2, AKEY_STATE_DOWN);
-    mapper1->setScanCodeState(3, AKEY_STATE_UP);
-    mapper1->setSwitchState(4, AKEY_STATE_DOWN);
-    mDevice->addMapper(mapper1);
-
-    FakeInputMapper* mapper2 = new FakeInputMapper(mDevice, AINPUT_SOURCE_TOUCHSCREEN);
-    mapper2->setMetaState(AMETA_SHIFT_ON);
-    mDevice->addMapper(mapper2);
-
-    mDevice->configure();
-
-    String8 propertyValue;
-    ASSERT_TRUE(mDevice->getConfiguration().tryGetProperty(String8("key"), propertyValue))
-            << "Device should have read configuration during configuration phase.";
-    ASSERT_STREQ("value", propertyValue.string());
-
-    ASSERT_NO_FATAL_FAILURE(mapper1->assertConfigureWasCalled());
-    ASSERT_NO_FATAL_FAILURE(mapper2->assertConfigureWasCalled());
-
-    // Metadata.
-    ASSERT_FALSE(mDevice->isIgnored());
-    ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
-
-    InputDeviceInfo info;
-    mDevice->getDeviceInfo(&info);
-    ASSERT_EQ(DEVICE_ID, info.getId());
-    ASSERT_STREQ(DEVICE_NAME, info.getName().string());
-    ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
-    ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
-
-    // State queries.
-    ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
-            << "Should query mappers and combine meta states.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return unknown key code state when source not supported.";
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return unknown scan code state when source not supported.";
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return unknown switch state when source not supported.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
-            << "Should query mapper when source is supported.";
-    ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
-            << "Should query mapper when source is supported.";
-    ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
-            << "Should query mapper when source is supported.";
-
-    const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
-    uint8_t flags[4] = { 0, 0, 0, 1 };
-    ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
-            << "Should do nothing when source is unsupported.";
-    ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
-    ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
-    ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
-    ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
-
-    ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 4, keyCodes, flags))
-            << "Should query mapper when source is supported.";
-    ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
-    ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
-    ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
-    ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
-
-    // Event handling.
-    RawEvent event;
-    mDevice->process(&event);
-
-    ASSERT_NO_FATAL_FAILURE(mapper1->assertProcessWasCalled());
-    ASSERT_NO_FATAL_FAILURE(mapper2->assertProcessWasCalled());
-
-    // Reset.
-    mDevice->reset();
-
-    ASSERT_NO_FATAL_FAILURE(mapper1->assertResetWasCalled());
-    ASSERT_NO_FATAL_FAILURE(mapper2->assertResetWasCalled());
-}
-
-
-// --- InputMapperTest ---
-
-class InputMapperTest : public testing::Test {
-protected:
-    static const char* DEVICE_NAME;
-    static const int32_t DEVICE_ID;
-
-    sp<FakeEventHub> mFakeEventHub;
-    sp<FakeInputReaderPolicy> mFakePolicy;
-    sp<FakeInputDispatcher> mFakeDispatcher;
-    FakeInputReaderContext* mFakeContext;
-    InputDevice* mDevice;
-
-    virtual void SetUp() {
-        mFakeEventHub = new FakeEventHub();
-        mFakePolicy = new FakeInputReaderPolicy();
-        mFakeDispatcher = new FakeInputDispatcher();
-        mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
-        mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
-
-        mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
-    }
-
-    virtual void TearDown() {
-        delete mDevice;
-        delete mFakeContext;
-        mFakeDispatcher.clear();
-        mFakePolicy.clear();
-        mFakeEventHub.clear();
-    }
-
-    void addConfigurationProperty(const char* key, const char* value) {
-        mFakeEventHub->addConfigurationProperty(DEVICE_ID, String8(key), String8(value));
-    }
-
-    void addMapperAndConfigure(InputMapper* mapper) {
-        mDevice->addMapper(mapper);
-        mDevice->configure();
-    }
-
-    static void process(InputMapper* mapper, nsecs_t when, int32_t deviceId, int32_t type,
-            int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) {
-        RawEvent event;
-        event.when = when;
-        event.deviceId = deviceId;
-        event.type = type;
-        event.scanCode = scanCode;
-        event.keyCode = keyCode;
-        event.value = value;
-        event.flags = flags;
-        mapper->process(&event);
-    }
-
-    static void assertMotionRange(const InputDeviceInfo& info,
-            int32_t rangeType, float min, float max, float flat, float fuzz) {
-        const InputDeviceInfo::MotionRange* range = info.getMotionRange(rangeType);
-        ASSERT_TRUE(range != NULL) << "Range: " << rangeType;
-        ASSERT_NEAR(min, range->min, EPSILON) << "Range: " << rangeType;
-        ASSERT_NEAR(max, range->max, EPSILON) << "Range: " << rangeType;
-        ASSERT_NEAR(flat, range->flat, EPSILON) << "Range: " << rangeType;
-        ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Range: " << rangeType;
-    }
-
-    static void assertPointerCoords(const PointerCoords& coords,
-            float x, float y, float pressure, float size,
-            float touchMajor, float touchMinor, float toolMajor, float toolMinor,
-            float orientation) {
-        ASSERT_NEAR(x, coords.x, 1);
-        ASSERT_NEAR(y, coords.y, 1);
-        ASSERT_NEAR(pressure, coords.pressure, EPSILON);
-        ASSERT_NEAR(size, coords.size, EPSILON);
-        ASSERT_NEAR(touchMajor, coords.touchMajor, 1);
-        ASSERT_NEAR(touchMinor, coords.touchMinor, 1);
-        ASSERT_NEAR(toolMajor, coords.toolMajor, 1);
-        ASSERT_NEAR(toolMinor, coords.toolMinor, 1);
-        ASSERT_NEAR(orientation, coords.orientation, EPSILON);
-    }
-};
-
-const char* InputMapperTest::DEVICE_NAME = "device";
-const int32_t InputMapperTest::DEVICE_ID = 1;
-
-
-// --- SwitchInputMapperTest ---
-
-class SwitchInputMapperTest : public InputMapperTest {
-protected:
-};
-
-TEST_F(SwitchInputMapperTest, GetSources) {
-    SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    ASSERT_EQ(uint32_t(0), mapper->getSources());
-}
-
-TEST_F(SwitchInputMapperTest, GetSwitchState) {
-    SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 1);
-    ASSERT_EQ(1, mapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
-
-    mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 0);
-    ASSERT_EQ(0, mapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
-}
-
-TEST_F(SwitchInputMapperTest, Process) {
-    SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_LID, 0, 1, 0);
-
-    FakeInputDispatcher::NotifySwitchArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifySwitchWasCalled(&args));
-    ASSERT_EQ(ARBITRARY_TIME, args.when);
-    ASSERT_EQ(SW_LID, args.switchCode);
-    ASSERT_EQ(1, args.switchValue);
-    ASSERT_EQ(uint32_t(0), args.policyFlags);
-}
-
-
-// --- KeyboardInputMapperTest ---
-
-class KeyboardInputMapperTest : public InputMapperTest {
-protected:
-    void testDPadKeyRotation(KeyboardInputMapper* mapper,
-            int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode);
-};
-
-void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper* mapper,
-        int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode) {
-    FakeInputDispatcher::NotifyKeyArgs args;
-
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
-    ASSERT_EQ(originalScanCode, args.scanCode);
-    ASSERT_EQ(rotatedKeyCode, args.keyCode);
-
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(originalScanCode, args.scanCode);
-    ASSERT_EQ(rotatedKeyCode, args.keyCode);
-}
-
-
-TEST_F(KeyboardInputMapperTest, GetSources) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper->getSources());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    // Key down.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE);
-    FakeInputDispatcher::NotifyKeyArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
-    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
-    ASSERT_EQ(KEY_HOME, args.scanCode);
-    ASSERT_EQ(AMETA_NONE, args.metaState);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
-    ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
-    // Key up.
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
-            EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
-    ASSERT_EQ(KEY_HOME, args.scanCode);
-    ASSERT_EQ(AMETA_NONE, args.metaState);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
-    ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreNotDown_DoesNotSynthesizeKeyUp) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    // Key down.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Key up.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Reset.  Since no keys still down, should not synthesize any key ups.
-    mapper->reset();
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-}
-
-TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreDown_SynthesizesKeyUps) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    // Metakey down.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Key down.
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
-            EV_KEY, KEY_A, AKEYCODE_A, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Reset.  Since two keys are still down, should synthesize two key ups in reverse order.
-    mapper->reset();
-
-    FakeInputDispatcher::NotifyKeyArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(AKEYCODE_A, args.keyCode);
-    ASSERT_EQ(KEY_A, args.scanCode);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
-    ASSERT_EQ(uint32_t(0), args.policyFlags);
-    ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(AKEYCODE_SHIFT_LEFT, args.keyCode);
-    ASSERT_EQ(KEY_LEFTSHIFT, args.scanCode);
-    ASSERT_EQ(AMETA_NONE, args.metaState);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
-    ASSERT_EQ(uint32_t(0), args.policyFlags);
-    ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime);
-
-    // And that's it.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    // Initial metastate.
-    ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
-
-    // Metakey down.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0);
-    FakeInputDispatcher::NotifyKeyArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
-    ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
-
-    // Key down.
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
-            EV_KEY, KEY_A, AKEYCODE_A, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
-
-    // Key up.
-    process(mapper, ARBITRARY_TIME + 2, DEVICE_ID,
-            EV_KEY, KEY_A, AKEYCODE_A, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
-
-    // Metakey up.
-    process(mapper, ARBITRARY_TIME + 3, DEVICE_ID,
-            EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AMETA_NONE, args.metaState);
-    ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
-    ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_90);
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
-}
-
-TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addConfigurationProperty("keyboard.orientationAware", "1");
-    addMapperAndConfigure(mapper);
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_0);
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_90);
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN));
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_180);
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_LEFT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_UP));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT));
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_270);
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_DOWN));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_LEFT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_UP));
-
-    // Special case: if orientation changes while key is down, we still emit the same keycode
-    // in the key up as we did in the key down.
-    FakeInputDispatcher::NotifyKeyArgs args;
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_270);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
-    ASSERT_EQ(KEY_UP, args.scanCode);
-    ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_180);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(KEY_UP, args.scanCode);
-    ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
-}
-
-TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 1);
-    ASSERT_EQ(1, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-
-    mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 0);
-    ASSERT_EQ(0, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-}
-
-TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 1);
-    ASSERT_EQ(1, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-
-    mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 0);
-    ASSERT_EQ(0, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-}
-
-TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    mFakeEventHub->addKey(DEVICE_ID, KEY_A, AKEYCODE_A, 0);
-
-    const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
-    uint8_t flags[2] = { 0, 0 };
-    ASSERT_TRUE(mapper->markSupportedKeyCodes(AINPUT_SOURCE_ANY, 1, keyCodes, flags));
-    ASSERT_TRUE(flags[0]);
-    ASSERT_FALSE(flags[1]);
-}
-
-TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
-    mFakeEventHub->addLed(DEVICE_ID, LED_CAPSL, true /*initially on*/);
-    mFakeEventHub->addLed(DEVICE_ID, LED_NUML, false /*initially off*/);
-    mFakeEventHub->addLed(DEVICE_ID, LED_SCROLLL, false /*initially off*/);
-
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    // Initialization should have turned all of the lights off.
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-
-    // Toggle caps lock on.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0);
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-    ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper->getMetaState());
-
-    // Toggle num lock on.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0, 0);
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-    ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper->getMetaState());
-
-    // Toggle caps lock off.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0);
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-    ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper->getMetaState());
-
-    // Toggle scroll lock on.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0, 0);
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-    ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper->getMetaState());
-
-    // Toggle num lock off.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0, 0);
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-    ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper->getMetaState());
-
-    // Toggle scroll lock off.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0, 0);
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-    ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
-}
-
-
-// --- TrackballInputMapperTest ---
-
-class TrackballInputMapperTest : public InputMapperTest {
-protected:
-    static const int32_t TRACKBALL_MOVEMENT_THRESHOLD;
-
-    void testMotionRotation(TrackballInputMapper* mapper,
-            int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY);
-};
-
-const int32_t TrackballInputMapperTest::TRACKBALL_MOVEMENT_THRESHOLD = 6;
-
-void TrackballInputMapperTest::testMotionRotation(TrackballInputMapper* mapper,
-        int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY) {
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, originalX, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, originalY, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            float(rotatedX) / TRACKBALL_MOVEMENT_THRESHOLD,
-            float(rotatedY) / TRACKBALL_MOVEMENT_THRESHOLD,
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(TrackballInputMapperTest, GetSources) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, mapper->getSources());
-}
-
-TEST_F(TrackballInputMapperTest, PopulateDeviceInfo) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    InputDeviceInfo info;
-    mapper->populateDeviceInfo(&info);
-
-    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_X,
-            -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
-    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_Y,
-            -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
-}
-
-TEST_F(TrackballInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaState) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Button press.
-    // Mostly testing non x/y behavior here so we don't need to check again elsewhere.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source);
-    ASSERT_EQ(uint32_t(0), args.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
-    ASSERT_EQ(0, args.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(0, args.edgeFlags);
-    ASSERT_EQ(uint32_t(1), args.pointerCount);
-    ASSERT_EQ(0, args.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-    ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
-    ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
-    // Button release.  Should have same down time.
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source);
-    ASSERT_EQ(uint32_t(0), args.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(0, args.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(0, args.edgeFlags);
-    ASSERT_EQ(uint32_t(1), args.pointerCount);
-    ASSERT_EQ(0, args.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-    ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
-    ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(TrackballInputMapperTest, Process_ShouldHandleIndependentXYUpdates) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Motion in X but not Y.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            1.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
-    // Motion in Y but not X.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
-    ASSERT_NEAR(0.0f, args.pointerCoords[0].x, EPSILON);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(TrackballInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Button press without following sync.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
-    // Button release without following sync.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(TrackballInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Combined X, Y and Button.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            1.0f / TRACKBALL_MOVEMENT_THRESHOLD, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD,
-            1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
-    // Move X, Y a bit while pressed.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 2, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD,
-            1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
-    // Release Button.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(TrackballInputMapperTest, Reset_WhenButtonIsNotDown_ShouldNotSynthesizeButtonUp) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Button press.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-
-    // Button release.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-
-    // Reset.  Should not synthesize button up since button is not pressed.
-    mapper->reset();
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(TrackballInputMapperTest, Reset_WhenButtonIsDown_ShouldSynthesizeButtonUp) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Button press.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-
-    // Reset.  Should synthesize button up.
-    mapper->reset();
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(TrackballInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMotions) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_90);
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1,  0,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1,  1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0,  1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1,  1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1,  0, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0, -1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1, -1,  1));
-}
-
-TEST_F(TrackballInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addConfigurationProperty("trackball.orientationAware", "1");
-    addMapperAndConfigure(mapper);
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_0);
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1,  0,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1,  1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0,  1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1,  1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1,  0, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0, -1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1, -1,  1));
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_90);
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1,  1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1,  1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0,  0, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1, -1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1, -1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0,  0,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1,  1,  1));
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_180);
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1,  0, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1, -1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0, -1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1, -1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1,  0,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1,  1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0,  1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1,  1, -1));
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_270);
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1, -1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1, -1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0,  0,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1,  1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1,  1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1,  1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0,  0, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1, -1, -1));
-}
-
-
-// --- TouchInputMapperTest ---
-
-class TouchInputMapperTest : public InputMapperTest {
-protected:
-    static const int32_t RAW_X_MIN;
-    static const int32_t RAW_X_MAX;
-    static const int32_t RAW_Y_MIN;
-    static const int32_t RAW_Y_MAX;
-    static const int32_t RAW_TOUCH_MIN;
-    static const int32_t RAW_TOUCH_MAX;
-    static const int32_t RAW_TOOL_MIN;
-    static const int32_t RAW_TOOL_MAX;
-    static const int32_t RAW_PRESSURE_MIN;
-    static const int32_t RAW_PRESSURE_MAX;
-    static const int32_t RAW_ORIENTATION_MIN;
-    static const int32_t RAW_ORIENTATION_MAX;
-    static const int32_t RAW_ID_MIN;
-    static const int32_t RAW_ID_MAX;
-    static const float X_PRECISION;
-    static const float Y_PRECISION;
-
-    static const VirtualKeyDefinition VIRTUAL_KEYS[2];
-
-    enum Axes {
-        POSITION = 1 << 0,
-        TOUCH = 1 << 1,
-        TOOL = 1 << 2,
-        PRESSURE = 1 << 3,
-        ORIENTATION = 1 << 4,
-        MINOR = 1 << 5,
-        ID = 1 << 6,
-    };
-
-    void prepareDisplay(int32_t orientation);
-    void prepareVirtualKeys();
-    int32_t toRawX(float displayX);
-    int32_t toRawY(float displayY);
-    float toDisplayX(int32_t rawX);
-    float toDisplayY(int32_t rawY);
-};
-
-const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
-const int32_t TouchInputMapperTest::RAW_X_MAX = 1020;
-const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
-const int32_t TouchInputMapperTest::RAW_Y_MAX = 1010;
-const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
-const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
-const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = RAW_TOUCH_MIN;
-const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = RAW_TOUCH_MAX;
-const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
-const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
-const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
-const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN) / DISPLAY_WIDTH;
-const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN) / DISPLAY_HEIGHT;
-
-const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
-        { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
-        { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
-};
-
-void TouchInputMapperTest::prepareDisplay(int32_t orientation) {
-    mFakePolicy->setDisplayInfo(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation);
-}
-
-void TouchInputMapperTest::prepareVirtualKeys() {
-    mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[0]);
-    mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[1]);
-    mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, AKEYCODE_HOME, POLICY_FLAG_WAKE);
-    mFakeEventHub->addKey(DEVICE_ID, KEY_MENU, AKEYCODE_MENU, POLICY_FLAG_WAKE);
-}
-
-int32_t TouchInputMapperTest::toRawX(float displayX) {
-    return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN) / DISPLAY_WIDTH + RAW_X_MIN);
-}
-
-int32_t TouchInputMapperTest::toRawY(float displayY) {
-    return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN) / DISPLAY_HEIGHT + RAW_Y_MIN);
-}
-
-float TouchInputMapperTest::toDisplayX(int32_t rawX) {
-    return float(rawX - RAW_X_MIN) * DISPLAY_WIDTH / (RAW_X_MAX - RAW_X_MIN);
-}
-
-float TouchInputMapperTest::toDisplayY(int32_t rawY) {
-    return float(rawY - RAW_Y_MIN) * DISPLAY_HEIGHT / (RAW_Y_MAX - RAW_Y_MIN);
-}
-
-
-// --- SingleTouchInputMapperTest ---
-
-class SingleTouchInputMapperTest : public TouchInputMapperTest {
-protected:
-    void prepareAxes(int axes);
-
-    void processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
-    void processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
-    void processUp(SingleTouchInputMapper* mappery);
-    void processPressure(SingleTouchInputMapper* mapper, int32_t pressure);
-    void processToolMajor(SingleTouchInputMapper* mapper, int32_t toolMajor);
-    void processSync(SingleTouchInputMapper* mapper);
-};
-
-void SingleTouchInputMapperTest::prepareAxes(int axes) {
-    if (axes & POSITION) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
-    }
-    if (axes & PRESSURE) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_PRESSURE, RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
-    }
-    if (axes & TOOL) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
-    }
-}
-
-void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, 0, x, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, 0, y, 0);
-}
-
-void SingleTouchInputMapperTest::processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, 0, x, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, 0, y, 0);
-}
-
-void SingleTouchInputMapperTest::processUp(SingleTouchInputMapper* mapper) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0, 0, 0);
-}
-
-void SingleTouchInputMapperTest::processPressure(
-        SingleTouchInputMapper* mapper, int32_t pressure) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_PRESSURE, 0, pressure, 0);
-}
-
-void SingleTouchInputMapperTest::processToolMajor(
-        SingleTouchInputMapper* mapper, int32_t toolMajor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TOOL_WIDTH, 0, toolMajor, 0);
-}
-
-void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper* mapper) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-}
-
-
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareAxes(POSITION);
-    addConfigurationProperty("touch.deviceType", "touchPad");
-    addMapperAndConfigure(mapper);
-
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
-}
-
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareAxes(POSITION);
-    addConfigurationProperty("touch.deviceType", "touchScreen");
-    addMapperAndConfigure(mapper);
-
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper->getSources());
-}
-
-TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    // Unknown key.
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-
-    // Virtual key is down.
-    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
-    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
-    processDown(mapper, x, y);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
-
-    // Virtual key is up.
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    ASSERT_EQ(AKEY_STATE_UP, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
-}
-
-TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    // Unknown key.
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-
-    // Virtual key is down.
-    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
-    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
-    processDown(mapper, x, y);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
-
-    // Virtual key is up.
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    ASSERT_EQ(AKEY_STATE_UP, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
-}
-
-TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    const int32_t keys[2] = { AKEYCODE_HOME, AKEYCODE_A };
-    uint8_t flags[2] = { 0, 0 };
-    ASSERT_TRUE(mapper->markSupportedKeyCodes(AINPUT_SOURCE_ANY, 2, keys, flags));
-    ASSERT_TRUE(flags[0]);
-    ASSERT_FALSE(flags[1]);
-}
-
-TEST_F(SingleTouchInputMapperTest, Reset_WhenVirtualKeysAreDown_SendsUp) {
-    // Note: Ideally we should send cancels but the implementation is more straightforward
-    // with up and this will only happen if a device is forcibly removed.
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    // Press virtual key.
-    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
-    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
-    processDown(mapper, x, y);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Reset.  Since key is down, synthesize key up.
-    mapper->reset();
-
-    FakeInputDispatcher::NotifyKeyArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    //ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
-    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
-    ASSERT_EQ(KEY_HOME, args.scanCode);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(SingleTouchInputMapperTest, Reset_WhenNothingIsPressed_NothingMuchHappens) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    // Press virtual key.
-    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
-    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
-    processDown(mapper, x, y);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Release virtual key.
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Reset.  Since no key is down, nothing happens.
-    mapper->reset();
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyKeyArgs args;
-
-    // Press virtual key.
-    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
-    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
-    processDown(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
-    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
-    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
-    ASSERT_EQ(KEY_HOME, args.scanCode);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
-    // Release virtual key.
-    processUp(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
-    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
-    ASSERT_EQ(KEY_HOME, args.scanCode);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
-    // Should not have sent any motions.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyKeyArgs keyArgs;
-
-    // Press virtual key.
-    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
-    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
-    processDown(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&keyArgs));
-    ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
-    ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
-    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
-    ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
-    ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
-    ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
-
-    // Move out of bounds.  This should generate a cancel and a pointer down since we moved
-    // into the display area.
-    y -= 100;
-    processMove(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&keyArgs));
-    ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
-    ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
-            | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
-    ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
-    ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
-    ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
-
-    FakeInputDispatcher::NotifyMotionArgs motionArgs;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Keep moving out of bounds.  Should generate a pointer move.
-    y -= 50;
-    processMove(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Release out of bounds.  Should generate a pointer up.
-    processUp(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Should not have sent any more keys or motions.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyMotionArgs motionArgs;
-
-    // Initially go down out of bounds.
-    int32_t x = -10;
-    int32_t y = -10;
-    processDown(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-
-    // Move into the display area.  Should generate a pointer down.
-    x = 50;
-    y = 75;
-    processMove(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Release.  Should generate a pointer up.
-    processUp(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Should not have sent any more keys or motions.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyMotionArgs motionArgs;
-
-    // Down.
-    int32_t x = 100;
-    int32_t y = 125;
-    processDown(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Move.
-    x += 50;
-    y += 75;
-    processMove(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Up.
-    processUp(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Should not have sent any more keys or motions.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotateMotions) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareAxes(POSITION);
-    addConfigurationProperty("touch.orientationAware", "0");
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Rotation 90.
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_90);
-    processDown(mapper, toRawX(50), toRawY(75));
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NEAR(50, args.pointerCoords[0].x, 1);
-    ASSERT_NEAR(75, args.pointerCoords[0].y, 1);
-
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareAxes(POSITION);
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Rotation 0.
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    processDown(mapper, toRawX(50), toRawY(75));
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NEAR(50, args.pointerCoords[0].x, 1);
-    ASSERT_NEAR(75, args.pointerCoords[0].y, 1);
-
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-
-    // Rotation 90.
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_90);
-    processDown(mapper, toRawX(50), toRawY(75));
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NEAR(75, args.pointerCoords[0].x, 1);
-    ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].y, 1);
-
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-
-    // Rotation 180.
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_180);
-    processDown(mapper, toRawX(50), toRawY(75));
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].x, 1);
-    ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].y, 1);
-
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-
-    // Rotation 270.
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_270);
-    processDown(mapper, toRawX(50), toRawY(75));
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].x, 1);
-    ASSERT_NEAR(50, args.pointerCoords[0].y, 1);
-
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION | PRESSURE | TOOL);
-    addMapperAndConfigure(mapper);
-
-    // These calculations are based on the input device calibration documentation.
-    int32_t rawX = 100;
-    int32_t rawY = 200;
-    int32_t rawPressure = 10;
-    int32_t rawToolMajor = 12;
-
-    float x = toDisplayX(rawX);
-    float y = toDisplayY(rawY);
-    float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
-    float size = float(rawToolMajor) / RAW_TOOL_MAX;
-    float tool = min(DISPLAY_WIDTH, DISPLAY_HEIGHT) * size;
-    float touch = min(tool * pressure, tool);
-
-    processDown(mapper, rawX, rawY);
-    processPressure(mapper, rawPressure);
-    processToolMajor(mapper, rawToolMajor);
-    processSync(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            x, y, pressure, size, touch, touch, tool, tool, 0));
-}
-
-
-// --- MultiTouchInputMapperTest ---
-
-class MultiTouchInputMapperTest : public TouchInputMapperTest {
-protected:
-    void prepareAxes(int axes);
-
-    void processPosition(MultiTouchInputMapper* mapper, int32_t x, int32_t y);
-    void processTouchMajor(MultiTouchInputMapper* mapper, int32_t touchMajor);
-    void processTouchMinor(MultiTouchInputMapper* mapper, int32_t touchMinor);
-    void processToolMajor(MultiTouchInputMapper* mapper, int32_t toolMajor);
-    void processToolMinor(MultiTouchInputMapper* mapper, int32_t toolMinor);
-    void processOrientation(MultiTouchInputMapper* mapper, int32_t orientation);
-    void processPressure(MultiTouchInputMapper* mapper, int32_t pressure);
-    void processId(MultiTouchInputMapper* mapper, int32_t id);
-    void processMTSync(MultiTouchInputMapper* mapper);
-    void processSync(MultiTouchInputMapper* mapper);
-};
-
-void MultiTouchInputMapperTest::prepareAxes(int axes) {
-    if (axes & POSITION) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
-    }
-    if (axes & TOUCH) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
-        if (axes & MINOR) {
-            mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MINOR,
-                    RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
-        }
-    }
-    if (axes & TOOL) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
-        if (axes & MINOR) {
-            mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MINOR,
-                    RAW_TOOL_MAX, RAW_TOOL_MAX, 0, 0);
-        }
-    }
-    if (axes & ORIENTATION) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_ORIENTATION,
-                RAW_ORIENTATION_MIN, RAW_ORIENTATION_MAX, 0, 0);
-    }
-    if (axes & PRESSURE) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_PRESSURE,
-                RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
-    }
-    if (axes & ID) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TRACKING_ID,
-                RAW_ID_MIN, RAW_ID_MAX, 0, 0);
-    }
-}
-
-void MultiTouchInputMapperTest::processPosition(
-        MultiTouchInputMapper* mapper, int32_t x, int32_t y) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_X, 0, x, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_Y, 0, y, 0);
-}
-
-void MultiTouchInputMapperTest::processTouchMajor(
-        MultiTouchInputMapper* mapper, int32_t touchMajor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MAJOR, 0, touchMajor, 0);
-}
-
-void MultiTouchInputMapperTest::processTouchMinor(
-        MultiTouchInputMapper* mapper, int32_t touchMinor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MINOR, 0, touchMinor, 0);
-}
-
-void MultiTouchInputMapperTest::processToolMajor(
-        MultiTouchInputMapper* mapper, int32_t toolMajor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MAJOR, 0, toolMajor, 0);
-}
-
-void MultiTouchInputMapperTest::processToolMinor(
-        MultiTouchInputMapper* mapper, int32_t toolMinor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MINOR, 0, toolMinor, 0);
-}
-
-void MultiTouchInputMapperTest::processOrientation(
-        MultiTouchInputMapper* mapper, int32_t orientation) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_ORIENTATION, 0, orientation, 0);
-}
-
-void MultiTouchInputMapperTest::processPressure(
-        MultiTouchInputMapper* mapper, int32_t pressure) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_PRESSURE, 0, pressure, 0);
-}
-
-void MultiTouchInputMapperTest::processId(
-        MultiTouchInputMapper* mapper, int32_t id) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TRACKING_ID, 0, id, 0);
-}
-
-void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper* mapper) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_MT_REPORT, 0, 0, 0);
-}
-
-void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper* mapper) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-}
-
-
-TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyMotionArgs motionArgs;
-
-    // Two fingers down at once.
-    int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
-    processPosition(mapper, x1, y1);
-    processMTSync(mapper);
-    processPosition(mapper, x2, y2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_EQ(1, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Move.
-    x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
-    processPosition(mapper, x1, y1);
-    processMTSync(mapper);
-    processPosition(mapper, x2, y2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_EQ(1, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // First finger up.
-    x2 += 15; y2 -= 20;
-    processPosition(mapper, x2, y2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_EQ(1, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Move.
-    x2 += 20; y2 -= 25;
-    processPosition(mapper, x2, y2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // New finger down.
-    int32_t x3 = 700, y3 = 300;
-    processPosition(mapper, x2, y2);
-    processMTSync(mapper);
-    processPosition(mapper, x3, y3);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_EQ(1, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Second finger up.
-    x3 += 30; y3 -= 20;
-    processPosition(mapper, x3, y3);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_EQ(1, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Last finger up.
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Should not have sent any more keys or motions.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION | ID);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyMotionArgs motionArgs;
-
-    // Two fingers down at once.
-    int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
-    processPosition(mapper, x1, y1);
-    processId(mapper, 1);
-    processMTSync(mapper);
-    processPosition(mapper, x2, y2);
-    processId(mapper, 2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerIds[0]);
-    ASSERT_EQ(2, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
-    // Move.
-    x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
-    processPosition(mapper, x1, y1);
-    processId(mapper, 1);
-    processMTSync(mapper);
-    processPosition(mapper, x2, y2);
-    processId(mapper, 2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerIds[0]);
-    ASSERT_EQ(2, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
-    // First finger up.
-    x2 += 15; y2 -= 20;
-    processPosition(mapper, x2, y2);
-    processId(mapper, 2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerIds[0]);
-    ASSERT_EQ(2, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(2, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
-    // Move.
-    x2 += 20; y2 -= 25;
-    processPosition(mapper, x2, y2);
-    processId(mapper, 2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(2, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
-    // New finger down.
-    int32_t x3 = 700, y3 = 300;
-    processPosition(mapper, x2, y2);
-    processId(mapper, 2);
-    processMTSync(mapper);
-    processPosition(mapper, x3, y3);
-    processId(mapper, 3);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(2, motionArgs.pointerIds[0]);
-    ASSERT_EQ(3, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-
-    // Second finger up.
-    x3 += 30; y3 -= 20;
-    processPosition(mapper, x3, y3);
-    processId(mapper, 3);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(2, motionArgs.pointerIds[0]);
-    ASSERT_EQ(3, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(3, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-
-    // Last finger up.
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(3, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-
-    // Should not have sent any more keys or motions.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR);
-    addMapperAndConfigure(mapper);
-
-    // These calculations are based on the input device calibration documentation.
-    int32_t rawX = 100;
-    int32_t rawY = 200;
-    int32_t rawTouchMajor = 7;
-    int32_t rawTouchMinor = 6;
-    int32_t rawToolMajor = 9;
-    int32_t rawToolMinor = 8;
-    int32_t rawPressure = 11;
-    int32_t rawOrientation = 3;
-    int32_t id = 5;
-
-    float x = toDisplayX(rawX);
-    float y = toDisplayY(rawY);
-    float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
-    float size = avg(rawToolMajor, rawToolMinor) / RAW_TOOL_MAX;
-    float toolMajor = float(min(DISPLAY_WIDTH, DISPLAY_HEIGHT)) * rawToolMajor / RAW_TOOL_MAX;
-    float toolMinor = float(min(DISPLAY_WIDTH, DISPLAY_HEIGHT)) * rawToolMinor / RAW_TOOL_MAX;
-    float touchMajor = min(toolMajor * pressure, toolMajor);
-    float touchMinor = min(toolMinor * pressure, toolMinor);
-    float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
-
-    processPosition(mapper, rawX, rawY);
-    processTouchMajor(mapper, rawTouchMajor);
-    processTouchMinor(mapper, rawTouchMinor);
-    processToolMajor(mapper, rawToolMajor);
-    processToolMinor(mapper, rawToolMinor);
-    processPressure(mapper, rawPressure);
-    processOrientation(mapper, rawOrientation);
-    processId(mapper, id);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(id, args.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, orientation));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION | TOUCH | TOOL | MINOR);
-    addConfigurationProperty("touch.touchSize.calibration", "geometric");
-    addConfigurationProperty("touch.toolSize.calibration", "geometric");
-    addMapperAndConfigure(mapper);
-
-    // These calculations are based on the input device calibration documentation.
-    int32_t rawX = 100;
-    int32_t rawY = 200;
-    int32_t rawTouchMajor = 140;
-    int32_t rawTouchMinor = 120;
-    int32_t rawToolMajor = 180;
-    int32_t rawToolMinor = 160;
-
-    float x = toDisplayX(rawX);
-    float y = toDisplayY(rawY);
-    float pressure = float(rawTouchMajor) / RAW_TOUCH_MAX;
-    float size = avg(rawToolMajor, rawToolMinor) / RAW_TOOL_MAX;
-    float scale = avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN),
-            float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN));
-    float toolMajor = float(rawToolMajor) * scale;
-    float toolMinor = float(rawToolMinor) * scale;
-    float touchMajor = min(float(rawTouchMajor) * scale, toolMajor);
-    float touchMinor = min(float(rawTouchMinor) * scale, toolMinor);
-
-    processPosition(mapper, rawX, rawY);
-    processTouchMajor(mapper, rawTouchMajor);
-    processTouchMinor(mapper, rawTouchMinor);
-    processToolMajor(mapper, rawToolMajor);
-    processToolMinor(mapper, rawToolMinor);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, 0));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_SummedLinearCalibration) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION | TOUCH | TOOL);
-    addConfigurationProperty("touch.touchSize.calibration", "pressure");
-    addConfigurationProperty("touch.toolSize.calibration", "linear");
-    addConfigurationProperty("touch.toolSize.linearScale", "10");
-    addConfigurationProperty("touch.toolSize.linearBias", "160");
-    addConfigurationProperty("touch.toolSize.isSummed", "1");
-    addConfigurationProperty("touch.pressure.calibration", "amplitude");
-    addConfigurationProperty("touch.pressure.source", "touch");
-    addConfigurationProperty("touch.pressure.scale", "0.01");
-    addMapperAndConfigure(mapper);
-
-    // These calculations are based on the input device calibration documentation.
-    // Note: We only provide a single common touch/tool value because the device is assumed
-    //       not to emit separate values for each pointer (isSummed = 1).
-    int32_t rawX = 100;
-    int32_t rawY = 200;
-    int32_t rawX2 = 150;
-    int32_t rawY2 = 250;
-    int32_t rawTouchMajor = 60;
-    int32_t rawToolMajor = 5;
-
-    float x = toDisplayX(rawX);
-    float y = toDisplayY(rawY);
-    float x2 = toDisplayX(rawX2);
-    float y2 = toDisplayY(rawY2);
-    float pressure = float(rawTouchMajor) * 0.01f;
-    float size = float(rawToolMajor) / RAW_TOOL_MAX;
-    float tool = (float(rawToolMajor) * 10.0f + 160.0f) / 2;
-    float touch = min(tool * pressure, tool);
-
-    processPosition(mapper, rawX, rawY);
-    processTouchMajor(mapper, rawTouchMajor);
-    processToolMajor(mapper, rawToolMajor);
-    processMTSync(mapper);
-    processPosition(mapper, rawX2, rawY2);
-    processTouchMajor(mapper, rawTouchMajor);
-    processToolMajor(mapper, rawToolMajor);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            args.action);
-    ASSERT_EQ(size_t(2), args.pointerCount);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            x, y, pressure, size, touch, touch, tool, tool, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
-            x2, y2, pressure, size, touch, touch, tool, tool, 0));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_AreaCalibration) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION | TOUCH | TOOL);
-    addConfigurationProperty("touch.touchSize.calibration", "pressure");
-    addConfigurationProperty("touch.toolSize.calibration", "area");
-    addConfigurationProperty("touch.toolSize.areaScale", "22");
-    addConfigurationProperty("touch.toolSize.areaBias", "1");
-    addConfigurationProperty("touch.toolSize.linearScale", "9.2");
-    addConfigurationProperty("touch.toolSize.linearBias", "3");
-    addConfigurationProperty("touch.pressure.calibration", "amplitude");
-    addConfigurationProperty("touch.pressure.source", "touch");
-    addConfigurationProperty("touch.pressure.scale", "0.01");
-    addMapperAndConfigure(mapper);
-
-    // These calculations are based on the input device calibration documentation.
-    int32_t rawX = 100;
-    int32_t rawY = 200;
-    int32_t rawTouchMajor = 60;
-    int32_t rawToolMajor = 5;
-
-    float x = toDisplayX(rawX);
-    float y = toDisplayY(rawY);
-    float pressure = float(rawTouchMajor) * 0.01f;
-    float size = float(rawToolMajor) / RAW_TOOL_MAX;
-    float tool = sqrtf(float(rawToolMajor) * 22.0f + 1.0f) * 9.2f + 3.0f;
-    float touch = min(tool * pressure, tool);
-
-    processPosition(mapper, rawX, rawY);
-    processTouchMajor(mapper, rawTouchMajor);
-    processToolMajor(mapper, rawToolMajor);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            x, y, pressure, size, touch, touch, tool, tool, 0));
-}
-
-} // namespace android
diff --git a/libs/utils/PropertyMap.cpp b/libs/utils/PropertyMap.cpp
index fd7edec..d472d45 100644
--- a/libs/utils/PropertyMap.cpp
+++ b/libs/utils/PropertyMap.cpp
@@ -109,6 +109,12 @@
     return true;
 }
 
+void PropertyMap::addAll(const PropertyMap* map) {
+    for (size_t i = 0; i < map->mProperties.size(); i++) {
+        mProperties.add(map->mProperties.keyAt(i), map->mProperties.valueAt(i));
+    }
+}
+
 status_t PropertyMap::load(const String8& filename, PropertyMap** outMap) {
     *outMap = NULL;
 
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index f6c55e4..ad9a94f 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -774,6 +774,9 @@
             self->mExitPending = true;
             self->mLock.lock();
             self->mRunning = false;
+            // clear thread ID so that requestExitAndWait() does not exit if
+            // called by a new thread using the same thread ID as this one.
+            self->mThread = thread_id_t(-1);
             self->mThreadExitedCondition.broadcast();
             self->mLock.unlock();
             break;
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 1d9ef65..6a79384 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -85,7 +85,7 @@
 
     private Context mContext;
     private ContentResolver mContentResolver;
-
+    private boolean mVoiceCapable;
 
     /** The UI */
     private VolumePanel mVolumePanel;
@@ -275,6 +275,15 @@
     // in call audio)
     private static final int SCO_STATE_ACTIVE_EXTERNAL = 2;
 
+    // true if boot sequence has been completed
+    private boolean mBootCompleted;
+    // listener for SoundPool sample load completion indication
+    private SoundPoolCallback mSoundPoolCallBack;
+    // thread for SoundPool listener
+    private SoundPoolListenerThread mSoundPoolListenerThread;
+    // message looper for SoundPool listener
+    private Looper mSoundPoolLooper = null;
+
     ///////////////////////////////////////////////////////////////////////////
     // Construction
     ///////////////////////////////////////////////////////////////////////////
@@ -283,6 +292,8 @@
     public AudioService(Context context) {
         mContext = context;
         mContentResolver = context.getContentResolver();
+        mVoiceCapable = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_voice_capable);
 
        // Intialized volume
         MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = SystemProperties.getInt(
@@ -306,7 +317,6 @@
         setRingerModeInt(getRingerMode(), false);
 
         AudioSystem.setErrorCallback(mAudioSystemCallback);
-        loadSoundEffects();
 
         mBluetoothHeadsetDevice = null;
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -866,12 +876,42 @@
      * This method must be called at when sound effects are enabled
      */
     public boolean loadSoundEffects() {
+        int status;
+
         synchronized (mSoundEffectsLock) {
+            if (!mBootCompleted) {
+                Log.w(TAG, "loadSoundEffects() called before boot complete");
+                return false;
+            }
+
             if (mSoundPool != null) {
                 return true;
             }
             mSoundPool = new SoundPool(NUM_SOUNDPOOL_CHANNELS, AudioSystem.STREAM_SYSTEM, 0);
             if (mSoundPool == null) {
+                Log.w(TAG, "loadSoundEffects() could not allocate sound pool");
+                return false;
+            }
+
+            try {
+                mSoundPoolCallBack = null;
+                mSoundPoolListenerThread = new SoundPoolListenerThread();
+                mSoundPoolListenerThread.start();
+                // Wait for mSoundPoolCallBack to be set by the other thread
+                mSoundEffectsLock.wait();
+            } catch (InterruptedException e) {
+                Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
+            }
+
+            if (mSoundPoolCallBack == null) {
+                Log.w(TAG, "loadSoundEffects() could not create SoundPool listener or thread");
+                if (mSoundPoolLooper != null) {
+                    mSoundPoolLooper.quit();
+                    mSoundPoolLooper = null;
+                }
+                mSoundPoolListenerThread = null;
+                mSoundPool.release();
+                mSoundPool = null;
                 return false;
             }
             /*
@@ -889,26 +929,49 @@
              * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
              * this indicates we have a valid sample loaded for this effect.
              */
+
             for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
                 // Do not load sample if this effect uses the MediaPlayer
                 if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
                     continue;
                 }
                 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
-                    String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + SOUND_EFFECT_FILES[SOUND_EFFECT_FILES_MAP[effect][0]];
+                    String filePath = Environment.getRootDirectory()
+                            + SOUND_EFFECTS_PATH
+                            + SOUND_EFFECT_FILES[SOUND_EFFECT_FILES_MAP[effect][0]];
                     int sampleId = mSoundPool.load(filePath, 0);
                     SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
                     poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
                     if (sampleId <= 0) {
                         Log.w(TAG, "Soundpool could not load file: "+filePath);
                     }
+                    mSoundPoolCallBack.setLastSample(sampleId);
                 } else {
                     SOUND_EFFECT_FILES_MAP[effect][1] = poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
                 }
             }
+            // wait for all samples to be loaded
+            try {
+                mSoundEffectsLock.wait();
+                status = mSoundPoolCallBack.status();
+            } catch (java.lang.InterruptedException e) {
+                status = -1;
+            }
+            if (mSoundPoolLooper != null) {
+                mSoundPoolLooper.quit();
+                mSoundPoolLooper = null;
+            }
+            mSoundPoolListenerThread = null;
+            if (status != 0) {
+                Log.w(TAG,
+                        "loadSoundEffects(), Error "
+                                + mSoundPoolCallBack.status()
+                                + " while loading samples");
+                mSoundPool.release();
+                mSoundPool = null;
+            }
         }
-
-        return true;
+        return (status == 0);
     }
 
     /**
@@ -921,6 +984,9 @@
             if (mSoundPool == null) {
                 return;
             }
+
+            mAudioHandler.removeMessages(MSG_PLAY_SOUND_EFFECT);
+
             int[] poolId = new int[SOUND_EFFECT_FILES.length];
             for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.length; fileIdx++) {
                 poolId[fileIdx] = 0;
@@ -936,10 +1002,60 @@
                     poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
                 }
             }
+            mSoundPool.release();
             mSoundPool = null;
         }
     }
 
+    class SoundPoolListenerThread extends Thread {
+        public SoundPoolListenerThread() {
+            super("SoundPoolListenerThread");
+        }
+
+        @Override
+        public void run() {
+
+            Looper.prepare();
+            mSoundPoolLooper = Looper.myLooper();
+
+            synchronized (mSoundEffectsLock) {
+                if (mSoundPool != null) {
+                    mSoundPoolCallBack = new SoundPoolCallback();
+                    mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
+                }
+                mSoundEffectsLock.notify();
+            }
+            Looper.loop();
+        }
+    }
+
+    private final class SoundPoolCallback implements
+            android.media.SoundPool.OnLoadCompleteListener {
+
+        int mStatus;
+        int mLastSample;
+
+        public int status() {
+            return mStatus;
+        }
+
+        public void setLastSample(int sample) {
+            mLastSample = sample;
+        }
+
+        public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
+            synchronized (mSoundEffectsLock) {
+                if (status != 0) {
+                    mStatus = status;
+                }
+                if (sampleId == mLastSample) {
+                    Log.e(TAG, "onLoadComplete last sample loaded");
+                    mSoundEffectsLock.notify();
+                }
+            }
+        }
+    }
+
     /** @see AudioManager#reloadAudioSettings() */
     public void reloadAudioSettings() {
         // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
@@ -1323,8 +1439,15 @@
             // Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC...");
             return AudioSystem.STREAM_MUSIC;
         } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
-            // Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING...");
-            return AudioSystem.STREAM_RING;
+            if (mVoiceCapable) {
+                // Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING..."
+                //        + " b/c USE_DEFAULT_STREAM_TYPE...");
+                return AudioSystem.STREAM_RING;
+            } else {
+                // Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC "
+                //        + " b/c USE_DEFAULT_STREAM_TYPE...");
+                return AudioSystem.STREAM_MUSIC;
+            }
         } else {
             // Log.v(TAG, "getActiveStreamType: Returning suggested type " + suggestedStreamType);
             return suggestedStreamType;
@@ -2121,6 +2244,8 @@
                     mContext.sendStickyBroadcast(newIntent);
                 }
             } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
+                mBootCompleted = true;
+                loadSoundEffects();
                 Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
                 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
                         AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index beac04c..6a3ff7c 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -23,6 +23,7 @@
 import android.media.DecoderCapabilities;
 import android.media.DecoderCapabilities.VideoDecoder;
 import android.media.DecoderCapabilities.AudioDecoder;
+import android.mtp.MtpConstants;
 
 import java.util.HashMap;
 import java.util.Iterator;
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index c92fc23..77e939e 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -29,7 +29,6 @@
 /**
  * MediaMetadataRetriever class provides a unified interface for retrieving
  * frame and meta data from an input media file.
- * {@hide}
  */
 public class MediaMetadataRetriever
 {
@@ -42,35 +41,13 @@
     @SuppressWarnings("unused")
     private int mNativeContext;
  
+    private static final int EMBEDDED_PICTURE_TYPE_ANY = 0xFFFF;
+
     public MediaMetadataRetriever() {
         native_setup();
     }
 
     /**
-     * Call this method before setDataSource() so that the mode becomes
-     * effective for subsequent operations. This method can be called only once
-     * at the beginning if the intended mode of operation for a
-     * MediaMetadataRetriever object remains the same for its whole lifetime,
-     * and thus it is unnecessary to call this method each time setDataSource()
-     * is called. If this is not never called (which is allowed), by default the
-     * intended mode of operation is to both capture frame and retrieve meta
-     * data (i.e., MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY).
-     * Often, this may not be what one wants, since doing this has negative
-     * performance impact on execution time of a call to setDataSource(), since
-     * both types of operations may be time consuming.
-     * 
-     * @param mode The intended mode of operation. Can be any combination of 
-     * MODE_GET_METADATA_ONLY and MODE_CAPTURE_FRAME_ONLY:
-     * 1. MODE_GET_METADATA_ONLY & MODE_CAPTURE_FRAME_ONLY: 
-     *    For neither frame capture nor meta data retrieval
-     * 2. MODE_GET_METADATA_ONLY: For meta data retrieval only
-     * 3. MODE_CAPTURE_FRAME_ONLY: For frame capture only
-     * 4. MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY: 
-     *    For both frame capture and meta data retrieval
-     */
-    public native void setMode(int mode);
-    
-    /**
      * Sets the data source (file pathname) to use. Call this
      * method before the rest of the methods in this class. This method may be
      * time-consuming.
@@ -197,15 +174,15 @@
      * that the implementation considers as representative may be returned.
      *
      * @param option a hint on how the frame is found. Use
-     * {@link OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame
+     * {@link #OPTION_PREVIOUS_SYNC} if one wants to retrieve a sync frame
      * that has a timestamp earlier than or the same as timeUs. Use
-     * {@link OPTION_NEXT_SYNC} if one wants to retrieve a sync frame
+     * {@link #OPTION_NEXT_SYNC} if one wants to retrieve a sync frame
      * that has a timestamp later than or the same as timeUs. Use
-     * {@link OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame
+     * {@link #OPTION_CLOSEST_SYNC} if one wants to retrieve a sync frame
      * that has a timestamp closest to or the same as timeUs. Use
-     * {@link OPTION_CLOSEST} if one wants to retrieve a frame that may
+     * {@link #OPTION_CLOSEST} if one wants to retrieve a frame that may
      * or may not be a sync frame but is closest to or the same as timeUs.
-     * {@link OPTION_CLOSEST} often has larger performance overhead compared
+     * {@link #OPTION_CLOSEST} often has larger performance overhead compared
      * to the other options if there is no sync frame located at timeUs.
      *
      * @return A Bitmap containing a representative video frame, which 
@@ -226,7 +203,7 @@
      * and returns it as a bitmap. This is useful for generating a thumbnail
      * for an input data source. Call this method if one does not care
      * how the frame is found as long as it is close to the given time;
-     * otherwise, please call {@link getFrameAtTime(long, int)}.
+     * otherwise, please call {@link #getFrameAtTime(long, int)}.
      *
      * @param timeUs The time position where the frame will be retrieved.
      * When retrieving the frame at the given time position, there is no
@@ -250,7 +227,7 @@
      * and returns it as a bitmap. This is useful for generating a thumbnail
      * for an input data source. Call this method if one does not
      * care about where the frame is located; otherwise, please call
-     * {@link getFrameAtTime(long)} or {@link getFrameAtTime(long, int)}
+     * {@link #getFrameAtTime(long)} or {@link #getFrameAtTime(long, int)}
      *
      * @return A Bitmap containing a representative video frame, which
      *         can be null, if such a frame cannot be retrieved.
@@ -262,25 +239,21 @@
         return getFrameAtTime(-1, OPTION_CLOSEST_SYNC);
     }
 
-    /**
-     * FIXME
-     * To be removed and replaced by getFrameAt().
-     */
-    public Bitmap captureFrame() {
-        return _getFrameAtTime(-1, OPTION_CLOSEST_SYNC);
-    }
-
     private native Bitmap _getFrameAtTime(long timeUs, int option);
 
     
     /**
      * Call this method after setDataSource(). This method finds the optional
-     * graphic or album art associated (embedded or external url linked) the 
-     * related data source.
+     * graphic or album art associated associated with the data source. If
+     * there are more than one pictures, (any) one of them is returned.
      * 
      * @return null if no such graphic is found.
      */
-    public native byte[] extractAlbumArt();
+    public byte[] getEmbeddedPicture() {
+        return getEmbeddedPicture(EMBEDDED_PICTURE_TYPE_ANY);
+    }
+
+    private native byte[] getEmbeddedPicture(int pictureType);
 
     /**
      * Call it when one is done with the object. This method releases the memory
@@ -301,51 +274,129 @@
         }
     }
 
-    public static final int MODE_GET_METADATA_ONLY  = 0x01;
-    public static final int MODE_CAPTURE_FRAME_ONLY = 0x02;
-
     /**
-     * Option used in method {@link getFrameAtTime(long, int)} to get a
+     * Option used in method {@link #getFrameAtTime(long, int)} to get a
      * frame at a specified location.
      *
      * @see #getFrameAtTime(long, int)
      */
-    /* Do not change these values without updating their counterparts
+    /* Do not change these option values without updating their counterparts
      * in include/media/stagefright/MediaSource.h!
      */
+    /**
+     * This option is used with {@link #getFrameAtTime(long, int)} to retrieve
+     * a sync (or key) frame associated with a data source that is located
+     * right before or at the given time.
+     *
+     * @see #getFrameAtTime(long, int)
+     */
     public static final int OPTION_PREVIOUS_SYNC    = 0x00;
+    /**
+     * This option is used with {@link #getFrameAtTime(long, int)} to retrieve
+     * a sync (or key) frame associated with a data source that is located
+     * right after or at the given time.
+     *
+     * @see #getFrameAtTime(long, int)
+     */
     public static final int OPTION_NEXT_SYNC        = 0x01;
+    /**
+     * This option is used with {@link #getFrameAtTime(long, int)} to retrieve
+     * a sync (or key) frame associated with a data source that is located
+     * closest to (in time) or at the given time.
+     *
+     * @see #getFrameAtTime(long, int)
+     */
     public static final int OPTION_CLOSEST_SYNC     = 0x02;
+    /**
+     * This option is used with {@link #getFrameAtTime(long, int)} to retrieve
+     * a frame (not necessarily a key frame) associated with a data source that
+     * is located closest to or at the given time.
+     *
+     * @see #getFrameAtTime(long, int)
+     */
     public static final int OPTION_CLOSEST          = 0x03;
 
     /*
-     * Do not change these values without updating their counterparts
-     * in include/media/mediametadataretriever.h!
+     * Do not change these metadata key values without updating their
+     * counterparts in include/media/mediametadataretriever.h!
+     */
+    /**
+     * The metadata key to retrieve the numberic string describing the
+     * order of the audio data source on its original recording.
      */
     public static final int METADATA_KEY_CD_TRACK_NUMBER = 0;
+    /**
+     * The metadata key to retrieve the information about the album title
+     * of the data source.
+     */
     public static final int METADATA_KEY_ALBUM           = 1;
+    /**
+     * The metadata key to retrieve the information about the artist of
+     * the data source.
+     */
     public static final int METADATA_KEY_ARTIST          = 2;
+    /**
+     * The metadata key to retrieve the information about the author of
+     * the data source.
+     */
     public static final int METADATA_KEY_AUTHOR          = 3;
+    /**
+     * The metadata key to retrieve the information about the composer of
+     * the data source.
+     */
     public static final int METADATA_KEY_COMPOSER        = 4;
+    /**
+     * The metadata key to retrieve the date when the data source was created
+     * or modified.
+     */
     public static final int METADATA_KEY_DATE            = 5;
+    /**
+     * The metadata key to retrieve the content type or genre of the data
+     * source.
+     */
     public static final int METADATA_KEY_GENRE           = 6;
+    /**
+     * The metadata key to retrieve the data source title.
+     */
     public static final int METADATA_KEY_TITLE           = 7;
+    /**
+     * The metadata key to retrieve the year when the data source was created
+     * or modified.
+     */
     public static final int METADATA_KEY_YEAR            = 8;
+    /**
+     * The metadata key to retrieve the playback duration of the data source.
+     */
     public static final int METADATA_KEY_DURATION        = 9;
+    /**
+     * The metadata key to retrieve the number of tracks, such as audio, video,
+     * text, in the data source, such as a mp4 or 3gpp file.
+     */
     public static final int METADATA_KEY_NUM_TRACKS      = 10;
-    public static final int METADATA_KEY_IS_DRM_CRIPPLED = 11;
-    public static final int METADATA_KEY_CODEC           = 12;
-    public static final int METADATA_KEY_RATING          = 13;
-    public static final int METADATA_KEY_COMMENT         = 14;
-    public static final int METADATA_KEY_COPYRIGHT       = 15;
-    public static final int METADATA_KEY_BIT_RATE        = 16;
-    public static final int METADATA_KEY_FRAME_RATE      = 17;
-    public static final int METADATA_KEY_VIDEO_FORMAT    = 18;
-    public static final int METADATA_KEY_VIDEO_HEIGHT    = 19;
-    public static final int METADATA_KEY_VIDEO_WIDTH     = 20;
-    public static final int METADATA_KEY_WRITER          = 21;
-    public static final int METADATA_KEY_MIMETYPE        = 22;
-    public static final int METADATA_KEY_DISCNUMBER      = 23;
-    public static final int METADATA_KEY_ALBUMARTIST     = 24;
+    /**
+     * The metadata key to retrieve the information of the writer (such as
+     * lyricist) of the data source.
+     */
+    public static final int METADATA_KEY_WRITER          = 11;
+    /**
+     * The metadata key to retrieve the mime type of the data source. Some
+     * example mime types include: "video/mp4", "audio/mp4", "audio/amr-wb",
+     * etc.
+     */
+    public static final int METADATA_KEY_MIMETYPE        = 12;
+    /**
+     * The metadata key to retrieve the information about the performers or
+     * artist associated with the data source.
+     */
+    public static final int METADATA_KEY_ALBUMARTIST     = 13;
+    /**
+     * The metadata key to retrieve the numberic string that describes which
+     * part of a set the audio data source comes from.
+     */
+    public static final int METADATA_KEY_DISC_NUMBER     = 14;
+    /**
+     * The metadata key to retrieve the music album compilation status.
+     */
+    public static final int METADATA_KEY_COMPILATION     = 15;
     // Add more here...
 }
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 01134f2..f61ac0f 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1300,9 +1300,9 @@
                 return;
 
             case MEDIA_INFO:
-                // For PV specific code values (msg.arg2) look in
-                // opencore/pvmi/pvmf/include/pvmf_return_codes.h
-                Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")");
+                if (msg.arg1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
+                    Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")");
+                }
                 if (mOnInfoListener != null) {
                     mOnInfoListener.onInfo(mMediaPlayer, msg.arg1, msg.arg2);
                 }
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 39c4a28..11900d4 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -188,11 +188,12 @@
 
         /** The following formats are audio only .aac or .amr formats **/
         /** @deprecated  Deprecated in favor of AMR_NB */
-        /** TODO: change link when AMR_NB is exposed. Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB */
+        /** Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB */
+        /** AMR NB file format */
         public static final int RAW_AMR = 3;
-        /** @hide AMR NB file format */
+        /** AMR NB file format */
         public static final int AMR_NB = 3;
-        /** @hide AMR WB file format */
+        /** AMR WB file format */
         public static final int AMR_WB = 4;
         /** @hide AAC ADIF file format */
         public static final int AAC_ADIF = 5;
@@ -218,9 +219,9 @@
         public static final int DEFAULT = 0;
         /** AMR (Narrowband) audio codec */
         public static final int AMR_NB = 1;
-        /** @hide AMR (Wideband) audio codec */
+        /** AMR (Wideband) audio codec */
         public static final int AMR_WB = 2;
-        /** @hide AAC audio codec */
+        /** AAC audio codec */
         public static final int AAC = 3;
         /** @hide enhanced AAC audio codec */
         public static final int AAC_PLUS = 4;
@@ -452,8 +453,9 @@
      * the specified audio sampling rate is applicable. The sampling rate really depends
      * on the format for the audio recording, as well as the capabilities of the platform.
      * For instance, the sampling rate supported by AAC audio coding standard ranges
-     * from 8 to 96 kHz. Please consult with the related audio coding standard for the
-     * supported audio sampling rate.
+     * from 8 to 96 kHz, the sampling rate supported by AMRNB is 8kHz, and the sampling
+     * rate supported by AMRWB is 16kHz. Please consult with the related audio coding
+     * standard for the supported audio sampling rate.
      *
      * @param samplingRate the sampling rate for audio in samples per second.
      */
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 63ec6b2..8929393 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -28,6 +28,7 @@
 import android.database.SQLException;
 import android.drm.DrmManagerClient;
 import android.graphics.BitmapFactory;
+import android.mtp.MtpConstants;
 import android.net.Uri;
 import android.os.Environment;
 import android.os.Process;
@@ -291,7 +292,6 @@
     private boolean mProcessPlaylists, mProcessGenres;
     private int mMtpObjectHandle;
 
-    private final String mMediaStoragePath;
     private final String mExternalStoragePath;
 
     // used when scanning the image database so we know whether we have to prune
@@ -364,12 +364,6 @@
 
         setDefaultRingtoneFileNames();
 
-        String mediaStoragePath = SystemProperties.get("ro.media.storage");
-        if (mediaStoragePath != null &&  mediaStoragePath.length() > 0) {
-            mMediaStoragePath = mediaStoragePath;
-        } else {
-            mMediaStoragePath = null;
-        }
         mExternalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();
     }
 
@@ -388,7 +382,7 @@
         String prop = SystemProperties.get("drm.service.enabled");
         return prop != null && prop.equals("true");
     }
-    
+
     private class MyMediaScannerClient implements MediaScannerClient {
 
         private String mArtist;
@@ -406,71 +400,77 @@
         private long mLastModified;
         private long mFileSize;
         private String mWriter;
+        private int mCompilation;
 
-        public FileCacheEntry beginFile(String path, String mimeType, long lastModified, long fileSize) {
-
-            // special case certain file names
-            // I use regionMatches() instead of substring() below
-            // to avoid memory allocation
-            int lastSlash = path.lastIndexOf('/');
-            if (lastSlash >= 0 && lastSlash + 2 < path.length()) {
-                // ignore those ._* files created by MacOS
-                if (path.regionMatches(lastSlash + 1, "._", 0, 2)) {
-                    return null;
-                }
-
-                // ignore album art files created by Windows Media Player:
-                // Folder.jpg, AlbumArtSmall.jpg, AlbumArt_{...}_Large.jpg and AlbumArt_{...}_Small.jpg
-                if (path.regionMatches(true, path.length() - 4, ".jpg", 0, 4)) {
-                    if (path.regionMatches(true, lastSlash + 1, "AlbumArt_{", 0, 10) ||
-                            path.regionMatches(true, lastSlash + 1, "AlbumArt.", 0, 9)) {
-                        return null;
-                    }
-                    int length = path.length() - lastSlash - 1;
-                    if ((length == 17 && path.regionMatches(true, lastSlash + 1, "AlbumArtSmall", 0, 13)) ||
-                            (length == 10 && path.regionMatches(true, lastSlash + 1, "Folder", 0, 6))) {
-                        return null;
-                    }
-                }
-            }
-
+        public FileCacheEntry beginFile(String path, String mimeType, long lastModified,
+                long fileSize, boolean isDirectory) {
             mMimeType = mimeType;
             mFileType = 0;
             mFileSize = fileSize;
 
-            // try mimeType first, if it is specified
-            if (mimeType != null) {
-                mFileType = MediaFile.getFileTypeForMimeType(mimeType);
-            }
-
-            // if mimeType was not specified, compute file type based on file extension.
-            if (mFileType == 0) {
-                MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path);
-                if (mediaFileType != null) {
-                    mFileType = mediaFileType.fileType;
-                    if (mMimeType == null) {
-                        mMimeType = mediaFileType.mimeType;
+            if (!isDirectory) {
+                // special case certain file names
+                // I use regionMatches() instead of substring() below
+                // to avoid memory allocation
+                int lastSlash = path.lastIndexOf('/');
+                if (lastSlash >= 0 && lastSlash + 2 < path.length()) {
+                    // ignore those ._* files created by MacOS
+                    if (path.regionMatches(lastSlash + 1, "._", 0, 2)) {
+                        return null;
                     }
+
+                    // ignore album art files created by Windows Media Player:
+                    // Folder.jpg, AlbumArtSmall.jpg, AlbumArt_{...}_Large.jpg
+                    // and AlbumArt_{...}_Small.jpg
+                    if (path.regionMatches(true, path.length() - 4, ".jpg", 0, 4)) {
+                        if (path.regionMatches(true, lastSlash + 1, "AlbumArt_{", 0, 10) ||
+                                path.regionMatches(true, lastSlash + 1, "AlbumArt.", 0, 9)) {
+                            return null;
+                        }
+                        int length = path.length() - lastSlash - 1;
+                        if ((length == 17 && path.regionMatches(
+                                true, lastSlash + 1, "AlbumArtSmall", 0, 13)) ||
+                                (length == 10
+                                 && path.regionMatches(true, lastSlash + 1, "Folder", 0, 6))) {
+                            return null;
+                        }
+                    }
+                }
+
+                // try mimeType first, if it is specified
+                if (mimeType != null) {
+                    mFileType = MediaFile.getFileTypeForMimeType(mimeType);
+                }
+
+                // if mimeType was not specified, compute file type based on file extension.
+                if (mFileType == 0) {
+                    MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path);
+                    if (mediaFileType != null) {
+                        mFileType = mediaFileType.fileType;
+                        if (mMimeType == null) {
+                            mMimeType = mediaFileType.mimeType;
+                        }
+                    }
+                }
+
+                if (isDrmEnabled() && MediaFile.isDrmFileType(mFileType)) {
+                    mFileType = getFileTypeFromDrm(path);
                 }
             }
 
-            if (isDrmEnabled() && MediaFile.isDrmFileType(mFileType)) {
-                mFileType = getFileTypeFromDrm(path);
-            }
-
             String key = path;
-            if (mMediaStoragePath != null && key.startsWith(mMediaStoragePath)) {
-                // MediaProvider uses external variant of path for _data, so we need to match
-                // against that path instead.
-                key = mExternalStoragePath + key.substring(mMediaStoragePath.length());
-            }
             if (mCaseInsensitivePaths) {
                 key = path.toLowerCase();
             }
             FileCacheEntry entry = mFileCache.get(key);
-            if (entry == null) {
+            // add some slack to avoid a rounding error
+            long delta = (entry != null) ? (lastModified - entry.mLastModified) : 0;
+            boolean wasModified = delta > 1 || delta < -1;
+            if (entry == null || wasModified) {
                 Uri tableUri;
-                if (MediaFile.isVideoFileType(mFileType)) {
+                if (isDirectory) {
+                    tableUri = mFilesUri;
+                } else if (MediaFile.isVideoFileType(mFileType)) {
                     tableUri = mVideoUri;
                 } else if (MediaFile.isImageFileType(mFileType)) {
                     tableUri = mImagesUri;
@@ -479,17 +479,17 @@
                 } else {
                     tableUri = mFilesUri;
                 }
-                entry = new FileCacheEntry(tableUri, 0, path, 0, 0);
-                mFileCache.put(key, entry);
-            }
-            entry.mSeenInFileSystem = true;
-
-            // add some slack to avoid a rounding error
-            long delta = lastModified - entry.mLastModified;
-            if (delta > 1 || delta < -1) {
-                entry.mLastModified = lastModified;
+                if (wasModified) {
+                    entry.mLastModified = lastModified;
+                    entry.mTableUri = tableUri;
+                } else {
+                    entry = new FileCacheEntry(tableUri, 0, path, lastModified,
+                            (isDirectory ? MtpConstants.FORMAT_ASSOCIATION : 0));
+                    mFileCache.put(key, entry);
+                }
                 entry.mLastModifiedChanged = true;
             }
+            entry.mSeenInFileSystem = true;
 
             if (mProcessPlaylists && MediaFile.isPlayListFileType(mFileType)) {
                 mPlayLists.add(entry);
@@ -510,26 +510,24 @@
             mPath = path;
             mLastModified = lastModified;
             mWriter = null;
+            mCompilation = 0;
 
             return entry;
         }
 
-        public void scanFile(String path, long lastModified, long fileSize) {
+        public void scanFile(String path, long lastModified, long fileSize, boolean isDirectory) {
             // This is the callback funtion from native codes.
             // Log.v(TAG, "scanFile: "+path);
-            doScanFile(path, null, lastModified, fileSize, false);
-        }
-
-        public void scanFile(String path, String mimeType, long lastModified, long fileSize) {
-            doScanFile(path, mimeType, lastModified, fileSize, false);
+            doScanFile(path, null, lastModified, fileSize, isDirectory, false);
         }
 
         public Uri doScanFile(String path, String mimeType, long lastModified,
-                long fileSize, boolean scanAlways) {
+                long fileSize, boolean isDirectory, boolean scanAlways) {
             Uri result = null;
 //            long t1 = System.currentTimeMillis();
             try {
-                FileCacheEntry entry = beginFile(path, mimeType, lastModified, fileSize);
+                FileCacheEntry entry = beginFile(path, mimeType, lastModified,
+                        fileSize, isDirectory);
                 // rescan for metadata if file was modified since last scan
                 if (entry != null && (entry.mLastModifiedChanged || scanAlways)) {
                     String lowpath = path.toLowerCase();
@@ -624,6 +622,8 @@
                 mDuration = parseSubstring(value, 0, 0);
             } else if (name.equalsIgnoreCase("writer") || name.startsWith("writer;")) {
                 mWriter = value.trim();
+            } else if (name.equalsIgnoreCase("compilation")) {
+                mCompilation = parseSubstring(value, 0, 0);
             }
         }
 
@@ -674,6 +674,7 @@
                 }
                 map.put(Audio.Media.TRACK, mTrack);
                 map.put(Audio.Media.DURATION, mDuration);
+                map.put(Audio.Media.COMPILATION, mCompilation);
             }
             return map;
         }
@@ -775,7 +776,11 @@
                     values.put(MediaStore.MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, mMtpObjectHandle);
                 }
                 if (tableUri == mFilesUri) {
-                    values.put(Files.FileColumns.FORMAT, MediaFile.getFormatCode(entry.mPath, mMimeType));
+                    int format = entry.mFormat;
+                    if (format == 0) {
+                        format = MediaFile.getFormatCode(entry.mPath, mMimeType);
+                    }
+                    values.put(Files.FileColumns.FORMAT, format);
                 }
                 // new file, insert it
                 result = mMediaProvider.insert(tableUri, values);
@@ -786,6 +791,9 @@
             } else {
                 // updated file
                 result = ContentUris.withAppendedId(tableUri, rowId);
+                // path should never change, and we want to avoid replacing mixed cased paths
+                // with squashed lower case paths
+                values.remove(MediaStore.MediaColumns.DATA);
                 mMediaProvider.update(result, values, null, null);
             }
             if (mProcessGenres && mGenre != null) {
@@ -930,12 +938,6 @@
         }
 
         if (filePath != null) {
-            if (mMediaStoragePath != null && filePath.startsWith(mMediaStoragePath)) {
-                // MediaProvider uses external variant of path for _data, so we need to query
-                // using that path instead.
-                filePath = mExternalStoragePath + filePath.substring(mMediaStoragePath.length());
-            }
-
             // query for only one file
             where = Files.FileColumns.DATA + "=?";
             selectionArgs = new String[] { filePath };
@@ -993,10 +995,6 @@
     private boolean inScanDirectory(String path, String[] directories) {
         for (int i = 0; i < directories.length; i++) {
             String directory = directories[i];
-            if (mExternalStoragePath != null && directory.equals(mMediaStoragePath)) {
-                // database paths use external storage prefix
-                directory = mExternalStoragePath;
-            }
             if (path.startsWith(directory)) {
                 return true;
             }
@@ -1060,8 +1058,7 @@
             boolean fileMissing = false;
 
             if (!entry.mSeenInFileSystem && !MtpConstants.isAbstractObject(entry.mFormat)) {
-                if (entry.mFormat != MtpConstants.FORMAT_ASSOCIATION &&
-                        inScanDirectory(path, directories)) {
+                if (inScanDirectory(path, directories)) {
                     // we didn't see this file in the scan directory.
                     fileMissing = true;
                 } else {
@@ -1180,7 +1177,7 @@
             long lastModifiedSeconds = file.lastModified() / 1000;
 
             // always scan the file, so we can return the content://media Uri for existing files
-            return mClient.doScanFile(path, mimeType, lastModifiedSeconds, file.length(), true);
+            return mClient.doScanFile(path, mimeType, lastModifiedSeconds, file.length(),false, true);
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e);
             return null;
@@ -1205,11 +1202,6 @@
                 prescan(null, true);
 
                 String key = path;
-                if (mMediaStoragePath != null && key.startsWith(mMediaStoragePath)) {
-                    // MediaProvider uses external variant of path for _data, so we need to match
-                    // against that path instead.
-                    key = mExternalStoragePath + key.substring(mMediaStoragePath.length());
-                }
                 if (mCaseInsensitivePaths) {
                     key = path.toLowerCase();
                 }
@@ -1227,7 +1219,8 @@
                 long lastModifiedSeconds = file.lastModified() / 1000;
 
                 // always scan the file, so we can return the content://media Uri for existing files
-                mClient.doScanFile(path, mediaFileType.mimeType, lastModifiedSeconds, file.length(), true);
+                mClient.doScanFile(path, mediaFileType.mimeType, lastModifiedSeconds, file.length(),
+                    (format == MtpConstants.FORMAT_ASSOCIATION), true);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e);
diff --git a/media/java/android/media/MediaScannerClient.java b/media/java/android/media/MediaScannerClient.java
index 258c3b4..ac326ef 100644
--- a/media/java/android/media/MediaScannerClient.java
+++ b/media/java/android/media/MediaScannerClient.java
@@ -21,9 +21,7 @@
  */
 public interface MediaScannerClient
 {    
-    public void scanFile(String path, long lastModified, long fileSize);
-    
-    public void scanFile(String path, String mimeType, long lastModified, long fileSize);
+    public void scanFile(String path, long lastModified, long fileSize, boolean isDirectory);
 
     public void addNoMediaFolder(String path);
 
diff --git a/media/java/android/media/MtpConstants.java b/media/java/android/media/MtpConstants.java
deleted file mode 100644
index b20cbd1..0000000
--- a/media/java/android/media/MtpConstants.java
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * {@hide}
- */
-public final class MtpConstants {
-
-// MTP Data Types
-    public static final int TYPE_UNDEFINED = 0x0000;
-    public static final int TYPE_INT8 = 0x0001;
-    public static final int TYPE_UINT8 = 0x0002;
-    public static final int TYPE_INT16 = 0x0003;
-    public static final int TYPE_UINT16 = 0x0004;
-    public static final int TYPE_INT32 = 0x0005;
-    public static final int TYPE_UINT32 = 0x0006;
-    public static final int TYPE_INT64 = 0x0007;
-    public static final int TYPE_UINT64 = 0x0008;
-    public static final int TYPE_INT128 = 0x0009;
-    public static final int TYPE_UINT128 = 0x000A;
-    public static final int TYPE_AINT8 = 0x4001;
-    public static final int TYPE_AUINT8 = 0x4002;
-    public static final int TYPE_AINT16 = 0x4003;
-    public static final int TYPE_AUINT16 = 0x4004;
-    public static final int TYPE_AINT32 = 0x4005;
-    public static final int TYPE_AUINT32 = 0x4006;
-    public static final int TYPE_AINT64 = 0x4007;
-    public static final int TYPE_AUINT64 = 0x4008;
-    public static final int TYPE_AINT128 = 0x4009;
-    public static final int TYPE_AUINT128 = 0x400A;
-    public static final int TYPE_STR = 0xFFFF;
-
-// MTP Response Codes
-    public static final int RESPONSE_UNDEFINED = 0x2000;
-    public static final int RESPONSE_OK = 0x2001;
-    public static final int RESPONSE_GENERAL_ERROR = 0x2002;
-    public static final int RESPONSE_SESSION_NOT_OPEN = 0x2003;
-    public static final int RESPONSE_INVALID_TRANSACTION_ID = 0x2004;
-    public static final int RESPONSE_OPERATION_NOT_SUPPORTED = 0x2005;
-    public static final int RESPONSE_PARAMETER_NOT_SUPPORTED = 0x2006;
-    public static final int RESPONSE_INCOMPLETE_TRANSFER = 0x2007;
-    public static final int RESPONSE_INVALID_STORAGE_ID = 0x2008;
-    public static final int RESPONSE_INVALID_OBJECT_HANDLE = 0x2009;
-    public static final int RESPONSE_DEVICE_PROP_NOT_SUPPORTED = 0x200A;
-    public static final int RESPONSE_INVALID_OBJECT_FORMAT_CODE = 0x200B;
-    public static final int RESPONSE_STORAGE_FULL = 0x200C;
-    public static final int RESPONSE_OBJECT_WRITE_PROTECTED = 0x200D;
-    public static final int RESPONSE_STORE_READ_ONLY = 0x200E;
-    public static final int RESPONSE_ACCESS_DENIED = 0x200F;
-    public static final int RESPONSE_NO_THUMBNAIL_PRESENT = 0x2010;
-    public static final int RESPONSE_SELF_TEST_FAILED = 0x2011;
-    public static final int RESPONSE_PARTIAL_DELETION = 0x2012;
-    public static final int RESPONSE_STORE_NOT_AVAILABLE = 0x2013;
-    public static final int RESPONSE_SPECIFICATION_BY_FORMAT_UNSUPPORTED = 0x2014;
-    public static final int RESPONSE_NO_VALID_OBJECT_INFO = 0x2015;
-    public static final int RESPONSE_INVALID_CODE_FORMAT = 0x2016;
-    public static final int RESPONSE_UNKNOWN_VENDOR_CODE = 0x2017;
-    public static final int RESPONSE_CAPTURE_ALREADY_TERMINATED = 0x2018;
-    public static final int RESPONSE_DEVICE_BUSY = 0x2019;
-    public static final int RESPONSE_INVALID_PARENT_OBJECT = 0x201A;
-    public static final int RESPONSE_INVALID_DEVICE_PROP_FORMAT = 0x201B;
-    public static final int RESPONSE_INVALID_DEVICE_PROP_VALUE = 0x201C;
-    public static final int RESPONSE_INVALID_PARAMETER = 0x201D;
-    public static final int RESPONSE_SESSION_ALREADY_OPEN = 0x201E;
-    public static final int RESPONSE_TRANSACTION_CANCELLED = 0x201F;
-    public static final int RESPONSE_SPECIFICATION_OF_DESTINATION_UNSUPPORTED = 0x2020;
-    public static final int RESPONSE_INVALID_OBJECT_PROP_CODE = 0xA801;
-    public static final int RESPONSE_INVALID_OBJECT_PROP_FORMAT = 0xA802;
-    public static final int RESPONSE_INVALID_OBJECT_PROP_VALUE = 0xA803;
-    public static final int RESPONSE_INVALID_OBJECT_REFERENCE = 0xA804;
-    public static final int RESPONSE_GROUP_NOT_SUPPORTED = 0xA805;
-    public static final int RESPONSE_INVALID_DATASET = 0xA806;
-    public static final int RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED = 0xA807;
-    public static final int RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED = 0xA808;
-    public static final int RESPONSE_OBJECT_TOO_LARGE = 0xA809;
-    public static final int RESPONSE_OBJECT_PROP_NOT_SUPPORTED = 0xA80A;
-
-    // MTP format codes
-    public static final int FORMAT_UNDEFINED = 0x3000;
-    public static final int FORMAT_ASSOCIATION = 0x3001;
-    public static final int FORMAT_SCRIPT = 0x3002;
-    public static final int FORMAT_EXECUTABLE = 0x3003;
-    public static final int FORMAT_TEXT = 0x3004;
-    public static final int FORMAT_HTML = 0x3005;
-    public static final int FORMAT_DPOF = 0x3006;
-    public static final int FORMAT_AIFF = 0x3007;
-    public static final int FORMAT_WAV = 0x3008;
-    public static final int FORMAT_MP3 = 0x3009;
-    public static final int FORMAT_AVI = 0x300A;
-    public static final int FORMAT_MPEG = 0x300B;
-    public static final int FORMAT_ASF = 0x300C;
-    public static final int FORMAT_DEFINED = 0x3800;
-    public static final int FORMAT_EXIF_JPEG = 0x3801;
-    public static final int FORMAT_TIFF_EP = 0x3802;
-    public static final int FORMAT_FLASHPIX = 0x3803;
-    public static final int FORMAT_BMP = 0x3804;
-    public static final int FORMAT_CIFF = 0x3805;
-    public static final int FORMAT_GIF = 0x3807;
-    public static final int FORMAT_JFIF = 0x3808;
-    public static final int FORMAT_CD = 0x3809;
-    public static final int FORMAT_PICT = 0x380A;
-    public static final int FORMAT_PNG = 0x380B;
-    public static final int FORMAT_TIFF = 0x380D;
-    public static final int FORMAT_TIFF_IT = 0x380E;
-    public static final int FORMAT_JP2 = 0x380F;
-    public static final int FORMAT_JPX = 0x3810;
-    public static final int FORMAT_UNDEFINED_FIRMWARE = 0xB802;
-    public static final int FORMAT_WINDOWS_IMAGE_FORMAT = 0xB881;
-    public static final int FORMAT_UNDEFINED_AUDIO = 0xB900;
-    public static final int FORMAT_WMA = 0xB901;
-    public static final int FORMAT_OGG = 0xB902;
-    public static final int FORMAT_AAC = 0xB903;
-    public static final int FORMAT_AUDIBLE = 0xB904;
-    public static final int FORMAT_FLAC = 0xB906;
-    public static final int FORMAT_UNDEFINED_VIDEO = 0xB980;
-    public static final int FORMAT_WMV = 0xB981;
-    public static final int FORMAT_MP4_CONTAINER = 0xB982;
-    public static final int FORMAT_MP2 = 0xB983;
-    public static final int FORMAT_3GP_CONTAINER = 0xB984;
-    public static final int FORMAT_UNDEFINED_COLLECTION = 0xBA00;
-    public static final int FORMAT_ABSTRACT_MULTIMEDIA_ALBUM = 0xBA01;
-    public static final int FORMAT_ABSTRACT_IMAGE_ALBUM = 0xBA02;
-    public static final int FORMAT_ABSTRACT_AUDIO_ALBUM = 0xBA03;
-    public static final int FORMAT_ABSTRACT_VIDEO_ALBUM = 0xBA04;
-    public static final int FORMAT_ABSTRACT_AV_PLAYLIST = 0xBA05;
-    public static final int FORMAT_ABSTRACT_CONTACT_GROUP = 0xBA06;
-    public static final int FORMAT_ABSTRACT_MESSAGE_FOLDER = 0xBA07;
-    public static final int FORMAT_ABSTRACT_CHAPTERED_PRODUCTION = 0xBA08;
-    public static final int FORMAT_ABSTRACT_AUDIO_PLAYLIST = 0xBA09;
-    public static final int FORMAT_ABSTRACT_VIDEO_PLAYLIST = 0xBA0A;
-    public static final int FORMAT_ABSTRACT_MEDIACAST = 0xBA0B;
-    public static final int FORMAT_WPL_PLAYLIST = 0xBA10;
-    public static final int FORMAT_M3U_PLAYLIST = 0xBA11;
-    public static final int FORMAT_MPL_PLAYLIST = 0xBA12;
-    public static final int FORMAT_ASX_PLAYLIST = 0xBA13;
-    public static final int FORMAT_PLS_PLAYLIST = 0xBA14;
-    public static final int FORMAT_UNDEFINED_DOCUMENT = 0xBA80;
-    public static final int FORMAT_ABSTRACT_DOCUMENT = 0xBA81;
-    public static final int FORMAT_XML_DOCUMENT = 0xBA82;
-    public static final int FORMAT_MS_WORD_DOCUMENT = 0xBA83;
-    public static final int FORMAT_MHT_COMPILED_HTML_DOCUMENT = 0xBA84;
-    public static final int FORMAT_MS_EXCEL_SPREADSHEET = 0xBA85;
-    public static final int FORMAT_MS_POWERPOINT_PRESENTATION = 0xBA86;
-    public static final int FORMAT_UNDEFINED_MESSAGE = 0xBB00;
-    public static final int FORMAT_ABSTRACT_MESSSAGE = 0xBB01;
-    public static final int FORMAT_UNDEFINED_CONTACT = 0xBB80;
-    public static final int FORMAT_ABSTRACT_CONTACT = 0xBB81;
-    public static final int FORMAT_VCARD_2 = 0xBB82;
-
-    public static boolean isAbstractObject(int format) {
-        switch (format) {
-            case FORMAT_ABSTRACT_MULTIMEDIA_ALBUM:
-            case FORMAT_ABSTRACT_IMAGE_ALBUM:
-            case FORMAT_ABSTRACT_AUDIO_ALBUM:
-            case FORMAT_ABSTRACT_VIDEO_ALBUM:
-            case FORMAT_ABSTRACT_AV_PLAYLIST:
-            case FORMAT_ABSTRACT_CONTACT_GROUP:
-            case FORMAT_ABSTRACT_MESSAGE_FOLDER:
-            case FORMAT_ABSTRACT_CHAPTERED_PRODUCTION:
-            case FORMAT_ABSTRACT_AUDIO_PLAYLIST:
-            case FORMAT_ABSTRACT_VIDEO_PLAYLIST:
-            case FORMAT_ABSTRACT_MEDIACAST:
-            case FORMAT_ABSTRACT_DOCUMENT:
-            case FORMAT_ABSTRACT_MESSSAGE:
-            case FORMAT_ABSTRACT_CONTACT:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    // MTP object properties
-    public static final int PROPERTY_STORAGE_ID = 0xDC01;
-    public static final int PROPERTY_OBJECT_FORMAT = 0xDC02;
-    public static final int PROPERTY_PROTECTION_STATUS = 0xDC03;
-    public static final int PROPERTY_OBJECT_SIZE = 0xDC04;
-    public static final int PROPERTY_ASSOCIATION_TYPE = 0xDC05;
-    public static final int PROPERTY_ASSOCIATION_DESC = 0xDC06;
-    public static final int PROPERTY_OBJECT_FILE_NAME = 0xDC07;
-    public static final int PROPERTY_DATE_CREATED = 0xDC08;
-    public static final int PROPERTY_DATE_MODIFIED = 0xDC09;
-    public static final int PROPERTY_KEYWORDS = 0xDC0A;
-    public static final int PROPERTY_PARENT_OBJECT = 0xDC0B;
-    public static final int PROPERTY_ALLOWED_FOLDER_CONTENTS = 0xDC0C;
-    public static final int PROPERTY_HIDDEN = 0xDC0D;
-    public static final int PROPERTY_SYSTEM_OBJECT = 0xDC0E;
-    public static final int PROPERTY_PERSISTENT_UID = 0xDC41;
-    public static final int PROPERTY_SYNC_ID = 0xDC42;
-    public static final int PROPERTY_PROPERTY_BAG = 0xDC43;
-    public static final int PROPERTY_NAME = 0xDC44;
-    public static final int PROPERTY_CREATED_BY = 0xDC45;
-    public static final int PROPERTY_ARTIST = 0xDC46;
-    public static final int PROPERTY_DATE_AUTHORED = 0xDC47;
-    public static final int PROPERTY_DESCRIPTION = 0xDC48;
-    public static final int PROPERTY_URL_REFERENCE = 0xDC49;
-    public static final int PROPERTY_LANGUAGE_LOCALE = 0xDC4A;
-    public static final int PROPERTY_COPYRIGHT_INFORMATION = 0xDC4B;
-    public static final int PROPERTY_SOURCE = 0xDC4C;
-    public static final int PROPERTY_ORIGIN_LOCATION = 0xDC4D;
-    public static final int PROPERTY_DATE_ADDED = 0xDC4E;
-    public static final int PROPERTY_NON_CONSUMABLE = 0xDC4F;
-    public static final int PROPERTY_CORRUPT_UNPLAYABLE = 0xDC50;
-    public static final int PROPERTY_PRODUCER_SERIAL_NUMBER = 0xDC51;
-    public static final int PROPERTY_REPRESENTATIVE_SAMPLE_FORMAT = 0xDC81;
-    public static final int PROPERTY_REPRESENTATIVE_SAMPLE_SIZE = 0xDC82;
-    public static final int PROPERTY_REPRESENTATIVE_SAMPLE_HEIGHT = 0xDC83;
-    public static final int PROPERTY_REPRESENTATIVE_SAMPLE_WIDTH = 0xDC84;
-    public static final int PROPERTY_REPRESENTATIVE_SAMPLE_DURATION = 0xDC85;
-    public static final int PROPERTY_REPRESENTATIVE_SAMPLE_DATA = 0xDC86;
-    public static final int PROPERTY_WIDTH = 0xDC87;
-    public static final int PROPERTY_HEIGHT = 0xDC88;
-    public static final int PROPERTY_DURATION = 0xDC89;
-    public static final int PROPERTY_RATING = 0xDC8A;
-    public static final int PROPERTY_TRACK = 0xDC8B;
-    public static final int PROPERTY_GENRE = 0xDC8C;
-    public static final int PROPERTY_CREDITS = 0xDC8D;
-    public static final int PROPERTY_LYRICS = 0xDC8E;
-    public static final int PROPERTY_SUBSCRIPTION_CONTENT_ID = 0xDC8F;
-    public static final int PROPERTY_PRODUCED_BY = 0xDC90;
-    public static final int PROPERTY_USE_COUNT = 0xDC91;
-    public static final int PROPERTY_SKIP_COUNT = 0xDC92;
-    public static final int PROPERTY_LAST_ACCESSED = 0xDC93;
-    public static final int PROPERTY_PARENTAL_RATING = 0xDC94;
-    public static final int PROPERTY_META_GENRE = 0xDC95;
-    public static final int PROPERTY_COMPOSER = 0xDC96;
-    public static final int PROPERTY_EFFECTIVE_RATING = 0xDC97;
-    public static final int PROPERTY_SUBTITLE = 0xDC98;
-    public static final int PROPERTY_ORIGINAL_RELEASE_DATE = 0xDC99;
-    public static final int PROPERTY_ALBUM_NAME = 0xDC9A;
-    public static final int PROPERTY_ALBUM_ARTIST = 0xDC9B;
-    public static final int PROPERTY_MOOD = 0xDC9C;
-    public static final int PROPERTY_DRM_STATUS = 0xDC9D;
-    public static final int PROPERTY_SUB_DESCRIPTION = 0xDC9E;
-    public static final int PROPERTY_IS_CROPPED = 0xDCD1;
-    public static final int PROPERTY_IS_COLOUR_CORRECTED = 0xDCD2;
-    public static final int PROPERTY_IMAGE_BIT_DEPTH = 0xDCD3;
-    public static final int PROPERTY_F_NUMBER = 0xDCD4;
-    public static final int PROPERTY_EXPOSURE_TIME = 0xDCD5;
-    public static final int PROPERTY_EXPOSURE_INDEX = 0xDCD6;
-    public static final int PROPERTY_TOTAL_BITRATE = 0xDE91;
-    public static final int PROPERTY_BITRATE_TYPE = 0xDE92;
-    public static final int PROPERTY_SAMPLE_RATE = 0xDE93;
-    public static final int PROPERTY_NUMBER_OF_CHANNELS = 0xDE94;
-    public static final int PROPERTY_AUDIO_BIT_DEPTH = 0xDE95;
-    public static final int PROPERTY_SCAN_TYPE = 0xDE97;
-    public static final int PROPERTY_AUDIO_WAVE_CODEC = 0xDE99;
-    public static final int PROPERTY_AUDIO_BITRATE = 0xDE9A;
-    public static final int PROPERTY_VIDEO_FOURCC_CODEC = 0xDE9B;
-    public static final int PROPERTY_VIDEO_BITRATE = 0xDE9C;
-    public static final int PROPERTY_FRAMES_PER_THOUSAND_SECONDS = 0xDE9D;
-    public static final int PROPERTY_KEYFRAME_DISTANCE = 0xDE9E;
-    public static final int PROPERTY_BUFFER_SIZE = 0xDE9F;
-    public static final int PROPERTY_ENCODING_QUALITY = 0xDEA0;
-    public static final int PROPERTY_ENCODING_PROFILE = 0xDEA1;
-    public static final int PROPERTY_DISPLAY_NAME = 0xDCE0;
-    public static final int PROPERTY_BODY_TEXT = 0xDCE1;
-    public static final int PROPERTY_SUBJECT = 0xDCE2;
-    public static final int PROPERTY_PRIORITY = 0xDCE3;
-    public static final int PROPERTY_GIVEN_NAME = 0xDD00;
-    public static final int PROPERTY_MIDDLE_NAMES = 0xDD01;
-    public static final int PROPERTY_FAMILY_NAME = 0xDD02;
-    public static final int PROPERTY_PREFIX = 0xDD03;
-    public static final int PROPERTY_SUFFIX = 0xDD04;
-    public static final int PROPERTY_PHONETIC_GIVEN_NAME = 0xDD05;
-    public static final int PROPERTY_PHONETIC_FAMILY_NAME = 0xDD06;
-    public static final int PROPERTY_EMAIL_PRIMARY = 0xDD07;
-    public static final int PROPERTY_EMAIL_PERSONAL_1 = 0xDD08;
-    public static final int PROPERTY_EMAIL_PERSONAL_2 = 0xDD09;
-    public static final int PROPERTY_EMAIL_BUSINESS_1 = 0xDD0A;
-    public static final int PROPERTY_EMAIL_BUSINESS_2 = 0xDD0B;
-    public static final int PROPERTY_EMAIL_OTHERS = 0xDD0C;
-    public static final int PROPERTY_PHONE_NUMBER_PRIMARY = 0xDD0D;
-    public static final int PROPERTY_PHONE_NUMBER_PERSONAL = 0xDD0E;
-    public static final int PROPERTY_PHONE_NUMBER_PERSONAL_2 = 0xDD0F;
-    public static final int PROPERTY_PHONE_NUMBER_BUSINESS = 0xDD10;
-    public static final int PROPERTY_PHONE_NUMBER_BUSINESS_2 = 0xDD11;
-    public static final int PROPERTY_PHONE_NUMBER_MOBILE= 0xDD12;
-    public static final int PROPERTY_PHONE_NUMBER_MOBILE_2 = 0xDD13;
-    public static final int PROPERTY_FAX_NUMBER_PRIMARY = 0xDD14;
-    public static final int PROPERTY_FAX_NUMBER_PERSONAL= 0xDD15;
-    public static final int PROPERTY_FAX_NUMBER_BUSINESS= 0xDD16;
-    public static final int PROPERTY_PAGER_NUMBER = 0xDD17;
-    public static final int PROPERTY_PHONE_NUMBER_OTHERS= 0xDD18;
-    public static final int PROPERTY_PRIMARY_WEB_ADDRESS= 0xDD19;
-    public static final int PROPERTY_PERSONAL_WEB_ADDRESS = 0xDD1A;
-    public static final int PROPERTY_BUSINESS_WEB_ADDRESS = 0xDD1B;
-    public static final int PROPERTY_INSTANT_MESSANGER_ADDRESS = 0xDD1C;
-    public static final int PROPERTY_INSTANT_MESSANGER_ADDRESS_2 = 0xDD1D;
-    public static final int PROPERTY_INSTANT_MESSANGER_ADDRESS_3 = 0xDD1E;
-    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_FULL = 0xDD1F;
-    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_1 = 0xDD20;
-    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_2 = 0xDD21;
-    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_CITY = 0xDD22;
-    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_REGION = 0xDD23;
-    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE = 0xDD24;
-    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_COUNTRY = 0xDD25;
-    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_FULL = 0xDD26;
-    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_1 = 0xDD27;
-    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_2 = 0xDD28;
-    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_CITY = 0xDD29;
-    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_REGION = 0xDD2A;
-    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE = 0xDD2B;
-    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_COUNTRY = 0xDD2C;
-    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_FULL = 0xDD2D;
-    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_LINE_1 = 0xDD2E;
-    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_LINE_2 = 0xDD2F;
-    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_CITY = 0xDD30;
-    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_REGION = 0xDD31;
-    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_POSTAL_CODE = 0xDD32;
-    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_COUNTRY = 0xDD33;
-    public static final int PROPERTY_ORGANIZATION_NAME = 0xDD34;
-    public static final int PROPERTY_PHONETIC_ORGANIZATION_NAME = 0xDD35;
-    public static final int PROPERTY_ROLE = 0xDD36;
-    public static final int PROPERTY_BIRTHDATE = 0xDD37;
-    public static final int PROPERTY_MESSAGE_TO = 0xDD40;
-    public static final int PROPERTY_MESSAGE_CC = 0xDD41;
-    public static final int PROPERTY_MESSAGE_BCC = 0xDD42;
-    public static final int PROPERTY_MESSAGE_READ = 0xDD43;
-    public static final int PROPERTY_MESSAGE_RECEIVED_TIME = 0xDD44;
-    public static final int PROPERTY_MESSAGE_SENDER = 0xDD45;
-    public static final int PROPERTY_ACTIVITY_BEGIN_TIME = 0xDD50;
-    public static final int PROPERTY_ACTIVITY_END_TIME = 0xDD51;
-    public static final int PROPERTY_ACTIVITY_LOCATION = 0xDD52;
-    public static final int PROPERTY_ACTIVITY_REQUIRED_ATTENDEES = 0xDD54;
-    public static final int PROPERTY_ACTIVITY_OPTIONAL_ATTENDEES = 0xDD55;
-    public static final int PROPERTY_ACTIVITY_RESOURCES = 0xDD56;
-    public static final int PROPERTY_ACTIVITY_ACCEPTED = 0xDD57;
-    public static final int PROPERTY_ACTIVITY_TENTATIVE = 0xDD58;
-    public static final int PROPERTY_ACTIVITY_DECLINED = 0xDD59;
-    public static final int PROPERTY_ACTIVITY_REMAINDER_TIME = 0xDD5A;
-    public static final int PROPERTY_ACTIVITY_OWNER = 0xDD5B;
-    public static final int PROPERTY_ACTIVITY_STATUS = 0xDD5C;
-    public static final int PROPERTY_OWNER = 0xDD5D;
-    public static final int PROPERTY_EDITOR = 0xDD5E;
-    public static final int PROPERTY_WEBMASTER = 0xDD5F;
-    public static final int PROPERTY_URL_SOURCE = 0xDD60;
-    public static final int PROPERTY_URL_DESTINATION = 0xDD61;
-    public static final int PROPERTY_TIME_BOOKMARK = 0xDD62;
-    public static final int PROPERTY_OBJECT_BOOKMARK = 0xDD63;
-    public static final int PROPERTY_BYTE_BOOKMARK = 0xDD64;
-    public static final int PROPERTY_LAST_BUILD_DATE = 0xDD70;
-    public static final int PROPERTY_TIME_TO_LIVE = 0xDD71;
-    public static final int PROPERTY_MEDIA_GUID = 0xDD72;
-
-    // MTP device properties
-    public static final int DEVICE_PROPERTY_UNDEFINED = 0x5000;
-    public static final int DEVICE_PROPERTY_BATTERY_LEVEL = 0x5001;
-    public static final int DEVICE_PROPERTY_FUNCTIONAL_MODE = 0x5002;
-    public static final int DEVICE_PROPERTY_IMAGE_SIZE = 0x5003;
-    public static final int DEVICE_PROPERTY_COMPRESSION_SETTING = 0x5004;
-    public static final int DEVICE_PROPERTY_WHITE_BALANCE = 0x5005;
-    public static final int DEVICE_PROPERTY_RGB_GAIN = 0x5006;
-    public static final int DEVICE_PROPERTY_F_NUMBER = 0x5007;
-    public static final int DEVICE_PROPERTY_FOCAL_LENGTH = 0x5008;
-    public static final int DEVICE_PROPERTY_FOCUS_DISTANCE = 0x5009;
-    public static final int DEVICE_PROPERTY_FOCUS_MODE = 0x500A;
-    public static final int DEVICE_PROPERTY_EXPOSURE_METERING_MODE = 0x500B;
-    public static final int DEVICE_PROPERTY_FLASH_MODE = 0x500C;
-    public static final int DEVICE_PROPERTY_EXPOSURE_TIME = 0x500D;
-    public static final int DEVICE_PROPERTY_EXPOSURE_PROGRAM_MODE = 0x500E;
-    public static final int DEVICE_PROPERTY_EXPOSURE_INDEX = 0x500F;
-    public static final int DEVICE_PROPERTY_EXPOSURE_BIAS_COMPENSATION = 0x5010;
-    public static final int DEVICE_PROPERTY_DATETIME = 0x5011;
-    public static final int DEVICE_PROPERTY_CAPTURE_DELAY = 0x5012;
-    public static final int DEVICE_PROPERTY_STILL_CAPTURE_MODE = 0x5013;
-    public static final int DEVICE_PROPERTY_CONTRAST = 0x5014;
-    public static final int DEVICE_PROPERTY_SHARPNESS = 0x5015;
-    public static final int DEVICE_PROPERTY_DIGITAL_ZOOM = 0x5016;
-    public static final int DEVICE_PROPERTY_EFFECT_MODE = 0x5017;
-    public static final int DEVICE_PROPERTY_BURST_NUMBER= 0x5018;
-    public static final int DEVICE_PROPERTY_BURST_INTERVAL = 0x5019;
-    public static final int DEVICE_PROPERTY_TIMELAPSE_NUMBER = 0x501A;
-    public static final int DEVICE_PROPERTY_TIMELAPSE_INTERVAL = 0x501B;
-    public static final int DEVICE_PROPERTY_FOCUS_METERING_MODE = 0x501C;
-    public static final int DEVICE_PROPERTY_UPLOAD_URL = 0x501D;
-    public static final int DEVICE_PROPERTY_ARTIST = 0x501E;
-    public static final int DEVICE_PROPERTY_COPYRIGHT_INFO = 0x501F;
-    public static final int DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER = 0xD401;
-    public static final int DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME = 0xD402;
-    public static final int DEVICE_PROPERTY_VOLUME = 0xD403;
-    public static final int DEVICE_PROPERTY_SUPPORTED_FORMATS_ORDERED = 0xD404;
-    public static final int DEVICE_PROPERTY_DEVICE_ICON = 0xD405;
-    public static final int DEVICE_PROPERTY_PLAYBACK_RATE = 0xD410;
-    public static final int DEVICE_PROPERTY_PLAYBACK_OBJECT = 0xD411;
-    public static final int DEVICE_PROPERTY_PLAYBACK_CONTAINER_INDEX = 0xD412;
-    public static final int DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO = 0xD406;
-    public static final int DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE = 0xD407;
-
-
-    /**
-     * Object is not protected. It may be modified and deleted, and its properties
-     * may be modified.
-     */
-    public static final int PROTECTION_STATUS_NONE = 0;
-
-    /**
-     * Object can not be modified or deleted and its properties can not be modified.
-     */
-    public static final int PROTECTION_STATUS_READ_ONLY = 0x8001;
-
-    /**
-     * Object can not be modified or deleted but its properties are modifiable.
-     */
-    public static final int PROTECTION_STATUS_READ_ONLY_DATA = 0x8002;
-
-    /**
-     * Object's contents can not be transfered from the device, but the object
-     * may be moved or deleted and its properties may be modified.
-     */
-    public static final int PROTECTION_STATUS_NON_TRANSFERABLE_DATA = 0x8003;
-
-    public static final int ASSOCIATION_TYPE_GENERIC_FOLDER = 0x0001;
-}
diff --git a/media/java/android/media/MtpDatabase.java b/media/java/android/media/MtpDatabase.java
deleted file mode 100644
index db08b27..0000000
--- a/media/java/android/media/MtpDatabase.java
+++ /dev/null
@@ -1,841 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.content.Context;
-import android.content.ContentValues;
-import android.content.IContentProvider;
-import android.content.Intent;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
-import android.os.Environment;
-import android.os.RemoteException;
-import android.provider.MediaStore;
-import android.provider.MediaStore.Audio;
-import android.provider.MediaStore.Files;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.MediaColumns;
-import android.util.Log;
-import android.view.Display;
-import android.view.WindowManager;
-
-import java.io.File;
-import java.util.HashMap;
-
-/**
- * {@hide}
- */
-public class MtpDatabase {
-
-    private static final String TAG = "MtpDatabase";
-
-    private final Context mContext;
-    private final IContentProvider mMediaProvider;
-    private final String mVolumeName;
-    private final Uri mObjectsUri;
-    private final String mMediaStoragePath;
-    private final String mExternalStoragePath;
-
-    // cached property groups for single properties
-    private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByProperty
-            = new HashMap<Integer, MtpPropertyGroup>();
-
-    // cached property groups for all properties for a given format
-    private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByFormat
-            = new HashMap<Integer, MtpPropertyGroup>();
-
-    // true if the database has been modified in the current MTP session
-    private boolean mDatabaseModified;
-
-    // database for writable MTP device properties
-    private SQLiteDatabase mDevicePropDb;
-    private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1;
-
-    // FIXME - this should be passed in via the constructor
-    private final int mStorageID = 0x00010001;
-
-    private static final String[] ID_PROJECTION = new String[] {
-            Files.FileColumns._ID, // 0
-    };
-    private static final String[] PATH_PROJECTION = new String[] {
-            Files.FileColumns._ID, // 0
-            Files.FileColumns.DATA, // 1
-    };
-    private static final String[] PATH_SIZE_FORMAT_PROJECTION = new String[] {
-            Files.FileColumns._ID, // 0
-            Files.FileColumns.DATA, // 1
-            Files.FileColumns.SIZE, // 2
-            Files.FileColumns.FORMAT, // 3
-    };
-    private static final String[] OBJECT_INFO_PROJECTION = new String[] {
-            Files.FileColumns._ID, // 0
-            Files.FileColumns.DATA, // 1
-            Files.FileColumns.FORMAT, // 2
-            Files.FileColumns.PARENT, // 3
-            Files.FileColumns.SIZE, // 4
-            Files.FileColumns.DATE_MODIFIED, // 5
-    };
-    private static final String ID_WHERE = Files.FileColumns._ID + "=?";
-    private static final String PATH_WHERE = Files.FileColumns.DATA + "=?";
-    private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?";
-    private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND "
-                                            + Files.FileColumns.FORMAT + "=?";
-
-    private static final String[] DEVICE_PROPERTY_PROJECTION = new String[] { "_id", "value" };
-    private  static final String DEVICE_PROPERTY_WHERE = "code=?";
-
-    private final MediaScanner mMediaScanner;
-
-    static {
-        System.loadLibrary("media_jni");
-    }
-
-    public MtpDatabase(Context context, String volumeName, String storagePath) {
-        native_setup();
-
-        mContext = context;
-        mMediaProvider = context.getContentResolver().acquireProvider("media");
-        mVolumeName = volumeName;
-        mMediaStoragePath = storagePath;
-        mExternalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();
-        mObjectsUri = Files.getMtpObjectsUri(volumeName);
-        mMediaScanner = new MediaScanner(context);
-        openDevicePropertiesDatabase(context);
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            native_finalize();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private String externalToMediaPath(String path) {
-        // convert external storage path to media path
-        if (path != null && mMediaStoragePath != null
-                && mExternalStoragePath != null
-                && path.startsWith(mExternalStoragePath)) {
-            path = mMediaStoragePath + path.substring(mExternalStoragePath.length());
-        }
-        return path;
-    }
-
-    private void openDevicePropertiesDatabase(Context context) {
-        mDevicePropDb = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null);
-        int version = mDevicePropDb.getVersion();
-
-        // initialize if necessary
-        if (version != DEVICE_PROPERTIES_DATABASE_VERSION) {
-            mDevicePropDb.execSQL("CREATE TABLE properties (" +
-                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
-                    "code INTEGER UNIQUE ON CONFLICT REPLACE," +
-                    "value TEXT" +
-                    ");");
-            mDevicePropDb.execSQL("CREATE INDEX property_index ON properties (code);");
-            mDevicePropDb.setVersion(DEVICE_PROPERTIES_DATABASE_VERSION);
-        }
-    }
-
-    private int beginSendObject(String path, int format, int parent,
-                         int storage, long size, long modified) {
-        // first make sure the object does not exist
-        if (path != null) {
-            Cursor c = null;
-            try {
-                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PATH_WHERE,
-                        new String[] { path }, null);
-                if (c != null && c.getCount() > 0) {
-                    Log.w(TAG, "file already exists in beginSendObject: " + path);
-                    return -1;
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "RemoteException in beginSendObject", e);
-            } finally {
-                if (c != null) {
-                    c.close();
-                }
-            }
-        }
-
-        mDatabaseModified = true;
-        ContentValues values = new ContentValues();
-        values.put(Files.FileColumns.DATA, path);
-        values.put(Files.FileColumns.FORMAT, format);
-        values.put(Files.FileColumns.PARENT, parent);
-        // storage is ignored for now
-        values.put(Files.FileColumns.SIZE, size);
-        values.put(Files.FileColumns.DATE_MODIFIED, modified);
-
-        try {
-            Uri uri = mMediaProvider.insert(mObjectsUri, values);
-            if (uri != null) {
-                return Integer.parseInt(uri.getPathSegments().get(2));
-            } else {
-                return -1;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in beginSendObject", e);
-            return -1;
-        }
-    }
-
-    private void endSendObject(String path, int handle, int format, long actualSize, boolean succeeded) {
-        if (succeeded) {
-            // handle abstract playlists separately
-            // they do not exist in the file system so don't use the media scanner here
-            if (format == MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST) {
-                // extract name from path
-                String name = path;
-                int lastSlash = name.lastIndexOf('/');
-                if (lastSlash >= 0) {
-                    name = name.substring(lastSlash + 1);
-                }
-
-                ContentValues values = new ContentValues(1);
-                values.put(Audio.Playlists.DATA, path);
-                values.put(Audio.Playlists.NAME, name);
-                values.put(Files.FileColumns.FORMAT, format);
-                values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle);
-                try {
-                    Uri uri = mMediaProvider.insert(Audio.Playlists.EXTERNAL_CONTENT_URI, values);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "RemoteException in endSendObject", e);
-                }
-            } else {
-                if (actualSize >= 0) {
-                    // update size if necessary
-                    ContentValues values = new ContentValues();
-                    values.put(Files.FileColumns.SIZE, actualSize);
-                    try {
-                        String[] whereArgs = new String[] {  Integer.toString(handle) };
-                        mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "RemoteException in mMediaProvider.update", e);
-                    }
-                }
-
-                mMediaScanner.scanMtpFile(path, mVolumeName, handle, format);
-            }
-        } else {
-            deleteFile(handle);
-        }
-    }
-
-    private int[] getObjectList(int storageID, int format, int parent) {
-        // we can ignore storageID until we support multiple storages
-        Log.d(TAG, "getObjectList parent: " + parent);
-        Cursor c = null;
-        try {
-            if (format != 0) {
-                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
-                            PARENT_FORMAT_WHERE,
-                            new String[] { Integer.toString(parent), Integer.toString(format) },
-                             null);
-            } else {
-                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
-                            PARENT_WHERE, new String[] { Integer.toString(parent) }, null);
-            }
-            if (c == null) {
-                Log.d(TAG, "null cursor");
-                return null;
-            }
-            int count = c.getCount();
-            if (count > 0) {
-                int[] result = new int[count];
-                for (int i = 0; i < count; i++) {
-                    c.moveToNext();
-                    result[i] = c.getInt(0);
-                }
-                Log.d(TAG, "returning " + result);
-                return result;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getObjectList", e);
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-        return null;
-    }
-
-    private int getNumObjects(int storageID, int format, int parent) {
-        // we can ignore storageID until we support multiple storages
-        Log.d(TAG, "getObjectList parent: " + parent);
-        Cursor c = null;
-        try {
-            if (format != 0) {
-                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
-                            PARENT_FORMAT_WHERE,
-                            new String[] { Integer.toString(parent), Integer.toString(format) },
-                             null);
-            } else {
-                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
-                            PARENT_WHERE, new String[] { Integer.toString(parent) }, null);
-            }
-            if (c != null) {
-                return c.getCount();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getNumObjects", e);
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-        return -1;
-    }
-
-    private int[] getSupportedPlaybackFormats() {
-        return new int[] {
-            // allow transfering arbitrary files
-            MtpConstants.FORMAT_UNDEFINED,
-
-            MtpConstants.FORMAT_ASSOCIATION,
-            MtpConstants.FORMAT_TEXT,
-            MtpConstants.FORMAT_HTML,
-            MtpConstants.FORMAT_WAV,
-            MtpConstants.FORMAT_MP3,
-            MtpConstants.FORMAT_MPEG,
-            MtpConstants.FORMAT_EXIF_JPEG,
-            MtpConstants.FORMAT_TIFF_EP,
-            MtpConstants.FORMAT_GIF,
-            MtpConstants.FORMAT_JFIF,
-            MtpConstants.FORMAT_PNG,
-            MtpConstants.FORMAT_TIFF,
-            MtpConstants.FORMAT_WMA,
-            MtpConstants.FORMAT_OGG,
-            MtpConstants.FORMAT_AAC,
-            MtpConstants.FORMAT_MP4_CONTAINER,
-            MtpConstants.FORMAT_MP2,
-            MtpConstants.FORMAT_3GP_CONTAINER,
-            MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST,
-            MtpConstants.FORMAT_WPL_PLAYLIST,
-            MtpConstants.FORMAT_M3U_PLAYLIST,
-            MtpConstants.FORMAT_PLS_PLAYLIST,
-            MtpConstants.FORMAT_XML_DOCUMENT,
-        };
-    }
-
-    private int[] getSupportedCaptureFormats() {
-        // no capture formats yet
-        return null;
-    }
-
-    static final int[] FILE_PROPERTIES = {
-            // NOTE must match beginning of AUDIO_PROPERTIES, VIDEO_PROPERTIES
-            // and IMAGE_PROPERTIES below
-            MtpConstants.PROPERTY_STORAGE_ID,
-            MtpConstants.PROPERTY_OBJECT_FORMAT,
-            MtpConstants.PROPERTY_PROTECTION_STATUS,
-            MtpConstants.PROPERTY_OBJECT_SIZE,
-            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
-            MtpConstants.PROPERTY_DATE_MODIFIED,
-            MtpConstants.PROPERTY_PARENT_OBJECT,
-            MtpConstants.PROPERTY_PERSISTENT_UID,
-            MtpConstants.PROPERTY_NAME,
-            MtpConstants.PROPERTY_DATE_ADDED,
-    };
-
-    static final int[] AUDIO_PROPERTIES = {
-            // NOTE must match FILE_PROPERTIES above
-            MtpConstants.PROPERTY_STORAGE_ID,
-            MtpConstants.PROPERTY_OBJECT_FORMAT,
-            MtpConstants.PROPERTY_PROTECTION_STATUS,
-            MtpConstants.PROPERTY_OBJECT_SIZE,
-            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
-            MtpConstants.PROPERTY_DATE_MODIFIED,
-            MtpConstants.PROPERTY_PARENT_OBJECT,
-            MtpConstants.PROPERTY_PERSISTENT_UID,
-            MtpConstants.PROPERTY_NAME,
-            MtpConstants.PROPERTY_DISPLAY_NAME,
-            MtpConstants.PROPERTY_DATE_ADDED,
-
-            // audio specific properties
-            MtpConstants.PROPERTY_ARTIST,
-            MtpConstants.PROPERTY_ALBUM_NAME,
-            MtpConstants.PROPERTY_ALBUM_ARTIST,
-            MtpConstants.PROPERTY_TRACK,
-            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
-            MtpConstants.PROPERTY_DURATION,
-            MtpConstants.PROPERTY_GENRE,
-            MtpConstants.PROPERTY_COMPOSER,
-    };
-
-    static final int[] VIDEO_PROPERTIES = {
-            // NOTE must match FILE_PROPERTIES above
-            MtpConstants.PROPERTY_STORAGE_ID,
-            MtpConstants.PROPERTY_OBJECT_FORMAT,
-            MtpConstants.PROPERTY_PROTECTION_STATUS,
-            MtpConstants.PROPERTY_OBJECT_SIZE,
-            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
-            MtpConstants.PROPERTY_DATE_MODIFIED,
-            MtpConstants.PROPERTY_PARENT_OBJECT,
-            MtpConstants.PROPERTY_PERSISTENT_UID,
-            MtpConstants.PROPERTY_NAME,
-            MtpConstants.PROPERTY_DISPLAY_NAME,
-            MtpConstants.PROPERTY_DATE_ADDED,
-
-            // video specific properties
-            MtpConstants.PROPERTY_ARTIST,
-            MtpConstants.PROPERTY_ALBUM_NAME,
-            MtpConstants.PROPERTY_DURATION,
-            MtpConstants.PROPERTY_DESCRIPTION,
-    };
-
-    static final int[] IMAGE_PROPERTIES = {
-            // NOTE must match FILE_PROPERTIES above
-            MtpConstants.PROPERTY_STORAGE_ID,
-            MtpConstants.PROPERTY_OBJECT_FORMAT,
-            MtpConstants.PROPERTY_PROTECTION_STATUS,
-            MtpConstants.PROPERTY_OBJECT_SIZE,
-            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
-            MtpConstants.PROPERTY_DATE_MODIFIED,
-            MtpConstants.PROPERTY_PARENT_OBJECT,
-            MtpConstants.PROPERTY_PERSISTENT_UID,
-            MtpConstants.PROPERTY_NAME,
-            MtpConstants.PROPERTY_DISPLAY_NAME,
-            MtpConstants.PROPERTY_DATE_ADDED,
-
-            // image specific properties
-            MtpConstants.PROPERTY_DESCRIPTION,
-    };
-
-    static final int[] ALL_PROPERTIES = {
-            // NOTE must match FILE_PROPERTIES above
-            MtpConstants.PROPERTY_STORAGE_ID,
-            MtpConstants.PROPERTY_OBJECT_FORMAT,
-            MtpConstants.PROPERTY_PROTECTION_STATUS,
-            MtpConstants.PROPERTY_OBJECT_SIZE,
-            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
-            MtpConstants.PROPERTY_DATE_MODIFIED,
-            MtpConstants.PROPERTY_PARENT_OBJECT,
-            MtpConstants.PROPERTY_PERSISTENT_UID,
-            MtpConstants.PROPERTY_NAME,
-            MtpConstants.PROPERTY_DISPLAY_NAME,
-            MtpConstants.PROPERTY_DATE_ADDED,
-
-            // image specific properties
-            MtpConstants.PROPERTY_DESCRIPTION,
-
-            // audio specific properties
-            MtpConstants.PROPERTY_ARTIST,
-            MtpConstants.PROPERTY_ALBUM_NAME,
-            MtpConstants.PROPERTY_ALBUM_ARTIST,
-            MtpConstants.PROPERTY_TRACK,
-            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
-            MtpConstants.PROPERTY_DURATION,
-            MtpConstants.PROPERTY_GENRE,
-            MtpConstants.PROPERTY_COMPOSER,
-
-            // video specific properties
-            MtpConstants.PROPERTY_ARTIST,
-            MtpConstants.PROPERTY_ALBUM_NAME,
-            MtpConstants.PROPERTY_DURATION,
-            MtpConstants.PROPERTY_DESCRIPTION,
-
-            // image specific properties
-            MtpConstants.PROPERTY_DESCRIPTION,
-    };
-
-    private int[] getSupportedObjectProperties(int format) {
-        switch (format) {
-            case MtpConstants.FORMAT_MP3:
-            case MtpConstants.FORMAT_WAV:
-            case MtpConstants.FORMAT_WMA:
-            case MtpConstants.FORMAT_OGG:
-            case MtpConstants.FORMAT_AAC:
-                return AUDIO_PROPERTIES;
-            case MtpConstants.FORMAT_MPEG:
-            case MtpConstants.FORMAT_3GP_CONTAINER:
-            case MtpConstants.FORMAT_WMV:
-                return VIDEO_PROPERTIES;
-            case MtpConstants.FORMAT_EXIF_JPEG:
-            case MtpConstants.FORMAT_GIF:
-            case MtpConstants.FORMAT_PNG:
-            case MtpConstants.FORMAT_BMP:
-                return IMAGE_PROPERTIES;
-            case 0:
-                return ALL_PROPERTIES;
-            default:
-                return FILE_PROPERTIES;
-        }
-    }
-
-    private int[] getSupportedDeviceProperties() {
-        return new int[] {
-            MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
-            MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
-            MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE,
-        };
-    }
-
-
-    private MtpPropertyList getObjectPropertyList(long handle, int format, long property,
-                        int groupCode, int depth) {
-        // FIXME - implement group support
-        if (groupCode != 0) {
-            return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED);
-        }
-
-        MtpPropertyGroup propertyGroup;
-        if (property == 0xFFFFFFFFL) {
-             propertyGroup = mPropertyGroupsByFormat.get(format);
-             if (propertyGroup == null) {
-                int[] propertyList = getSupportedObjectProperties(format);
-                propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mVolumeName, propertyList);
-                mPropertyGroupsByFormat.put(new Integer(format), propertyGroup);
-            }
-        } else {
-              propertyGroup = mPropertyGroupsByProperty.get(property);
-             if (propertyGroup == null) {
-                int[] propertyList = new int[] { (int)property };
-                propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mVolumeName, propertyList);
-                mPropertyGroupsByProperty.put(new Integer((int)property), propertyGroup);
-            }
-        }
-
-        return propertyGroup.getPropertyList((int)handle, format, depth, mStorageID);
-    }
-
-    private int renameFile(int handle, String newName) {
-        Cursor c = null;
-
-        // first compute current path
-        String path = null;
-        String[] whereArgs = new String[] {  Integer.toString(handle) };
-        try {
-            c = mMediaProvider.query(mObjectsUri, PATH_PROJECTION, ID_WHERE, whereArgs, null);
-            if (c != null && c.moveToNext()) {
-                path = externalToMediaPath(c.getString(1));
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getObjectFilePath", e);
-            return MtpConstants.RESPONSE_GENERAL_ERROR;
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-        if (path == null) {
-            return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
-        }
-
-        // now rename the file.  make sure this succeeds before updating database
-        File oldFile = new File(path);
-        int lastSlash = path.lastIndexOf('/');
-        if (lastSlash <= 1) {
-            return MtpConstants.RESPONSE_GENERAL_ERROR;
-        }
-        String newPath = path.substring(0, lastSlash + 1) + newName;
-        File newFile = new File(newPath);
-        boolean success = oldFile.renameTo(newFile);
-        Log.d(TAG, "renaming "+ path + " to " + newPath + (success ? " succeeded" : " failed"));
-        if (!success) {
-            return MtpConstants.RESPONSE_GENERAL_ERROR;
-        }
-
-        // finally update database
-        ContentValues values = new ContentValues();
-        values.put(Files.FileColumns.DATA, newPath);
-        int updated = 0;
-        try {
-            // note - we are relying on a special case in MediaProvider.update() to update
-            // the paths for all children in the case where this is a directory.
-            updated = mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in mMediaProvider.update", e);
-        }
-        if (updated == 0) {
-            Log.e(TAG, "Unable to update path for " + path + " to " + newPath);
-            // this shouldn't happen, but if it does we need to rename the file to its original name
-            newFile.renameTo(oldFile);
-            return MtpConstants.RESPONSE_GENERAL_ERROR;
-        }
-
-        return MtpConstants.RESPONSE_OK;
-    }
-
-    private int setObjectProperty(int handle, int property,
-                            long intValue, String stringValue) {
-        Log.d(TAG, "setObjectProperty: " + property);
-
-        switch (property) {
-            case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
-                return renameFile(handle, stringValue);
-
-            default:
-                return MtpConstants.RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
-        }
-    }
-
-    private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) {
-        Log.d(TAG, "getDeviceProperty: " + property);
-
-        switch (property) {
-            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
-            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
-                // writable string properties kept in our device property database
-                Cursor c = null;
-                try {
-                    c = mDevicePropDb.query("properties", DEVICE_PROPERTY_PROJECTION,
-                        DEVICE_PROPERTY_WHERE, new String[] {  Integer.toString(property) },
-                        null, null, null);
-
-                    if (c != null && c.moveToNext()) {
-                        String value = c.getString(1);
-                        int length = value.length();
-                        if (length > 255) {
-                            length = 255;
-                        }
-                        value.getChars(0, length, outStringValue, 0);
-                        outStringValue[length] = 0;
-                    } else {
-                        outStringValue[0] = 0;
-                    }
-                    return MtpConstants.RESPONSE_OK;
-                } finally {
-                    if (c != null) {
-                        c.close();
-                    }
-                }
-
-            case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE:
-                // use screen size as max image size
-                Display display = ((WindowManager)mContext.getSystemService(
-                        Context.WINDOW_SERVICE)).getDefaultDisplay();
-                int width = display.getWidth();
-                int height = display.getHeight();
-                String imageSize = Integer.toString(width) + "x" +  Integer.toString(height);
-                imageSize.getChars(0, imageSize.length(), outStringValue, 0);
-                outStringValue[imageSize.length()] = 0;
-                return MtpConstants.RESPONSE_OK;
-
-            default:
-                return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
-        }
-    }
-
-    private int setDeviceProperty(int property, long intValue, String stringValue) {
-        Log.d(TAG, "setDeviceProperty: " + property + " : " + stringValue);
-
-        switch (property) {
-            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
-            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
-                // writable string properties kept in our device property database
-                try {
-                    ContentValues values = new ContentValues();
-                    values.put("code", property);
-                    values.put("value", stringValue);
-                    mDevicePropDb.insert("properties", "code", values);
-                    return MtpConstants.RESPONSE_OK;
-                } catch (Exception e) {
-                    return MtpConstants.RESPONSE_GENERAL_ERROR;
-                }
-        }
-
-        return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
-    }
-
-    private boolean getObjectInfo(int handle, int[] outStorageFormatParent,
-                        char[] outName, long[] outSizeModified) {
-        Log.d(TAG, "getObjectInfo: " + handle);
-        Cursor c = null;
-        try {
-            c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION,
-                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
-            if (c != null && c.moveToNext()) {
-                outStorageFormatParent[0] = mStorageID;
-                outStorageFormatParent[1] = c.getInt(2);
-                outStorageFormatParent[2] = c.getInt(3);
-
-                // extract name from path
-                String path = c.getString(1);
-                int lastSlash = path.lastIndexOf('/');
-                int start = (lastSlash >= 0 ? lastSlash + 1 : 0);
-                int end = path.length();
-                if (end - start > 255) {
-                    end = start + 255;
-                }
-                path.getChars(start, end, outName, 0);
-                outName[end - start] = 0;
-
-                outSizeModified[0] = c.getLong(4);
-                outSizeModified[1] = c.getLong(5);
-                return true;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getObjectInfo", e);
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-        return false;
-    }
-
-    private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLengthFormat) {
-        Log.d(TAG, "getObjectFilePath: " + handle);
-        if (handle == 0) {
-            // special case root directory
-            mMediaStoragePath.getChars(0, mMediaStoragePath.length(), outFilePath, 0);
-            outFilePath[mMediaStoragePath.length()] = 0;
-            outFileLengthFormat[0] = 0;
-            outFileLengthFormat[1] = MtpConstants.FORMAT_ASSOCIATION;
-            return MtpConstants.RESPONSE_OK;
-        }
-        Cursor c = null;
-        try {
-            c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION,
-                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
-            if (c != null && c.moveToNext()) {
-                String path = externalToMediaPath(c.getString(1));
-                path.getChars(0, path.length(), outFilePath, 0);
-                outFilePath[path.length()] = 0;
-                outFileLengthFormat[0] = c.getLong(2);
-                outFileLengthFormat[1] = c.getLong(3);
-                return MtpConstants.RESPONSE_OK;
-            } else {
-                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getObjectFilePath", e);
-            return MtpConstants.RESPONSE_GENERAL_ERROR;
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-    }
-
-    private int deleteFile(int handle) {
-        Log.d(TAG, "deleteFile: " + handle);
-        mDatabaseModified = true;
-        String path = null;
-        int format = 0;
-
-        Cursor c = null;
-        try {
-            c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION,
-                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
-            if (c != null && c.moveToNext()) {
-                // don't convert to media path here, since we will be matching
-                // against paths in the database matching /data/media
-                path = c.getString(1);
-                format = c.getInt(3);
-            } else {
-                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
-            }
-
-            if (path == null || format == 0) {
-                return MtpConstants.RESPONSE_GENERAL_ERROR;
-            }
-
-            if (format == MtpConstants.FORMAT_ASSOCIATION) {
-                // recursive case - delete all children first
-                Uri uri = Files.getMtpObjectsUri(mVolumeName);
-                int count = mMediaProvider.delete(uri, "_data LIKE ?",
-                        new String[] { path + "/%"});
-            }
-
-            Uri uri = Files.getMtpObjectsUri(mVolumeName, handle);
-            if (mMediaProvider.delete(uri, null, null) > 0) {
-                return MtpConstants.RESPONSE_OK;
-            } else {
-                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in deleteFile", e);
-            return MtpConstants.RESPONSE_GENERAL_ERROR;
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-    }
-
-    private int[] getObjectReferences(int handle) {
-        Log.d(TAG, "getObjectReferences for: " + handle);
-        Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
-        Cursor c = null;
-        try {
-            c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null);
-            if (c == null) {
-                return null;
-            }
-            int count = c.getCount();
-            if (count > 0) {
-                int[] result = new int[count];
-                for (int i = 0; i < count; i++) {
-                    c.moveToNext();
-                    result[i] = c.getInt(0);
-                }
-                return result;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in getObjectList", e);
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-        return null;
-    }
-
-    private int setObjectReferences(int handle, int[] references) {
-        mDatabaseModified = true;
-        Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
-        int count = references.length;
-        ContentValues[] valuesList = new ContentValues[count];
-        for (int i = 0; i < count; i++) {
-            ContentValues values = new ContentValues();
-            values.put(Files.FileColumns._ID, references[i]);
-            valuesList[i] = values;
-        }
-        try {
-            if (mMediaProvider.bulkInsert(uri, valuesList) > 0) {
-                return MtpConstants.RESPONSE_OK;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in setObjectReferences", e);
-        }
-        return MtpConstants.RESPONSE_GENERAL_ERROR;
-    }
-
-    private void sessionStarted() {
-        Log.d(TAG, "sessionStarted");
-        mDatabaseModified = false;
-    }
-
-    private void sessionEnded() {
-        Log.d(TAG, "sessionEnded");
-        if (mDatabaseModified) {
-            Log.d(TAG, "sending ACTION_MTP_SESSION_END");
-            mContext.sendBroadcast(new Intent(MediaStore.ACTION_MTP_SESSION_END));
-            mDatabaseModified = false;
-        }
-    }
-
-    // used by the JNI code
-    private int mNativeContext;
-
-    private native final void native_setup();
-    private native final void native_finalize();
-}
diff --git a/media/java/android/media/MtpPropertyGroup.java b/media/java/android/media/MtpPropertyGroup.java
deleted file mode 100644
index bb733e2..0000000
--- a/media/java/android/media/MtpPropertyGroup.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.content.IContentProvider;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.provider.MediaStore;
-import android.provider.MediaStore.Audio;
-import android.provider.MediaStore.Files;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.MediaColumns;
-import android.util.Log;
-
-import java.util.ArrayList;
-
-class MtpPropertyGroup {
-
-    private static final String TAG = "MtpPropertyGroup";
-
-    private class Property {
-        // MTP property code
-        int     code;
-        // MTP data type
-        int     type;
-        // column index for our query
-        int     column;
-
-        Property(int code, int type, int column) {
-            this.code = code;
-            this.type = type;
-            this.column = column;
-        }
-    }
-
-    private final MtpDatabase mDatabase;
-    private final IContentProvider mProvider;
-    private final String mVolumeName;
-    private final Uri mUri;
-
-    // list of all properties in this group
-    private final Property[]    mProperties;
-
-    // list of columns for database query
-    private String[]             mColumns;
-
-    private static final String ID_WHERE = Files.FileColumns._ID + "=?";
-    private static final String ID_FORMAT_WHERE = ID_WHERE + " AND "
-                                            + Files.FileColumns.FORMAT + "=?";
-    private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?";
-    private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND "
-                                            + Files.FileColumns.FORMAT + "=?";
-    // constructs a property group for a list of properties
-    public MtpPropertyGroup(MtpDatabase database, IContentProvider provider, String volume,
-            int[] properties) {
-        mDatabase = database;
-        mProvider = provider;
-        mVolumeName = volume;
-        mUri = Files.getMtpObjectsUri(volume);
-
-        int count = properties.length;
-        ArrayList<String> columns = new ArrayList<String>(count);
-        columns.add(Files.FileColumns._ID);
-
-        mProperties = new Property[count];
-        for (int i = 0; i < count; i++) {
-            mProperties[i] = createProperty(properties[i], columns);
-        }
-        count = columns.size();
-        mColumns = new String[count];
-        for (int i = 0; i < count; i++) {
-            mColumns[i] = columns.get(i);
-        }
-    }
-
-    private Property createProperty(int code, ArrayList<String> columns) {
-        String column = null;
-        int type;
-
-         switch (code) {
-            case MtpConstants.PROPERTY_STORAGE_ID:
-                // no query needed until we support multiple storage units
-                type = MtpConstants.TYPE_UINT32;
-                break;
-             case MtpConstants.PROPERTY_OBJECT_FORMAT:
-                column = Files.FileColumns.FORMAT;
-                type = MtpConstants.TYPE_UINT16;
-                break;
-            case MtpConstants.PROPERTY_PROTECTION_STATUS:
-                // protection status is always 0
-                type = MtpConstants.TYPE_UINT16;
-                break;
-            case MtpConstants.PROPERTY_OBJECT_SIZE:
-                column = Files.FileColumns.SIZE;
-                type = MtpConstants.TYPE_UINT64;
-                break;
-            case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
-                column = Files.FileColumns.DATA;
-                type = MtpConstants.TYPE_STR;
-                break;
-            case MtpConstants.PROPERTY_NAME:
-                column = MediaColumns.TITLE;
-                type = MtpConstants.TYPE_STR;
-                break;
-            case MtpConstants.PROPERTY_DATE_MODIFIED:
-                column = Files.FileColumns.DATE_MODIFIED;
-                type = MtpConstants.TYPE_STR;
-                break;
-            case MtpConstants.PROPERTY_DATE_ADDED:
-                column = Files.FileColumns.DATE_ADDED;
-                type = MtpConstants.TYPE_STR;
-                break;
-            case MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE:
-                column = Audio.AudioColumns.YEAR;
-                type = MtpConstants.TYPE_STR;
-                break;
-            case MtpConstants.PROPERTY_PARENT_OBJECT:
-                column = Files.FileColumns.PARENT;
-                type = MtpConstants.TYPE_UINT32;
-                break;
-            case MtpConstants.PROPERTY_PERSISTENT_UID:
-                // PUID is concatenation of storageID and object handle
-                type = MtpConstants.TYPE_UINT128;
-                break;
-            case MtpConstants.PROPERTY_DURATION:
-                column = Audio.AudioColumns.DURATION;
-                type = MtpConstants.TYPE_UINT32;
-                break;
-            case MtpConstants.PROPERTY_TRACK:
-                column = Audio.AudioColumns.TRACK;
-                type = MtpConstants.TYPE_UINT16;
-                break;
-            case MtpConstants.PROPERTY_DISPLAY_NAME:
-                column = MediaColumns.DISPLAY_NAME;
-                type = MtpConstants.TYPE_STR;
-                break;
-            case MtpConstants.PROPERTY_ARTIST:
-                type = MtpConstants.TYPE_STR;
-                break;
-            case MtpConstants.PROPERTY_ALBUM_NAME:
-                type = MtpConstants.TYPE_STR;
-                break;
-            case MtpConstants.PROPERTY_ALBUM_ARTIST:
-                column = Audio.AudioColumns.ALBUM_ARTIST;
-                type = MtpConstants.TYPE_STR;
-                break;
-            case MtpConstants.PROPERTY_GENRE:
-                // genre requires a special query
-                type = MtpConstants.TYPE_STR;
-                break;
-            case MtpConstants.PROPERTY_COMPOSER:
-                column = Audio.AudioColumns.COMPOSER;
-                type = MtpConstants.TYPE_STR;
-                break;
-            case MtpConstants.PROPERTY_DESCRIPTION:
-                column = Images.ImageColumns.DESCRIPTION;
-                type = MtpConstants.TYPE_STR;
-                break;
-            default:
-                type = MtpConstants.TYPE_UNDEFINED;
-                Log.e(TAG, "unsupported property " + code);
-                break;
-        }
-
-        if (column != null) {
-            columns.add(column);
-            return new Property(code, type, columns.size() - 1);
-        } else {
-            return new Property(code, type, -1);
-        }
-    }
-
-   private String queryString(int id, String column) {
-        Cursor c = null;
-        try {
-            // for now we are only reading properties from the "objects" table
-            c = mProvider.query(mUri,
-                            new String [] { Files.FileColumns._ID, column },
-                            ID_WHERE, new String[] { Integer.toString(id) }, null);
-            if (c != null && c.moveToNext()) {
-                return c.getString(1);
-            } else {
-                return "";
-            }
-        } catch (Exception e) {
-            return null;
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-    }
-
-    private String queryAudio(int id, String column) {
-        Cursor c = null;
-        try {
-            c = mProvider.query(Audio.Media.getContentUri(mVolumeName),
-                            new String [] { Files.FileColumns._ID, column },
-                            ID_WHERE, new String[] { Integer.toString(id) }, null);
-            if (c != null && c.moveToNext()) {
-                return c.getString(1);
-            } else {
-                return "";
-            }
-        } catch (Exception e) {
-            return null;
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-    }
-
-    private String queryGenre(int id) {
-        Cursor c = null;
-        try {
-            Uri uri = Audio.Genres.getContentUriForAudioId(mVolumeName, id);
-            c = mProvider.query(uri,
-                            new String [] { Files.FileColumns._ID, Audio.GenresColumns.NAME },
-                            null, null, null);
-            if (c != null && c.moveToNext()) {
-                return c.getString(1);
-            } else {
-                return "";
-            }
-        } catch (Exception e) {
-            Log.e(TAG, "queryGenre exception", e);
-            return null;
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-    }
-
-    private Long queryLong(int id, String column) {
-        Cursor c = null;
-        try {
-            // for now we are only reading properties from the "objects" table
-            c = mProvider.query(mUri,
-                            new String [] { Files.FileColumns._ID, column },
-                            ID_WHERE, new String[] { Integer.toString(id) }, null);
-            if (c != null && c.moveToNext()) {
-                return new Long(c.getLong(1));
-            }
-        } catch (Exception e) {
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-        return null;
-    }
-
-    private static String nameFromPath(String path) {
-        // extract name from full path
-        int start = 0;
-        int lastSlash = path.lastIndexOf('/');
-        if (lastSlash >= 0) {
-            start = lastSlash + 1;
-        }
-        int end = path.length();
-        if (end - start > 255) {
-            end = start + 255;
-        }
-        return path.substring(start, end);
-    }
-
-    MtpPropertyList getPropertyList(int handle, int format, int depth, int storageID) {
-        Log.d(TAG, "getPropertyList handle: " + handle + " format: " + format + " depth: " + depth);
-        if (depth > 1) {
-            // we only support depth 0 and 1
-            // depth 0: single object, depth 1: immediate children
-            return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED);
-        }
-
-        String where;
-        String[] whereArgs;
-        if (format == 0) {
-            whereArgs = new String[] { Integer.toString(handle) };
-            if (depth == 1) {
-                where = PARENT_WHERE;
-            } else {
-                where = ID_WHERE;
-            }
-        } else {
-            whereArgs = new String[] { Integer.toString(handle), Integer.toString(format) };
-            if (depth == 1) {
-                where = PARENT_FORMAT_WHERE;
-            } else {
-                where = ID_FORMAT_WHERE;
-            }
-        }
-
-        Cursor c = null;
-        try {
-            // don't query if not necessary
-            if (depth > 0 || mColumns.length > 1) {
-                c = mProvider.query(mUri, mColumns, where, whereArgs, null);
-                if (c == null) {
-                    return new MtpPropertyList(0, MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
-                }
-            }
-
-            int count = (c == null ? 1 : c.getCount());
-            MtpPropertyList result = new MtpPropertyList(count * mProperties.length,
-                    MtpConstants.RESPONSE_OK);
-
-            // iterate over all objects in the query
-            for (int objectIndex = 0; objectIndex < count; objectIndex++) {
-                if (c != null) {
-                    c.moveToNext();
-                }
-                if (depth == 1) {
-                    handle = (int)c.getLong(0);
-                }
-
-                // iterate over all properties in the query for the given object
-                for (int propertyIndex = 0; propertyIndex < mProperties.length; propertyIndex++) {
-                    Property property = mProperties[propertyIndex];
-                    int propertyCode = property.code;
-                    int column = property.column;
-
-                    // handle some special cases
-                    switch (propertyCode) {
-                        case MtpConstants.PROPERTY_STORAGE_ID:
-                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT32,
-                                    storageID);
-                            break;
-                        case MtpConstants.PROPERTY_PROTECTION_STATUS:
-                            // protection status is always 0
-                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT16, 0);
-                            break;
-                        case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
-                            // special case - need to extract file name from full path
-                            String value = c.getString(column);
-                            if (value != null) {
-                                result.append(handle, propertyCode, nameFromPath(value));
-                            } else {
-                                result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
-                            }
-                            break;
-                        case MtpConstants.PROPERTY_NAME:
-                            // first try title
-                            String name = c.getString(column);
-                            // then try name
-                            if (name == null) {
-                                name = queryString(handle, Audio.PlaylistsColumns.NAME);
-                            }
-                            // if title and name fail, extract name from full path
-                            if (name == null) {
-                                name = queryString(handle, Files.FileColumns.DATA);
-                                if (name != null) {
-                                    name = nameFromPath(name);
-                                }
-                            }
-                            if (name != null) {
-                                result.append(handle, propertyCode, name);
-                            } else {
-                                result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
-                            }
-                            break;
-                        case MtpConstants.PROPERTY_DATE_MODIFIED:
-                        case MtpConstants.PROPERTY_DATE_ADDED:
-                            // convert from seconds to DateTime
-                            result.append(handle, propertyCode, format_date_time(c.getInt(column)));
-                            break;
-                        case MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE:
-                            // release date is stored internally as just the year
-                            int year = c.getInt(column);
-                            String dateTime = Integer.toString(year) + "0101T000000";
-                            result.append(handle, propertyCode, dateTime);
-                            break;
-                        case MtpConstants.PROPERTY_PERSISTENT_UID:
-                            // PUID is concatenation of storageID and object handle
-                            long puid = storageID;
-                            puid <<= 32;
-                            puid += handle;
-                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT128, puid);
-                            break;
-                        case MtpConstants.PROPERTY_TRACK:
-                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT16,
-                                        c.getInt(column) % 1000);
-                            break;
-                        case MtpConstants.PROPERTY_ARTIST:
-                            result.append(handle, propertyCode,
-                                    queryAudio(handle, Audio.AudioColumns.ARTIST));
-                            break;
-                        case MtpConstants.PROPERTY_ALBUM_NAME:
-                            result.append(handle, propertyCode,
-                                    queryAudio(handle, Audio.AudioColumns.ALBUM));
-                            break;
-                        case MtpConstants.PROPERTY_GENRE:
-                            String genre = queryGenre(handle);
-                            if (genre != null) {
-                                result.append(handle, propertyCode, genre);
-                            } else {
-                                result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
-                            }
-                            break;
-                        default:
-                            if (property.type == MtpConstants.TYPE_STR) {
-                                result.append(handle, propertyCode, c.getString(column));
-                            } else if (property.type == MtpConstants.TYPE_UNDEFINED) {
-                                result.append(handle, propertyCode, property.type, 0);
-                            } else {
-                                result.append(handle, propertyCode, property.type,
-                                        c.getLong(column));
-                            }
-                            break;
-                    }
-                }
-            }
-
-            return result;
-        } catch (RemoteException e) {
-            return new MtpPropertyList(0, MtpConstants.RESPONSE_GENERAL_ERROR);
-        } finally {
-            if (c != null) {
-                c.close();
-            }
-        }
-        // impossible to get here, so no return statement
-    }
-
-    private native String format_date_time(long seconds);
-}
diff --git a/media/java/android/media/MtpPropertyList.java b/media/java/android/media/MtpPropertyList.java
deleted file mode 100644
index d3f0b34..0000000
--- a/media/java/android/media/MtpPropertyList.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * Encapsulates the ObjectPropList dataset used by the GetObjectPropList command.
- * The fields of this class are read by JNI code in android_media_MtpDatabase.cpp
- */
-
-class MtpPropertyList {
-
-    // number of results returned
-    private int             mCount;
-    // maximum number of results
-    private final int       mMaxCount;
-    // result code for GetObjectPropList
-    public int              mResult;
-    // list of object handles (first field in quadruplet)
-    public final int[]      mObjectHandles;
-    // list of object propery codes (second field in quadruplet)
-    public final int[]      mPropertyCodes;
-    // list of data type codes (third field in quadruplet)
-    public final int[]     mDataTypes;
-    // list of long int property values (fourth field in quadruplet, when value is integer type)
-    public long[]     mLongValues;
-    // list of long int property values (fourth field in quadruplet, when value is string type)
-    public String[]   mStringValues;
-
-    // constructor only called from MtpDatabase
-    public MtpPropertyList(int maxCount, int result) {
-        mMaxCount = maxCount;
-        mResult = result;
-        mObjectHandles = new int[maxCount];
-        mPropertyCodes = new int[maxCount];
-        mDataTypes = new int[maxCount];
-        // mLongValues and mStringValues are created lazily since both might not be necessary
-    }
-
-    public void append(int handle, int property, int type, long value) {
-        int index = mCount++;
-        if (mLongValues == null) {
-            mLongValues = new long[mMaxCount];
-        }
-        mObjectHandles[index] = handle;
-        mPropertyCodes[index] = property;
-        mDataTypes[index] = type;
-        mLongValues[index] = value;
-    }
-
-    public void append(int handle, int property, String value) {
-        int index = mCount++;
-        if (mStringValues == null) {
-            mStringValues = new String[mMaxCount];
-        }
-        mObjectHandles[index] = handle;
-        mPropertyCodes[index] = property;
-        mDataTypes[index] = MtpConstants.TYPE_STR;
-        mStringValues[index] = value;
-    }
-
-    public void setResult(int result) {
-        mResult = result;
-    }
-}
diff --git a/media/java/android/media/MtpServer.java b/media/java/android/media/MtpServer.java
deleted file mode 100644
index 76e6f3f..0000000
--- a/media/java/android/media/MtpServer.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.util.Log;
-
-/**
- * Java wrapper for MTP/PTP support as USB responder.
- * {@hide}
- */
-public class MtpServer {
-
-    private static final String TAG = "MtpServer";
-
-    static {
-        System.loadLibrary("media_jni");
-    }
-
-    public MtpServer(MtpDatabase database, String storagePath, long reserveSpace) {
-        native_setup(database, storagePath, reserveSpace);
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            native_finalize();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    public void start() {
-        native_start();
-    }
-
-    public void stop() {
-        native_stop();
-    }
-
-    public void sendObjectAdded(int handle) {
-        native_send_object_added(handle);
-    }
-
-    public void sendObjectRemoved(int handle) {
-        native_send_object_removed(handle);
-    }
-
-    public void setPtpMode(boolean usePtp) {
-        native_set_ptp_mode(usePtp);
-    }
-
-    // used by the JNI code
-    private int mNativeContext;
-
-    private native final void native_setup(MtpDatabase database, String storagePath,
-            long reserveSpace);
-    private native final void native_finalize();
-    private native final void native_start();
-    private native final void native_stop();
-    private native final void native_send_object_added(int handle);
-    private native final void native_send_object_removed(int handle);
-    private native final void native_set_ptp_mode(boolean usePtp);
-}
diff --git a/media/java/android/media/PtpClient.java b/media/java/android/media/PtpClient.java
deleted file mode 100644
index 2e40635..0000000
--- a/media/java/android/media/PtpClient.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.util.Log;
-
-/**
- * {@hide}
- */
-public class PtpClient {
-
-    private static final String TAG = "PtpClient";
-
-    private final Listener mListener;
-
-    static {
-        System.loadLibrary("media_jni");
-    }
-
-    public PtpClient(Listener listener) {
-        native_setup();
-        if (listener == null) {
-            throw new NullPointerException("PtpClient: listener is null");
-        }
-        mListener = listener;
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            native_finalize();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    public boolean start() {
-        return native_start();
-    }
-
-    public void stop() {
-        native_stop();
-    }
-
-    public boolean deleteObject(int deviceID, long objectID) {
-        return native_delete_object(deviceID, objectID);
-    }
-
-    public long getParent(int deviceID, long objectID) {
-        return native_get_parent(deviceID, objectID);
-    }
-
-    public long getStorageID(int deviceID, long objectID) {
-        return native_get_storage_id(deviceID, objectID);
-    }
-
-    // Reads a file from device to host to the specified destination.
-    // Returns true if the transfer succeeds.
-    public boolean importFile(int deviceID, long objectID, String destPath) {
-        return native_import_file(deviceID, objectID, destPath);
-    }
-
-    public interface Listener {
-        // called when a new PTP device has been discovered
-        void deviceAdded(int id);
-
-        // called when an PTP device has been removed
-        void deviceRemoved(int id);
-    }
-
-    // called from native code
-    private void deviceAdded(int id) {
-        Log.d(TAG, "deviceAdded " + id);
-        mListener.deviceAdded(id);
-    }
-
-    // called from native code
-    private void deviceRemoved(int id) {
-        Log.d(TAG, "deviceRemoved " + id);
-        mListener.deviceRemoved(id);
-    }
-
-    // used by the JNI code
-    private int mNativeContext;
-
-    private native final void native_setup();
-    private native final void native_finalize();
-    private native boolean native_start();
-    private native void native_stop();
-    private native boolean native_delete_object(int deviceID, long objectID);
-    private native long native_get_parent(int deviceID, long objectID);
-    private native long native_get_storage_id(int deviceID, long objectID);
-    private native boolean native_import_file(int deviceID, long objectID, String destPath);
-}
diff --git a/media/java/android/media/PtpCursor.java b/media/java/android/media/PtpCursor.java
deleted file mode 100644
index bb5b1ec..0000000
--- a/media/java/android/media/PtpCursor.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.database.AbstractWindowedCursor;
-import android.database.CursorWindow;
-import android.provider.Ptp;
-import android.util.Log;
-
-import java.util.HashMap;
-
-/**
-  * Cursor class for PTP content provider
-  * @hide
-  */
-public final class PtpCursor extends AbstractWindowedCursor {
-    static final String TAG = "PtpCursor";
-    static final int NO_COUNT = -1;
-
-    /* constants for queryType */
-    public static final int DEVICE              = 1;
-    public static final int DEVICE_ID           = 2;
-    public static final int STORAGE             = 3;
-    public static final int STORAGE_ID          = 4;
-    public static final int OBJECT              = 5;
-    public static final int OBJECT_ID           = 6;
-    public static final int STORAGE_CHILDREN    = 7;
-    public static final int OBJECT_CHILDREN     = 8;
-    public static final int OBJECT_IMPORT       = 9;
-
-    /** The names of the columns in the projection */
-    private String[] mColumns;
-
-    /** The number of rows in the cursor */
-    private int mCount = NO_COUNT;
-
-
-    public PtpCursor(PtpClient client, int queryType, int deviceID, long storageID, long objectID,
-            String[] projection) {
-        if (client == null) {
-            throw new NullPointerException("client null in PtpCursor constructor");
-        }
-        mColumns = projection;
-
-        HashMap<String, Integer> map;
-        switch (queryType) {
-            case DEVICE:
-            case DEVICE_ID:
-                map = sDeviceProjectionMap;
-                break;
-            case STORAGE:
-            case STORAGE_ID:
-                map = sStorageProjectionMap;
-                break;
-            case OBJECT:
-            case OBJECT_ID:
-            case STORAGE_CHILDREN:
-            case OBJECT_CHILDREN:
-                map = sObjectProjectionMap;
-                break;
-            default:
-                throw new IllegalArgumentException("unknown query type "  + queryType);
-        }
-
-        int[] columns = new int[projection.length];
-        for (int i = 0; i < projection.length; i++) {
-            Integer id = map.get(projection[i]);
-            if (id == null) {
-                throw new IllegalArgumentException("unknown column "  + projection[i]);
-            }
-            columns[i] = id.intValue();
-        }
-        native_setup(client, queryType, deviceID, storageID, objectID, columns);
-    }
-
-    @Override
-    protected void finalize() {
-        try {
-            native_finalize();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    @Override
-    public int getCount() {
-        if (mCount == NO_COUNT) {
-            fillWindow(0);
-        }
-        return mCount;
-    }
-
-    @Override
-    public boolean requery() {
-        Log.d(TAG, "requery");
-        mCount = NO_COUNT;
-        if (mWindow != null) {
-            mWindow.clear();
-        }
-        return super.requery();
-    }
-
-    private void fillWindow(int startPos) {
-        if (mWindow == null) {
-            // If there isn't a window set already it will only be accessed locally
-            mWindow = new CursorWindow(true /* the window is local only */);
-        } else {
-                mWindow.clear();
-        }
-        mWindow.setStartPosition(startPos);
-        mCount = native_fill_window(mWindow, startPos);
-    }
-
-    @Override
-    public String[] getColumnNames() {
-        Log.d(TAG, "getColumnNames returning " + mColumns);
-        return mColumns;
-    }
-
-    /* Device Column IDs */
-     /* These must match the values in PtpCursor.cpp */
-   private static final int DEVICE_ROW_ID          = 1;
-    private static final int DEVICE_MANUFACTURER    = 2;
-    private static final int DEVICE_MODEL           = 3;
-
-    /* Storage Column IDs */
-    /* These must match the values in PtpCursor.cpp */
-    private static final int STORAGE_ROW_ID         = 101;
-    private static final int STORAGE_IDENTIFIER     = 102;
-    private static final int STORAGE_DESCRIPTION    = 103;
-
-    /* Object Column IDs */
-    /* These must match the values in PtpCursor.cpp */
-    private static final int OBJECT_ROW_ID              = 201;
-    private static final int OBJECT_STORAGE_ID          = 202;
-    private static final int OBJECT_FORMAT              = 203;
-    private static final int OBJECT_PROTECTION_STATUS   = 204;
-    private static final int OBJECT_SIZE                = 205;
-    private static final int OBJECT_THUMB_FORMAT        = 206;
-    private static final int OBJECT_THUMB_SIZE          = 207;
-    private static final int OBJECT_THUMB_WIDTH         = 208;
-    private static final int OBJECT_THUMB_HEIGHT        = 209;
-    private static final int OBJECT_IMAGE_WIDTH         = 210;
-    private static final int OBJECT_IMAGE_HEIGHT        = 211;
-    private static final int OBJECT_IMAGE_DEPTH         = 212;
-    private static final int OBJECT_PARENT              = 213;
-    private static final int OBJECT_ASSOCIATION_TYPE    = 214;
-    private static final int OBJECT_ASSOCIATION_DESC    = 215;
-    private static final int OBJECT_SEQUENCE_NUMBER     = 216;
-    private static final int OBJECT_NAME                = 217;
-    private static final int OBJECT_DATE_CREATED        = 218;
-    private static final int OBJECT_DATE_MODIFIED       = 219;
-    private static final int OBJECT_KEYWORDS            = 220;
-    private static final int OBJECT_THUMB               = 221;
-
-    private static HashMap<String, Integer> sDeviceProjectionMap;
-    private static HashMap<String, Integer> sStorageProjectionMap;
-    private static HashMap<String, Integer> sObjectProjectionMap;
-
-    static {
-        sDeviceProjectionMap = new HashMap<String, Integer>();
-        sDeviceProjectionMap.put(Ptp.Device._ID, new Integer(DEVICE_ROW_ID));
-        sDeviceProjectionMap.put(Ptp.Device.MANUFACTURER, new Integer(DEVICE_MANUFACTURER));
-        sDeviceProjectionMap.put(Ptp.Device.MODEL, new Integer(DEVICE_MODEL));
-
-        sStorageProjectionMap = new HashMap<String, Integer>();
-        sStorageProjectionMap.put(Ptp.Storage._ID, new Integer(STORAGE_ROW_ID));
-        sStorageProjectionMap.put(Ptp.Storage.IDENTIFIER, new Integer(STORAGE_IDENTIFIER));
-        sStorageProjectionMap.put(Ptp.Storage.DESCRIPTION, new Integer(STORAGE_DESCRIPTION));
-
-        sObjectProjectionMap = new HashMap<String, Integer>();
-        sObjectProjectionMap.put(Ptp.Object._ID, new Integer(OBJECT_ROW_ID));
-        sObjectProjectionMap.put(Ptp.Object.STORAGE_ID, new Integer(OBJECT_STORAGE_ID));
-        sObjectProjectionMap.put(Ptp.Object.FORMAT, new Integer(OBJECT_FORMAT));
-        sObjectProjectionMap.put(Ptp.Object.PROTECTION_STATUS, new Integer(OBJECT_PROTECTION_STATUS));
-        sObjectProjectionMap.put(Ptp.Object.SIZE, new Integer(OBJECT_SIZE));
-        sObjectProjectionMap.put(Ptp.Object.THUMB_FORMAT, new Integer(OBJECT_THUMB_FORMAT));
-        sObjectProjectionMap.put(Ptp.Object.THUMB_SIZE, new Integer(OBJECT_THUMB_SIZE));
-        sObjectProjectionMap.put(Ptp.Object.THUMB_WIDTH, new Integer(OBJECT_THUMB_WIDTH));
-        sObjectProjectionMap.put(Ptp.Object.THUMB_HEIGHT, new Integer(OBJECT_THUMB_HEIGHT));
-        sObjectProjectionMap.put(Ptp.Object.IMAGE_WIDTH, new Integer(OBJECT_IMAGE_WIDTH));
-        sObjectProjectionMap.put(Ptp.Object.IMAGE_HEIGHT, new Integer(OBJECT_IMAGE_HEIGHT));
-        sObjectProjectionMap.put(Ptp.Object.IMAGE_DEPTH, new Integer(OBJECT_IMAGE_DEPTH));
-        sObjectProjectionMap.put(Ptp.Object.PARENT, new Integer(OBJECT_PARENT));
-        sObjectProjectionMap.put(Ptp.Object.ASSOCIATION_TYPE, new Integer(OBJECT_ASSOCIATION_TYPE));
-        sObjectProjectionMap.put(Ptp.Object.ASSOCIATION_DESC, new Integer(OBJECT_ASSOCIATION_DESC));
-        sObjectProjectionMap.put(Ptp.Object.SEQUENCE_NUMBER, new Integer(OBJECT_SEQUENCE_NUMBER));
-        sObjectProjectionMap.put(Ptp.Object.NAME, new Integer(OBJECT_NAME));
-        sObjectProjectionMap.put(Ptp.Object.DATE_CREATED, new Integer(OBJECT_DATE_CREATED));
-        sObjectProjectionMap.put(Ptp.Object.DATE_MODIFIED, new Integer(OBJECT_DATE_MODIFIED));
-        sObjectProjectionMap.put(Ptp.Object.KEYWORDS, new Integer(OBJECT_KEYWORDS));
-        sObjectProjectionMap.put(Ptp.Object.THUMB, new Integer(OBJECT_THUMB));
-
-        sObjectProjectionMap.put(Ptp.Object.NAME, new Integer(OBJECT_NAME));
-    }
-
-    // used by the JNI code
-    private int mNativeContext;
-
-    private native final void native_setup(PtpClient client, int queryType,
-            int deviceID, long storageID, long objectID, int[] columns);
-    private native final void native_finalize();
-    private native void native_wait_for_event();
-    private native int native_fill_window(CursorWindow window, int startPos);
-}
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 18ce5c1..5e9c018 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -141,17 +141,6 @@
             throw new RuntimeException("Native setup failed");
         }
         mLock = new Object();
-
-        // setup message handler
-        Looper looper;
-        if ((looper = Looper.myLooper()) != null) {
-            mEventHandler = new EventHandler(this, looper);
-        } else if ((looper = Looper.getMainLooper()) != null) {
-            mEventHandler = new EventHandler(this, looper);
-        } else {
-            mEventHandler = null;
-        }
-
     }
 
     /**
@@ -427,6 +416,19 @@
     public void setOnLoadCompleteListener(OnLoadCompleteListener listener)
     {
         synchronized(mLock) {
+            if (listener != null) {
+                // setup message handler
+                Looper looper;
+                if ((looper = Looper.myLooper()) != null) {
+                    mEventHandler = new EventHandler(this, looper);
+                } else if ((looper = Looper.getMainLooper()) != null) {
+                    mEventHandler = new EventHandler(this, looper);
+                } else {
+                    mEventHandler = null;
+                }
+            } else {
+                mEventHandler = null;
+            }
             mOnLoadCompleteListener = listener;
         }
     }
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 0edd449..7fdf448 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -146,7 +146,6 @@
         Bitmap bitmap = null;
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
         try {
-            retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
             retriever.setDataSource(filePath);
             bitmap = retriever.getFrameAtTime(-1);
         } catch (IllegalArgumentException ex) {
@@ -160,7 +159,21 @@
                 // Ignore failures while cleaning up.
             }
         }
-        if (kind == Images.Thumbnails.MICRO_KIND && bitmap != null) {
+
+        if (bitmap == null) return null;
+
+        if (kind == Images.Thumbnails.MINI_KIND) {
+            // Scale down the bitmap if it's too large.
+            int width = bitmap.getWidth();
+            int height = bitmap.getHeight();
+            int max = Math.max(width, height);
+            if (max > 512) {
+                float scale = 512f / max;
+                int w = Math.round(scale * width);
+                int h = Math.round(scale * height);
+                bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
+            }
+        } else if (kind == Images.Thumbnails.MICRO_KIND) {
             bitmap = extractThumbnail(bitmap,
                     TARGET_SIZE_MICRO_THUMBNAIL,
                     TARGET_SIZE_MICRO_THUMBNAIL,
@@ -282,7 +295,7 @@
     private static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
             Uri uri, ContentResolver cr, ParcelFileDescriptor pfd,
             BitmapFactory.Options options) {
-            Bitmap b = null;
+        Bitmap b = null;
         try {
             if (pfd == null) pfd = makeInputStream(uri, cr);
             if (pfd == null) return null;
diff --git a/media/java/android/mtp/MtpConstants.java b/media/java/android/mtp/MtpConstants.java
new file mode 100644
index 0000000..8fa47ee
--- /dev/null
+++ b/media/java/android/mtp/MtpConstants.java
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mtp;
+
+/**
+ * {@hide}
+ */
+public final class MtpConstants {
+
+// MTP Data Types
+    public static final int TYPE_UNDEFINED = 0x0000;
+    public static final int TYPE_INT8 = 0x0001;
+    public static final int TYPE_UINT8 = 0x0002;
+    public static final int TYPE_INT16 = 0x0003;
+    public static final int TYPE_UINT16 = 0x0004;
+    public static final int TYPE_INT32 = 0x0005;
+    public static final int TYPE_UINT32 = 0x0006;
+    public static final int TYPE_INT64 = 0x0007;
+    public static final int TYPE_UINT64 = 0x0008;
+    public static final int TYPE_INT128 = 0x0009;
+    public static final int TYPE_UINT128 = 0x000A;
+    public static final int TYPE_AINT8 = 0x4001;
+    public static final int TYPE_AUINT8 = 0x4002;
+    public static final int TYPE_AINT16 = 0x4003;
+    public static final int TYPE_AUINT16 = 0x4004;
+    public static final int TYPE_AINT32 = 0x4005;
+    public static final int TYPE_AUINT32 = 0x4006;
+    public static final int TYPE_AINT64 = 0x4007;
+    public static final int TYPE_AUINT64 = 0x4008;
+    public static final int TYPE_AINT128 = 0x4009;
+    public static final int TYPE_AUINT128 = 0x400A;
+    public static final int TYPE_STR = 0xFFFF;
+
+// MTP Response Codes
+    public static final int RESPONSE_UNDEFINED = 0x2000;
+    public static final int RESPONSE_OK = 0x2001;
+    public static final int RESPONSE_GENERAL_ERROR = 0x2002;
+    public static final int RESPONSE_SESSION_NOT_OPEN = 0x2003;
+    public static final int RESPONSE_INVALID_TRANSACTION_ID = 0x2004;
+    public static final int RESPONSE_OPERATION_NOT_SUPPORTED = 0x2005;
+    public static final int RESPONSE_PARAMETER_NOT_SUPPORTED = 0x2006;
+    public static final int RESPONSE_INCOMPLETE_TRANSFER = 0x2007;
+    public static final int RESPONSE_INVALID_STORAGE_ID = 0x2008;
+    public static final int RESPONSE_INVALID_OBJECT_HANDLE = 0x2009;
+    public static final int RESPONSE_DEVICE_PROP_NOT_SUPPORTED = 0x200A;
+    public static final int RESPONSE_INVALID_OBJECT_FORMAT_CODE = 0x200B;
+    public static final int RESPONSE_STORAGE_FULL = 0x200C;
+    public static final int RESPONSE_OBJECT_WRITE_PROTECTED = 0x200D;
+    public static final int RESPONSE_STORE_READ_ONLY = 0x200E;
+    public static final int RESPONSE_ACCESS_DENIED = 0x200F;
+    public static final int RESPONSE_NO_THUMBNAIL_PRESENT = 0x2010;
+    public static final int RESPONSE_SELF_TEST_FAILED = 0x2011;
+    public static final int RESPONSE_PARTIAL_DELETION = 0x2012;
+    public static final int RESPONSE_STORE_NOT_AVAILABLE = 0x2013;
+    public static final int RESPONSE_SPECIFICATION_BY_FORMAT_UNSUPPORTED = 0x2014;
+    public static final int RESPONSE_NO_VALID_OBJECT_INFO = 0x2015;
+    public static final int RESPONSE_INVALID_CODE_FORMAT = 0x2016;
+    public static final int RESPONSE_UNKNOWN_VENDOR_CODE = 0x2017;
+    public static final int RESPONSE_CAPTURE_ALREADY_TERMINATED = 0x2018;
+    public static final int RESPONSE_DEVICE_BUSY = 0x2019;
+    public static final int RESPONSE_INVALID_PARENT_OBJECT = 0x201A;
+    public static final int RESPONSE_INVALID_DEVICE_PROP_FORMAT = 0x201B;
+    public static final int RESPONSE_INVALID_DEVICE_PROP_VALUE = 0x201C;
+    public static final int RESPONSE_INVALID_PARAMETER = 0x201D;
+    public static final int RESPONSE_SESSION_ALREADY_OPEN = 0x201E;
+    public static final int RESPONSE_TRANSACTION_CANCELLED = 0x201F;
+    public static final int RESPONSE_SPECIFICATION_OF_DESTINATION_UNSUPPORTED = 0x2020;
+    public static final int RESPONSE_INVALID_OBJECT_PROP_CODE = 0xA801;
+    public static final int RESPONSE_INVALID_OBJECT_PROP_FORMAT = 0xA802;
+    public static final int RESPONSE_INVALID_OBJECT_PROP_VALUE = 0xA803;
+    public static final int RESPONSE_INVALID_OBJECT_REFERENCE = 0xA804;
+    public static final int RESPONSE_GROUP_NOT_SUPPORTED = 0xA805;
+    public static final int RESPONSE_INVALID_DATASET = 0xA806;
+    public static final int RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED = 0xA807;
+    public static final int RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED = 0xA808;
+    public static final int RESPONSE_OBJECT_TOO_LARGE = 0xA809;
+    public static final int RESPONSE_OBJECT_PROP_NOT_SUPPORTED = 0xA80A;
+
+    // MTP format codes
+    public static final int FORMAT_UNDEFINED = 0x3000;
+    public static final int FORMAT_ASSOCIATION = 0x3001;
+    public static final int FORMAT_SCRIPT = 0x3002;
+    public static final int FORMAT_EXECUTABLE = 0x3003;
+    public static final int FORMAT_TEXT = 0x3004;
+    public static final int FORMAT_HTML = 0x3005;
+    public static final int FORMAT_DPOF = 0x3006;
+    public static final int FORMAT_AIFF = 0x3007;
+    public static final int FORMAT_WAV = 0x3008;
+    public static final int FORMAT_MP3 = 0x3009;
+    public static final int FORMAT_AVI = 0x300A;
+    public static final int FORMAT_MPEG = 0x300B;
+    public static final int FORMAT_ASF = 0x300C;
+    public static final int FORMAT_DEFINED = 0x3800;
+    public static final int FORMAT_EXIF_JPEG = 0x3801;
+    public static final int FORMAT_TIFF_EP = 0x3802;
+    public static final int FORMAT_FLASHPIX = 0x3803;
+    public static final int FORMAT_BMP = 0x3804;
+    public static final int FORMAT_CIFF = 0x3805;
+    public static final int FORMAT_GIF = 0x3807;
+    public static final int FORMAT_JFIF = 0x3808;
+    public static final int FORMAT_CD = 0x3809;
+    public static final int FORMAT_PICT = 0x380A;
+    public static final int FORMAT_PNG = 0x380B;
+    public static final int FORMAT_TIFF = 0x380D;
+    public static final int FORMAT_TIFF_IT = 0x380E;
+    public static final int FORMAT_JP2 = 0x380F;
+    public static final int FORMAT_JPX = 0x3810;
+    public static final int FORMAT_UNDEFINED_FIRMWARE = 0xB802;
+    public static final int FORMAT_WINDOWS_IMAGE_FORMAT = 0xB881;
+    public static final int FORMAT_UNDEFINED_AUDIO = 0xB900;
+    public static final int FORMAT_WMA = 0xB901;
+    public static final int FORMAT_OGG = 0xB902;
+    public static final int FORMAT_AAC = 0xB903;
+    public static final int FORMAT_AUDIBLE = 0xB904;
+    public static final int FORMAT_FLAC = 0xB906;
+    public static final int FORMAT_UNDEFINED_VIDEO = 0xB980;
+    public static final int FORMAT_WMV = 0xB981;
+    public static final int FORMAT_MP4_CONTAINER = 0xB982;
+    public static final int FORMAT_MP2 = 0xB983;
+    public static final int FORMAT_3GP_CONTAINER = 0xB984;
+    public static final int FORMAT_UNDEFINED_COLLECTION = 0xBA00;
+    public static final int FORMAT_ABSTRACT_MULTIMEDIA_ALBUM = 0xBA01;
+    public static final int FORMAT_ABSTRACT_IMAGE_ALBUM = 0xBA02;
+    public static final int FORMAT_ABSTRACT_AUDIO_ALBUM = 0xBA03;
+    public static final int FORMAT_ABSTRACT_VIDEO_ALBUM = 0xBA04;
+    public static final int FORMAT_ABSTRACT_AV_PLAYLIST = 0xBA05;
+    public static final int FORMAT_ABSTRACT_CONTACT_GROUP = 0xBA06;
+    public static final int FORMAT_ABSTRACT_MESSAGE_FOLDER = 0xBA07;
+    public static final int FORMAT_ABSTRACT_CHAPTERED_PRODUCTION = 0xBA08;
+    public static final int FORMAT_ABSTRACT_AUDIO_PLAYLIST = 0xBA09;
+    public static final int FORMAT_ABSTRACT_VIDEO_PLAYLIST = 0xBA0A;
+    public static final int FORMAT_ABSTRACT_MEDIACAST = 0xBA0B;
+    public static final int FORMAT_WPL_PLAYLIST = 0xBA10;
+    public static final int FORMAT_M3U_PLAYLIST = 0xBA11;
+    public static final int FORMAT_MPL_PLAYLIST = 0xBA12;
+    public static final int FORMAT_ASX_PLAYLIST = 0xBA13;
+    public static final int FORMAT_PLS_PLAYLIST = 0xBA14;
+    public static final int FORMAT_UNDEFINED_DOCUMENT = 0xBA80;
+    public static final int FORMAT_ABSTRACT_DOCUMENT = 0xBA81;
+    public static final int FORMAT_XML_DOCUMENT = 0xBA82;
+    public static final int FORMAT_MS_WORD_DOCUMENT = 0xBA83;
+    public static final int FORMAT_MHT_COMPILED_HTML_DOCUMENT = 0xBA84;
+    public static final int FORMAT_MS_EXCEL_SPREADSHEET = 0xBA85;
+    public static final int FORMAT_MS_POWERPOINT_PRESENTATION = 0xBA86;
+    public static final int FORMAT_UNDEFINED_MESSAGE = 0xBB00;
+    public static final int FORMAT_ABSTRACT_MESSSAGE = 0xBB01;
+    public static final int FORMAT_UNDEFINED_CONTACT = 0xBB80;
+    public static final int FORMAT_ABSTRACT_CONTACT = 0xBB81;
+    public static final int FORMAT_VCARD_2 = 0xBB82;
+
+    public static boolean isAbstractObject(int format) {
+        switch (format) {
+            case FORMAT_ABSTRACT_MULTIMEDIA_ALBUM:
+            case FORMAT_ABSTRACT_IMAGE_ALBUM:
+            case FORMAT_ABSTRACT_AUDIO_ALBUM:
+            case FORMAT_ABSTRACT_VIDEO_ALBUM:
+            case FORMAT_ABSTRACT_AV_PLAYLIST:
+            case FORMAT_ABSTRACT_CONTACT_GROUP:
+            case FORMAT_ABSTRACT_MESSAGE_FOLDER:
+            case FORMAT_ABSTRACT_CHAPTERED_PRODUCTION:
+            case FORMAT_ABSTRACT_AUDIO_PLAYLIST:
+            case FORMAT_ABSTRACT_VIDEO_PLAYLIST:
+            case FORMAT_ABSTRACT_MEDIACAST:
+            case FORMAT_ABSTRACT_DOCUMENT:
+            case FORMAT_ABSTRACT_MESSSAGE:
+            case FORMAT_ABSTRACT_CONTACT:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    // MTP object properties
+    public static final int PROPERTY_STORAGE_ID = 0xDC01;
+    public static final int PROPERTY_OBJECT_FORMAT = 0xDC02;
+    public static final int PROPERTY_PROTECTION_STATUS = 0xDC03;
+    public static final int PROPERTY_OBJECT_SIZE = 0xDC04;
+    public static final int PROPERTY_ASSOCIATION_TYPE = 0xDC05;
+    public static final int PROPERTY_ASSOCIATION_DESC = 0xDC06;
+    public static final int PROPERTY_OBJECT_FILE_NAME = 0xDC07;
+    public static final int PROPERTY_DATE_CREATED = 0xDC08;
+    public static final int PROPERTY_DATE_MODIFIED = 0xDC09;
+    public static final int PROPERTY_KEYWORDS = 0xDC0A;
+    public static final int PROPERTY_PARENT_OBJECT = 0xDC0B;
+    public static final int PROPERTY_ALLOWED_FOLDER_CONTENTS = 0xDC0C;
+    public static final int PROPERTY_HIDDEN = 0xDC0D;
+    public static final int PROPERTY_SYSTEM_OBJECT = 0xDC0E;
+    public static final int PROPERTY_PERSISTENT_UID = 0xDC41;
+    public static final int PROPERTY_SYNC_ID = 0xDC42;
+    public static final int PROPERTY_PROPERTY_BAG = 0xDC43;
+    public static final int PROPERTY_NAME = 0xDC44;
+    public static final int PROPERTY_CREATED_BY = 0xDC45;
+    public static final int PROPERTY_ARTIST = 0xDC46;
+    public static final int PROPERTY_DATE_AUTHORED = 0xDC47;
+    public static final int PROPERTY_DESCRIPTION = 0xDC48;
+    public static final int PROPERTY_URL_REFERENCE = 0xDC49;
+    public static final int PROPERTY_LANGUAGE_LOCALE = 0xDC4A;
+    public static final int PROPERTY_COPYRIGHT_INFORMATION = 0xDC4B;
+    public static final int PROPERTY_SOURCE = 0xDC4C;
+    public static final int PROPERTY_ORIGIN_LOCATION = 0xDC4D;
+    public static final int PROPERTY_DATE_ADDED = 0xDC4E;
+    public static final int PROPERTY_NON_CONSUMABLE = 0xDC4F;
+    public static final int PROPERTY_CORRUPT_UNPLAYABLE = 0xDC50;
+    public static final int PROPERTY_PRODUCER_SERIAL_NUMBER = 0xDC51;
+    public static final int PROPERTY_REPRESENTATIVE_SAMPLE_FORMAT = 0xDC81;
+    public static final int PROPERTY_REPRESENTATIVE_SAMPLE_SIZE = 0xDC82;
+    public static final int PROPERTY_REPRESENTATIVE_SAMPLE_HEIGHT = 0xDC83;
+    public static final int PROPERTY_REPRESENTATIVE_SAMPLE_WIDTH = 0xDC84;
+    public static final int PROPERTY_REPRESENTATIVE_SAMPLE_DURATION = 0xDC85;
+    public static final int PROPERTY_REPRESENTATIVE_SAMPLE_DATA = 0xDC86;
+    public static final int PROPERTY_WIDTH = 0xDC87;
+    public static final int PROPERTY_HEIGHT = 0xDC88;
+    public static final int PROPERTY_DURATION = 0xDC89;
+    public static final int PROPERTY_RATING = 0xDC8A;
+    public static final int PROPERTY_TRACK = 0xDC8B;
+    public static final int PROPERTY_GENRE = 0xDC8C;
+    public static final int PROPERTY_CREDITS = 0xDC8D;
+    public static final int PROPERTY_LYRICS = 0xDC8E;
+    public static final int PROPERTY_SUBSCRIPTION_CONTENT_ID = 0xDC8F;
+    public static final int PROPERTY_PRODUCED_BY = 0xDC90;
+    public static final int PROPERTY_USE_COUNT = 0xDC91;
+    public static final int PROPERTY_SKIP_COUNT = 0xDC92;
+    public static final int PROPERTY_LAST_ACCESSED = 0xDC93;
+    public static final int PROPERTY_PARENTAL_RATING = 0xDC94;
+    public static final int PROPERTY_META_GENRE = 0xDC95;
+    public static final int PROPERTY_COMPOSER = 0xDC96;
+    public static final int PROPERTY_EFFECTIVE_RATING = 0xDC97;
+    public static final int PROPERTY_SUBTITLE = 0xDC98;
+    public static final int PROPERTY_ORIGINAL_RELEASE_DATE = 0xDC99;
+    public static final int PROPERTY_ALBUM_NAME = 0xDC9A;
+    public static final int PROPERTY_ALBUM_ARTIST = 0xDC9B;
+    public static final int PROPERTY_MOOD = 0xDC9C;
+    public static final int PROPERTY_DRM_STATUS = 0xDC9D;
+    public static final int PROPERTY_SUB_DESCRIPTION = 0xDC9E;
+    public static final int PROPERTY_IS_CROPPED = 0xDCD1;
+    public static final int PROPERTY_IS_COLOUR_CORRECTED = 0xDCD2;
+    public static final int PROPERTY_IMAGE_BIT_DEPTH = 0xDCD3;
+    public static final int PROPERTY_F_NUMBER = 0xDCD4;
+    public static final int PROPERTY_EXPOSURE_TIME = 0xDCD5;
+    public static final int PROPERTY_EXPOSURE_INDEX = 0xDCD6;
+    public static final int PROPERTY_TOTAL_BITRATE = 0xDE91;
+    public static final int PROPERTY_BITRATE_TYPE = 0xDE92;
+    public static final int PROPERTY_SAMPLE_RATE = 0xDE93;
+    public static final int PROPERTY_NUMBER_OF_CHANNELS = 0xDE94;
+    public static final int PROPERTY_AUDIO_BIT_DEPTH = 0xDE95;
+    public static final int PROPERTY_SCAN_TYPE = 0xDE97;
+    public static final int PROPERTY_AUDIO_WAVE_CODEC = 0xDE99;
+    public static final int PROPERTY_AUDIO_BITRATE = 0xDE9A;
+    public static final int PROPERTY_VIDEO_FOURCC_CODEC = 0xDE9B;
+    public static final int PROPERTY_VIDEO_BITRATE = 0xDE9C;
+    public static final int PROPERTY_FRAMES_PER_THOUSAND_SECONDS = 0xDE9D;
+    public static final int PROPERTY_KEYFRAME_DISTANCE = 0xDE9E;
+    public static final int PROPERTY_BUFFER_SIZE = 0xDE9F;
+    public static final int PROPERTY_ENCODING_QUALITY = 0xDEA0;
+    public static final int PROPERTY_ENCODING_PROFILE = 0xDEA1;
+    public static final int PROPERTY_DISPLAY_NAME = 0xDCE0;
+    public static final int PROPERTY_BODY_TEXT = 0xDCE1;
+    public static final int PROPERTY_SUBJECT = 0xDCE2;
+    public static final int PROPERTY_PRIORITY = 0xDCE3;
+    public static final int PROPERTY_GIVEN_NAME = 0xDD00;
+    public static final int PROPERTY_MIDDLE_NAMES = 0xDD01;
+    public static final int PROPERTY_FAMILY_NAME = 0xDD02;
+    public static final int PROPERTY_PREFIX = 0xDD03;
+    public static final int PROPERTY_SUFFIX = 0xDD04;
+    public static final int PROPERTY_PHONETIC_GIVEN_NAME = 0xDD05;
+    public static final int PROPERTY_PHONETIC_FAMILY_NAME = 0xDD06;
+    public static final int PROPERTY_EMAIL_PRIMARY = 0xDD07;
+    public static final int PROPERTY_EMAIL_PERSONAL_1 = 0xDD08;
+    public static final int PROPERTY_EMAIL_PERSONAL_2 = 0xDD09;
+    public static final int PROPERTY_EMAIL_BUSINESS_1 = 0xDD0A;
+    public static final int PROPERTY_EMAIL_BUSINESS_2 = 0xDD0B;
+    public static final int PROPERTY_EMAIL_OTHERS = 0xDD0C;
+    public static final int PROPERTY_PHONE_NUMBER_PRIMARY = 0xDD0D;
+    public static final int PROPERTY_PHONE_NUMBER_PERSONAL = 0xDD0E;
+    public static final int PROPERTY_PHONE_NUMBER_PERSONAL_2 = 0xDD0F;
+    public static final int PROPERTY_PHONE_NUMBER_BUSINESS = 0xDD10;
+    public static final int PROPERTY_PHONE_NUMBER_BUSINESS_2 = 0xDD11;
+    public static final int PROPERTY_PHONE_NUMBER_MOBILE= 0xDD12;
+    public static final int PROPERTY_PHONE_NUMBER_MOBILE_2 = 0xDD13;
+    public static final int PROPERTY_FAX_NUMBER_PRIMARY = 0xDD14;
+    public static final int PROPERTY_FAX_NUMBER_PERSONAL= 0xDD15;
+    public static final int PROPERTY_FAX_NUMBER_BUSINESS= 0xDD16;
+    public static final int PROPERTY_PAGER_NUMBER = 0xDD17;
+    public static final int PROPERTY_PHONE_NUMBER_OTHERS= 0xDD18;
+    public static final int PROPERTY_PRIMARY_WEB_ADDRESS= 0xDD19;
+    public static final int PROPERTY_PERSONAL_WEB_ADDRESS = 0xDD1A;
+    public static final int PROPERTY_BUSINESS_WEB_ADDRESS = 0xDD1B;
+    public static final int PROPERTY_INSTANT_MESSANGER_ADDRESS = 0xDD1C;
+    public static final int PROPERTY_INSTANT_MESSANGER_ADDRESS_2 = 0xDD1D;
+    public static final int PROPERTY_INSTANT_MESSANGER_ADDRESS_3 = 0xDD1E;
+    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_FULL = 0xDD1F;
+    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_1 = 0xDD20;
+    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_2 = 0xDD21;
+    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_CITY = 0xDD22;
+    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_REGION = 0xDD23;
+    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE = 0xDD24;
+    public static final int PROPERTY_POSTAL_ADDRESS_PERSONAL_COUNTRY = 0xDD25;
+    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_FULL = 0xDD26;
+    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_1 = 0xDD27;
+    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_2 = 0xDD28;
+    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_CITY = 0xDD29;
+    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_REGION = 0xDD2A;
+    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE = 0xDD2B;
+    public static final int PROPERTY_POSTAL_ADDRESS_BUSINESS_COUNTRY = 0xDD2C;
+    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_FULL = 0xDD2D;
+    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_LINE_1 = 0xDD2E;
+    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_LINE_2 = 0xDD2F;
+    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_CITY = 0xDD30;
+    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_REGION = 0xDD31;
+    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_POSTAL_CODE = 0xDD32;
+    public static final int PROPERTY_POSTAL_ADDRESS_OTHER_COUNTRY = 0xDD33;
+    public static final int PROPERTY_ORGANIZATION_NAME = 0xDD34;
+    public static final int PROPERTY_PHONETIC_ORGANIZATION_NAME = 0xDD35;
+    public static final int PROPERTY_ROLE = 0xDD36;
+    public static final int PROPERTY_BIRTHDATE = 0xDD37;
+    public static final int PROPERTY_MESSAGE_TO = 0xDD40;
+    public static final int PROPERTY_MESSAGE_CC = 0xDD41;
+    public static final int PROPERTY_MESSAGE_BCC = 0xDD42;
+    public static final int PROPERTY_MESSAGE_READ = 0xDD43;
+    public static final int PROPERTY_MESSAGE_RECEIVED_TIME = 0xDD44;
+    public static final int PROPERTY_MESSAGE_SENDER = 0xDD45;
+    public static final int PROPERTY_ACTIVITY_BEGIN_TIME = 0xDD50;
+    public static final int PROPERTY_ACTIVITY_END_TIME = 0xDD51;
+    public static final int PROPERTY_ACTIVITY_LOCATION = 0xDD52;
+    public static final int PROPERTY_ACTIVITY_REQUIRED_ATTENDEES = 0xDD54;
+    public static final int PROPERTY_ACTIVITY_OPTIONAL_ATTENDEES = 0xDD55;
+    public static final int PROPERTY_ACTIVITY_RESOURCES = 0xDD56;
+    public static final int PROPERTY_ACTIVITY_ACCEPTED = 0xDD57;
+    public static final int PROPERTY_ACTIVITY_TENTATIVE = 0xDD58;
+    public static final int PROPERTY_ACTIVITY_DECLINED = 0xDD59;
+    public static final int PROPERTY_ACTIVITY_REMAINDER_TIME = 0xDD5A;
+    public static final int PROPERTY_ACTIVITY_OWNER = 0xDD5B;
+    public static final int PROPERTY_ACTIVITY_STATUS = 0xDD5C;
+    public static final int PROPERTY_OWNER = 0xDD5D;
+    public static final int PROPERTY_EDITOR = 0xDD5E;
+    public static final int PROPERTY_WEBMASTER = 0xDD5F;
+    public static final int PROPERTY_URL_SOURCE = 0xDD60;
+    public static final int PROPERTY_URL_DESTINATION = 0xDD61;
+    public static final int PROPERTY_TIME_BOOKMARK = 0xDD62;
+    public static final int PROPERTY_OBJECT_BOOKMARK = 0xDD63;
+    public static final int PROPERTY_BYTE_BOOKMARK = 0xDD64;
+    public static final int PROPERTY_LAST_BUILD_DATE = 0xDD70;
+    public static final int PROPERTY_TIME_TO_LIVE = 0xDD71;
+    public static final int PROPERTY_MEDIA_GUID = 0xDD72;
+
+    // MTP device properties
+    public static final int DEVICE_PROPERTY_UNDEFINED = 0x5000;
+    public static final int DEVICE_PROPERTY_BATTERY_LEVEL = 0x5001;
+    public static final int DEVICE_PROPERTY_FUNCTIONAL_MODE = 0x5002;
+    public static final int DEVICE_PROPERTY_IMAGE_SIZE = 0x5003;
+    public static final int DEVICE_PROPERTY_COMPRESSION_SETTING = 0x5004;
+    public static final int DEVICE_PROPERTY_WHITE_BALANCE = 0x5005;
+    public static final int DEVICE_PROPERTY_RGB_GAIN = 0x5006;
+    public static final int DEVICE_PROPERTY_F_NUMBER = 0x5007;
+    public static final int DEVICE_PROPERTY_FOCAL_LENGTH = 0x5008;
+    public static final int DEVICE_PROPERTY_FOCUS_DISTANCE = 0x5009;
+    public static final int DEVICE_PROPERTY_FOCUS_MODE = 0x500A;
+    public static final int DEVICE_PROPERTY_EXPOSURE_METERING_MODE = 0x500B;
+    public static final int DEVICE_PROPERTY_FLASH_MODE = 0x500C;
+    public static final int DEVICE_PROPERTY_EXPOSURE_TIME = 0x500D;
+    public static final int DEVICE_PROPERTY_EXPOSURE_PROGRAM_MODE = 0x500E;
+    public static final int DEVICE_PROPERTY_EXPOSURE_INDEX = 0x500F;
+    public static final int DEVICE_PROPERTY_EXPOSURE_BIAS_COMPENSATION = 0x5010;
+    public static final int DEVICE_PROPERTY_DATETIME = 0x5011;
+    public static final int DEVICE_PROPERTY_CAPTURE_DELAY = 0x5012;
+    public static final int DEVICE_PROPERTY_STILL_CAPTURE_MODE = 0x5013;
+    public static final int DEVICE_PROPERTY_CONTRAST = 0x5014;
+    public static final int DEVICE_PROPERTY_SHARPNESS = 0x5015;
+    public static final int DEVICE_PROPERTY_DIGITAL_ZOOM = 0x5016;
+    public static final int DEVICE_PROPERTY_EFFECT_MODE = 0x5017;
+    public static final int DEVICE_PROPERTY_BURST_NUMBER= 0x5018;
+    public static final int DEVICE_PROPERTY_BURST_INTERVAL = 0x5019;
+    public static final int DEVICE_PROPERTY_TIMELAPSE_NUMBER = 0x501A;
+    public static final int DEVICE_PROPERTY_TIMELAPSE_INTERVAL = 0x501B;
+    public static final int DEVICE_PROPERTY_FOCUS_METERING_MODE = 0x501C;
+    public static final int DEVICE_PROPERTY_UPLOAD_URL = 0x501D;
+    public static final int DEVICE_PROPERTY_ARTIST = 0x501E;
+    public static final int DEVICE_PROPERTY_COPYRIGHT_INFO = 0x501F;
+    public static final int DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER = 0xD401;
+    public static final int DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME = 0xD402;
+    public static final int DEVICE_PROPERTY_VOLUME = 0xD403;
+    public static final int DEVICE_PROPERTY_SUPPORTED_FORMATS_ORDERED = 0xD404;
+    public static final int DEVICE_PROPERTY_DEVICE_ICON = 0xD405;
+    public static final int DEVICE_PROPERTY_PLAYBACK_RATE = 0xD410;
+    public static final int DEVICE_PROPERTY_PLAYBACK_OBJECT = 0xD411;
+    public static final int DEVICE_PROPERTY_PLAYBACK_CONTAINER_INDEX = 0xD412;
+    public static final int DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO = 0xD406;
+    public static final int DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE = 0xD407;
+
+
+    /**
+     * Object is not protected. It may be modified and deleted, and its properties
+     * may be modified.
+     */
+    public static final int PROTECTION_STATUS_NONE = 0;
+
+    /**
+     * Object can not be modified or deleted and its properties can not be modified.
+     */
+    public static final int PROTECTION_STATUS_READ_ONLY = 0x8001;
+
+    /**
+     * Object can not be modified or deleted but its properties are modifiable.
+     */
+    public static final int PROTECTION_STATUS_READ_ONLY_DATA = 0x8002;
+
+    /**
+     * Object's contents can not be transfered from the device, but the object
+     * may be moved or deleted and its properties may be modified.
+     */
+    public static final int PROTECTION_STATUS_NON_TRANSFERABLE_DATA = 0x8003;
+
+    public static final int ASSOCIATION_TYPE_GENERIC_FOLDER = 0x0001;
+}
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
new file mode 100644
index 0000000..ac476ff
--- /dev/null
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -0,0 +1,830 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mtp;
+
+import android.content.Context;
+import android.content.ContentValues;
+import android.content.IContentProvider;
+import android.content.Intent;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.media.MediaScanner;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.RemoteException;
+import android.provider.MediaStore;
+import android.provider.MediaStore.Audio;
+import android.provider.MediaStore.Files;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.MediaColumns;
+import android.util.Log;
+import android.view.Display;
+import android.view.WindowManager;
+
+import java.io.File;
+import java.util.HashMap;
+
+/**
+ * {@hide}
+ */
+public class MtpDatabase {
+
+    private static final String TAG = "MtpDatabase";
+
+    private final Context mContext;
+    private final IContentProvider mMediaProvider;
+    private final String mVolumeName;
+    private final Uri mObjectsUri;
+    private final String mMediaStoragePath;
+
+    // cached property groups for single properties
+    private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByProperty
+            = new HashMap<Integer, MtpPropertyGroup>();
+
+    // cached property groups for all properties for a given format
+    private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByFormat
+            = new HashMap<Integer, MtpPropertyGroup>();
+
+    // true if the database has been modified in the current MTP session
+    private boolean mDatabaseModified;
+
+    // database for writable MTP device properties
+    private SQLiteDatabase mDevicePropDb;
+    private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1;
+
+    // FIXME - this should be passed in via the constructor
+    private final int mStorageID = 0x00010001;
+
+    private static final String[] ID_PROJECTION = new String[] {
+            Files.FileColumns._ID, // 0
+    };
+    private static final String[] PATH_PROJECTION = new String[] {
+            Files.FileColumns._ID, // 0
+            Files.FileColumns.DATA, // 1
+    };
+    private static final String[] PATH_SIZE_FORMAT_PROJECTION = new String[] {
+            Files.FileColumns._ID, // 0
+            Files.FileColumns.DATA, // 1
+            Files.FileColumns.SIZE, // 2
+            Files.FileColumns.FORMAT, // 3
+    };
+    private static final String[] OBJECT_INFO_PROJECTION = new String[] {
+            Files.FileColumns._ID, // 0
+            Files.FileColumns.DATA, // 1
+            Files.FileColumns.FORMAT, // 2
+            Files.FileColumns.PARENT, // 3
+            Files.FileColumns.SIZE, // 4
+            Files.FileColumns.DATE_MODIFIED, // 5
+    };
+    private static final String ID_WHERE = Files.FileColumns._ID + "=?";
+    private static final String PATH_WHERE = Files.FileColumns.DATA + "=?";
+    private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?";
+    private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND "
+                                            + Files.FileColumns.FORMAT + "=?";
+
+    private static final String[] DEVICE_PROPERTY_PROJECTION = new String[] { "_id", "value" };
+    private  static final String DEVICE_PROPERTY_WHERE = "code=?";
+
+    private final MediaScanner mMediaScanner;
+
+    static {
+        System.loadLibrary("media_jni");
+    }
+
+    public MtpDatabase(Context context, String volumeName, String storagePath) {
+        native_setup();
+
+        mContext = context;
+        mMediaProvider = context.getContentResolver().acquireProvider("media");
+        mVolumeName = volumeName;
+        mMediaStoragePath = storagePath;
+        mObjectsUri = Files.getMtpObjectsUri(volumeName);
+        mMediaScanner = new MediaScanner(context);
+        openDevicePropertiesDatabase(context);
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            native_finalize();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    private void openDevicePropertiesDatabase(Context context) {
+        mDevicePropDb = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null);
+        int version = mDevicePropDb.getVersion();
+
+        // initialize if necessary
+        if (version != DEVICE_PROPERTIES_DATABASE_VERSION) {
+            mDevicePropDb.execSQL("CREATE TABLE properties (" +
+                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
+                    "code INTEGER UNIQUE ON CONFLICT REPLACE," +
+                    "value TEXT" +
+                    ");");
+            mDevicePropDb.execSQL("CREATE INDEX property_index ON properties (code);");
+            mDevicePropDb.setVersion(DEVICE_PROPERTIES_DATABASE_VERSION);
+        }
+    }
+
+    private int beginSendObject(String path, int format, int parent,
+                         int storage, long size, long modified) {
+        // first make sure the object does not exist
+        if (path != null) {
+            Cursor c = null;
+            try {
+                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PATH_WHERE,
+                        new String[] { path }, null);
+                if (c != null && c.getCount() > 0) {
+                    Log.w(TAG, "file already exists in beginSendObject: " + path);
+                    return -1;
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException in beginSendObject", e);
+            } finally {
+                if (c != null) {
+                    c.close();
+                }
+            }
+        }
+
+        mDatabaseModified = true;
+        ContentValues values = new ContentValues();
+        values.put(Files.FileColumns.DATA, path);
+        values.put(Files.FileColumns.FORMAT, format);
+        values.put(Files.FileColumns.PARENT, parent);
+        // storage is ignored for now
+        values.put(Files.FileColumns.SIZE, size);
+        values.put(Files.FileColumns.DATE_MODIFIED, modified);
+
+        try {
+            Uri uri = mMediaProvider.insert(mObjectsUri, values);
+            if (uri != null) {
+                return Integer.parseInt(uri.getPathSegments().get(2));
+            } else {
+                return -1;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in beginSendObject", e);
+            return -1;
+        }
+    }
+
+    private void endSendObject(String path, int handle, int format, long actualSize, boolean succeeded) {
+        if (succeeded) {
+            // handle abstract playlists separately
+            // they do not exist in the file system so don't use the media scanner here
+            if (format == MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST) {
+                // extract name from path
+                String name = path;
+                int lastSlash = name.lastIndexOf('/');
+                if (lastSlash >= 0) {
+                    name = name.substring(lastSlash + 1);
+                }
+
+                ContentValues values = new ContentValues(1);
+                values.put(Audio.Playlists.DATA, path);
+                values.put(Audio.Playlists.NAME, name);
+                values.put(Files.FileColumns.FORMAT, format);
+                values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle);
+                try {
+                    Uri uri = mMediaProvider.insert(Audio.Playlists.EXTERNAL_CONTENT_URI, values);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "RemoteException in endSendObject", e);
+                }
+            } else {
+                if (actualSize >= 0) {
+                    // update size if necessary
+                    ContentValues values = new ContentValues();
+                    values.put(Files.FileColumns.SIZE, actualSize);
+                    try {
+                        String[] whereArgs = new String[] {  Integer.toString(handle) };
+                        mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "RemoteException in mMediaProvider.update", e);
+                    }
+                }
+
+                mMediaScanner.scanMtpFile(path, mVolumeName, handle, format);
+            }
+        } else {
+            deleteFile(handle);
+        }
+    }
+
+    private int[] getObjectList(int storageID, int format, int parent) {
+        // we can ignore storageID until we support multiple storages
+        Log.d(TAG, "getObjectList parent: " + parent);
+        Cursor c = null;
+        try {
+            if (format != 0) {
+                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
+                            PARENT_FORMAT_WHERE,
+                            new String[] { Integer.toString(parent), Integer.toString(format) },
+                             null);
+            } else {
+                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
+                            PARENT_WHERE, new String[] { Integer.toString(parent) }, null);
+            }
+            if (c == null) {
+                Log.d(TAG, "null cursor");
+                return null;
+            }
+            int count = c.getCount();
+            if (count > 0) {
+                int[] result = new int[count];
+                for (int i = 0; i < count; i++) {
+                    c.moveToNext();
+                    result[i] = c.getInt(0);
+                }
+                Log.d(TAG, "returning " + result);
+                return result;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getObjectList", e);
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        return null;
+    }
+
+    private int getNumObjects(int storageID, int format, int parent) {
+        // we can ignore storageID until we support multiple storages
+        Log.d(TAG, "getObjectList parent: " + parent);
+        Cursor c = null;
+        try {
+            if (format != 0) {
+                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
+                            PARENT_FORMAT_WHERE,
+                            new String[] { Integer.toString(parent), Integer.toString(format) },
+                             null);
+            } else {
+                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
+                            PARENT_WHERE, new String[] { Integer.toString(parent) }, null);
+            }
+            if (c != null) {
+                return c.getCount();
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getNumObjects", e);
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        return -1;
+    }
+
+    private int[] getSupportedPlaybackFormats() {
+        return new int[] {
+            // allow transfering arbitrary files
+            MtpConstants.FORMAT_UNDEFINED,
+
+            MtpConstants.FORMAT_ASSOCIATION,
+            MtpConstants.FORMAT_TEXT,
+            MtpConstants.FORMAT_HTML,
+            MtpConstants.FORMAT_WAV,
+            MtpConstants.FORMAT_MP3,
+            MtpConstants.FORMAT_MPEG,
+            MtpConstants.FORMAT_EXIF_JPEG,
+            MtpConstants.FORMAT_TIFF_EP,
+            MtpConstants.FORMAT_GIF,
+            MtpConstants.FORMAT_JFIF,
+            MtpConstants.FORMAT_PNG,
+            MtpConstants.FORMAT_TIFF,
+            MtpConstants.FORMAT_WMA,
+            MtpConstants.FORMAT_OGG,
+            MtpConstants.FORMAT_AAC,
+            MtpConstants.FORMAT_MP4_CONTAINER,
+            MtpConstants.FORMAT_MP2,
+            MtpConstants.FORMAT_3GP_CONTAINER,
+            MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST,
+            MtpConstants.FORMAT_WPL_PLAYLIST,
+            MtpConstants.FORMAT_M3U_PLAYLIST,
+            MtpConstants.FORMAT_PLS_PLAYLIST,
+            MtpConstants.FORMAT_XML_DOCUMENT,
+        };
+    }
+
+    private int[] getSupportedCaptureFormats() {
+        // no capture formats yet
+        return null;
+    }
+
+    static final int[] FILE_PROPERTIES = {
+            // NOTE must match beginning of AUDIO_PROPERTIES, VIDEO_PROPERTIES
+            // and IMAGE_PROPERTIES below
+            MtpConstants.PROPERTY_STORAGE_ID,
+            MtpConstants.PROPERTY_OBJECT_FORMAT,
+            MtpConstants.PROPERTY_PROTECTION_STATUS,
+            MtpConstants.PROPERTY_OBJECT_SIZE,
+            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
+            MtpConstants.PROPERTY_DATE_MODIFIED,
+            MtpConstants.PROPERTY_PARENT_OBJECT,
+            MtpConstants.PROPERTY_PERSISTENT_UID,
+            MtpConstants.PROPERTY_NAME,
+            MtpConstants.PROPERTY_DATE_ADDED,
+    };
+
+    static final int[] AUDIO_PROPERTIES = {
+            // NOTE must match FILE_PROPERTIES above
+            MtpConstants.PROPERTY_STORAGE_ID,
+            MtpConstants.PROPERTY_OBJECT_FORMAT,
+            MtpConstants.PROPERTY_PROTECTION_STATUS,
+            MtpConstants.PROPERTY_OBJECT_SIZE,
+            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
+            MtpConstants.PROPERTY_DATE_MODIFIED,
+            MtpConstants.PROPERTY_PARENT_OBJECT,
+            MtpConstants.PROPERTY_PERSISTENT_UID,
+            MtpConstants.PROPERTY_NAME,
+            MtpConstants.PROPERTY_DISPLAY_NAME,
+            MtpConstants.PROPERTY_DATE_ADDED,
+
+            // audio specific properties
+            MtpConstants.PROPERTY_ARTIST,
+            MtpConstants.PROPERTY_ALBUM_NAME,
+            MtpConstants.PROPERTY_ALBUM_ARTIST,
+            MtpConstants.PROPERTY_TRACK,
+            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
+            MtpConstants.PROPERTY_DURATION,
+            MtpConstants.PROPERTY_GENRE,
+            MtpConstants.PROPERTY_COMPOSER,
+    };
+
+    static final int[] VIDEO_PROPERTIES = {
+            // NOTE must match FILE_PROPERTIES above
+            MtpConstants.PROPERTY_STORAGE_ID,
+            MtpConstants.PROPERTY_OBJECT_FORMAT,
+            MtpConstants.PROPERTY_PROTECTION_STATUS,
+            MtpConstants.PROPERTY_OBJECT_SIZE,
+            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
+            MtpConstants.PROPERTY_DATE_MODIFIED,
+            MtpConstants.PROPERTY_PARENT_OBJECT,
+            MtpConstants.PROPERTY_PERSISTENT_UID,
+            MtpConstants.PROPERTY_NAME,
+            MtpConstants.PROPERTY_DISPLAY_NAME,
+            MtpConstants.PROPERTY_DATE_ADDED,
+
+            // video specific properties
+            MtpConstants.PROPERTY_ARTIST,
+            MtpConstants.PROPERTY_ALBUM_NAME,
+            MtpConstants.PROPERTY_DURATION,
+            MtpConstants.PROPERTY_DESCRIPTION,
+    };
+
+    static final int[] IMAGE_PROPERTIES = {
+            // NOTE must match FILE_PROPERTIES above
+            MtpConstants.PROPERTY_STORAGE_ID,
+            MtpConstants.PROPERTY_OBJECT_FORMAT,
+            MtpConstants.PROPERTY_PROTECTION_STATUS,
+            MtpConstants.PROPERTY_OBJECT_SIZE,
+            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
+            MtpConstants.PROPERTY_DATE_MODIFIED,
+            MtpConstants.PROPERTY_PARENT_OBJECT,
+            MtpConstants.PROPERTY_PERSISTENT_UID,
+            MtpConstants.PROPERTY_NAME,
+            MtpConstants.PROPERTY_DISPLAY_NAME,
+            MtpConstants.PROPERTY_DATE_ADDED,
+
+            // image specific properties
+            MtpConstants.PROPERTY_DESCRIPTION,
+    };
+
+    static final int[] ALL_PROPERTIES = {
+            // NOTE must match FILE_PROPERTIES above
+            MtpConstants.PROPERTY_STORAGE_ID,
+            MtpConstants.PROPERTY_OBJECT_FORMAT,
+            MtpConstants.PROPERTY_PROTECTION_STATUS,
+            MtpConstants.PROPERTY_OBJECT_SIZE,
+            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
+            MtpConstants.PROPERTY_DATE_MODIFIED,
+            MtpConstants.PROPERTY_PARENT_OBJECT,
+            MtpConstants.PROPERTY_PERSISTENT_UID,
+            MtpConstants.PROPERTY_NAME,
+            MtpConstants.PROPERTY_DISPLAY_NAME,
+            MtpConstants.PROPERTY_DATE_ADDED,
+
+            // image specific properties
+            MtpConstants.PROPERTY_DESCRIPTION,
+
+            // audio specific properties
+            MtpConstants.PROPERTY_ARTIST,
+            MtpConstants.PROPERTY_ALBUM_NAME,
+            MtpConstants.PROPERTY_ALBUM_ARTIST,
+            MtpConstants.PROPERTY_TRACK,
+            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
+            MtpConstants.PROPERTY_DURATION,
+            MtpConstants.PROPERTY_GENRE,
+            MtpConstants.PROPERTY_COMPOSER,
+
+            // video specific properties
+            MtpConstants.PROPERTY_ARTIST,
+            MtpConstants.PROPERTY_ALBUM_NAME,
+            MtpConstants.PROPERTY_DURATION,
+            MtpConstants.PROPERTY_DESCRIPTION,
+
+            // image specific properties
+            MtpConstants.PROPERTY_DESCRIPTION,
+    };
+
+    private int[] getSupportedObjectProperties(int format) {
+        switch (format) {
+            case MtpConstants.FORMAT_MP3:
+            case MtpConstants.FORMAT_WAV:
+            case MtpConstants.FORMAT_WMA:
+            case MtpConstants.FORMAT_OGG:
+            case MtpConstants.FORMAT_AAC:
+                return AUDIO_PROPERTIES;
+            case MtpConstants.FORMAT_MPEG:
+            case MtpConstants.FORMAT_3GP_CONTAINER:
+            case MtpConstants.FORMAT_WMV:
+                return VIDEO_PROPERTIES;
+            case MtpConstants.FORMAT_EXIF_JPEG:
+            case MtpConstants.FORMAT_GIF:
+            case MtpConstants.FORMAT_PNG:
+            case MtpConstants.FORMAT_BMP:
+                return IMAGE_PROPERTIES;
+            case 0:
+                return ALL_PROPERTIES;
+            default:
+                return FILE_PROPERTIES;
+        }
+    }
+
+    private int[] getSupportedDeviceProperties() {
+        return new int[] {
+            MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
+            MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
+            MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE,
+        };
+    }
+
+
+    private MtpPropertyList getObjectPropertyList(long handle, int format, long property,
+                        int groupCode, int depth) {
+        // FIXME - implement group support
+        if (groupCode != 0) {
+            return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED);
+        }
+
+        MtpPropertyGroup propertyGroup;
+        if (property == 0xFFFFFFFFL) {
+             propertyGroup = mPropertyGroupsByFormat.get(format);
+             if (propertyGroup == null) {
+                int[] propertyList = getSupportedObjectProperties(format);
+                propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mVolumeName, propertyList);
+                mPropertyGroupsByFormat.put(new Integer(format), propertyGroup);
+            }
+        } else {
+              propertyGroup = mPropertyGroupsByProperty.get(property);
+             if (propertyGroup == null) {
+                int[] propertyList = new int[] { (int)property };
+                propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mVolumeName, propertyList);
+                mPropertyGroupsByProperty.put(new Integer((int)property), propertyGroup);
+            }
+        }
+
+        return propertyGroup.getPropertyList((int)handle, format, depth, mStorageID);
+    }
+
+    private int renameFile(int handle, String newName) {
+        Cursor c = null;
+
+        // first compute current path
+        String path = null;
+        String[] whereArgs = new String[] {  Integer.toString(handle) };
+        try {
+            c = mMediaProvider.query(mObjectsUri, PATH_PROJECTION, ID_WHERE, whereArgs, null);
+            if (c != null && c.moveToNext()) {
+                path = c.getString(1);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getObjectFilePath", e);
+            return MtpConstants.RESPONSE_GENERAL_ERROR;
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        if (path == null) {
+            return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
+        }
+
+        // now rename the file.  make sure this succeeds before updating database
+        File oldFile = new File(path);
+        int lastSlash = path.lastIndexOf('/');
+        if (lastSlash <= 1) {
+            return MtpConstants.RESPONSE_GENERAL_ERROR;
+        }
+        String newPath = path.substring(0, lastSlash + 1) + newName;
+        File newFile = new File(newPath);
+        boolean success = oldFile.renameTo(newFile);
+        Log.d(TAG, "renaming "+ path + " to " + newPath + (success ? " succeeded" : " failed"));
+        if (!success) {
+            return MtpConstants.RESPONSE_GENERAL_ERROR;
+        }
+
+        // finally update database
+        ContentValues values = new ContentValues();
+        values.put(Files.FileColumns.DATA, newPath);
+        int updated = 0;
+        try {
+            // note - we are relying on a special case in MediaProvider.update() to update
+            // the paths for all children in the case where this is a directory.
+            updated = mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in mMediaProvider.update", e);
+        }
+        if (updated == 0) {
+            Log.e(TAG, "Unable to update path for " + path + " to " + newPath);
+            // this shouldn't happen, but if it does we need to rename the file to its original name
+            newFile.renameTo(oldFile);
+            return MtpConstants.RESPONSE_GENERAL_ERROR;
+        }
+
+        return MtpConstants.RESPONSE_OK;
+    }
+
+    private int setObjectProperty(int handle, int property,
+                            long intValue, String stringValue) {
+        Log.d(TAG, "setObjectProperty: " + property);
+
+        switch (property) {
+            case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
+                return renameFile(handle, stringValue);
+
+            default:
+                return MtpConstants.RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
+        }
+    }
+
+    private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) {
+        Log.d(TAG, "getDeviceProperty: " + property);
+
+        switch (property) {
+            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
+            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
+                // writable string properties kept in our device property database
+                Cursor c = null;
+                try {
+                    c = mDevicePropDb.query("properties", DEVICE_PROPERTY_PROJECTION,
+                        DEVICE_PROPERTY_WHERE, new String[] {  Integer.toString(property) },
+                        null, null, null);
+
+                    if (c != null && c.moveToNext()) {
+                        String value = c.getString(1);
+                        int length = value.length();
+                        if (length > 255) {
+                            length = 255;
+                        }
+                        value.getChars(0, length, outStringValue, 0);
+                        outStringValue[length] = 0;
+                    } else {
+                        outStringValue[0] = 0;
+                    }
+                    return MtpConstants.RESPONSE_OK;
+                } finally {
+                    if (c != null) {
+                        c.close();
+                    }
+                }
+
+            case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE:
+                // use screen size as max image size
+                Display display = ((WindowManager)mContext.getSystemService(
+                        Context.WINDOW_SERVICE)).getDefaultDisplay();
+                int width = display.getWidth();
+                int height = display.getHeight();
+                String imageSize = Integer.toString(width) + "x" +  Integer.toString(height);
+                imageSize.getChars(0, imageSize.length(), outStringValue, 0);
+                outStringValue[imageSize.length()] = 0;
+                return MtpConstants.RESPONSE_OK;
+
+            default:
+                return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+        }
+    }
+
+    private int setDeviceProperty(int property, long intValue, String stringValue) {
+        Log.d(TAG, "setDeviceProperty: " + property + " : " + stringValue);
+
+        switch (property) {
+            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
+            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
+                // writable string properties kept in our device property database
+                try {
+                    ContentValues values = new ContentValues();
+                    values.put("code", property);
+                    values.put("value", stringValue);
+                    mDevicePropDb.insert("properties", "code", values);
+                    return MtpConstants.RESPONSE_OK;
+                } catch (Exception e) {
+                    return MtpConstants.RESPONSE_GENERAL_ERROR;
+                }
+        }
+
+        return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+    }
+
+    private boolean getObjectInfo(int handle, int[] outStorageFormatParent,
+                        char[] outName, long[] outSizeModified) {
+        Log.d(TAG, "getObjectInfo: " + handle);
+        Cursor c = null;
+        try {
+            c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION,
+                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
+            if (c != null && c.moveToNext()) {
+                outStorageFormatParent[0] = mStorageID;
+                outStorageFormatParent[1] = c.getInt(2);
+                outStorageFormatParent[2] = c.getInt(3);
+
+                // extract name from path
+                String path = c.getString(1);
+                int lastSlash = path.lastIndexOf('/');
+                int start = (lastSlash >= 0 ? lastSlash + 1 : 0);
+                int end = path.length();
+                if (end - start > 255) {
+                    end = start + 255;
+                }
+                path.getChars(start, end, outName, 0);
+                outName[end - start] = 0;
+
+                outSizeModified[0] = c.getLong(4);
+                outSizeModified[1] = c.getLong(5);
+                return true;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getObjectInfo", e);
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        return false;
+    }
+
+    private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLengthFormat) {
+        Log.d(TAG, "getObjectFilePath: " + handle);
+        if (handle == 0) {
+            // special case root directory
+            mMediaStoragePath.getChars(0, mMediaStoragePath.length(), outFilePath, 0);
+            outFilePath[mMediaStoragePath.length()] = 0;
+            outFileLengthFormat[0] = 0;
+            outFileLengthFormat[1] = MtpConstants.FORMAT_ASSOCIATION;
+            return MtpConstants.RESPONSE_OK;
+        }
+        Cursor c = null;
+        try {
+            c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION,
+                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
+            if (c != null && c.moveToNext()) {
+                String path = c.getString(1);
+                path.getChars(0, path.length(), outFilePath, 0);
+                outFilePath[path.length()] = 0;
+                outFileLengthFormat[0] = c.getLong(2);
+                outFileLengthFormat[1] = c.getLong(3);
+                return MtpConstants.RESPONSE_OK;
+            } else {
+                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getObjectFilePath", e);
+            return MtpConstants.RESPONSE_GENERAL_ERROR;
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+    }
+
+    private int deleteFile(int handle) {
+        Log.d(TAG, "deleteFile: " + handle);
+        mDatabaseModified = true;
+        String path = null;
+        int format = 0;
+
+        Cursor c = null;
+        try {
+            c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION,
+                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
+            if (c != null && c.moveToNext()) {
+                // don't convert to media path here, since we will be matching
+                // against paths in the database matching /data/media
+                path = c.getString(1);
+                format = c.getInt(3);
+            } else {
+                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
+            }
+
+            if (path == null || format == 0) {
+                return MtpConstants.RESPONSE_GENERAL_ERROR;
+            }
+
+            if (format == MtpConstants.FORMAT_ASSOCIATION) {
+                // recursive case - delete all children first
+                Uri uri = Files.getMtpObjectsUri(mVolumeName);
+                int count = mMediaProvider.delete(uri, "_data LIKE ?",
+                        new String[] { path + "/%"});
+            }
+
+            Uri uri = Files.getMtpObjectsUri(mVolumeName, handle);
+            if (mMediaProvider.delete(uri, null, null) > 0) {
+                return MtpConstants.RESPONSE_OK;
+            } else {
+                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in deleteFile", e);
+            return MtpConstants.RESPONSE_GENERAL_ERROR;
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+    }
+
+    private int[] getObjectReferences(int handle) {
+        Log.d(TAG, "getObjectReferences for: " + handle);
+        Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
+        Cursor c = null;
+        try {
+            c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null);
+            if (c == null) {
+                return null;
+            }
+            int count = c.getCount();
+            if (count > 0) {
+                int[] result = new int[count];
+                for (int i = 0; i < count; i++) {
+                    c.moveToNext();
+                    result[i] = c.getInt(0);
+                }
+                return result;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getObjectList", e);
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        return null;
+    }
+
+    private int setObjectReferences(int handle, int[] references) {
+        mDatabaseModified = true;
+        Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
+        int count = references.length;
+        ContentValues[] valuesList = new ContentValues[count];
+        for (int i = 0; i < count; i++) {
+            ContentValues values = new ContentValues();
+            values.put(Files.FileColumns._ID, references[i]);
+            valuesList[i] = values;
+        }
+        try {
+            if (mMediaProvider.bulkInsert(uri, valuesList) > 0) {
+                return MtpConstants.RESPONSE_OK;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in setObjectReferences", e);
+        }
+        return MtpConstants.RESPONSE_GENERAL_ERROR;
+    }
+
+    private void sessionStarted() {
+        Log.d(TAG, "sessionStarted");
+        mDatabaseModified = false;
+    }
+
+    private void sessionEnded() {
+        Log.d(TAG, "sessionEnded");
+        if (mDatabaseModified) {
+            Log.d(TAG, "sending ACTION_MTP_SESSION_END");
+            mContext.sendBroadcast(new Intent(MediaStore.ACTION_MTP_SESSION_END));
+            mDatabaseModified = false;
+        }
+    }
+
+    // used by the JNI code
+    private int mNativeContext;
+
+    private native final void native_setup();
+    private native final void native_finalize();
+}
diff --git a/media/java/android/mtp/MtpPropertyGroup.java b/media/java/android/mtp/MtpPropertyGroup.java
new file mode 100644
index 0000000..fff96c7
--- /dev/null
+++ b/media/java/android/mtp/MtpPropertyGroup.java
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mtp;
+
+import android.content.IContentProvider;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.provider.MediaStore;
+import android.provider.MediaStore.Audio;
+import android.provider.MediaStore.Files;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.MediaColumns;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+class MtpPropertyGroup {
+
+    private static final String TAG = "MtpPropertyGroup";
+
+    private class Property {
+        // MTP property code
+        int     code;
+        // MTP data type
+        int     type;
+        // column index for our query
+        int     column;
+
+        Property(int code, int type, int column) {
+            this.code = code;
+            this.type = type;
+            this.column = column;
+        }
+    }
+
+    private final MtpDatabase mDatabase;
+    private final IContentProvider mProvider;
+    private final String mVolumeName;
+    private final Uri mUri;
+
+    // list of all properties in this group
+    private final Property[]    mProperties;
+
+    // list of columns for database query
+    private String[]             mColumns;
+
+    private static final String ID_WHERE = Files.FileColumns._ID + "=?";
+    private static final String ID_FORMAT_WHERE = ID_WHERE + " AND "
+                                            + Files.FileColumns.FORMAT + "=?";
+    private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?";
+    private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND "
+                                            + Files.FileColumns.FORMAT + "=?";
+    // constructs a property group for a list of properties
+    public MtpPropertyGroup(MtpDatabase database, IContentProvider provider, String volume,
+            int[] properties) {
+        mDatabase = database;
+        mProvider = provider;
+        mVolumeName = volume;
+        mUri = Files.getMtpObjectsUri(volume);
+
+        int count = properties.length;
+        ArrayList<String> columns = new ArrayList<String>(count);
+        columns.add(Files.FileColumns._ID);
+
+        mProperties = new Property[count];
+        for (int i = 0; i < count; i++) {
+            mProperties[i] = createProperty(properties[i], columns);
+        }
+        count = columns.size();
+        mColumns = new String[count];
+        for (int i = 0; i < count; i++) {
+            mColumns[i] = columns.get(i);
+        }
+    }
+
+    private Property createProperty(int code, ArrayList<String> columns) {
+        String column = null;
+        int type;
+
+         switch (code) {
+            case MtpConstants.PROPERTY_STORAGE_ID:
+                // no query needed until we support multiple storage units
+                type = MtpConstants.TYPE_UINT32;
+                break;
+             case MtpConstants.PROPERTY_OBJECT_FORMAT:
+                column = Files.FileColumns.FORMAT;
+                type = MtpConstants.TYPE_UINT16;
+                break;
+            case MtpConstants.PROPERTY_PROTECTION_STATUS:
+                // protection status is always 0
+                type = MtpConstants.TYPE_UINT16;
+                break;
+            case MtpConstants.PROPERTY_OBJECT_SIZE:
+                column = Files.FileColumns.SIZE;
+                type = MtpConstants.TYPE_UINT64;
+                break;
+            case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
+                column = Files.FileColumns.DATA;
+                type = MtpConstants.TYPE_STR;
+                break;
+            case MtpConstants.PROPERTY_NAME:
+                column = MediaColumns.TITLE;
+                type = MtpConstants.TYPE_STR;
+                break;
+            case MtpConstants.PROPERTY_DATE_MODIFIED:
+                column = Files.FileColumns.DATE_MODIFIED;
+                type = MtpConstants.TYPE_STR;
+                break;
+            case MtpConstants.PROPERTY_DATE_ADDED:
+                column = Files.FileColumns.DATE_ADDED;
+                type = MtpConstants.TYPE_STR;
+                break;
+            case MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE:
+                column = Audio.AudioColumns.YEAR;
+                type = MtpConstants.TYPE_STR;
+                break;
+            case MtpConstants.PROPERTY_PARENT_OBJECT:
+                column = Files.FileColumns.PARENT;
+                type = MtpConstants.TYPE_UINT32;
+                break;
+            case MtpConstants.PROPERTY_PERSISTENT_UID:
+                // PUID is concatenation of storageID and object handle
+                type = MtpConstants.TYPE_UINT128;
+                break;
+            case MtpConstants.PROPERTY_DURATION:
+                column = Audio.AudioColumns.DURATION;
+                type = MtpConstants.TYPE_UINT32;
+                break;
+            case MtpConstants.PROPERTY_TRACK:
+                column = Audio.AudioColumns.TRACK;
+                type = MtpConstants.TYPE_UINT16;
+                break;
+            case MtpConstants.PROPERTY_DISPLAY_NAME:
+                column = MediaColumns.DISPLAY_NAME;
+                type = MtpConstants.TYPE_STR;
+                break;
+            case MtpConstants.PROPERTY_ARTIST:
+                type = MtpConstants.TYPE_STR;
+                break;
+            case MtpConstants.PROPERTY_ALBUM_NAME:
+                type = MtpConstants.TYPE_STR;
+                break;
+            case MtpConstants.PROPERTY_ALBUM_ARTIST:
+                column = Audio.AudioColumns.ALBUM_ARTIST;
+                type = MtpConstants.TYPE_STR;
+                break;
+            case MtpConstants.PROPERTY_GENRE:
+                // genre requires a special query
+                type = MtpConstants.TYPE_STR;
+                break;
+            case MtpConstants.PROPERTY_COMPOSER:
+                column = Audio.AudioColumns.COMPOSER;
+                type = MtpConstants.TYPE_STR;
+                break;
+            case MtpConstants.PROPERTY_DESCRIPTION:
+                column = Images.ImageColumns.DESCRIPTION;
+                type = MtpConstants.TYPE_STR;
+                break;
+            default:
+                type = MtpConstants.TYPE_UNDEFINED;
+                Log.e(TAG, "unsupported property " + code);
+                break;
+        }
+
+        if (column != null) {
+            columns.add(column);
+            return new Property(code, type, columns.size() - 1);
+        } else {
+            return new Property(code, type, -1);
+        }
+    }
+
+   private String queryString(int id, String column) {
+        Cursor c = null;
+        try {
+            // for now we are only reading properties from the "objects" table
+            c = mProvider.query(mUri,
+                            new String [] { Files.FileColumns._ID, column },
+                            ID_WHERE, new String[] { Integer.toString(id) }, null);
+            if (c != null && c.moveToNext()) {
+                return c.getString(1);
+            } else {
+                return "";
+            }
+        } catch (Exception e) {
+            return null;
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+    }
+
+    private String queryAudio(int id, String column) {
+        Cursor c = null;
+        try {
+            c = mProvider.query(Audio.Media.getContentUri(mVolumeName),
+                            new String [] { Files.FileColumns._ID, column },
+                            ID_WHERE, new String[] { Integer.toString(id) }, null);
+            if (c != null && c.moveToNext()) {
+                return c.getString(1);
+            } else {
+                return "";
+            }
+        } catch (Exception e) {
+            return null;
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+    }
+
+    private String queryGenre(int id) {
+        Cursor c = null;
+        try {
+            Uri uri = Audio.Genres.getContentUriForAudioId(mVolumeName, id);
+            c = mProvider.query(uri,
+                            new String [] { Files.FileColumns._ID, Audio.GenresColumns.NAME },
+                            null, null, null);
+            if (c != null && c.moveToNext()) {
+                return c.getString(1);
+            } else {
+                return "";
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "queryGenre exception", e);
+            return null;
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+    }
+
+    private Long queryLong(int id, String column) {
+        Cursor c = null;
+        try {
+            // for now we are only reading properties from the "objects" table
+            c = mProvider.query(mUri,
+                            new String [] { Files.FileColumns._ID, column },
+                            ID_WHERE, new String[] { Integer.toString(id) }, null);
+            if (c != null && c.moveToNext()) {
+                return new Long(c.getLong(1));
+            }
+        } catch (Exception e) {
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        return null;
+    }
+
+    private static String nameFromPath(String path) {
+        // extract name from full path
+        int start = 0;
+        int lastSlash = path.lastIndexOf('/');
+        if (lastSlash >= 0) {
+            start = lastSlash + 1;
+        }
+        int end = path.length();
+        if (end - start > 255) {
+            end = start + 255;
+        }
+        return path.substring(start, end);
+    }
+
+    MtpPropertyList getPropertyList(int handle, int format, int depth, int storageID) {
+        Log.d(TAG, "getPropertyList handle: " + handle + " format: " + format + " depth: " + depth);
+        if (depth > 1) {
+            // we only support depth 0 and 1
+            // depth 0: single object, depth 1: immediate children
+            return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED);
+        }
+
+        String where;
+        String[] whereArgs;
+        if (format == 0) {
+            whereArgs = new String[] { Integer.toString(handle) };
+            if (depth == 1) {
+                where = PARENT_WHERE;
+            } else {
+                where = ID_WHERE;
+            }
+        } else {
+            whereArgs = new String[] { Integer.toString(handle), Integer.toString(format) };
+            if (depth == 1) {
+                where = PARENT_FORMAT_WHERE;
+            } else {
+                where = ID_FORMAT_WHERE;
+            }
+        }
+
+        Cursor c = null;
+        try {
+            // don't query if not necessary
+            if (depth > 0 || mColumns.length > 1) {
+                c = mProvider.query(mUri, mColumns, where, whereArgs, null);
+                if (c == null) {
+                    return new MtpPropertyList(0, MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
+                }
+            }
+
+            int count = (c == null ? 1 : c.getCount());
+            MtpPropertyList result = new MtpPropertyList(count * mProperties.length,
+                    MtpConstants.RESPONSE_OK);
+
+            // iterate over all objects in the query
+            for (int objectIndex = 0; objectIndex < count; objectIndex++) {
+                if (c != null) {
+                    c.moveToNext();
+                }
+                if (depth == 1) {
+                    handle = (int)c.getLong(0);
+                }
+
+                // iterate over all properties in the query for the given object
+                for (int propertyIndex = 0; propertyIndex < mProperties.length; propertyIndex++) {
+                    Property property = mProperties[propertyIndex];
+                    int propertyCode = property.code;
+                    int column = property.column;
+
+                    // handle some special cases
+                    switch (propertyCode) {
+                        case MtpConstants.PROPERTY_STORAGE_ID:
+                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT32,
+                                    storageID);
+                            break;
+                        case MtpConstants.PROPERTY_PROTECTION_STATUS:
+                            // protection status is always 0
+                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT16, 0);
+                            break;
+                        case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
+                            // special case - need to extract file name from full path
+                            String value = c.getString(column);
+                            if (value != null) {
+                                result.append(handle, propertyCode, nameFromPath(value));
+                            } else {
+                                result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
+                            }
+                            break;
+                        case MtpConstants.PROPERTY_NAME:
+                            // first try title
+                            String name = c.getString(column);
+                            // then try name
+                            if (name == null) {
+                                name = queryString(handle, Audio.PlaylistsColumns.NAME);
+                            }
+                            // if title and name fail, extract name from full path
+                            if (name == null) {
+                                name = queryString(handle, Files.FileColumns.DATA);
+                                if (name != null) {
+                                    name = nameFromPath(name);
+                                }
+                            }
+                            if (name != null) {
+                                result.append(handle, propertyCode, name);
+                            } else {
+                                result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
+                            }
+                            break;
+                        case MtpConstants.PROPERTY_DATE_MODIFIED:
+                        case MtpConstants.PROPERTY_DATE_ADDED:
+                            // convert from seconds to DateTime
+                            result.append(handle, propertyCode, format_date_time(c.getInt(column)));
+                            break;
+                        case MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE:
+                            // release date is stored internally as just the year
+                            int year = c.getInt(column);
+                            String dateTime = Integer.toString(year) + "0101T000000";
+                            result.append(handle, propertyCode, dateTime);
+                            break;
+                        case MtpConstants.PROPERTY_PERSISTENT_UID:
+                            // PUID is concatenation of storageID and object handle
+                            long puid = storageID;
+                            puid <<= 32;
+                            puid += handle;
+                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT128, puid);
+                            break;
+                        case MtpConstants.PROPERTY_TRACK:
+                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT16,
+                                        c.getInt(column) % 1000);
+                            break;
+                        case MtpConstants.PROPERTY_ARTIST:
+                            result.append(handle, propertyCode,
+                                    queryAudio(handle, Audio.AudioColumns.ARTIST));
+                            break;
+                        case MtpConstants.PROPERTY_ALBUM_NAME:
+                            result.append(handle, propertyCode,
+                                    queryAudio(handle, Audio.AudioColumns.ALBUM));
+                            break;
+                        case MtpConstants.PROPERTY_GENRE:
+                            String genre = queryGenre(handle);
+                            if (genre != null) {
+                                result.append(handle, propertyCode, genre);
+                            } else {
+                                result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
+                            }
+                            break;
+                        default:
+                            if (property.type == MtpConstants.TYPE_STR) {
+                                result.append(handle, propertyCode, c.getString(column));
+                            } else if (property.type == MtpConstants.TYPE_UNDEFINED) {
+                                result.append(handle, propertyCode, property.type, 0);
+                            } else {
+                                result.append(handle, propertyCode, property.type,
+                                        c.getLong(column));
+                            }
+                            break;
+                    }
+                }
+            }
+
+            return result;
+        } catch (RemoteException e) {
+            return new MtpPropertyList(0, MtpConstants.RESPONSE_GENERAL_ERROR);
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        // impossible to get here, so no return statement
+    }
+
+    private native String format_date_time(long seconds);
+}
diff --git a/media/java/android/mtp/MtpPropertyList.java b/media/java/android/mtp/MtpPropertyList.java
new file mode 100644
index 0000000..f9bc603
--- /dev/null
+++ b/media/java/android/mtp/MtpPropertyList.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mtp;
+
+/**
+ * Encapsulates the ObjectPropList dataset used by the GetObjectPropList command.
+ * The fields of this class are read by JNI code in android_media_MtpDatabase.cpp
+ */
+
+class MtpPropertyList {
+
+    // number of results returned
+    private int             mCount;
+    // maximum number of results
+    private final int       mMaxCount;
+    // result code for GetObjectPropList
+    public int              mResult;
+    // list of object handles (first field in quadruplet)
+    public final int[]      mObjectHandles;
+    // list of object propery codes (second field in quadruplet)
+    public final int[]      mPropertyCodes;
+    // list of data type codes (third field in quadruplet)
+    public final int[]     mDataTypes;
+    // list of long int property values (fourth field in quadruplet, when value is integer type)
+    public long[]     mLongValues;
+    // list of long int property values (fourth field in quadruplet, when value is string type)
+    public String[]   mStringValues;
+
+    // constructor only called from MtpDatabase
+    public MtpPropertyList(int maxCount, int result) {
+        mMaxCount = maxCount;
+        mResult = result;
+        mObjectHandles = new int[maxCount];
+        mPropertyCodes = new int[maxCount];
+        mDataTypes = new int[maxCount];
+        // mLongValues and mStringValues are created lazily since both might not be necessary
+    }
+
+    public void append(int handle, int property, int type, long value) {
+        int index = mCount++;
+        if (mLongValues == null) {
+            mLongValues = new long[mMaxCount];
+        }
+        mObjectHandles[index] = handle;
+        mPropertyCodes[index] = property;
+        mDataTypes[index] = type;
+        mLongValues[index] = value;
+    }
+
+    public void append(int handle, int property, String value) {
+        int index = mCount++;
+        if (mStringValues == null) {
+            mStringValues = new String[mMaxCount];
+        }
+        mObjectHandles[index] = handle;
+        mPropertyCodes[index] = property;
+        mDataTypes[index] = MtpConstants.TYPE_STR;
+        mStringValues[index] = value;
+    }
+
+    public void setResult(int result) {
+        mResult = result;
+    }
+}
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
new file mode 100644
index 0000000..af6e8eb
--- /dev/null
+++ b/media/java/android/mtp/MtpServer.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.mtp;
+
+import android.util.Log;
+
+/**
+ * Java wrapper for MTP/PTP support as USB responder.
+ * {@hide}
+ */
+public class MtpServer {
+
+    private static final String TAG = "MtpServer";
+
+    static {
+        System.loadLibrary("media_jni");
+    }
+
+    public MtpServer(MtpDatabase database, String storagePath, long reserveSpace) {
+        native_setup(database, storagePath, reserveSpace);
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            native_finalize();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    public void start() {
+        native_start();
+    }
+
+    public void stop() {
+        native_stop();
+    }
+
+    public void sendObjectAdded(int handle) {
+        native_send_object_added(handle);
+    }
+
+    public void sendObjectRemoved(int handle) {
+        native_send_object_removed(handle);
+    }
+
+    public void setPtpMode(boolean usePtp) {
+        native_set_ptp_mode(usePtp);
+    }
+
+    // used by the JNI code
+    private int mNativeContext;
+
+    private native final void native_setup(MtpDatabase database, String storagePath,
+            long reserveSpace);
+    private native final void native_finalize();
+    private native final void native_start();
+    private native final void native_stop();
+    private native final void native_send_object_added(int handle);
+    private native final void native_send_object_removed(int handle);
+    private native final void native_set_ptp_mode(boolean usePtp);
+}
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index fbdfa67..ab6e512 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -9,10 +9,8 @@
     android_media_ResampleInputStream.cpp \
     android_media_MediaProfiles.cpp \
     android_media_AmrInputStream.cpp \
-	android_media_MtpDatabase.cpp \
-	android_media_MtpServer.cpp \
-	android_media_PtpClient.cpp \
-	android_media_PtpCursor.cpp \
+    android_mtp_MtpDatabase.cpp \
+    android_mtp_MtpServer.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
     libandroid_runtime \
@@ -26,11 +24,9 @@
     libsurfaceflinger_client \
     libstagefright \
     libcamera_client \
-	libsqlite
-
-ifneq ($(TARGET_SIMULATOR),true)
-LOCAL_STATIC_LIBRARIES := libmtp libusbhost
-endif
+    libsqlite \
+    libmtp \
+    libusbhost
 
 LOCAL_C_INCLUDES += \
     external/tremor/Tremor \
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 9662817..ec88bb2 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -22,6 +22,9 @@
 #include <utils/Log.h>
 #include <utils/threads.h>
 #include <core/SkBitmap.h>
+#include <core/SkCanvas.h>
+#include <core/SkDevice.h>
+#include <core/SkScalar.h>
 #include <media/mediametadataretriever.h>
 #include <private/media/VideoFrame.h>
 
@@ -35,8 +38,10 @@
 struct fields_t {
     jfieldID context;
     jclass bitmapClazz;
-    jmethodID bitmapConstructor;
+    jfieldID nativeBitmap;
     jmethodID createBitmapMethod;
+    jclass configClazz;
+    jmethodID createConfigMethod;
 };
 
 static fields_t fields;
@@ -131,17 +136,6 @@
     process_media_retriever_call(env, retriever->setDataSource(fd, offset, length), "java/lang/RuntimeException", "setDataSource failed");
 }
 
-static void android_media_MediaMetadataRetriever_setMode(JNIEnv *env, jobject thiz, jint mode)
-{
-    LOGV("setMode");
-    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
-    if (retriever == 0) {
-        jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
-        return;
-    }
-    process_media_retriever_call(env, retriever->setMode(mode), "java/lang/RuntimeException", "setMode failed");
-}
-
 static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option)
 {
     LOGV("getFrameAtTime: %lld us option: %d", timeUs, option);
@@ -162,88 +156,63 @@
         return NULL;
     }
 
-    jobject matrix = NULL;
+    LOGV("Dimension = %dx%d and bytes = %d",
+            videoFrame->mDisplayWidth,
+            videoFrame->mDisplayHeight,
+            videoFrame->mSize);
+
+    jobject config = env->CallStaticObjectMethod(
+                        fields.configClazz,
+                        fields.createConfigMethod,
+                        SkBitmap::kRGB_565_Config);
+
+    jobject jBitmap = env->CallStaticObjectMethod(
+                            fields.bitmapClazz,
+                            fields.createBitmapMethod,
+                            videoFrame->mDisplayWidth,
+                            videoFrame->mDisplayHeight,
+                            config);
+    SkBitmap *bitmap =
+            (SkBitmap *) env->GetIntField(jBitmap, fields.nativeBitmap);
+
+    bitmap->lockPixels();
+
+    memcpy((uint8_t*)bitmap->getPixels(),
+            (uint8_t*)videoFrame + sizeof(VideoFrame), videoFrame->mSize);
+
+    bitmap->unlockPixels();
+
     if (videoFrame->mRotationAngle != 0) {
-        LOGD("Create a rotation matrix: %d degrees", videoFrame->mRotationAngle);
-        jclass matrixClazz = env->FindClass("android/graphics/Matrix");
-        if (matrixClazz == NULL) {
-            jniThrowException(env, "java/lang/RuntimeException",
-                "Can't find android/graphics/Matrix");
-            return NULL;
-        }
-        jmethodID matrixConstructor =
-            env->GetMethodID(matrixClazz, "<init>", "()V");
-        if (matrixConstructor == NULL) {
-            jniThrowException(env, "java/lang/RuntimeException",
-                "Can't find Matrix constructor");
-            return NULL;
-        }
-        matrix =
-            env->NewObject(matrixClazz, matrixConstructor);
-        if (matrix == NULL) {
-            LOGE("Could not create a Matrix object");
-            return NULL;
-        }
-
-        LOGV("Rotate the matrix: %d degrees", videoFrame->mRotationAngle);
-        jmethodID setRotateMethod =
-                env->GetMethodID(matrixClazz, "setRotate", "(F)V");
-        if (setRotateMethod == NULL) {
-            jniThrowException(env, "java/lang/RuntimeException",
-                "Can't find Matrix setRotate method");
-            return NULL;
-        }
-        env->CallVoidMethod(matrix, setRotateMethod, 1.0 * videoFrame->mRotationAngle);
-        env->DeleteLocalRef(matrixClazz);
+        SkDevice device(*bitmap);
+        SkCanvas canvas(&device);
+        canvas.rotate((SkScalar) (videoFrame->mRotationAngle * 1.0));
+        canvas.drawBitmap(*bitmap, 0, 0);
     }
 
-    // Create a SkBitmap to hold the pixels
-    SkBitmap *bitmap = new SkBitmap();
-    if (bitmap == NULL) {
-        LOGE("getFrameAtTime: cannot instantiate a SkBitmap object.");
-        return NULL;
-    }
-    bitmap->setConfig(SkBitmap::kRGB_565_Config, videoFrame->mDisplayWidth, videoFrame->mDisplayHeight);
-    if (!bitmap->allocPixels()) {
-        delete bitmap;
-        LOGE("failed to allocate pixel buffer");
-        return NULL;
-    }
-    memcpy((uint8_t*)bitmap->getPixels(), (uint8_t*)videoFrame + sizeof(VideoFrame), videoFrame->mSize);
-
-    // Since internally SkBitmap uses reference count to manage the reference to
-    // its pixels, it is important that the pixels (along with SkBitmap) be
-    // available after creating the Bitmap is returned to Java app.
-    jobject jSrcBitmap = env->NewObject(fields.bitmapClazz,
-            fields.bitmapConstructor, (int) bitmap, NULL, true, NULL, -1);
-
     LOGV("Return a new bitmap constructed with the rotation matrix");
-    return env->CallStaticObjectMethod(
-                fields.bitmapClazz, fields.createBitmapMethod,
-                jSrcBitmap,                     // source Bitmap
-                0,                              // x
-                0,                              // y
-                videoFrame->mDisplayWidth,      // width
-                videoFrame->mDisplayHeight,     // height
-                matrix,                         // transform matrix
-                false);                         // filter
+    return jBitmap;
 }
 
-static jbyteArray android_media_MediaMetadataRetriever_extractAlbumArt(JNIEnv *env, jobject thiz)
+static jbyteArray android_media_MediaMetadataRetriever_getEmbeddedPicture(
+        JNIEnv *env, jobject thiz, jint pictureType)
 {
-    LOGV("extractAlbumArt");
+    LOGV("getEmbeddedPicture: %d", pictureType);
     MediaMetadataRetriever* retriever = getRetriever(env, thiz);
     if (retriever == 0) {
         jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
         return NULL;
     }
     MediaAlbumArt* mediaAlbumArt = NULL;
+
+    // FIXME:
+    // Use pictureType to retrieve the intended embedded picture and also change
+    // the method name to getEmbeddedPicture().
     sp<IMemory> albumArtMemory = retriever->extractAlbumArt();
     if (albumArtMemory != 0) {  // cast the shared structure to a MediaAlbumArt object
         mediaAlbumArt = static_cast<MediaAlbumArt *>(albumArtMemory->pointer());
     }
     if (mediaAlbumArt == NULL) {
-        LOGE("extractAlbumArt: Call to extractAlbumArt failed.");
+        LOGE("getEmbeddedPicture: Call to getEmbeddedPicture failed.");
         return NULL;
     }
 
@@ -251,7 +220,7 @@
     char* data = (char*) mediaAlbumArt + sizeof(MediaAlbumArt);
     jbyteArray array = env->NewByteArray(len);
     if (!array) {  // OutOfMemoryError exception has already been thrown.
-        LOGE("extractAlbumArt: OutOfMemoryError is thrown.");
+        LOGE("getEmbeddedPicture: OutOfMemoryError is thrown.");
     } else {
         jbyte* bytes = env->GetByteArrayElements(array, NULL);
         if (bytes != NULL) {
@@ -293,7 +262,6 @@
 static void android_media_MediaMetadataRetriever_native_finalize(JNIEnv *env, jobject thiz)
 {
     LOGV("native_finalize");
-    
     // No lock is needed, since android_media_MediaMetadataRetriever_release() is protected
     android_media_MediaMetadataRetriever_release(env, thiz);
 }
@@ -320,21 +288,52 @@
         jniThrowException(env, "java/lang/RuntimeException", "Can't find android/graphics/Bitmap");
         return;
     }
-
+#if USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR
     fields.bitmapConstructor = env->GetMethodID(fields.bitmapClazz, "<init>", "(I[BZ[BI)V");
     if (fields.bitmapConstructor == NULL) {
         jniThrowException(env, "java/lang/RuntimeException", "Can't find Bitmap constructor");
         return;
     }
-    fields.createBitmapMethod =
+    fields.createBitmapRotationMethod =
             env->GetStaticMethodID(fields.bitmapClazz, "createBitmap",
                     "(Landroid/graphics/Bitmap;IIIILandroid/graphics/Matrix;Z)"
                     "Landroid/graphics/Bitmap;");
-    if (fields.createBitmapMethod == NULL) {
+    if (fields.createBitmapRotationMethod == NULL) {
         jniThrowException(env, "java/lang/RuntimeException",
                 "Can't find Bitmap.createBitmap method");
         return;
     }
+#else
+    fields.createBitmapMethod =
+            env->GetStaticMethodID(fields.bitmapClazz, "createBitmap",
+                    "(IILandroid/graphics/Bitmap$Config;)"
+                    "Landroid/graphics/Bitmap;");
+    if (fields.createBitmapMethod == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException",
+                "Can't find Bitmap.createBitmap(int, int, Config)  method");
+        return;
+    }
+    fields.nativeBitmap = env->GetFieldID(fields.bitmapClazz, "mNativeBitmap", "I");
+    if (fields.nativeBitmap == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException",
+                "Can't find Bitmap.mNativeBitmap field");
+    }
+
+    fields.configClazz = env->FindClass("android/graphics/Bitmap$Config");
+    if (fields.configClazz == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException",
+                               "Can't find Bitmap$Config class");
+        return;
+    }
+    fields.createConfigMethod =
+            env->GetStaticMethodID(fields.configClazz, "nativeToConfig",
+                    "(I)Landroid/graphics/Bitmap$Config;");
+    if (fields.createConfigMethod == NULL) {
+        jniThrowException(env, "java/lang/RuntimeException",
+                "Can't find Bitmap$Config.nativeToConfig(int)  method");
+        return;
+    }
+#endif
 }
 
 static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz)
@@ -352,10 +351,9 @@
 static JNINativeMethod nativeMethods[] = {
         {"setDataSource",   "(Ljava/lang/String;)V", (void *)android_media_MediaMetadataRetriever_setDataSource},
         {"setDataSource",   "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaMetadataRetriever_setDataSourceFD},
-        {"setMode",         "(I)V", (void *)android_media_MediaMetadataRetriever_setMode},
         {"_getFrameAtTime", "(JI)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime},
         {"extractMetadata", "(I)Ljava/lang/String;", (void *)android_media_MediaMetadataRetriever_extractMetadata},
-        {"extractAlbumArt", "()[B", (void *)android_media_MediaMetadataRetriever_extractAlbumArt},
+        {"getEmbeddedPicture", "(I)[B", (void *)android_media_MediaMetadataRetriever_getEmbeddedPicture},
         {"release",         "()V", (void *)android_media_MediaMetadataRetriever_release},
         {"native_finalize", "()V", (void *)android_media_MediaMetadataRetriever_native_finalize},
         {"native_setup",    "()V", (void *)android_media_MediaMetadataRetriever_native_setup},
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 28aef0c..f0609b2 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -774,11 +774,9 @@
 extern int register_android_media_MediaScanner(JNIEnv *env);
 extern int register_android_media_ResampleInputStream(JNIEnv *env);
 extern int register_android_media_MediaProfiles(JNIEnv *env);
-extern int register_android_media_PtpClient(JNIEnv *env);
-extern int register_android_media_PtpCursor(JNIEnv *env);
-extern int register_android_media_MtpDatabase(JNIEnv *env);
-extern int register_android_media_MtpServer(JNIEnv *env);
 extern int register_android_media_AmrInputStream(JNIEnv *env);
+extern int register_android_mtp_MtpDatabase(JNIEnv *env);
+extern int register_android_mtp_MtpServer(JNIEnv *env);
 
 jint JNI_OnLoad(JavaVM* vm, void* reserved)
 {
@@ -826,22 +824,12 @@
         goto bail;
     }
 
-    if (register_android_media_PtpClient(env) < 0) {
-        LOGE("ERROR: PtpClient native registration failed");
-        goto bail;
-    }
-
-    if (register_android_media_PtpCursor(env) < 0) {
-        LOGE("ERROR: PtpCursor native registration failed");
-        goto bail;
-    }
-
-    if (register_android_media_MtpDatabase(env) < 0) {
+    if (register_android_mtp_MtpDatabase(env) < 0) {
         LOGE("ERROR: MtpDatabase native registration failed");
         goto bail;
     }
 
-    if (register_android_media_MtpServer(env) < 0) {
+    if (register_android_mtp_MtpServer(env) < 0) {
         LOGE("ERROR: MtpServer native registration failed");
         goto bail;
     }
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index fd0b233..a5176fa 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -62,7 +62,7 @@
         }
         else {
             mScanFileMethodID = env->GetMethodID(mediaScannerClientInterface, "scanFile",
-                                                     "(Ljava/lang/String;JJ)V");
+                                                     "(Ljava/lang/String;JJZ)V");
             mHandleStringTagMethodID = env->GetMethodID(mediaScannerClientInterface, "handleStringTag",
                                                      "(Ljava/lang/String;Ljava/lang/String;)V");
             mSetMimeTypeMethodID = env->GetMethodID(mediaScannerClientInterface, "setMimeType",
@@ -78,12 +78,14 @@
     }
     
     // returns true if it succeeded, false if an exception occured in the Java code
-    virtual bool scanFile(const char* path, long long lastModified, long long fileSize)
+    virtual bool scanFile(const char* path, long long lastModified,
+            long long fileSize, bool isDirectory)
     {
         jstring pathStr;
         if ((pathStr = mEnv->NewStringUTF(path)) == NULL) return false;
 
-        mEnv->CallVoidMethod(mClient, mScanFileMethodID, pathStr, lastModified, fileSize);
+        mEnv->CallVoidMethod(mClient, mScanFileMethodID, pathStr, lastModified,
+                fileSize, isDirectory);
 
         mEnv->DeleteLocalRef(pathStr);
         return (!mEnv->ExceptionCheck());
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
deleted file mode 100644
index c08e51b..0000000
--- a/media/jni/android_media_MtpDatabase.cpp
+++ /dev/null
@@ -1,1243 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "MtpDatabaseJNI"
-#include "utils/Log.h"
-
-#include <stdio.h>
-#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include "android_runtime/AndroidRuntime.h"
-
-#include "MtpDatabase.h"
-#include "MtpDataPacket.h"
-#include "MtpProperty.h"
-#include "MtpStringBuffer.h"
-#include "MtpUtils.h"
-#include "mtp.h"
-
-using namespace android;
-
-// ----------------------------------------------------------------------------
-
-static jmethodID method_beginSendObject;
-static jmethodID method_endSendObject;
-static jmethodID method_getObjectList;
-static jmethodID method_getNumObjects;
-static jmethodID method_getSupportedPlaybackFormats;
-static jmethodID method_getSupportedCaptureFormats;
-static jmethodID method_getSupportedObjectProperties;
-static jmethodID method_getSupportedDeviceProperties;
-static jmethodID method_setObjectProperty;
-static jmethodID method_getDeviceProperty;
-static jmethodID method_setDeviceProperty;
-static jmethodID method_getObjectPropertyList;
-static jmethodID method_getObjectInfo;
-static jmethodID method_getObjectFilePath;
-static jmethodID method_deleteFile;
-static jmethodID method_getObjectReferences;
-static jmethodID method_setObjectReferences;
-static jmethodID method_sessionStarted;
-static jmethodID method_sessionEnded;
-
-static jfieldID field_context;
-
-// MtpPropertyList fields
-static jfieldID field_mCount;
-static jfieldID field_mResult;
-static jfieldID field_mObjectHandles;
-static jfieldID field_mPropertyCodes;
-static jfieldID field_mDataTypes;
-static jfieldID field_mLongValues;
-static jfieldID field_mStringValues;
-
-
-MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
-    return (MtpDatabase *)env->GetIntField(database, field_context);
-}
-
-#ifdef HAVE_ANDROID_OS
-// ----------------------------------------------------------------------------
-
-class MyMtpDatabase : public MtpDatabase {
-private:
-    jobject         mDatabase;
-    jintArray       mIntBuffer;
-    jlongArray      mLongBuffer;
-    jcharArray      mStringBuffer;
-
-public:
-                                    MyMtpDatabase(JNIEnv *env, jobject client);
-    virtual                         ~MyMtpDatabase();
-    void                            cleanup(JNIEnv *env);
-
-    virtual MtpObjectHandle         beginSendObject(const char* path,
-                                            MtpObjectFormat format,
-                                            MtpObjectHandle parent,
-                                            MtpStorageID storage,
-                                            uint64_t size,
-                                            time_t modified);
-
-    virtual void                    endSendObject(const char* path,
-                                            MtpObjectHandle handle,
-                                            MtpObjectFormat format,
-                                            int64_t actualSize,
-                                            bool succeeded);
-
-    virtual MtpObjectHandleList*    getObjectList(MtpStorageID storageID,
-                                    MtpObjectFormat format,
-                                    MtpObjectHandle parent);
-
-    virtual int                     getNumObjects(MtpStorageID storageID,
-                                            MtpObjectFormat format,
-                                            MtpObjectHandle parent);
-
-    // callee should delete[] the results from these
-    // results can be NULL
-    virtual MtpObjectFormatList*    getSupportedPlaybackFormats();
-    virtual MtpObjectFormatList*    getSupportedCaptureFormats();
-    virtual MtpObjectPropertyList*  getSupportedObjectProperties(MtpObjectFormat format);
-    virtual MtpDevicePropertyList*  getSupportedDeviceProperties();
-
-    virtual MtpResponseCode         getObjectPropertyValue(MtpObjectHandle handle,
-                                            MtpObjectProperty property,
-                                            MtpDataPacket& packet);
-
-    virtual MtpResponseCode         setObjectPropertyValue(MtpObjectHandle handle,
-                                            MtpObjectProperty property,
-                                            MtpDataPacket& packet);
-
-    virtual MtpResponseCode         getDevicePropertyValue(MtpDeviceProperty property,
-                                            MtpDataPacket& packet);
-
-    virtual MtpResponseCode         setDevicePropertyValue(MtpDeviceProperty property,
-                                            MtpDataPacket& packet);
-
-    virtual MtpResponseCode         resetDeviceProperty(MtpDeviceProperty property);
-
-    virtual MtpResponseCode         getObjectPropertyList(MtpObjectHandle handle,
-                                            uint32_t format, uint32_t property,
-                                            int groupCode, int depth,
-                                            MtpDataPacket& packet);
-
-    virtual MtpResponseCode         getObjectInfo(MtpObjectHandle handle,
-                                            MtpDataPacket& packet);
-
-    virtual MtpResponseCode         getObjectFilePath(MtpObjectHandle handle,
-                                            MtpString& outFilePath,
-                                            int64_t& outFileLength,
-                                            MtpObjectFormat& outFormat);
-    virtual MtpResponseCode         deleteFile(MtpObjectHandle handle);
-
-    bool                            getObjectPropertyInfo(MtpObjectProperty property, int& type);
-    bool                            getDevicePropertyInfo(MtpDeviceProperty property, int& type);
-
-    virtual MtpObjectHandleList*    getObjectReferences(MtpObjectHandle handle);
-
-    virtual MtpResponseCode         setObjectReferences(MtpObjectHandle handle,
-                                            MtpObjectHandleList* references);
-
-    virtual MtpProperty*            getObjectPropertyDesc(MtpObjectProperty property,
-                                            MtpObjectFormat format);
-
-    virtual MtpProperty*            getDevicePropertyDesc(MtpDeviceProperty property);
-
-    virtual void                    sessionStarted();
-
-    virtual void                    sessionEnded();
-};
-
-// ----------------------------------------------------------------------------
-
-static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
-    if (env->ExceptionCheck()) {
-        LOGE("An exception was thrown by callback '%s'.", methodName);
-        LOGE_EX(env);
-        env->ExceptionClear();
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client)
-    :   mDatabase(env->NewGlobalRef(client)),
-        mIntBuffer(NULL),
-        mLongBuffer(NULL),
-        mStringBuffer(NULL)
-{
-    jintArray intArray;
-    jlongArray longArray;
-    jcharArray charArray;
-
-    // create buffers for out arguments
-    // we don't need to be thread-safe so this is OK
-    intArray = env->NewIntArray(3);
-    if (!intArray)
-        goto out_of_memory;
-    mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
-    longArray = env->NewLongArray(2);
-    if (!longArray)
-        goto out_of_memory;
-    mLongBuffer = (jlongArray)env->NewGlobalRef(longArray);
-    charArray = env->NewCharArray(256);
-    if (!charArray)
-        goto out_of_memory;
-    mStringBuffer = (jcharArray)env->NewGlobalRef(charArray);
-    return;
-
-out_of_memory:
-    env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), NULL);
-}
-
-void MyMtpDatabase::cleanup(JNIEnv *env) {
-    env->DeleteGlobalRef(mDatabase);
-    env->DeleteGlobalRef(mIntBuffer);
-    env->DeleteGlobalRef(mLongBuffer);
-    env->DeleteGlobalRef(mStringBuffer);
-}
-
-MyMtpDatabase::~MyMtpDatabase() {
-}
-
-MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
-                                            MtpObjectFormat format,
-                                            MtpObjectHandle parent,
-                                            MtpStorageID storage,
-                                            uint64_t size,
-                                            time_t modified) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jstring pathStr = env->NewStringUTF(path);
-    MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
-            pathStr, (jint)format, (jint)parent, (jint)storage,
-            (jlong)size, (jlong)modified);
-
-    if (pathStr)
-        env->DeleteLocalRef(pathStr);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return result;
-}
-
-void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
-                                MtpObjectFormat format, int64_t actualSize, bool succeeded) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jstring pathStr = env->NewStringUTF(path);
-    env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
-                        (jint)handle, (jint)format, (jlong)actualSize, (jboolean)succeeded);
-
-    if (pathStr)
-        env->DeleteLocalRef(pathStr);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
-                                    MtpObjectFormat format,
-                                    MtpObjectHandle parent) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
-                (jint)storageID, (jint)format, (jint)parent);
-    if (!array)
-        return NULL;
-    MtpObjectHandleList* list = new MtpObjectHandleList();
-    jint* handles = env->GetIntArrayElements(array, 0);
-    jsize length = env->GetArrayLength(array);
-    for (int i = 0; i < length; i++)
-        list->push(handles[i]);
-    env->ReleaseIntArrayElements(array, handles, 0);
-    env->DeleteLocalRef(array);
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return list;
-}
-
-int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
-                                MtpObjectFormat format,
-                                MtpObjectHandle parent) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    int result = env->CallIntMethod(mDatabase, method_getNumObjects,
-                (jint)storageID, (jint)format, (jint)parent);
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return result;
-}
-
-MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
-            method_getSupportedPlaybackFormats);
-    if (!array)
-        return NULL;
-    MtpObjectFormatList* list = new MtpObjectFormatList();
-    jint* formats = env->GetIntArrayElements(array, 0);
-    jsize length = env->GetArrayLength(array);
-    for (int i = 0; i < length; i++)
-        list->push(formats[i]);
-    env->ReleaseIntArrayElements(array, formats, 0);
-    env->DeleteLocalRef(array);
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return list;
-}
-
-MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
-            method_getSupportedCaptureFormats);
-    if (!array)
-        return NULL;
-    MtpObjectFormatList* list = new MtpObjectFormatList();
-    jint* formats = env->GetIntArrayElements(array, 0);
-    jsize length = env->GetArrayLength(array);
-    for (int i = 0; i < length; i++)
-        list->push(formats[i]);
-    env->ReleaseIntArrayElements(array, formats, 0);
-    env->DeleteLocalRef(array);
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return list;
-}
-
-MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
-            method_getSupportedObjectProperties, (jint)format);
-    if (!array)
-        return NULL;
-    MtpObjectPropertyList* list = new MtpObjectPropertyList();
-    jint* properties = env->GetIntArrayElements(array, 0);
-    jsize length = env->GetArrayLength(array);
-    for (int i = 0; i < length; i++)
-        list->push(properties[i]);
-    env->ReleaseIntArrayElements(array, properties, 0);
-    env->DeleteLocalRef(array);
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return list;
-}
-
-MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
-            method_getSupportedDeviceProperties);
-    if (!array)
-        return NULL;
-    MtpDevicePropertyList* list = new MtpDevicePropertyList();
-    jint* properties = env->GetIntArrayElements(array, 0);
-    jsize length = env->GetArrayLength(array);
-    for (int i = 0; i < length; i++)
-        list->push(properties[i]);
-    env->ReleaseIntArrayElements(array, properties, 0);
-    env->DeleteLocalRef(array);
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return list;
-}
-
-MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
-                                            MtpObjectProperty property,
-                                            MtpDataPacket& packet) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
-                (jlong)handle, 0, (jlong)property, 0, 0);
-    MtpResponseCode result = env->GetIntField(list, field_mResult);
-    int count = env->GetIntField(list, field_mCount);
-    if (result == MTP_RESPONSE_OK && count != 1)
-        result = MTP_RESPONSE_GENERAL_ERROR;
-
-    if (result == MTP_RESPONSE_OK) {
-        jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
-        jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
-        jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
-        jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
-        jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
-
-        jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
-        jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
-        jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
-        jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
-
-        int type = dataTypes[0];
-        jlong longValue = (longValues ? longValues[0] : 0);
-
-        // special case date properties, which are strings to MTP
-        // but stored internally as a uint64
-        if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
-            char    date[20];
-            formatDateTime(longValue, date, sizeof(date));
-            packet.putString(date);
-            goto out;
-        }
-        // release date is stored internally as just the year
-        if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
-            char    date[20];
-            snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
-            packet.putString(date);
-            goto out;
-        }
-
-        switch (type) {
-            case MTP_TYPE_INT8:
-                packet.putInt8(longValue);
-                break;
-            case MTP_TYPE_UINT8:
-                packet.putUInt8(longValue);
-                break;
-            case MTP_TYPE_INT16:
-                packet.putInt16(longValue);
-                break;
-            case MTP_TYPE_UINT16:
-                packet.putUInt16(longValue);
-                break;
-            case MTP_TYPE_INT32:
-                packet.putInt32(longValue);
-                break;
-            case MTP_TYPE_UINT32:
-                packet.putUInt32(longValue);
-                break;
-            case MTP_TYPE_INT64:
-                packet.putInt64(longValue);
-                break;
-            case MTP_TYPE_UINT64:
-                packet.putUInt64(longValue);
-                break;
-            case MTP_TYPE_INT128:
-                packet.putInt128(longValue);
-                break;
-            case MTP_TYPE_UINT128:
-                packet.putInt128(longValue);
-                break;
-            case MTP_TYPE_STR:
-            {
-                jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
-                if (stringValue) {
-                    const char* str = env->GetStringUTFChars(stringValue, NULL);
-                    packet.putString(str);
-                    env->ReleaseStringUTFChars(stringValue, str);
-                } else {
-                    packet.putEmptyString();
-                }
-                break;
-             }
-            default:
-                LOGE("unsupported type in getObjectPropertyValue\n");
-                result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
-        }
-out:
-        env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
-        env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
-        env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
-        if (longValues)
-            env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
-
-        env->DeleteLocalRef(objectHandlesArray);
-        env->DeleteLocalRef(propertyCodesArray);
-        env->DeleteLocalRef(dataTypesArray);
-        if (longValuesArray)
-            env->DeleteLocalRef(longValuesArray);
-        if (stringValuesArray)
-            env->DeleteLocalRef(stringValuesArray);
-    }
-
-    env->DeleteLocalRef(list);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return result;
-}
-
-MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
-                                            MtpObjectProperty property,
-                                            MtpDataPacket& packet) {
-    int         type;
-
-    if (!getObjectPropertyInfo(property, type))
-        return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jlong longValue = 0;
-    jstring stringValue = NULL;
-
-    switch (type) {
-        case MTP_TYPE_INT8:
-            longValue = packet.getInt8();
-            break;
-        case MTP_TYPE_UINT8:
-            longValue = packet.getUInt8();
-            break;
-        case MTP_TYPE_INT16:
-            longValue = packet.getInt16();
-            break;
-        case MTP_TYPE_UINT16:
-            longValue = packet.getUInt16();
-            break;
-        case MTP_TYPE_INT32:
-            longValue = packet.getInt32();
-            break;
-        case MTP_TYPE_UINT32:
-            longValue = packet.getUInt32();
-            break;
-        case MTP_TYPE_INT64:
-            longValue = packet.getInt64();
-            break;
-        case MTP_TYPE_UINT64:
-            longValue = packet.getUInt64();
-            break;
-        case MTP_TYPE_STR:
-        {
-            MtpStringBuffer buffer;
-            packet.getString(buffer);
-            stringValue = env->NewStringUTF((const char *)buffer);
-            break;
-         }
-        default:
-            LOGE("unsupported type in getObjectPropertyValue\n");
-            return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
-    }
-
-    jint result = env->CallIntMethod(mDatabase, method_setObjectProperty,
-                (jint)handle, (jint)property, longValue, stringValue);
-    if (stringValue)
-        env->DeleteLocalRef(stringValue);
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return result;
-}
-
-MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
-                                            MtpDataPacket& packet) {
-    int         type;
-
-    if (!getDevicePropertyInfo(property, type))
-        return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
-                (jint)property, mLongBuffer, mStringBuffer);
-    if (result != MTP_RESPONSE_OK) {
-        checkAndClearExceptionFromCallback(env, __FUNCTION__);
-        return result;
-    }
-
-    jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
-    jlong longValue = longValues[0];
-    env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
-
-    switch (type) {
-        case MTP_TYPE_INT8:
-            packet.putInt8(longValue);
-            break;
-        case MTP_TYPE_UINT8:
-            packet.putUInt8(longValue);
-            break;
-        case MTP_TYPE_INT16:
-            packet.putInt16(longValue);
-            break;
-        case MTP_TYPE_UINT16:
-            packet.putUInt16(longValue);
-            break;
-        case MTP_TYPE_INT32:
-            packet.putInt32(longValue);
-            break;
-        case MTP_TYPE_UINT32:
-            packet.putUInt32(longValue);
-            break;
-        case MTP_TYPE_INT64:
-            packet.putInt64(longValue);
-            break;
-        case MTP_TYPE_UINT64:
-            packet.putUInt64(longValue);
-            break;
-        case MTP_TYPE_INT128:
-            packet.putInt128(longValue);
-            break;
-        case MTP_TYPE_UINT128:
-            packet.putInt128(longValue);
-            break;
-        case MTP_TYPE_STR:
-        {
-            jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
-            packet.putString(str);
-            env->ReleaseCharArrayElements(mStringBuffer, str, 0);
-            break;
-         }
-        default:
-            LOGE("unsupported type in getDevicePropertyValue\n");
-            return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
-    }
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
-                                            MtpDataPacket& packet) {
-    int         type;
-
-    if (!getDevicePropertyInfo(property, type))
-        return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jlong longValue = 0;
-    jstring stringValue = NULL;
-
-    switch (type) {
-        case MTP_TYPE_INT8:
-            longValue = packet.getInt8();
-            break;
-        case MTP_TYPE_UINT8:
-            longValue = packet.getUInt8();
-            break;
-        case MTP_TYPE_INT16:
-            longValue = packet.getInt16();
-            break;
-        case MTP_TYPE_UINT16:
-            longValue = packet.getUInt16();
-            break;
-        case MTP_TYPE_INT32:
-            longValue = packet.getInt32();
-            break;
-        case MTP_TYPE_UINT32:
-            longValue = packet.getUInt32();
-            break;
-        case MTP_TYPE_INT64:
-            longValue = packet.getInt64();
-            break;
-        case MTP_TYPE_UINT64:
-            longValue = packet.getUInt64();
-            break;
-        case MTP_TYPE_STR:
-        {
-            MtpStringBuffer buffer;
-            packet.getString(buffer);
-            stringValue = env->NewStringUTF((const char *)buffer);
-            break;
-         }
-        default:
-            LOGE("unsupported type in setDevicePropertyValue\n");
-            return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
-    }
-
-    jint result = env->CallIntMethod(mDatabase, method_setDeviceProperty,
-                (jint)property, longValue, stringValue);
-    if (stringValue)
-        env->DeleteLocalRef(stringValue);
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return result;
-}
-
-MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
-    return -1;
-}
-
-MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
-                                            uint32_t format, uint32_t property,
-                                            int groupCode, int depth,
-                                            MtpDataPacket& packet) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
-                (jlong)handle, (jint)format, (jlong)property, (jint)groupCode, (jint)depth);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    if (!list)
-        return MTP_RESPONSE_GENERAL_ERROR;
-    int count = env->GetIntField(list, field_mCount);
-    MtpResponseCode result = env->GetIntField(list, field_mResult);
-
-    packet.putUInt32(count);
-    if (count > 0) {
-        jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
-        jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
-        jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
-        jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
-        jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
-
-        jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
-        jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
-        jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
-        jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
-
-        for (int i = 0; i < count; i++) {
-            packet.putUInt32(objectHandles[i]);
-            packet.putUInt16(propertyCodes[i]);
-            int type = dataTypes[i];
-            packet.putUInt16(type);
-
-            switch (type) {
-                case MTP_TYPE_INT8:
-                    packet.putInt8(longValues[i]);
-                    break;
-                case MTP_TYPE_UINT8:
-                    packet.putUInt8(longValues[i]);
-                    break;
-                case MTP_TYPE_INT16:
-                    packet.putInt16(longValues[i]);
-                    break;
-                case MTP_TYPE_UINT16:
-                    packet.putUInt16(longValues[i]);
-                    break;
-                case MTP_TYPE_INT32:
-                    packet.putInt32(longValues[i]);
-                    break;
-                case MTP_TYPE_UINT32:
-                    packet.putUInt32(longValues[i]);
-                    break;
-                case MTP_TYPE_INT64:
-                    packet.putInt64(longValues[i]);
-                    break;
-                case MTP_TYPE_UINT64:
-                    packet.putUInt64(longValues[i]);
-                    break;
-                case MTP_TYPE_INT128:
-                    packet.putInt128(longValues[i]);
-                    break;
-                case MTP_TYPE_UINT128:
-                    packet.putUInt128(longValues[i]);
-                    break;
-                case MTP_TYPE_STR: {
-                    jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
-                    const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL);
-                    if (valueStr) {
-                        packet.putString(valueStr);
-                        env->ReleaseStringUTFChars(value, valueStr);
-                    } else {
-                        packet.putEmptyString();
-                    }
-                    env->DeleteLocalRef(value);
-                    break;
-                }
-                default:
-                    LOGE("bad or unsupported data type in MyMtpDatabase::getObjectPropertyList");
-                    break;
-            }
-        }
-
-        env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
-        env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
-        env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
-        if (longValues)
-            env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
-
-        env->DeleteLocalRef(objectHandlesArray);
-        env->DeleteLocalRef(propertyCodesArray);
-        env->DeleteLocalRef(dataTypesArray);
-        if (longValuesArray)
-            env->DeleteLocalRef(longValuesArray);
-        if (stringValuesArray)
-            env->DeleteLocalRef(stringValuesArray);
-    }
-
-    env->DeleteLocalRef(list);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return result;
-}
-
-MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
-                                            MtpDataPacket& packet) {
-    char    date[20];
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jboolean result = env->CallBooleanMethod(mDatabase, method_getObjectInfo,
-                (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer);
-    if (!result)
-        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
-
-    jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
-    MtpStorageID storageID = intValues[0];
-    MtpObjectFormat format = intValues[1];
-    MtpObjectHandle parent = intValues[2];
-    env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
-
-    jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
-    uint64_t size = longValues[0];
-    uint64_t modified = longValues[1];
-    env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
-
-//    int associationType = (format == MTP_FORMAT_ASSOCIATION ?
-//                            MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
-//                            MTP_ASSOCIATION_TYPE_UNDEFINED);
-    int associationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
-
-    packet.putUInt32(storageID);
-    packet.putUInt16(format);
-    packet.putUInt16(0);   // protection status
-    packet.putUInt32((size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size));
-    packet.putUInt16(0);   // thumb format
-    packet.putUInt32(0);   // thumb compressed size
-    packet.putUInt32(0);   // thumb pix width
-    packet.putUInt32(0);   // thumb pix height
-    packet.putUInt32(0);   // image pix width
-    packet.putUInt32(0);   // image pix height
-    packet.putUInt32(0);   // image bit depth
-    packet.putUInt32(parent);
-    packet.putUInt16(associationType);
-    packet.putUInt32(0);   // association desc
-    packet.putUInt32(0);   // sequence number
-
-    jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
-    packet.putString(str);   // file name
-    env->ReleaseCharArrayElements(mStringBuffer, str, 0);
-
-    packet.putEmptyString();
-    formatDateTime(modified, date, sizeof(date));
-    packet.putString(date);   // date modified
-    packet.putEmptyString();   // keywords
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
-                                            MtpString& outFilePath,
-                                            int64_t& outFileLength,
-                                            MtpObjectFormat& outFormat) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
-                (jint)handle, mStringBuffer, mLongBuffer);
-    if (result != MTP_RESPONSE_OK) {
-        checkAndClearExceptionFromCallback(env, __FUNCTION__);
-        return result;
-    }
-
-    jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
-    outFilePath.setTo(str, strlen16(str));
-    env->ReleaseCharArrayElements(mStringBuffer, str, 0);
-
-    jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
-    outFileLength = longValues[0];
-    outFormat = longValues[1];
-    env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
-    
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return result;
-}
-
-MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    MtpResponseCode result = env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return result;
-}
-
-struct PropertyTableEntry {
-    MtpObjectProperty   property;
-    int                 type;
-};
-
-static const PropertyTableEntry   kObjectPropertyTable[] = {
-    {   MTP_PROPERTY_STORAGE_ID,        MTP_TYPE_UINT32     },
-    {   MTP_PROPERTY_OBJECT_FORMAT,     MTP_TYPE_UINT16     },
-    {   MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16     },
-    {   MTP_PROPERTY_OBJECT_SIZE,       MTP_TYPE_UINT64     },
-    {   MTP_PROPERTY_OBJECT_FILE_NAME,  MTP_TYPE_STR        },
-    {   MTP_PROPERTY_DATE_MODIFIED,     MTP_TYPE_STR        },
-    {   MTP_PROPERTY_PARENT_OBJECT,     MTP_TYPE_UINT32     },
-    {   MTP_PROPERTY_PERSISTENT_UID,    MTP_TYPE_UINT128    },
-    {   MTP_PROPERTY_NAME,              MTP_TYPE_STR        },
-    {   MTP_PROPERTY_DISPLAY_NAME,      MTP_TYPE_STR        },
-    {   MTP_PROPERTY_DATE_ADDED,        MTP_TYPE_STR        },
-    {   MTP_PROPERTY_ARTIST,            MTP_TYPE_STR        },
-    {   MTP_PROPERTY_ALBUM_NAME,        MTP_TYPE_STR        },
-    {   MTP_PROPERTY_ALBUM_ARTIST,      MTP_TYPE_STR        },
-    {   MTP_PROPERTY_TRACK,             MTP_TYPE_UINT16     },
-    {   MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR    },
-    {   MTP_PROPERTY_GENRE,             MTP_TYPE_STR        },
-    {   MTP_PROPERTY_COMPOSER,          MTP_TYPE_STR        },
-    {   MTP_PROPERTY_DURATION,          MTP_TYPE_UINT32     },
-    {   MTP_PROPERTY_DESCRIPTION,       MTP_TYPE_STR        },
-};
-
-static const PropertyTableEntry   kDevicePropertyTable[] = {
-    {   MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,    MTP_TYPE_STR },
-    {   MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,       MTP_TYPE_STR },
-    {   MTP_DEVICE_PROPERTY_IMAGE_SIZE,                 MTP_TYPE_STR },
-};
-
-bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
-    int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
-    const PropertyTableEntry* entry = kObjectPropertyTable;
-    for (int i = 0; i < count; i++, entry++) {
-        if (entry->property == property) {
-            type = entry->type;
-            return true;
-        }
-    }
-    return false;
-}
-
-bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
-    int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
-    const PropertyTableEntry* entry = kDevicePropertyTable;
-    for (int i = 0; i < count; i++, entry++) {
-        if (entry->property == property) {
-            type = entry->type;
-            return true;
-        }
-    }
-    return false;
-}
-
-MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
-                (jint)handle);
-    if (!array)
-        return NULL;
-    MtpObjectHandleList* list = new MtpObjectHandleList();
-    jint* handles = env->GetIntArrayElements(array, 0);
-    jsize length = env->GetArrayLength(array);
-    for (int i = 0; i < length; i++)
-        list->push(handles[i]);
-    env->ReleaseIntArrayElements(array, handles, 0);
-    env->DeleteLocalRef(array);
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return list;
-}
-
-MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
-                                                    MtpObjectHandleList* references) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    int count = references->size();
-    jintArray array = env->NewIntArray(count);
-    if (!array) {
-        LOGE("out of memory in setObjectReferences");
-        return false;
-    }
-    jint* handles = env->GetIntArrayElements(array, 0);
-     for (int i = 0; i < count; i++)
-        handles[i] = (*references)[i];
-    env->ReleaseIntArrayElements(array, handles, 0);
-    MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
-                (jint)handle, array);
-    env->DeleteLocalRef(array);
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return result;
-}
-
-MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
-                                            MtpObjectFormat format) {
-    MtpProperty* result = NULL;
-    switch (property) {
-        case MTP_PROPERTY_OBJECT_FORMAT:
-            // use format as default value
-            result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
-            break;
-        case MTP_PROPERTY_PROTECTION_STATUS:
-        case MTP_PROPERTY_TRACK:
-            result = new MtpProperty(property, MTP_TYPE_UINT16);
-            break;
-        case MTP_PROPERTY_STORAGE_ID:
-        case MTP_PROPERTY_PARENT_OBJECT:
-        case MTP_PROPERTY_DURATION:
-            result = new MtpProperty(property, MTP_TYPE_UINT32);
-            break;
-        case MTP_PROPERTY_OBJECT_SIZE:
-            result = new MtpProperty(property, MTP_TYPE_UINT64);
-            break;
-        case MTP_PROPERTY_PERSISTENT_UID:
-            result = new MtpProperty(property, MTP_TYPE_UINT128);
-            break;
-        case MTP_PROPERTY_NAME:
-        case MTP_PROPERTY_DISPLAY_NAME:
-        case MTP_PROPERTY_ARTIST:
-        case MTP_PROPERTY_ALBUM_NAME:
-        case MTP_PROPERTY_ALBUM_ARTIST:
-        case MTP_PROPERTY_GENRE:
-        case MTP_PROPERTY_COMPOSER:
-        case MTP_PROPERTY_DESCRIPTION:
-            result = new MtpProperty(property, MTP_TYPE_STR);
-            break;
-        case MTP_PROPERTY_DATE_MODIFIED:
-        case MTP_PROPERTY_DATE_ADDED:
-        case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
-            result = new MtpProperty(property, MTP_TYPE_STR);
-            result->setFormDateTime();
-            break;
-        case MTP_PROPERTY_OBJECT_FILE_NAME:
-            // We allow renaming files and folders
-            result = new MtpProperty(property, MTP_TYPE_STR, true);
-            break;
-    }
-
-    return result;
-}
-
-MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    MtpProperty* result = NULL;
-    bool writable = false;
-
-    switch (property) {
-        case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
-        case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
-            writable = true;
-            // fall through
-        case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
-            result = new MtpProperty(property, MTP_TYPE_STR, writable);
-
-            // get current value
-            jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
-                        (jint)property, mLongBuffer, mStringBuffer);
-            if (ret == MTP_RESPONSE_OK) {
-                jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
-                result->setCurrentValue(str);
-                // for read-only properties it is safe to assume current value is default value
-                if (!writable)
-                    result->setDefaultValue(str);
-                env->ReleaseCharArrayElements(mStringBuffer, str, 0);
-            } else {
-                LOGE("unable to read device property, response: %04X", ret);
-            }
-            break;
-    }
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return result;
-}
-
-void MyMtpDatabase::sessionStarted() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mDatabase, method_sessionStarted);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-void MyMtpDatabase::sessionEnded() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(mDatabase, method_sessionEnded);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-#endif // HAVE_ANDROID_OS
-
-// ----------------------------------------------------------------------------
-
-static void
-android_media_MtpDatabase_setup(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
-    LOGD("setup\n");
-    MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
-    env->SetIntField(thiz, field_context, (int)database);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-#endif
-}
-
-static void
-android_media_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
-    LOGD("finalize\n");
-    MyMtpDatabase* database = (MyMtpDatabase *)env->GetIntField(thiz, field_context);
-    database->cleanup(env);
-    delete database;
-    env->SetIntField(thiz, field_context, 0);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-#endif
-}
-
-static jstring
-android_media_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject thiz, jlong seconds)
-{
-#ifdef HAVE_ANDROID_OS
-    char    date[20];
-    formatDateTime(seconds, date, sizeof(date));
-    return env->NewStringUTF(date);
-#else
-    return NULL;
-#endif
-}
-
-// ----------------------------------------------------------------------------
-
-static JNINativeMethod gMtpDatabaseMethods[] = {
-    {"native_setup",            "()V",  (void *)android_media_MtpDatabase_setup},
-    {"native_finalize",         "()V",  (void *)android_media_MtpDatabase_finalize},
-};
-
-static JNINativeMethod gMtpPropertyGroupMethods[] = {
-    {"format_date_time",        "(J)Ljava/lang/String;",
-                                        (void *)android_media_MtpPropertyGroup_format_date_time},
-};
-
-static const char* const kClassPathName = "android/media/MtpDatabase";
-
-int register_android_media_MtpDatabase(JNIEnv *env)
-{
-    jclass clazz;
-
-    LOGD("register_android_media_MtpDatabase\n");
-
-    clazz = env->FindClass("android/media/MtpDatabase");
-    if (clazz == NULL) {
-        LOGE("Can't find android/media/MtpDatabase");
-        return -1;
-    }
-    method_beginSendObject = env->GetMethodID(clazz, "beginSendObject", "(Ljava/lang/String;IIIJJ)I");
-    if (method_beginSendObject == NULL) {
-        LOGE("Can't find beginSendObject");
-        return -1;
-    }
-    method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIJZ)V");
-    if (method_endSendObject == NULL) {
-        LOGE("Can't find endSendObject");
-        return -1;
-    }
-    method_getObjectList = env->GetMethodID(clazz, "getObjectList", "(III)[I");
-    if (method_getObjectList == NULL) {
-        LOGE("Can't find getObjectList");
-        return -1;
-    }
-    method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
-    if (method_getNumObjects == NULL) {
-        LOGE("Can't find getNumObjects");
-        return -1;
-    }
-    method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
-    if (method_getSupportedPlaybackFormats == NULL) {
-        LOGE("Can't find getSupportedPlaybackFormats");
-        return -1;
-    }
-    method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
-    if (method_getSupportedCaptureFormats == NULL) {
-        LOGE("Can't find getSupportedCaptureFormats");
-        return -1;
-    }
-    method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
-    if (method_getSupportedObjectProperties == NULL) {
-        LOGE("Can't find getSupportedObjectProperties");
-        return -1;
-    }
-    method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
-    if (method_getSupportedDeviceProperties == NULL) {
-        LOGE("Can't find getSupportedDeviceProperties");
-        return -1;
-    }
-    method_setObjectProperty = env->GetMethodID(clazz, "setObjectProperty", "(IIJLjava/lang/String;)I");
-    if (method_setObjectProperty == NULL) {
-        LOGE("Can't find setObjectProperty");
-        return -1;
-    }
-    method_getDeviceProperty = env->GetMethodID(clazz, "getDeviceProperty", "(I[J[C)I");
-    if (method_getDeviceProperty == NULL) {
-        LOGE("Can't find getDeviceProperty");
-        return -1;
-    }
-    method_setDeviceProperty = env->GetMethodID(clazz, "setDeviceProperty", "(IJLjava/lang/String;)I");
-    if (method_setDeviceProperty == NULL) {
-        LOGE("Can't find setDeviceProperty");
-        return -1;
-    }
-    method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
-            "(JIJII)Landroid/media/MtpPropertyList;");
-    if (method_getObjectPropertyList == NULL) {
-        LOGE("Can't find getObjectPropertyList");
-        return -1;
-    }
-    method_getObjectInfo = env->GetMethodID(clazz, "getObjectInfo", "(I[I[C[J)Z");
-    if (method_getObjectInfo == NULL) {
-        LOGE("Can't find getObjectInfo");
-        return -1;
-    }
-    method_getObjectFilePath = env->GetMethodID(clazz, "getObjectFilePath", "(I[C[J)I");
-    if (method_getObjectFilePath == NULL) {
-        LOGE("Can't find getObjectFilePath");
-        return -1;
-    }
-    method_deleteFile = env->GetMethodID(clazz, "deleteFile", "(I)I");
-    if (method_deleteFile == NULL) {
-        LOGE("Can't find deleteFile");
-        return -1;
-    }
-    method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
-    if (method_getObjectReferences == NULL) {
-        LOGE("Can't find getObjectReferences");
-        return -1;
-    }
-    method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I");
-    if (method_setObjectReferences == NULL) {
-        LOGE("Can't find setObjectReferences");
-        return -1;
-    }
-    method_sessionStarted = env->GetMethodID(clazz, "sessionStarted", "()V");
-    if (method_sessionStarted == NULL) {
-        LOGE("Can't find sessionStarted");
-        return -1;
-    }
-    method_sessionEnded = env->GetMethodID(clazz, "sessionEnded", "()V");
-    if (method_sessionEnded == NULL) {
-        LOGE("Can't find sessionEnded");
-        return -1;
-    }
-
-    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
-    if (field_context == NULL) {
-        LOGE("Can't find MtpDatabase.mNativeContext");
-        return -1;
-    }
-
-    // now set up fields for MtpPropertyList class
-    clazz = env->FindClass("android/media/MtpPropertyList");
-    if (clazz == NULL) {
-        LOGE("Can't find android/media/MtpPropertyList");
-        return -1;
-    }
-    field_mCount = env->GetFieldID(clazz, "mCount", "I");
-    if (field_mCount == NULL) {
-        LOGE("Can't find MtpPropertyList.mCount");
-        return -1;
-    }
-    field_mResult = env->GetFieldID(clazz, "mResult", "I");
-    if (field_mResult == NULL) {
-        LOGE("Can't find MtpPropertyList.mResult");
-        return -1;
-    }
-    field_mObjectHandles = env->GetFieldID(clazz, "mObjectHandles", "[I");
-    if (field_mObjectHandles == NULL) {
-        LOGE("Can't find MtpPropertyList.mObjectHandles");
-        return -1;
-    }
-    field_mPropertyCodes = env->GetFieldID(clazz, "mPropertyCodes", "[I");
-    if (field_mPropertyCodes == NULL) {
-        LOGE("Can't find MtpPropertyList.mPropertyCodes");
-        return -1;
-    }
-    field_mDataTypes = env->GetFieldID(clazz, "mDataTypes", "[I");
-    if (field_mDataTypes == NULL) {
-        LOGE("Can't find MtpPropertyList.mDataTypes");
-        return -1;
-    }
-    field_mLongValues = env->GetFieldID(clazz, "mLongValues", "[J");
-    if (field_mLongValues == NULL) {
-        LOGE("Can't find MtpPropertyList.mLongValues");
-        return -1;
-    }
-    field_mStringValues = env->GetFieldID(clazz, "mStringValues", "[Ljava/lang/String;");
-    if (field_mStringValues == NULL) {
-        LOGE("Can't find MtpPropertyList.mStringValues");
-        return -1;
-    }
-
-    if (AndroidRuntime::registerNativeMethods(env,
-                "android/media/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
-        return -1;
-
-    return AndroidRuntime::registerNativeMethods(env,
-                "android/media/MtpPropertyGroup", gMtpPropertyGroupMethods, NELEM(gMtpPropertyGroupMethods));
-}
diff --git a/media/jni/android_media_MtpServer.cpp b/media/jni/android_media_MtpServer.cpp
deleted file mode 100644
index 87ce12a..0000000
--- a/media/jni/android_media_MtpServer.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "MtpServerJNI"
-#include "utils/Log.h"
-
-#include <stdio.h>
-#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <utils/threads.h>
-
-#ifdef HAVE_ANDROID_OS
-#include <linux/usb/f_mtp.h>
-#endif
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "private/android_filesystem_config.h"
-
-#include "MtpServer.h"
-
-using namespace android;
-
-// ----------------------------------------------------------------------------
-
-static jfieldID field_context;
-static Mutex    sMutex;
-
-// in android_media_MtpDatabase.cpp
-extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
-
-// ----------------------------------------------------------------------------
-
-#ifdef HAVE_ANDROID_OS
-
-static bool ExceptionCheck(void* env)
-{
-    return ((JNIEnv *)env)->ExceptionCheck();
-}
-
-class MtpThread : public Thread {
-private:
-    MtpDatabase*    mDatabase;
-    MtpServer*      mServer;
-    String8         mStoragePath;
-    uint64_t        mReserveSpace;
-    jobject         mJavaServer;
-    int             mFd;
-
-public:
-    MtpThread(MtpDatabase* database, const char* storagePath, uint64_t reserveSpace,
-                jobject javaServer)
-        :   mDatabase(database),
-            mServer(NULL),
-            mStoragePath(storagePath),
-            mReserveSpace(reserveSpace),
-            mJavaServer(javaServer),
-            mFd(-1)
-    {
-    }
-
-    void setPtpMode(bool usePtp) {
-        sMutex.lock();
-        if (mFd >= 0) {
-            ioctl(mFd, MTP_SET_INTERFACE_MODE,
-                    (usePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP));
-        } else {
-            int fd = open("/dev/mtp_usb", O_RDWR);
-            if (fd >= 0) {
-                ioctl(fd, MTP_SET_INTERFACE_MODE,
-                        (usePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP));
-                close(fd);
-            }
-        }
-        sMutex.unlock();
-    }
-
-    virtual bool threadLoop() {
-        sMutex.lock();
-        mFd = open("/dev/mtp_usb", O_RDWR);
-        printf("open returned %d\n", mFd);
-        if (mFd < 0) {
-            LOGE("could not open MTP driver\n");
-            sMutex.unlock();
-            return false;
-        }
-
-        mServer = new MtpServer(mFd, mDatabase, AID_MEDIA_RW, 0664, 0775);
-        mServer->addStorage(mStoragePath, mReserveSpace);
-        sMutex.unlock();
-
-        LOGD("MtpThread mServer->run");
-        mServer->run();
-
-        sMutex.lock();
-        close(mFd);
-        mFd = -1;
-        delete mServer;
-        mServer = NULL;
-
-        JNIEnv* env = AndroidRuntime::getJNIEnv();
-        env->SetIntField(mJavaServer, field_context, 0);
-        env->DeleteGlobalRef(mJavaServer);
-        sMutex.unlock();
-
-        LOGD("threadLoop returning");
-        return false;
-    }
-
-    void sendObjectAdded(MtpObjectHandle handle) {
-        sMutex.lock();
-        if (mServer)
-            mServer->sendObjectAdded(handle);
-        sMutex.unlock();
-    }
-
-    void sendObjectRemoved(MtpObjectHandle handle) {
-        sMutex.lock();
-        if (mServer)
-            mServer->sendObjectRemoved(handle);
-        sMutex.unlock();
-    }
-};
-
-#endif // HAVE_ANDROID_OS
-
-static void
-android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase,
-        jstring storagePath, jlong reserveSpace)
-{
-#ifdef HAVE_ANDROID_OS
-    LOGD("setup\n");
-
-    MtpDatabase* database = getMtpDatabase(env, javaDatabase);
-    const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL);
-
-    MtpThread* thread = new MtpThread(database, storagePathStr,
-            reserveSpace, env->NewGlobalRef(thiz));
-    env->SetIntField(thiz, field_context, (int)thread);
-
-    env->ReleaseStringUTFChars(storagePath, storagePathStr);
-#endif
-}
-
-static void
-android_media_MtpServer_finalize(JNIEnv *env, jobject thiz)
-{
-    LOGD("finalize\n");
-}
-
-
-static void
-android_media_MtpServer_start(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
-    LOGD("start\n");
-    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
-    thread->run("MtpThread");
-#endif // HAVE_ANDROID_OS
-}
-
-static void
-android_media_MtpServer_stop(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
-    LOGD("stop\n");
-#endif
-}
-
-static void
-android_media_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
-{
-#ifdef HAVE_ANDROID_OS
-    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
-    if (thread)
-        thread->sendObjectAdded(handle);
-#endif
-}
-
-static void
-android_media_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
-{
-#ifdef HAVE_ANDROID_OS
-    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
-    if (thread)
-        thread->sendObjectRemoved(handle);
-#endif
-}
-
-static void
-android_media_MtpServer_set_ptp_mode(JNIEnv *env, jobject thiz, jboolean usePtp)
-{
-#ifdef HAVE_ANDROID_OS
-    LOGD("set_ptp_mode\n");
-    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
-    if (thread)
-        thread->setPtpMode(usePtp);
- #endif
-}
-
-// ----------------------------------------------------------------------------
-
-static JNINativeMethod gMethods[] = {
-    {"native_setup",                "(Landroid/media/MtpDatabase;Ljava/lang/String;J)V",
-                                            (void *)android_media_MtpServer_setup},
-    {"native_finalize",             "()V",  (void *)android_media_MtpServer_finalize},
-    {"native_start",                "()V",  (void *)android_media_MtpServer_start},
-    {"native_stop",                 "()V",  (void *)android_media_MtpServer_stop},
-    {"native_send_object_added",    "(I)V", (void *)android_media_MtpServer_send_object_added},
-    {"native_send_object_removed",  "(I)V", (void *)android_media_MtpServer_send_object_removed},
-    {"native_set_ptp_mode",         "(Z)V", (void *)android_media_MtpServer_set_ptp_mode},
-};
-
-static const char* const kClassPathName = "android/media/MtpServer";
-
-int register_android_media_MtpServer(JNIEnv *env)
-{
-    jclass clazz;
-
-    LOGD("register_android_media_MtpServer\n");
-
-    clazz = env->FindClass("android/media/MtpServer");
-    if (clazz == NULL) {
-        LOGE("Can't find android/media/MtpServer");
-        return -1;
-    }
-    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
-    if (field_context == NULL) {
-        LOGE("Can't find MtpServer.mNativeContext");
-        return -1;
-    }
-
-    return AndroidRuntime::registerNativeMethods(env,
-                "android/media/MtpServer", gMethods, NELEM(gMethods));
-}
diff --git a/media/jni/android_media_PtpClient.cpp b/media/jni/android_media_PtpClient.cpp
deleted file mode 100644
index 6af83e4..0000000
--- a/media/jni/android_media_PtpClient.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "PtpClientJNI"
-#include "utils/Log.h"
-
-#include <stdio.h>
-#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "private/android_filesystem_config.h"
-
-#include "MtpClient.h"
-#include "MtpDevice.h"
-#include "MtpObjectInfo.h"
-
-using namespace android;
-
-// ----------------------------------------------------------------------------
-
-static jmethodID method_deviceAdded;
-static jmethodID method_deviceRemoved;
-static jfieldID field_context;
-
-#ifdef HAVE_ANDROID_OS
-
-static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
-    if (env->ExceptionCheck()) {
-        LOGE("An exception was thrown by callback '%s'.", methodName);
-        LOGE_EX(env);
-        env->ExceptionClear();
-    }
-}
-
-class MyClient : public MtpClient {
-private:
-    virtual void    deviceAdded(MtpDevice *device);
-    virtual void    deviceRemoved(MtpDevice *device);
-
-    jobject         mClient;
-    MtpDevice*      mEventDevice;
-
-public:
-                    MyClient(JNIEnv *env, jobject client);
-    void            cleanup(JNIEnv *env);
-};
-
-MtpClient* get_client_from_object(JNIEnv* env, jobject javaClient)
-{
-    return (MtpClient*)env->GetIntField(javaClient, field_context);
-}
-
-
-MyClient::MyClient(JNIEnv *env, jobject client)
-    :   mClient(env->NewGlobalRef(client))
-{
-}
-
-void MyClient::cleanup(JNIEnv *env) {
-    env->DeleteGlobalRef(mClient);
-}
-
-void MyClient::deviceAdded(MtpDevice *device) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    const char* name = device->getDeviceName();
-    LOGD("MyClient::deviceAdded %s\n", name);
-
-    env->CallVoidMethod(mClient, method_deviceAdded, device->getID());
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-void MyClient::deviceRemoved(MtpDevice *device) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    const char* name = device->getDeviceName();
-    LOGD("MyClient::deviceRemoved %s\n", name);
-
-    env->CallVoidMethod(mClient, method_deviceRemoved, device->getID());
-
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-}
-
-#endif // HAVE_ANDROID_OS
-
-// ----------------------------------------------------------------------------
-
-static void
-android_media_PtpClient_setup(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
-    LOGD("setup\n");
-    MyClient* client = new MyClient(env, thiz);
-    client->start();
-    env->SetIntField(thiz, field_context, (int)client);
-#endif
-}
-
-static void
-android_media_PtpClient_finalize(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
-    LOGD("finalize\n");
-    MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
-    client->cleanup(env);
-    delete client;
-    env->SetIntField(thiz, field_context, 0);
-#endif
-}
-
-static jboolean
-android_media_PtpClient_start(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
-    LOGD("start\n");
-    MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
-    return client->start();
-#else
-    return false;
-#endif
-}
-
-static void
-android_media_PtpClient_stop(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
-    LOGD("stop\n");
-    MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
-    client->stop();
-#endif
-}
-
-static jboolean
-android_media_PtpClient_delete_object(JNIEnv *env, jobject thiz,
-        jint device_id, jlong object_id)
-{
-#ifdef HAVE_ANDROID_OS
-    MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
-    MtpDevice* device = client->getDevice(device_id);
-    if (device)
-        return device->deleteObject(object_id);
-    else
- #endif
-        return NULL;
-}
-
-static jlong
-android_media_PtpClient_get_parent(JNIEnv *env, jobject thiz,
-        jint device_id, jlong object_id)
-{
-#ifdef HAVE_ANDROID_OS
-    MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
-    MtpDevice* device = client->getDevice(device_id);
-    if (device)
-        return device->getParent(object_id);
-    else
-#endif
-        return -1;
-}
-
-static jlong
-android_media_PtpClient_get_storage_id(JNIEnv *env, jobject thiz,
-        jint device_id, jlong object_id)
-{
- #ifdef HAVE_ANDROID_OS
-    MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
-    MtpDevice* device = client->getDevice(device_id);
-    if (device)
-        return device->getStorageID(object_id);
-    else
-#endif
-        return -1;
-}
-
-static jboolean
-android_media_PtpClient_import_file(JNIEnv *env, jobject thiz,
-        jint device_id, jlong object_id, jstring dest_path)
-{
-#ifdef HAVE_ANDROID_OS
-    MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
-    MtpDevice* device = client->getDevice(device_id);
-    if (device) {
-        const char *destPathStr = env->GetStringUTFChars(dest_path, NULL);
-        bool result = device->readObject(object_id, destPathStr, AID_SDCARD_RW, 0664);
-        env->ReleaseStringUTFChars(dest_path, destPathStr);
-        return result;
-    }
-#endif
-    return NULL;
-}
-
-// ----------------------------------------------------------------------------
-
-static JNINativeMethod gMethods[] = {
-    {"native_setup",            "()V",  (void *)android_media_PtpClient_setup},
-    {"native_finalize",         "()V",  (void *)android_media_PtpClient_finalize},
-    {"native_start",            "()Z",  (void *)android_media_PtpClient_start},
-    {"native_stop",             "()V",  (void *)android_media_PtpClient_stop},
-    {"native_delete_object",   "(IJ)Z", (void *)android_media_PtpClient_delete_object},
-    {"native_get_parent",      "(IJ)J", (void *)android_media_PtpClient_get_parent},
-    {"native_get_storage_id",  "(IJ)J", (void *)android_media_PtpClient_get_storage_id},
-    {"native_import_file",     "(IJLjava/lang/String;)Z",
-                                        (void *)android_media_PtpClient_import_file},
-};
-
-static const char* const kClassPathName = "android/media/PtpClient";
-
-int register_android_media_PtpClient(JNIEnv *env)
-{
-    jclass clazz;
-
-    LOGD("register_android_media_PtpClient\n");
-
-    clazz = env->FindClass("android/media/PtpClient");
-    if (clazz == NULL) {
-        LOGE("Can't find android/media/PtpClient");
-        return -1;
-    }
-    method_deviceAdded = env->GetMethodID(clazz, "deviceAdded", "(I)V");
-    if (method_deviceAdded == NULL) {
-        LOGE("Can't find deviceAdded");
-        return -1;
-    }
-    method_deviceRemoved = env->GetMethodID(clazz, "deviceRemoved", "(I)V");
-    if (method_deviceRemoved == NULL) {
-        LOGE("Can't find deviceRemoved");
-        return -1;
-    }
-    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
-    if (field_context == NULL) {
-        LOGE("Can't find PtpClient.mNativeContext");
-        return -1;
-    }
-
-    return AndroidRuntime::registerNativeMethods(env,
-                "android/media/PtpClient", gMethods, NELEM(gMethods));
-}
diff --git a/media/jni/android_media_PtpCursor.cpp b/media/jni/android_media_PtpCursor.cpp
deleted file mode 100644
index 76c88f6..0000000
--- a/media/jni/android_media_PtpCursor.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "PtpCursorJNI"
-#include "utils/Log.h"
-
-#include <stdio.h>
-#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "binder/CursorWindow.h"
-
-#include "MtpClient.h"
-#include "PtpCursor.h"
-
-using namespace android;
-
-// ----------------------------------------------------------------------------
-
-static jfieldID field_context;
-
-// From android_media_PtpClient.cpp
-MtpClient * get_client_from_object(JNIEnv * env, jobject javaClient);
-
-// ----------------------------------------------------------------------------
-
-static bool ExceptionCheck(void* env)
-{
-    return ((JNIEnv *)env)->ExceptionCheck();
-}
-
-static void
-android_media_PtpCursor_setup(JNIEnv *env, jobject thiz, jobject javaClient,
-        jint queryType, jint deviceID, jlong storageID, jlong objectID, jintArray javaColumns)
-{
-#ifdef HAVE_ANDROID_OS
-    LOGD("android_media_PtpCursor_setup queryType: %d deviceID: %d storageID: %lld objectID: %lld\n",
-                queryType, deviceID, storageID, objectID);
-
-    int* columns = NULL;
-    int columnCount = 0;
-    if (javaColumns) {
-        columns = env->GetIntArrayElements(javaColumns, 0);
-        columnCount = env->GetArrayLength(javaColumns);
-    }
-
-    MtpClient* client = get_client_from_object(env, javaClient);
-    PtpCursor* cursor = new PtpCursor(client, queryType,
-            deviceID, storageID, objectID, columnCount, columns);
-
-    if (columns)
-        env->ReleaseIntArrayElements(javaColumns, columns, 0);
-    env->SetIntField(thiz, field_context, (int)cursor);
-#endif
-}
-
-static void
-android_media_PtpCursor_finalize(JNIEnv *env, jobject thiz)
-{
-#ifdef HAVE_ANDROID_OS
-    LOGD("finalize\n");
-    PtpCursor *cursor = (PtpCursor *)env->GetIntField(thiz, field_context);
-    delete cursor;
-#endif
-}
-
-static jint
-android_media_PtpCursor_fill_window(JNIEnv *env, jobject thiz, jobject javaWindow, jint startPos)
-{
-#ifdef HAVE_ANDROID_OS
-    CursorWindow* window = get_window_from_object(env, javaWindow);
-    if (!window) {
-        LOGE("Invalid CursorWindow");
-        jniThrowException(env, "java/lang/IllegalArgumentException",
-                          "Bad CursorWindow");
-        return 0;
-    }
-    PtpCursor *cursor = (PtpCursor *)env->GetIntField(thiz, field_context);
-
-    return cursor->fillWindow(window, startPos);
-#else
-    return 0;
-#endif
-}
-
-// ----------------------------------------------------------------------------
-
-static JNINativeMethod gMethods[] = {
-    {"native_setup",            "(Landroid/media/PtpClient;IIJJ[I)V",
-                                        (void *)android_media_PtpCursor_setup},
-    {"native_finalize",         "()V",  (void *)android_media_PtpCursor_finalize},
-    {"native_fill_window",      "(Landroid/database/CursorWindow;I)I",
-                                        (void *)android_media_PtpCursor_fill_window},
-
-};
-
-static const char* const kClassPathName = "android/media/PtpCursor";
-
-int register_android_media_PtpCursor(JNIEnv *env)
-{
-    jclass clazz;
-
-    LOGD("register_android_media_PtpCursor\n");
-
-    clazz = env->FindClass("android/media/PtpCursor");
-    if (clazz == NULL) {
-        LOGE("Can't find android/media/PtpCursor");
-        return -1;
-    }
-    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
-    if (field_context == NULL) {
-        LOGE("Can't find PtpCursor.mNativeContext");
-        return -1;
-    }
-
-    return AndroidRuntime::registerNativeMethods(env,
-                "android/media/PtpCursor", gMethods, NELEM(gMethods));
-}
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
new file mode 100644
index 0000000..8f9b8a2
--- /dev/null
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -0,0 +1,1243 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "MtpDatabaseJNI"
+#include "utils/Log.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+
+#include "MtpDatabase.h"
+#include "MtpDataPacket.h"
+#include "MtpProperty.h"
+#include "MtpStringBuffer.h"
+#include "MtpUtils.h"
+#include "mtp.h"
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+
+static jmethodID method_beginSendObject;
+static jmethodID method_endSendObject;
+static jmethodID method_getObjectList;
+static jmethodID method_getNumObjects;
+static jmethodID method_getSupportedPlaybackFormats;
+static jmethodID method_getSupportedCaptureFormats;
+static jmethodID method_getSupportedObjectProperties;
+static jmethodID method_getSupportedDeviceProperties;
+static jmethodID method_setObjectProperty;
+static jmethodID method_getDeviceProperty;
+static jmethodID method_setDeviceProperty;
+static jmethodID method_getObjectPropertyList;
+static jmethodID method_getObjectInfo;
+static jmethodID method_getObjectFilePath;
+static jmethodID method_deleteFile;
+static jmethodID method_getObjectReferences;
+static jmethodID method_setObjectReferences;
+static jmethodID method_sessionStarted;
+static jmethodID method_sessionEnded;
+
+static jfieldID field_context;
+
+// MtpPropertyList fields
+static jfieldID field_mCount;
+static jfieldID field_mResult;
+static jfieldID field_mObjectHandles;
+static jfieldID field_mPropertyCodes;
+static jfieldID field_mDataTypes;
+static jfieldID field_mLongValues;
+static jfieldID field_mStringValues;
+
+
+MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
+    return (MtpDatabase *)env->GetIntField(database, field_context);
+}
+
+#ifdef HAVE_ANDROID_OS
+// ----------------------------------------------------------------------------
+
+class MyMtpDatabase : public MtpDatabase {
+private:
+    jobject         mDatabase;
+    jintArray       mIntBuffer;
+    jlongArray      mLongBuffer;
+    jcharArray      mStringBuffer;
+
+public:
+                                    MyMtpDatabase(JNIEnv *env, jobject client);
+    virtual                         ~MyMtpDatabase();
+    void                            cleanup(JNIEnv *env);
+
+    virtual MtpObjectHandle         beginSendObject(const char* path,
+                                            MtpObjectFormat format,
+                                            MtpObjectHandle parent,
+                                            MtpStorageID storage,
+                                            uint64_t size,
+                                            time_t modified);
+
+    virtual void                    endSendObject(const char* path,
+                                            MtpObjectHandle handle,
+                                            MtpObjectFormat format,
+                                            int64_t actualSize,
+                                            bool succeeded);
+
+    virtual MtpObjectHandleList*    getObjectList(MtpStorageID storageID,
+                                    MtpObjectFormat format,
+                                    MtpObjectHandle parent);
+
+    virtual int                     getNumObjects(MtpStorageID storageID,
+                                            MtpObjectFormat format,
+                                            MtpObjectHandle parent);
+
+    // callee should delete[] the results from these
+    // results can be NULL
+    virtual MtpObjectFormatList*    getSupportedPlaybackFormats();
+    virtual MtpObjectFormatList*    getSupportedCaptureFormats();
+    virtual MtpObjectPropertyList*  getSupportedObjectProperties(MtpObjectFormat format);
+    virtual MtpDevicePropertyList*  getSupportedDeviceProperties();
+
+    virtual MtpResponseCode         getObjectPropertyValue(MtpObjectHandle handle,
+                                            MtpObjectProperty property,
+                                            MtpDataPacket& packet);
+
+    virtual MtpResponseCode         setObjectPropertyValue(MtpObjectHandle handle,
+                                            MtpObjectProperty property,
+                                            MtpDataPacket& packet);
+
+    virtual MtpResponseCode         getDevicePropertyValue(MtpDeviceProperty property,
+                                            MtpDataPacket& packet);
+
+    virtual MtpResponseCode         setDevicePropertyValue(MtpDeviceProperty property,
+                                            MtpDataPacket& packet);
+
+    virtual MtpResponseCode         resetDeviceProperty(MtpDeviceProperty property);
+
+    virtual MtpResponseCode         getObjectPropertyList(MtpObjectHandle handle,
+                                            uint32_t format, uint32_t property,
+                                            int groupCode, int depth,
+                                            MtpDataPacket& packet);
+
+    virtual MtpResponseCode         getObjectInfo(MtpObjectHandle handle,
+                                            MtpDataPacket& packet);
+
+    virtual MtpResponseCode         getObjectFilePath(MtpObjectHandle handle,
+                                            MtpString& outFilePath,
+                                            int64_t& outFileLength,
+                                            MtpObjectFormat& outFormat);
+    virtual MtpResponseCode         deleteFile(MtpObjectHandle handle);
+
+    bool                            getObjectPropertyInfo(MtpObjectProperty property, int& type);
+    bool                            getDevicePropertyInfo(MtpDeviceProperty property, int& type);
+
+    virtual MtpObjectHandleList*    getObjectReferences(MtpObjectHandle handle);
+
+    virtual MtpResponseCode         setObjectReferences(MtpObjectHandle handle,
+                                            MtpObjectHandleList* references);
+
+    virtual MtpProperty*            getObjectPropertyDesc(MtpObjectProperty property,
+                                            MtpObjectFormat format);
+
+    virtual MtpProperty*            getDevicePropertyDesc(MtpDeviceProperty property);
+
+    virtual void                    sessionStarted();
+
+    virtual void                    sessionEnded();
+};
+
+// ----------------------------------------------------------------------------
+
+static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
+    if (env->ExceptionCheck()) {
+        LOGE("An exception was thrown by callback '%s'.", methodName);
+        LOGE_EX(env);
+        env->ExceptionClear();
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client)
+    :   mDatabase(env->NewGlobalRef(client)),
+        mIntBuffer(NULL),
+        mLongBuffer(NULL),
+        mStringBuffer(NULL)
+{
+    jintArray intArray;
+    jlongArray longArray;
+    jcharArray charArray;
+
+    // create buffers for out arguments
+    // we don't need to be thread-safe so this is OK
+    intArray = env->NewIntArray(3);
+    if (!intArray)
+        goto out_of_memory;
+    mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
+    longArray = env->NewLongArray(2);
+    if (!longArray)
+        goto out_of_memory;
+    mLongBuffer = (jlongArray)env->NewGlobalRef(longArray);
+    charArray = env->NewCharArray(256);
+    if (!charArray)
+        goto out_of_memory;
+    mStringBuffer = (jcharArray)env->NewGlobalRef(charArray);
+    return;
+
+out_of_memory:
+    env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), NULL);
+}
+
+void MyMtpDatabase::cleanup(JNIEnv *env) {
+    env->DeleteGlobalRef(mDatabase);
+    env->DeleteGlobalRef(mIntBuffer);
+    env->DeleteGlobalRef(mLongBuffer);
+    env->DeleteGlobalRef(mStringBuffer);
+}
+
+MyMtpDatabase::~MyMtpDatabase() {
+}
+
+MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
+                                            MtpObjectFormat format,
+                                            MtpObjectHandle parent,
+                                            MtpStorageID storage,
+                                            uint64_t size,
+                                            time_t modified) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jstring pathStr = env->NewStringUTF(path);
+    MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
+            pathStr, (jint)format, (jint)parent, (jint)storage,
+            (jlong)size, (jlong)modified);
+
+    if (pathStr)
+        env->DeleteLocalRef(pathStr);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return result;
+}
+
+void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
+                                MtpObjectFormat format, int64_t actualSize, bool succeeded) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jstring pathStr = env->NewStringUTF(path);
+    env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
+                        (jint)handle, (jint)format, (jlong)actualSize, (jboolean)succeeded);
+
+    if (pathStr)
+        env->DeleteLocalRef(pathStr);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+}
+
+MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
+                                    MtpObjectFormat format,
+                                    MtpObjectHandle parent) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
+                (jint)storageID, (jint)format, (jint)parent);
+    if (!array)
+        return NULL;
+    MtpObjectHandleList* list = new MtpObjectHandleList();
+    jint* handles = env->GetIntArrayElements(array, 0);
+    jsize length = env->GetArrayLength(array);
+    for (int i = 0; i < length; i++)
+        list->push(handles[i]);
+    env->ReleaseIntArrayElements(array, handles, 0);
+    env->DeleteLocalRef(array);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return list;
+}
+
+int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
+                                MtpObjectFormat format,
+                                MtpObjectHandle parent) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    int result = env->CallIntMethod(mDatabase, method_getNumObjects,
+                (jint)storageID, (jint)format, (jint)parent);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return result;
+}
+
+MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
+            method_getSupportedPlaybackFormats);
+    if (!array)
+        return NULL;
+    MtpObjectFormatList* list = new MtpObjectFormatList();
+    jint* formats = env->GetIntArrayElements(array, 0);
+    jsize length = env->GetArrayLength(array);
+    for (int i = 0; i < length; i++)
+        list->push(formats[i]);
+    env->ReleaseIntArrayElements(array, formats, 0);
+    env->DeleteLocalRef(array);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return list;
+}
+
+MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
+            method_getSupportedCaptureFormats);
+    if (!array)
+        return NULL;
+    MtpObjectFormatList* list = new MtpObjectFormatList();
+    jint* formats = env->GetIntArrayElements(array, 0);
+    jsize length = env->GetArrayLength(array);
+    for (int i = 0; i < length; i++)
+        list->push(formats[i]);
+    env->ReleaseIntArrayElements(array, formats, 0);
+    env->DeleteLocalRef(array);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return list;
+}
+
+MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
+            method_getSupportedObjectProperties, (jint)format);
+    if (!array)
+        return NULL;
+    MtpObjectPropertyList* list = new MtpObjectPropertyList();
+    jint* properties = env->GetIntArrayElements(array, 0);
+    jsize length = env->GetArrayLength(array);
+    for (int i = 0; i < length; i++)
+        list->push(properties[i]);
+    env->ReleaseIntArrayElements(array, properties, 0);
+    env->DeleteLocalRef(array);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return list;
+}
+
+MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
+            method_getSupportedDeviceProperties);
+    if (!array)
+        return NULL;
+    MtpDevicePropertyList* list = new MtpDevicePropertyList();
+    jint* properties = env->GetIntArrayElements(array, 0);
+    jsize length = env->GetArrayLength(array);
+    for (int i = 0; i < length; i++)
+        list->push(properties[i]);
+    env->ReleaseIntArrayElements(array, properties, 0);
+    env->DeleteLocalRef(array);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return list;
+}
+
+MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
+                                            MtpObjectProperty property,
+                                            MtpDataPacket& packet) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
+                (jlong)handle, 0, (jlong)property, 0, 0);
+    MtpResponseCode result = env->GetIntField(list, field_mResult);
+    int count = env->GetIntField(list, field_mCount);
+    if (result == MTP_RESPONSE_OK && count != 1)
+        result = MTP_RESPONSE_GENERAL_ERROR;
+
+    if (result == MTP_RESPONSE_OK) {
+        jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
+        jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
+        jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
+        jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
+        jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
+
+        jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
+        jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
+        jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
+        jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
+
+        int type = dataTypes[0];
+        jlong longValue = (longValues ? longValues[0] : 0);
+
+        // special case date properties, which are strings to MTP
+        // but stored internally as a uint64
+        if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
+            char    date[20];
+            formatDateTime(longValue, date, sizeof(date));
+            packet.putString(date);
+            goto out;
+        }
+        // release date is stored internally as just the year
+        if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
+            char    date[20];
+            snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
+            packet.putString(date);
+            goto out;
+        }
+
+        switch (type) {
+            case MTP_TYPE_INT8:
+                packet.putInt8(longValue);
+                break;
+            case MTP_TYPE_UINT8:
+                packet.putUInt8(longValue);
+                break;
+            case MTP_TYPE_INT16:
+                packet.putInt16(longValue);
+                break;
+            case MTP_TYPE_UINT16:
+                packet.putUInt16(longValue);
+                break;
+            case MTP_TYPE_INT32:
+                packet.putInt32(longValue);
+                break;
+            case MTP_TYPE_UINT32:
+                packet.putUInt32(longValue);
+                break;
+            case MTP_TYPE_INT64:
+                packet.putInt64(longValue);
+                break;
+            case MTP_TYPE_UINT64:
+                packet.putUInt64(longValue);
+                break;
+            case MTP_TYPE_INT128:
+                packet.putInt128(longValue);
+                break;
+            case MTP_TYPE_UINT128:
+                packet.putInt128(longValue);
+                break;
+            case MTP_TYPE_STR:
+            {
+                jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
+                if (stringValue) {
+                    const char* str = env->GetStringUTFChars(stringValue, NULL);
+                    packet.putString(str);
+                    env->ReleaseStringUTFChars(stringValue, str);
+                } else {
+                    packet.putEmptyString();
+                }
+                break;
+             }
+            default:
+                LOGE("unsupported type in getObjectPropertyValue\n");
+                result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
+        }
+out:
+        env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
+        env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
+        env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
+        if (longValues)
+            env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
+
+        env->DeleteLocalRef(objectHandlesArray);
+        env->DeleteLocalRef(propertyCodesArray);
+        env->DeleteLocalRef(dataTypesArray);
+        if (longValuesArray)
+            env->DeleteLocalRef(longValuesArray);
+        if (stringValuesArray)
+            env->DeleteLocalRef(stringValuesArray);
+    }
+
+    env->DeleteLocalRef(list);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return result;
+}
+
+MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
+                                            MtpObjectProperty property,
+                                            MtpDataPacket& packet) {
+    int         type;
+
+    if (!getObjectPropertyInfo(property, type))
+        return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
+
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jlong longValue = 0;
+    jstring stringValue = NULL;
+
+    switch (type) {
+        case MTP_TYPE_INT8:
+            longValue = packet.getInt8();
+            break;
+        case MTP_TYPE_UINT8:
+            longValue = packet.getUInt8();
+            break;
+        case MTP_TYPE_INT16:
+            longValue = packet.getInt16();
+            break;
+        case MTP_TYPE_UINT16:
+            longValue = packet.getUInt16();
+            break;
+        case MTP_TYPE_INT32:
+            longValue = packet.getInt32();
+            break;
+        case MTP_TYPE_UINT32:
+            longValue = packet.getUInt32();
+            break;
+        case MTP_TYPE_INT64:
+            longValue = packet.getInt64();
+            break;
+        case MTP_TYPE_UINT64:
+            longValue = packet.getUInt64();
+            break;
+        case MTP_TYPE_STR:
+        {
+            MtpStringBuffer buffer;
+            packet.getString(buffer);
+            stringValue = env->NewStringUTF((const char *)buffer);
+            break;
+         }
+        default:
+            LOGE("unsupported type in getObjectPropertyValue\n");
+            return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
+    }
+
+    jint result = env->CallIntMethod(mDatabase, method_setObjectProperty,
+                (jint)handle, (jint)property, longValue, stringValue);
+    if (stringValue)
+        env->DeleteLocalRef(stringValue);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return result;
+}
+
+MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
+                                            MtpDataPacket& packet) {
+    int         type;
+
+    if (!getDevicePropertyInfo(property, type))
+        return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
+                (jint)property, mLongBuffer, mStringBuffer);
+    if (result != MTP_RESPONSE_OK) {
+        checkAndClearExceptionFromCallback(env, __FUNCTION__);
+        return result;
+    }
+
+    jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
+    jlong longValue = longValues[0];
+    env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
+
+    switch (type) {
+        case MTP_TYPE_INT8:
+            packet.putInt8(longValue);
+            break;
+        case MTP_TYPE_UINT8:
+            packet.putUInt8(longValue);
+            break;
+        case MTP_TYPE_INT16:
+            packet.putInt16(longValue);
+            break;
+        case MTP_TYPE_UINT16:
+            packet.putUInt16(longValue);
+            break;
+        case MTP_TYPE_INT32:
+            packet.putInt32(longValue);
+            break;
+        case MTP_TYPE_UINT32:
+            packet.putUInt32(longValue);
+            break;
+        case MTP_TYPE_INT64:
+            packet.putInt64(longValue);
+            break;
+        case MTP_TYPE_UINT64:
+            packet.putUInt64(longValue);
+            break;
+        case MTP_TYPE_INT128:
+            packet.putInt128(longValue);
+            break;
+        case MTP_TYPE_UINT128:
+            packet.putInt128(longValue);
+            break;
+        case MTP_TYPE_STR:
+        {
+            jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
+            packet.putString(str);
+            env->ReleaseCharArrayElements(mStringBuffer, str, 0);
+            break;
+         }
+        default:
+            LOGE("unsupported type in getDevicePropertyValue\n");
+            return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
+    }
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
+                                            MtpDataPacket& packet) {
+    int         type;
+
+    if (!getDevicePropertyInfo(property, type))
+        return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jlong longValue = 0;
+    jstring stringValue = NULL;
+
+    switch (type) {
+        case MTP_TYPE_INT8:
+            longValue = packet.getInt8();
+            break;
+        case MTP_TYPE_UINT8:
+            longValue = packet.getUInt8();
+            break;
+        case MTP_TYPE_INT16:
+            longValue = packet.getInt16();
+            break;
+        case MTP_TYPE_UINT16:
+            longValue = packet.getUInt16();
+            break;
+        case MTP_TYPE_INT32:
+            longValue = packet.getInt32();
+            break;
+        case MTP_TYPE_UINT32:
+            longValue = packet.getUInt32();
+            break;
+        case MTP_TYPE_INT64:
+            longValue = packet.getInt64();
+            break;
+        case MTP_TYPE_UINT64:
+            longValue = packet.getUInt64();
+            break;
+        case MTP_TYPE_STR:
+        {
+            MtpStringBuffer buffer;
+            packet.getString(buffer);
+            stringValue = env->NewStringUTF((const char *)buffer);
+            break;
+         }
+        default:
+            LOGE("unsupported type in setDevicePropertyValue\n");
+            return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
+    }
+
+    jint result = env->CallIntMethod(mDatabase, method_setDeviceProperty,
+                (jint)property, longValue, stringValue);
+    if (stringValue)
+        env->DeleteLocalRef(stringValue);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return result;
+}
+
+MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
+    return -1;
+}
+
+MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
+                                            uint32_t format, uint32_t property,
+                                            int groupCode, int depth,
+                                            MtpDataPacket& packet) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
+                (jlong)handle, (jint)format, (jlong)property, (jint)groupCode, (jint)depth);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    if (!list)
+        return MTP_RESPONSE_GENERAL_ERROR;
+    int count = env->GetIntField(list, field_mCount);
+    MtpResponseCode result = env->GetIntField(list, field_mResult);
+
+    packet.putUInt32(count);
+    if (count > 0) {
+        jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
+        jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
+        jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
+        jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
+        jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
+
+        jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
+        jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
+        jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
+        jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
+
+        for (int i = 0; i < count; i++) {
+            packet.putUInt32(objectHandles[i]);
+            packet.putUInt16(propertyCodes[i]);
+            int type = dataTypes[i];
+            packet.putUInt16(type);
+
+            switch (type) {
+                case MTP_TYPE_INT8:
+                    packet.putInt8(longValues[i]);
+                    break;
+                case MTP_TYPE_UINT8:
+                    packet.putUInt8(longValues[i]);
+                    break;
+                case MTP_TYPE_INT16:
+                    packet.putInt16(longValues[i]);
+                    break;
+                case MTP_TYPE_UINT16:
+                    packet.putUInt16(longValues[i]);
+                    break;
+                case MTP_TYPE_INT32:
+                    packet.putInt32(longValues[i]);
+                    break;
+                case MTP_TYPE_UINT32:
+                    packet.putUInt32(longValues[i]);
+                    break;
+                case MTP_TYPE_INT64:
+                    packet.putInt64(longValues[i]);
+                    break;
+                case MTP_TYPE_UINT64:
+                    packet.putUInt64(longValues[i]);
+                    break;
+                case MTP_TYPE_INT128:
+                    packet.putInt128(longValues[i]);
+                    break;
+                case MTP_TYPE_UINT128:
+                    packet.putUInt128(longValues[i]);
+                    break;
+                case MTP_TYPE_STR: {
+                    jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
+                    const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL);
+                    if (valueStr) {
+                        packet.putString(valueStr);
+                        env->ReleaseStringUTFChars(value, valueStr);
+                    } else {
+                        packet.putEmptyString();
+                    }
+                    env->DeleteLocalRef(value);
+                    break;
+                }
+                default:
+                    LOGE("bad or unsupported data type in MyMtpDatabase::getObjectPropertyList");
+                    break;
+            }
+        }
+
+        env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
+        env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
+        env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
+        if (longValues)
+            env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
+
+        env->DeleteLocalRef(objectHandlesArray);
+        env->DeleteLocalRef(propertyCodesArray);
+        env->DeleteLocalRef(dataTypesArray);
+        if (longValuesArray)
+            env->DeleteLocalRef(longValuesArray);
+        if (stringValuesArray)
+            env->DeleteLocalRef(stringValuesArray);
+    }
+
+    env->DeleteLocalRef(list);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return result;
+}
+
+MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
+                                            MtpDataPacket& packet) {
+    char    date[20];
+
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jboolean result = env->CallBooleanMethod(mDatabase, method_getObjectInfo,
+                (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer);
+    if (!result)
+        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+
+    jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
+    MtpStorageID storageID = intValues[0];
+    MtpObjectFormat format = intValues[1];
+    MtpObjectHandle parent = intValues[2];
+    env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
+
+    jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
+    uint64_t size = longValues[0];
+    uint64_t modified = longValues[1];
+    env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
+
+//    int associationType = (format == MTP_FORMAT_ASSOCIATION ?
+//                            MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
+//                            MTP_ASSOCIATION_TYPE_UNDEFINED);
+    int associationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
+
+    packet.putUInt32(storageID);
+    packet.putUInt16(format);
+    packet.putUInt16(0);   // protection status
+    packet.putUInt32((size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size));
+    packet.putUInt16(0);   // thumb format
+    packet.putUInt32(0);   // thumb compressed size
+    packet.putUInt32(0);   // thumb pix width
+    packet.putUInt32(0);   // thumb pix height
+    packet.putUInt32(0);   // image pix width
+    packet.putUInt32(0);   // image pix height
+    packet.putUInt32(0);   // image bit depth
+    packet.putUInt32(parent);
+    packet.putUInt16(associationType);
+    packet.putUInt32(0);   // association desc
+    packet.putUInt32(0);   // sequence number
+
+    jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
+    packet.putString(str);   // file name
+    env->ReleaseCharArrayElements(mStringBuffer, str, 0);
+
+    packet.putEmptyString();
+    formatDateTime(modified, date, sizeof(date));
+    packet.putString(date);   // date modified
+    packet.putEmptyString();   // keywords
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
+                                            MtpString& outFilePath,
+                                            int64_t& outFileLength,
+                                            MtpObjectFormat& outFormat) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
+                (jint)handle, mStringBuffer, mLongBuffer);
+    if (result != MTP_RESPONSE_OK) {
+        checkAndClearExceptionFromCallback(env, __FUNCTION__);
+        return result;
+    }
+
+    jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
+    outFilePath.setTo(str, strlen16(str));
+    env->ReleaseCharArrayElements(mStringBuffer, str, 0);
+
+    jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
+    outFileLength = longValues[0];
+    outFormat = longValues[1];
+    env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
+    
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return result;
+}
+
+MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    MtpResponseCode result = env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return result;
+}
+
+struct PropertyTableEntry {
+    MtpObjectProperty   property;
+    int                 type;
+};
+
+static const PropertyTableEntry   kObjectPropertyTable[] = {
+    {   MTP_PROPERTY_STORAGE_ID,        MTP_TYPE_UINT32     },
+    {   MTP_PROPERTY_OBJECT_FORMAT,     MTP_TYPE_UINT16     },
+    {   MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16     },
+    {   MTP_PROPERTY_OBJECT_SIZE,       MTP_TYPE_UINT64     },
+    {   MTP_PROPERTY_OBJECT_FILE_NAME,  MTP_TYPE_STR        },
+    {   MTP_PROPERTY_DATE_MODIFIED,     MTP_TYPE_STR        },
+    {   MTP_PROPERTY_PARENT_OBJECT,     MTP_TYPE_UINT32     },
+    {   MTP_PROPERTY_PERSISTENT_UID,    MTP_TYPE_UINT128    },
+    {   MTP_PROPERTY_NAME,              MTP_TYPE_STR        },
+    {   MTP_PROPERTY_DISPLAY_NAME,      MTP_TYPE_STR        },
+    {   MTP_PROPERTY_DATE_ADDED,        MTP_TYPE_STR        },
+    {   MTP_PROPERTY_ARTIST,            MTP_TYPE_STR        },
+    {   MTP_PROPERTY_ALBUM_NAME,        MTP_TYPE_STR        },
+    {   MTP_PROPERTY_ALBUM_ARTIST,      MTP_TYPE_STR        },
+    {   MTP_PROPERTY_TRACK,             MTP_TYPE_UINT16     },
+    {   MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR    },
+    {   MTP_PROPERTY_GENRE,             MTP_TYPE_STR        },
+    {   MTP_PROPERTY_COMPOSER,          MTP_TYPE_STR        },
+    {   MTP_PROPERTY_DURATION,          MTP_TYPE_UINT32     },
+    {   MTP_PROPERTY_DESCRIPTION,       MTP_TYPE_STR        },
+};
+
+static const PropertyTableEntry   kDevicePropertyTable[] = {
+    {   MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,    MTP_TYPE_STR },
+    {   MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,       MTP_TYPE_STR },
+    {   MTP_DEVICE_PROPERTY_IMAGE_SIZE,                 MTP_TYPE_STR },
+};
+
+bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
+    int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
+    const PropertyTableEntry* entry = kObjectPropertyTable;
+    for (int i = 0; i < count; i++, entry++) {
+        if (entry->property == property) {
+            type = entry->type;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
+    int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
+    const PropertyTableEntry* entry = kDevicePropertyTable;
+    for (int i = 0; i < count; i++, entry++) {
+        if (entry->property == property) {
+            type = entry->type;
+            return true;
+        }
+    }
+    return false;
+}
+
+MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
+                (jint)handle);
+    if (!array)
+        return NULL;
+    MtpObjectHandleList* list = new MtpObjectHandleList();
+    jint* handles = env->GetIntArrayElements(array, 0);
+    jsize length = env->GetArrayLength(array);
+    for (int i = 0; i < length; i++)
+        list->push(handles[i]);
+    env->ReleaseIntArrayElements(array, handles, 0);
+    env->DeleteLocalRef(array);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return list;
+}
+
+MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
+                                                    MtpObjectHandleList* references) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    int count = references->size();
+    jintArray array = env->NewIntArray(count);
+    if (!array) {
+        LOGE("out of memory in setObjectReferences");
+        return false;
+    }
+    jint* handles = env->GetIntArrayElements(array, 0);
+     for (int i = 0; i < count; i++)
+        handles[i] = (*references)[i];
+    env->ReleaseIntArrayElements(array, handles, 0);
+    MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
+                (jint)handle, array);
+    env->DeleteLocalRef(array);
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return result;
+}
+
+MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
+                                            MtpObjectFormat format) {
+    MtpProperty* result = NULL;
+    switch (property) {
+        case MTP_PROPERTY_OBJECT_FORMAT:
+            // use format as default value
+            result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
+            break;
+        case MTP_PROPERTY_PROTECTION_STATUS:
+        case MTP_PROPERTY_TRACK:
+            result = new MtpProperty(property, MTP_TYPE_UINT16);
+            break;
+        case MTP_PROPERTY_STORAGE_ID:
+        case MTP_PROPERTY_PARENT_OBJECT:
+        case MTP_PROPERTY_DURATION:
+            result = new MtpProperty(property, MTP_TYPE_UINT32);
+            break;
+        case MTP_PROPERTY_OBJECT_SIZE:
+            result = new MtpProperty(property, MTP_TYPE_UINT64);
+            break;
+        case MTP_PROPERTY_PERSISTENT_UID:
+            result = new MtpProperty(property, MTP_TYPE_UINT128);
+            break;
+        case MTP_PROPERTY_NAME:
+        case MTP_PROPERTY_DISPLAY_NAME:
+        case MTP_PROPERTY_ARTIST:
+        case MTP_PROPERTY_ALBUM_NAME:
+        case MTP_PROPERTY_ALBUM_ARTIST:
+        case MTP_PROPERTY_GENRE:
+        case MTP_PROPERTY_COMPOSER:
+        case MTP_PROPERTY_DESCRIPTION:
+            result = new MtpProperty(property, MTP_TYPE_STR);
+            break;
+        case MTP_PROPERTY_DATE_MODIFIED:
+        case MTP_PROPERTY_DATE_ADDED:
+        case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
+            result = new MtpProperty(property, MTP_TYPE_STR);
+            result->setFormDateTime();
+            break;
+        case MTP_PROPERTY_OBJECT_FILE_NAME:
+            // We allow renaming files and folders
+            result = new MtpProperty(property, MTP_TYPE_STR, true);
+            break;
+    }
+
+    return result;
+}
+
+MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    MtpProperty* result = NULL;
+    bool writable = false;
+
+    switch (property) {
+        case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
+        case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
+            writable = true;
+            // fall through
+        case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
+            result = new MtpProperty(property, MTP_TYPE_STR, writable);
+
+            // get current value
+            jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
+                        (jint)property, mLongBuffer, mStringBuffer);
+            if (ret == MTP_RESPONSE_OK) {
+                jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
+                result->setCurrentValue(str);
+                // for read-only properties it is safe to assume current value is default value
+                if (!writable)
+                    result->setDefaultValue(str);
+                env->ReleaseCharArrayElements(mStringBuffer, str, 0);
+            } else {
+                LOGE("unable to read device property, response: %04X", ret);
+            }
+            break;
+    }
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return result;
+}
+
+void MyMtpDatabase::sessionStarted() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mDatabase, method_sessionStarted);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+}
+
+void MyMtpDatabase::sessionEnded() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(mDatabase, method_sessionEnded);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+}
+
+#endif // HAVE_ANDROID_OS
+
+// ----------------------------------------------------------------------------
+
+static void
+android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
+{
+#ifdef HAVE_ANDROID_OS
+    LOGD("setup\n");
+    MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
+    env->SetIntField(thiz, field_context, (int)database);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+#endif
+}
+
+static void
+android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
+{
+#ifdef HAVE_ANDROID_OS
+    LOGD("finalize\n");
+    MyMtpDatabase* database = (MyMtpDatabase *)env->GetIntField(thiz, field_context);
+    database->cleanup(env);
+    delete database;
+    env->SetIntField(thiz, field_context, 0);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+#endif
+}
+
+static jstring
+android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject thiz, jlong seconds)
+{
+#ifdef HAVE_ANDROID_OS
+    char    date[20];
+    formatDateTime(seconds, date, sizeof(date));
+    return env->NewStringUTF(date);
+#else
+    return NULL;
+#endif
+}
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gMtpDatabaseMethods[] = {
+    {"native_setup",            "()V",  (void *)android_mtp_MtpDatabase_setup},
+    {"native_finalize",         "()V",  (void *)android_mtp_MtpDatabase_finalize},
+};
+
+static JNINativeMethod gMtpPropertyGroupMethods[] = {
+    {"format_date_time",        "(J)Ljava/lang/String;",
+                                        (void *)android_mtp_MtpPropertyGroup_format_date_time},
+};
+
+static const char* const kClassPathName = "android/mtp/MtpDatabase";
+
+int register_android_mtp_MtpDatabase(JNIEnv *env)
+{
+    jclass clazz;
+
+    LOGD("register_android_mtp_MtpDatabase\n");
+
+    clazz = env->FindClass("android/mtp/MtpDatabase");
+    if (clazz == NULL) {
+        LOGE("Can't find android/mtp/MtpDatabase");
+        return -1;
+    }
+    method_beginSendObject = env->GetMethodID(clazz, "beginSendObject", "(Ljava/lang/String;IIIJJ)I");
+    if (method_beginSendObject == NULL) {
+        LOGE("Can't find beginSendObject");
+        return -1;
+    }
+    method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIJZ)V");
+    if (method_endSendObject == NULL) {
+        LOGE("Can't find endSendObject");
+        return -1;
+    }
+    method_getObjectList = env->GetMethodID(clazz, "getObjectList", "(III)[I");
+    if (method_getObjectList == NULL) {
+        LOGE("Can't find getObjectList");
+        return -1;
+    }
+    method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
+    if (method_getNumObjects == NULL) {
+        LOGE("Can't find getNumObjects");
+        return -1;
+    }
+    method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
+    if (method_getSupportedPlaybackFormats == NULL) {
+        LOGE("Can't find getSupportedPlaybackFormats");
+        return -1;
+    }
+    method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
+    if (method_getSupportedCaptureFormats == NULL) {
+        LOGE("Can't find getSupportedCaptureFormats");
+        return -1;
+    }
+    method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
+    if (method_getSupportedObjectProperties == NULL) {
+        LOGE("Can't find getSupportedObjectProperties");
+        return -1;
+    }
+    method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
+    if (method_getSupportedDeviceProperties == NULL) {
+        LOGE("Can't find getSupportedDeviceProperties");
+        return -1;
+    }
+    method_setObjectProperty = env->GetMethodID(clazz, "setObjectProperty", "(IIJLjava/lang/String;)I");
+    if (method_setObjectProperty == NULL) {
+        LOGE("Can't find setObjectProperty");
+        return -1;
+    }
+    method_getDeviceProperty = env->GetMethodID(clazz, "getDeviceProperty", "(I[J[C)I");
+    if (method_getDeviceProperty == NULL) {
+        LOGE("Can't find getDeviceProperty");
+        return -1;
+    }
+    method_setDeviceProperty = env->GetMethodID(clazz, "setDeviceProperty", "(IJLjava/lang/String;)I");
+    if (method_setDeviceProperty == NULL) {
+        LOGE("Can't find setDeviceProperty");
+        return -1;
+    }
+    method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
+            "(JIJII)Landroid/mtp/MtpPropertyList;");
+    if (method_getObjectPropertyList == NULL) {
+        LOGE("Can't find getObjectPropertyList");
+        return -1;
+    }
+    method_getObjectInfo = env->GetMethodID(clazz, "getObjectInfo", "(I[I[C[J)Z");
+    if (method_getObjectInfo == NULL) {
+        LOGE("Can't find getObjectInfo");
+        return -1;
+    }
+    method_getObjectFilePath = env->GetMethodID(clazz, "getObjectFilePath", "(I[C[J)I");
+    if (method_getObjectFilePath == NULL) {
+        LOGE("Can't find getObjectFilePath");
+        return -1;
+    }
+    method_deleteFile = env->GetMethodID(clazz, "deleteFile", "(I)I");
+    if (method_deleteFile == NULL) {
+        LOGE("Can't find deleteFile");
+        return -1;
+    }
+    method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
+    if (method_getObjectReferences == NULL) {
+        LOGE("Can't find getObjectReferences");
+        return -1;
+    }
+    method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I");
+    if (method_setObjectReferences == NULL) {
+        LOGE("Can't find setObjectReferences");
+        return -1;
+    }
+    method_sessionStarted = env->GetMethodID(clazz, "sessionStarted", "()V");
+    if (method_sessionStarted == NULL) {
+        LOGE("Can't find sessionStarted");
+        return -1;
+    }
+    method_sessionEnded = env->GetMethodID(clazz, "sessionEnded", "()V");
+    if (method_sessionEnded == NULL) {
+        LOGE("Can't find sessionEnded");
+        return -1;
+    }
+
+    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (field_context == NULL) {
+        LOGE("Can't find MtpDatabase.mNativeContext");
+        return -1;
+    }
+
+    // now set up fields for MtpPropertyList class
+    clazz = env->FindClass("android/mtp/MtpPropertyList");
+    if (clazz == NULL) {
+        LOGE("Can't find android/mtp/MtpPropertyList");
+        return -1;
+    }
+    field_mCount = env->GetFieldID(clazz, "mCount", "I");
+    if (field_mCount == NULL) {
+        LOGE("Can't find MtpPropertyList.mCount");
+        return -1;
+    }
+    field_mResult = env->GetFieldID(clazz, "mResult", "I");
+    if (field_mResult == NULL) {
+        LOGE("Can't find MtpPropertyList.mResult");
+        return -1;
+    }
+    field_mObjectHandles = env->GetFieldID(clazz, "mObjectHandles", "[I");
+    if (field_mObjectHandles == NULL) {
+        LOGE("Can't find MtpPropertyList.mObjectHandles");
+        return -1;
+    }
+    field_mPropertyCodes = env->GetFieldID(clazz, "mPropertyCodes", "[I");
+    if (field_mPropertyCodes == NULL) {
+        LOGE("Can't find MtpPropertyList.mPropertyCodes");
+        return -1;
+    }
+    field_mDataTypes = env->GetFieldID(clazz, "mDataTypes", "[I");
+    if (field_mDataTypes == NULL) {
+        LOGE("Can't find MtpPropertyList.mDataTypes");
+        return -1;
+    }
+    field_mLongValues = env->GetFieldID(clazz, "mLongValues", "[J");
+    if (field_mLongValues == NULL) {
+        LOGE("Can't find MtpPropertyList.mLongValues");
+        return -1;
+    }
+    field_mStringValues = env->GetFieldID(clazz, "mStringValues", "[Ljava/lang/String;");
+    if (field_mStringValues == NULL) {
+        LOGE("Can't find MtpPropertyList.mStringValues");
+        return -1;
+    }
+
+    if (AndroidRuntime::registerNativeMethods(env,
+                "android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
+        return -1;
+
+    return AndroidRuntime::registerNativeMethods(env,
+                "android/mtp/MtpPropertyGroup", gMtpPropertyGroupMethods, NELEM(gMtpPropertyGroupMethods));
+}
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
new file mode 100644
index 0000000..241f18a
--- /dev/null
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "MtpServerJNI"
+#include "utils/Log.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <utils/threads.h>
+
+#ifdef HAVE_ANDROID_OS
+#include <linux/usb/f_mtp.h>
+#endif
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "private/android_filesystem_config.h"
+
+#include "MtpServer.h"
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+
+static jfieldID field_context;
+static Mutex    sMutex;
+
+// in android_mtp_MtpDatabase.cpp
+extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
+
+// ----------------------------------------------------------------------------
+
+#ifdef HAVE_ANDROID_OS
+
+static bool ExceptionCheck(void* env)
+{
+    return ((JNIEnv *)env)->ExceptionCheck();
+}
+
+class MtpThread : public Thread {
+private:
+    MtpDatabase*    mDatabase;
+    MtpServer*      mServer;
+    String8         mStoragePath;
+    uint64_t        mReserveSpace;
+    jobject         mJavaServer;
+    int             mFd;
+
+public:
+    MtpThread(MtpDatabase* database, const char* storagePath, uint64_t reserveSpace,
+                jobject javaServer)
+        :   mDatabase(database),
+            mServer(NULL),
+            mStoragePath(storagePath),
+            mReserveSpace(reserveSpace),
+            mJavaServer(javaServer),
+            mFd(-1)
+    {
+    }
+
+    void setPtpMode(bool usePtp) {
+        sMutex.lock();
+        if (mFd >= 0) {
+            ioctl(mFd, MTP_SET_INTERFACE_MODE,
+                    (usePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP));
+        } else {
+            int fd = open("/dev/mtp_usb", O_RDWR);
+            if (fd >= 0) {
+                ioctl(fd, MTP_SET_INTERFACE_MODE,
+                        (usePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP));
+                close(fd);
+            }
+        }
+        sMutex.unlock();
+    }
+
+    virtual bool threadLoop() {
+        sMutex.lock();
+        mFd = open("/dev/mtp_usb", O_RDWR);
+        printf("open returned %d\n", mFd);
+        if (mFd < 0) {
+            LOGE("could not open MTP driver\n");
+            sMutex.unlock();
+            return false;
+        }
+
+        mServer = new MtpServer(mFd, mDatabase, AID_MEDIA_RW, 0664, 0775);
+        mServer->addStorage(mStoragePath, mReserveSpace);
+        sMutex.unlock();
+
+        LOGD("MtpThread mServer->run");
+        mServer->run();
+
+        sMutex.lock();
+        close(mFd);
+        mFd = -1;
+        delete mServer;
+        mServer = NULL;
+
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        env->SetIntField(mJavaServer, field_context, 0);
+        env->DeleteGlobalRef(mJavaServer);
+        sMutex.unlock();
+
+        LOGD("threadLoop returning");
+        return false;
+    }
+
+    void sendObjectAdded(MtpObjectHandle handle) {
+        sMutex.lock();
+        if (mServer)
+            mServer->sendObjectAdded(handle);
+        sMutex.unlock();
+    }
+
+    void sendObjectRemoved(MtpObjectHandle handle) {
+        sMutex.lock();
+        if (mServer)
+            mServer->sendObjectRemoved(handle);
+        sMutex.unlock();
+    }
+};
+
+#endif // HAVE_ANDROID_OS
+
+static void
+android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase,
+        jstring storagePath, jlong reserveSpace)
+{
+#ifdef HAVE_ANDROID_OS
+    LOGD("setup\n");
+
+    MtpDatabase* database = getMtpDatabase(env, javaDatabase);
+    const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL);
+
+    MtpThread* thread = new MtpThread(database, storagePathStr,
+            reserveSpace, env->NewGlobalRef(thiz));
+    env->SetIntField(thiz, field_context, (int)thread);
+
+    env->ReleaseStringUTFChars(storagePath, storagePathStr);
+#endif
+}
+
+static void
+android_mtp_MtpServer_finalize(JNIEnv *env, jobject thiz)
+{
+    LOGD("finalize\n");
+}
+
+
+static void
+android_mtp_MtpServer_start(JNIEnv *env, jobject thiz)
+{
+#ifdef HAVE_ANDROID_OS
+    LOGD("start\n");
+    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
+    thread->run("MtpThread");
+#endif // HAVE_ANDROID_OS
+}
+
+static void
+android_mtp_MtpServer_stop(JNIEnv *env, jobject thiz)
+{
+#ifdef HAVE_ANDROID_OS
+    LOGD("stop\n");
+#endif
+}
+
+static void
+android_mtp_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
+{
+#ifdef HAVE_ANDROID_OS
+    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
+    if (thread)
+        thread->sendObjectAdded(handle);
+#endif
+}
+
+static void
+android_mtp_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
+{
+#ifdef HAVE_ANDROID_OS
+    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
+    if (thread)
+        thread->sendObjectRemoved(handle);
+#endif
+}
+
+static void
+android_mtp_MtpServer_set_ptp_mode(JNIEnv *env, jobject thiz, jboolean usePtp)
+{
+#ifdef HAVE_ANDROID_OS
+    LOGD("set_ptp_mode\n");
+    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
+    if (thread)
+        thread->setPtpMode(usePtp);
+ #endif
+}
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gMethods[] = {
+    {"native_setup",                "(Landroid/mtp/MtpDatabase;Ljava/lang/String;J)V",
+                                            (void *)android_mtp_MtpServer_setup},
+    {"native_finalize",             "()V",  (void *)android_mtp_MtpServer_finalize},
+    {"native_start",                "()V",  (void *)android_mtp_MtpServer_start},
+    {"native_stop",                 "()V",  (void *)android_mtp_MtpServer_stop},
+    {"native_send_object_added",    "(I)V", (void *)android_mtp_MtpServer_send_object_added},
+    {"native_send_object_removed",  "(I)V", (void *)android_mtp_MtpServer_send_object_removed},
+    {"native_set_ptp_mode",         "(Z)V", (void *)android_mtp_MtpServer_set_ptp_mode},
+};
+
+static const char* const kClassPathName = "android/mtp/MtpServer";
+
+int register_android_mtp_MtpServer(JNIEnv *env)
+{
+    jclass clazz;
+
+    LOGD("register_android_mtp_MtpServer\n");
+
+    clazz = env->FindClass("android/mtp/MtpServer");
+    if (clazz == NULL) {
+        LOGE("Can't find android/mtp/MtpServer");
+        return -1;
+    }
+    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (field_context == NULL) {
+        LOGE("Can't find MtpServer.mNativeContext");
+        return -1;
+    }
+
+    return AndroidRuntime::registerNativeMethods(env,
+                "android/mtp/MtpServer", gMethods, NELEM(gMethods));
+}
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index fef880b..1e2d6ce 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -81,10 +81,10 @@
     quit();
 
     Mutex::Autolock lock(&mLock);
+
     mChannels.clear();
     if (mChannelPool)
         delete [] mChannelPool;
-
     // clean up samples
     LOGV("clear samples");
     mSamples.clear();
@@ -96,8 +96,19 @@
 void SoundPool::addToRestartList(SoundChannel* channel)
 {
     Mutex::Autolock lock(&mRestartLock);
-    mRestart.push_back(channel);
-    mCondition.signal();
+    if (!mQuit) {
+        mRestart.push_back(channel);
+        mCondition.signal();
+    }
+}
+
+void SoundPool::addToStopList(SoundChannel* channel)
+{
+    Mutex::Autolock lock(&mRestartLock);
+    if (!mQuit) {
+        mStop.push_back(channel);
+        mCondition.signal();
+    }
 }
 
 int SoundPool::beginThread(void* arg)
@@ -114,17 +125,38 @@
         LOGV("awake");
         if (mQuit) break;
 
+        while (!mStop.empty()) {
+            SoundChannel* channel;
+            LOGV("Getting channel from stop list");
+            List<SoundChannel* >::iterator iter = mStop.begin();
+            channel = *iter;
+            mStop.erase(iter);
+            mRestartLock.unlock();
+            if (channel != 0) {
+                Mutex::Autolock lock(&mLock);
+                channel->stop();
+            }
+            mRestartLock.lock();
+            if (mQuit) break;
+        }
+
         while (!mRestart.empty()) {
             SoundChannel* channel;
             LOGV("Getting channel from list");
             List<SoundChannel*>::iterator iter = mRestart.begin();
             channel = *iter;
             mRestart.erase(iter);
-            if (channel) channel->nextEvent();
+            mRestartLock.unlock();
+            if (channel != 0) {
+                Mutex::Autolock lock(&mLock);
+                channel->nextEvent();
+            }
+            mRestartLock.lock();
             if (mQuit) break;
         }
     }
 
+    mStop.clear();
     mRestart.clear();
     mCondition.signal();
     mRestartLock.unlock();
@@ -208,43 +240,43 @@
 int SoundPool::play(int sampleID, float leftVolume, float rightVolume,
         int priority, int loop, float rate)
 {
-    LOGV("sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
+    LOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
             sampleID, leftVolume, rightVolume, priority, loop, rate);
     sp<Sample> sample;
     SoundChannel* channel;
     int channelID;
 
-    // scope for lock
-    {
-        Mutex::Autolock lock(&mLock);
+    Mutex::Autolock lock(&mLock);
 
-        // is sample ready?
-        sample = findSample(sampleID);
-        if ((sample == 0) || (sample->state() != Sample::READY)) {
-            LOGW("  sample %d not READY", sampleID);
-            return 0;
-        }
-
-        dump();
-
-        // allocate a channel
-        channel = allocateChannel(priority);
-
-        // no channel allocated - return 0
-        if (!channel) {
-            LOGV("No channel allocated");
-            return 0;
-        }
-
-        channelID = ++mNextChannelID;
+    if (mQuit) {
+        return 0;
+    }
+    // is sample ready?
+    sample = findSample(sampleID);
+    if ((sample == 0) || (sample->state() != Sample::READY)) {
+        LOGW("  sample %d not READY", sampleID);
+        return 0;
     }
 
-    LOGV("channel state = %d", channel->state());
+    dump();
+
+    // allocate a channel
+    channel = allocateChannel_l(priority);
+
+    // no channel allocated - return 0
+    if (!channel) {
+        LOGV("No channel allocated");
+        return 0;
+    }
+
+    channelID = ++mNextChannelID;
+
+    LOGV("play channel %p state = %d", channel, channel->state());
     channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate);
     return channelID;
 }
 
-SoundChannel* SoundPool::allocateChannel(int priority)
+SoundChannel* SoundPool::allocateChannel_l(int priority)
 {
     List<SoundChannel*>::iterator iter;
     SoundChannel* channel = NULL;
@@ -273,7 +305,7 @@
 }
 
 // move a channel from its current position to the front of the list
-void SoundPool::moveToFront(SoundChannel* channel)
+void SoundPool::moveToFront_l(SoundChannel* channel)
 {
     for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
         if (*iter == channel) {
@@ -378,10 +410,9 @@
 }
 
 // call with lock held
-void SoundPool::done(SoundChannel* channel)
+void SoundPool::done_l(SoundChannel* channel)
 {
-    LOGV("done(%d)", channel->channelID());
-
+    LOGV("done_l(%d)", channel->channelID());
     // if "stolen", play next event
     if (channel->nextChannelID() != 0) {
         LOGV("add to restart list");
@@ -391,7 +422,7 @@
     // return to idle state
     else {
         LOGV("move to front");
-        moveToFront(channel);
+        moveToFront_l(channel);
     }
 }
 
@@ -511,81 +542,88 @@
     mSoundPool = soundPool;
 }
 
+// call with sound pool lock held
 void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
         float rightVolume, int priority, int loop, float rate)
 {
     AudioTrack* oldTrack;
+    AudioTrack* newTrack;
+    status_t status;
 
-    LOGV("play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
-            this, sample->sampleID(), nextChannelID, leftVolume, rightVolume, priority, loop, rate);
+    { // scope for the lock
+        Mutex::Autolock lock(&mLock);
 
-    // if not idle, this voice is being stolen
-    if (mState != IDLE) {
-        LOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
-        mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
-        stop();
-        return;
-    }
+        LOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f,"
+                " priority=%d, loop=%d, rate=%f",
+                this, sample->sampleID(), nextChannelID, leftVolume, rightVolume,
+                priority, loop, rate);
 
-    // initialize track
-    int afFrameCount;
-    int afSampleRate;
-    int streamType = mSoundPool->streamType();
-    if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
-        afFrameCount = kDefaultFrameCount;
-    }
-    if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
-        afSampleRate = kDefaultSampleRate;
-    }
-    int numChannels = sample->numChannels();
-    uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
-    uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate;
-    uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
-    uint32_t frameCount = 0;
+        // if not idle, this voice is being stolen
+        if (mState != IDLE) {
+            LOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
+            mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
+            stop_l();
+            return;
+        }
 
-    if (loop) {
-        frameCount = sample->size()/numChannels/((sample->format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
-    }
+        // initialize track
+        int afFrameCount;
+        int afSampleRate;
+        int streamType = mSoundPool->streamType();
+        if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
+            afFrameCount = kDefaultFrameCount;
+        }
+        if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
+            afSampleRate = kDefaultSampleRate;
+        }
+        int numChannels = sample->numChannels();
+        uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
+        uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate;
+        uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
+        uint32_t frameCount = 0;
+
+        if (loop) {
+            frameCount = sample->size()/numChannels/
+                ((sample->format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
+        }
 
 #ifndef USE_SHARED_MEM_BUFFER
-    // Ensure minimum audio buffer size in case of short looped sample
-    if(frameCount < totalFrames) {
-        frameCount = totalFrames;
-    }
+        // Ensure minimum audio buffer size in case of short looped sample
+        if(frameCount < totalFrames) {
+            frameCount = totalFrames;
+        }
 #endif
 
-    AudioTrack* newTrack;
+        // mToggle toggles each time a track is started on a given channel.
+        // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
+        // as callback user data. This enables the detection of callbacks received from the old
+        // audio track while the new one is being started and avoids processing them with
+        // wrong audio audio buffer size  (mAudioBufferSize)
+        unsigned long toggle = mToggle ^ 1;
+        void *userData = (void *)((unsigned long)this | toggle);
+        uint32_t channels = (numChannels == 2) ?
+                AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO;
 
-    // mToggle toggles each time a track is started on a given channel.
-    // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
-    // as callback user data. This enables the detection of callbacks received from the old
-    // audio track while the new one is being started and avoids processing them with 
-    // wrong audio audio buffer size  (mAudioBufferSize)
-    unsigned long toggle = mToggle ^ 1;
-    void *userData = (void *)((unsigned long)this | toggle);
-    uint32_t channels = (numChannels == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO;
-
+        // do not create a new audio track if current track is compatible with sample parameters
 #ifdef USE_SHARED_MEM_BUFFER
-    newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
-            channels, sample->getIMemory(), 0, callback, userData);
+        newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
+                channels, sample->getIMemory(), 0, callback, userData);
 #else
-    newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
-            channels, frameCount, 0, callback, userData, bufferFrames);
+        newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
+                channels, frameCount, 0, callback, userData, bufferFrames);
 #endif
-    if (newTrack->initCheck() != NO_ERROR) {
-        LOGE("Error creating AudioTrack");
-        delete newTrack;
-        return;
-    }
-    LOGV("setVolume %p", newTrack);
-    newTrack->setVolume(leftVolume, rightVolume);
-    newTrack->setLoop(0, frameCount, loop);
+        oldTrack = mAudioTrack;
+        status = newTrack->initCheck();
+        if (status != NO_ERROR) {
+            LOGE("Error creating AudioTrack");
+            goto exit;
+        }
+        LOGV("setVolume %p", newTrack);
+        newTrack->setVolume(leftVolume, rightVolume);
+        newTrack->setLoop(0, frameCount, loop);
 
-    {
-        Mutex::Autolock lock(&mLock);
         // From now on, AudioTrack callbacks recevieved with previous toggle value will be ignored.
         mToggle = toggle;
-        oldTrack = mAudioTrack;
         mAudioTrack = newTrack;
         mPos = 0;
         mSample = sample;
@@ -602,8 +640,13 @@
         mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize();
     }
 
+exit:
     LOGV("delete oldTrack %p", oldTrack);
     delete oldTrack;
+    if (status != NO_ERROR) {
+        delete newTrack;
+        mAudioTrack = NULL;
+    }
 }
 
 void SoundChannel::nextEvent()
@@ -639,29 +682,44 @@
 
 void SoundChannel::callback(int event, void* user, void *info)
 {
-    unsigned long toggle = (unsigned long)user & 1;
     SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1));
     
-    if (channel->mToggle != toggle) {
-        LOGV("callback with wrong toggle");
-        return;
-    }
-    channel->process(event, info);
+    channel->process(event, info, (unsigned long)user & 1);
 }
 
-void SoundChannel::process(int event, void *info)
+void SoundChannel::process(int event, void *info, unsigned long toggle)
 {
     //LOGV("process(%d)", mChannelID);
+
+    Mutex::Autolock lock(&mLock);
+
+    AudioTrack::Buffer* b = NULL;
+    if (event == AudioTrack::EVENT_MORE_DATA) {
+       b = static_cast<AudioTrack::Buffer *>(info);
+    }
+
+    if (mToggle != toggle) {
+        LOGV("process wrong toggle %p channel %d", this, mChannelID);
+        if (b != NULL) {
+            b->size = 0;
+        }
+        return;
+    }
+
     sp<Sample> sample = mSample;
 
 //    LOGV("SoundChannel::process event %d", event);
 
     if (event == AudioTrack::EVENT_MORE_DATA) {
-       AudioTrack::Buffer* b = static_cast<AudioTrack::Buffer *>(info);
 
         // check for stop state
         if (b->size == 0) return;
 
+        if (mState == IDLE) {
+            b->size = 0;
+            return;
+        }
+
         if (sample != 0) {
             // fill buffer
             uint8_t* q = (uint8_t*) b->i8;
@@ -674,14 +732,14 @@
                     count = b->size;
                 }
                 memcpy(q, p, count);
-                LOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, count);
+//              LOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, count);
             } else if (mPos < mAudioBufferSize) {
                 count = mAudioBufferSize - mPos;
                 if (count > b->size) {
                     count = b->size;
                 }
                 memset(q, 0, count);
-                LOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count);
+//              LOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count);
             }
 
             mPos += count;
@@ -689,16 +747,16 @@
             //LOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]);
         }
     } else if (event == AudioTrack::EVENT_UNDERRUN) {
-        LOGV("stopping track");
-        stop();
+        LOGV("process %p channel %d EVENT_UNDERRUN", this, mChannelID);
+        mSoundPool->addToStopList(this);
     } else if (event == AudioTrack::EVENT_LOOP_END) {
-        LOGV("End loop: %d", *(int *)info);
+        LOGV("End loop %p channel %d count %d", this, mChannelID, *(int *)info);
     }
 }
 
 
 // call with lock held
-void SoundChannel::stop_l()
+bool SoundChannel::doStop_l()
 {
     if (mState != IDLE) {
         setVolume_l(0, 0);
@@ -707,16 +765,31 @@
         mSample.clear();
         mState = IDLE;
         mPriority = IDLE_PRIORITY;
+        return true;
+    }
+    return false;
+}
+
+// call with lock held and sound pool lock held
+void SoundChannel::stop_l()
+{
+    if (doStop_l()) {
+        mSoundPool->done_l(this);
     }
 }
 
+// call with sound pool lock held
 void SoundChannel::stop()
 {
+    bool stopped;
     {
         Mutex::Autolock lock(&mLock);
-        stop_l();
+        stopped = doStop_l();
     }
-    mSoundPool->done(this);
+
+    if (stopped) {
+        mSoundPool->done_l(this);
+    }
 }
 
 //FIXME: Pause is a little broken right now
@@ -791,21 +864,24 @@
 {
     Mutex::Autolock lock(&mLock);
     if (mAudioTrack != 0 && mSample.get() != 0) {
-        mAudioTrack->setLoop(0, mSample->size()/mNumChannels/((mSample->format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t)), loop);
+        uint32_t loopEnd = mSample->size()/mNumChannels/
+            ((mSample->format() == AudioSystem::PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
+        mAudioTrack->setLoop(0, loopEnd, loop);
         mLoop = loop;
     }
 }
 
 SoundChannel::~SoundChannel()
 {
-    LOGV("SoundChannel destructor");
-    if (mAudioTrack) {
-        LOGV("stop track");
-        mAudioTrack->stop();
-        delete mAudioTrack;
+    LOGV("SoundChannel destructor %p", this);
+    {
+        Mutex::Autolock lock(&mLock);
+        clearNextEvent();
+        doStop_l();
     }
-    clearNextEvent();
-    mSample.clear();
+    // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack
+    // callback thread to exit which may need to execute process() and acquire the mLock.
+    delete mAudioTrack;
 }
 
 void SoundChannel::dump()
@@ -817,7 +893,7 @@
 void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume,
             float rightVolume, int priority, int loop, float rate)
 {
-    mSample =sample;
+    mSample = sample;
     mChannelID = channelID;
     mLeftVolume = leftVolume;
     mRightVolume = rightVolume;
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index 1b0fd38..6010aac 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -142,7 +142,8 @@
 
 private:
     static void callback(int event, void* user, void *info);
-    void process(int event, void *info);
+    void process(int event, void *info, unsigned long toggle);
+    bool doStop_l();
 
     SoundPool*          mSoundPool;
     AudioTrack*         mAudioTrack;
@@ -184,7 +185,7 @@
     void sampleLoaded(int sampleID);
 
     // called from AudioTrack thread
-    void done(SoundChannel* channel);
+    void done_l(SoundChannel* channel);
 
     // callback function
     void setCallback(SoundPoolCallback* callback, void* user);
@@ -197,13 +198,14 @@
     sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
     SoundChannel* findChannel (int channelID);
     SoundChannel* findNextChannel (int channelID);
-    SoundChannel* allocateChannel(int priority);
-    void moveToFront(SoundChannel* channel);
+    SoundChannel* allocateChannel_l(int priority);
+    void moveToFront_l(SoundChannel* channel);
     void notify(SoundPoolEvent event);
     void dump();
 
     // restart thread
     void addToRestartList(SoundChannel* channel);
+    void addToStopList(SoundChannel* channel);
     static int beginThread(void* arg);
     int run();
     void quit();
@@ -215,6 +217,7 @@
     SoundChannel*           mChannelPool;
     List<SoundChannel*>     mChannels;
     List<SoundChannel*>     mRestart;
+    List<SoundChannel*>     mStop;
     DefaultKeyedVector< int, sp<Sample> >   mSamples;
     int                     mMaxChannels;
     int                     mStreamType;
diff --git a/media/jni/soundpool/SoundPoolThread.h b/media/jni/soundpool/SoundPoolThread.h
index bbd35e0..d388388 100644
--- a/media/jni/soundpool/SoundPoolThread.h
+++ b/media/jni/soundpool/SoundPoolThread.h
@@ -31,10 +31,8 @@
     SoundPoolMsg() : mMessageType(INVALID), mData(0) {}
     SoundPoolMsg(MessageType MessageType, int data) :
         mMessageType(MessageType), mData(data) {}
-    uint8_t         mMessageType;
-    uint8_t         mData;
-    uint8_t         mData2;
-    uint8_t         mData3;
+    uint16_t         mMessageType;
+    uint16_t         mData;
 };
 
 /*
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index 0193e25..d5298c9 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -81,7 +81,6 @@
     DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
     SET_DATA_SOURCE_URL,
     SET_DATA_SOURCE_FD,
-    SET_MODE,
     GET_FRAME_AT_TIME,
     EXTRACT_ALBUM_ART,
     EXTRACT_METADATA,
@@ -123,15 +122,6 @@
         return reply.readInt32();
     }
 
-    status_t setMode(int mode)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
-        data.writeInt32(mode);
-        remote()->transact(SET_MODE, data, &reply);
-        return reply.readInt32();
-    }
-
     sp<IMemory> getFrameAtTime(int64_t timeUs, int option)
     {
         LOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
@@ -209,12 +199,6 @@
             reply->writeInt32(setDataSource(fd, offset, length));
             return NO_ERROR;
         } break;
-        case SET_MODE: {
-            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
-            int mode = data.readInt32();
-            reply->writeInt32(setMode(mode));
-            return NO_ERROR;
-        } break;
         case GET_FRAME_AT_TIME: {
             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
             int64_t timeUs = data.readInt64();
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index c31b622..5ec573e 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -84,6 +84,7 @@
     // place to copy file or directory name
     char* fileSpot = path + strlen(path);
     struct dirent* entry;
+    struct stat statbuf;
 
     // ignore directories that contain a  ".nomedia" file
     if (pathRemaining >= 8 /* strlen(".nomedia") */ ) {
@@ -125,7 +126,6 @@
             // If the type is unknown, stat() the file instead.
             // This is sometimes necessary when accessing NFS mounted filesystems, but
             // could be needed in other cases well.
-            struct stat statbuf;
             if (stat(path, &statbuf) == 0) {
                 if (S_ISREG(statbuf.st_mode)) {
                     type = DT_REG;
@@ -142,8 +142,15 @@
                 // for example, the Mac ".Trashes" directory
                 if (name[0] == '.') continue;
 
+                // report the directory to the client
+                if (stat(path, &statbuf) == 0) {
+                    client.scanFile(path, statbuf.st_mtime, 0, true);
+                }
+
+                // and now process its contents
                 strcat(fileSpot, "/");
-                int err = doProcessDirectory(path, pathRemaining - nameLength - 1, client, exceptionCheck, exceptionEnv);
+                int err = doProcessDirectory(path, pathRemaining - nameLength - 1, client,
+                        exceptionCheck, exceptionEnv);
                 if (err) {
                     // pass exceptions up - ignore other errors
                     if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
@@ -151,11 +158,8 @@
                     continue;
                 }
             } else {
-                struct stat statbuf;
                 stat(path, &statbuf);
-                if (statbuf.st_size > 0) {
-                    client.scanFile(path, statbuf.st_mtime, statbuf.st_size);
-                }
+                client.scanFile(path, statbuf.st_mtime, statbuf.st_size, false);
                 if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
             }
         }
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 39b5bc3..8dfcb3b 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -123,17 +123,6 @@
     return mRetriever->setDataSource(fd, offset, length);
 }
 
-status_t MediaMetadataRetriever::setMode(int mode)
-{
-    LOGV("setMode(%d)", mode);
-    Mutex::Autolock _l(mLock);
-    if (mRetriever == 0) {
-        LOGE("retriever is not initialized");
-        return INVALID_OPERATION;
-    }
-    return mRetriever->setMode(mode);
-}
-
 sp<IMemory> MediaMetadataRetriever::getFrameAtTime(int64_t timeUs, int option)
 {
     LOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option);
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index a098d69..87c8fe4 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -607,7 +607,9 @@
     case MEDIA_INFO:
         // ext1: Media framework error code.
         // ext2: Implementation dependant error code.
-        LOGW("info/warning (%d, %d)", ext1, ext2);
+        if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
+            LOGW("info/warning (%d, %d)", ext1, ext2);
+        }
         break;
     case MEDIA_SEEK_COMPLETE:
         LOGV("Received seek complete");
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 6f011ce..439e4ce 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -732,6 +732,21 @@
         return TEST_PLAYER;
     }
 
+    char value[PROPERTY_VALUE_MAX];
+    if (!property_get("media.httplive.disable-nuplayer", value, NULL)
+            || (strcasecmp(value, "true") && strcmp(value, "1"))) {
+        if (!strncasecmp("http://", url, 7)) {
+            size_t len = strlen(url);
+            if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
+                return NU_PLAYER;
+            }
+
+            if (strstr(url,"m3u8")) {
+                return NU_PLAYER;
+            }
+        }
+    }
+
     // use MidiFile for MIDI extensions
     int lenURL = strlen(url);
     for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index abaec02..5fcf2a7 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -64,7 +64,6 @@
     mThumbnail = NULL;
     mAlbumArt = NULL;
     mRetriever = NULL;
-    mMode = METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL;
 }
 
 MetadataRetrieverClient::~MetadataRetrieverClient()
@@ -79,7 +78,7 @@
     char buffer[SIZE];
     String8 result;
     result.append(" MetadataRetrieverClient\n");
-    snprintf(buffer, 255, "  pid(%d) mode(%d)\n", mPid, mMode);
+    snprintf(buffer, 255, "  pid(%d)\n", mPid);
     result.append(buffer);
     write(fd, result.string(), result.size());
     write(fd, "\n", 1);
@@ -93,7 +92,6 @@
     mRetriever.clear();
     mThumbnail.clear();
     mAlbumArt.clear();
-    mMode = METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL;
     IPCThreadState::self()->flushCommands();
 }
 
@@ -133,10 +131,7 @@
     LOGV("player type = %d", playerType);
     sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
     if (p == NULL) return NO_INIT;
-    status_t ret = p->setMode(mMode);
-    if (ret == NO_ERROR) {
-        ret = p->setDataSource(url);
-    }
+    status_t ret = p->setDataSource(url);
     if (ret == NO_ERROR) mRetriever = p;
     return ret;
 }
@@ -174,28 +169,12 @@
         ::close(fd);
         return NO_INIT;
     }
-    status_t status = p->setMode(mMode);
-    if (status == NO_ERROR) {
-        p->setDataSource(fd, offset, length);
-    }
+    status_t status = p->setDataSource(fd, offset, length);
     if (status == NO_ERROR) mRetriever = p;
     ::close(fd);
     return status;
 }
 
-status_t MetadataRetrieverClient::setMode(int mode)
-{
-    LOGV("setMode");
-    Mutex::Autolock lock(mLock);
-    if (mode < METADATA_MODE_NOOP ||
-        mode > METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL) {
-        LOGE("invalid mode %d", mode);
-        return BAD_VALUE;
-    }
-    mMode = mode;
-    return NO_ERROR;
-}
-
 sp<IMemory> MetadataRetrieverClient::getFrameAtTime(int64_t timeUs, int option)
 {
     LOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option);
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
index 8b4c0c7..b834715 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.h
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -43,7 +43,6 @@
     virtual void                    disconnect();
     virtual status_t                setDataSource(const char *url);
     virtual status_t                setDataSource(int fd, int64_t offset, int64_t length);
-    virtual status_t                setMode(int mode);
     virtual sp<IMemory>             getFrameAtTime(int64_t timeUs, int option);
     virtual sp<IMemory>             extractAlbumArt();
     virtual const char*             extractMetadata(int keyCode);
@@ -59,7 +58,6 @@
     mutable Mutex                          mLock;
     sp<MediaMetadataRetrieverBase>         mRetriever;
     pid_t                                  mPid;
-    int                                    mMode;
 
     // Keep the shared memory copy of album art and capture frame (for thumbnail)
     sp<IMemory>                            mAlbumArt;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 576b009..992abd7 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -358,6 +358,8 @@
 
 status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
     LOGV("setParamMaxFileDurationUs: %lld us", timeUs);
+
+    // This is meant for backward compatibility for MediaRecorder.java
     if (timeUs <= 0) {
         LOGW("Max file duration is not positive: %lld us. Disabling duration limit.", timeUs);
         timeUs = 0; // Disable the duration limit for zero or negative values.
@@ -375,7 +377,13 @@
 
 status_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
     LOGV("setParamMaxFileSizeBytes: %lld bytes", bytes);
-    if (bytes <= 1024) {  // XXX: 1 kB
+
+    // This is meant for backward compatibility for MediaRecorder.java
+    if (bytes <= 0) {
+        LOGW("Max file size is not positive: %lld bytes. "
+             "Disabling file size limit.", bytes);
+        bytes = 0; // Disable the file size limit for zero or negative values.
+    } else if (bytes <= 1024) {  // XXX: 1 kB
         LOGE("Max file size is too small: %lld bytes", bytes);
         return BAD_VALUE;
     }
@@ -838,27 +846,12 @@
                     mAudioEncoder);
             return BAD_VALUE;
         }
-        if (mSampleRate != 8000) {
-            LOGE("Invalid sampling rate %d used for AMRNB recording",
-                    mSampleRate);
-            return BAD_VALUE;
-        }
     } else {  // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
         if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
             LOGE("Invlaid encoder %d used for AMRWB recording",
                     mAudioEncoder);
             return BAD_VALUE;
         }
-        if (mSampleRate != 16000) {
-            LOGE("Invalid sample rate %d used for AMRWB recording",
-                    mSampleRate);
-            return BAD_VALUE;
-        }
-    }
-    if (mAudioChannels != 1) {
-        LOGE("Invalid number of audio channels %d used for amr recording",
-                mAudioChannels);
-        return BAD_VALUE;
     }
 
     if (mAudioSource >= AUDIO_SOURCE_LIST_END) {
@@ -866,8 +859,12 @@
         return BAD_VALUE;
     }
 
-    sp<MediaSource> audioEncoder = createAudioSource();
+    status_t status = BAD_VALUE;
+    if (OK != (status = checkAudioEncoderCapabilities())) {
+        return status;
+    }
 
+    sp<MediaSource> audioEncoder = createAudioSource();
     if (audioEncoder == NULL) {
         return UNKNOWN_ERROR;
     }
@@ -1042,6 +1039,79 @@
     return OK;
 }
 
+status_t StagefrightRecorder::checkAudioEncoderCapabilities() {
+    clipAudioBitRate();
+    clipAudioSampleRate();
+    clipNumberOfAudioChannels();
+    return OK;
+}
+
+void StagefrightRecorder::clipAudioBitRate() {
+    LOGV("clipAudioBitRate: encoder %d", mAudioEncoder);
+
+    int minAudioBitRate =
+            mEncoderProfiles->getAudioEncoderParamByName(
+                "enc.aud.bps.min", mAudioEncoder);
+    if (mAudioBitRate < minAudioBitRate) {
+        LOGW("Intended audio encoding bit rate (%d) is too small"
+            " and will be set to (%d)", mAudioBitRate, minAudioBitRate);
+        mAudioBitRate = minAudioBitRate;
+    }
+
+    int maxAudioBitRate =
+            mEncoderProfiles->getAudioEncoderParamByName(
+                "enc.aud.bps.max", mAudioEncoder);
+    if (mAudioBitRate > maxAudioBitRate) {
+        LOGW("Intended audio encoding bit rate (%d) is too large"
+            " and will be set to (%d)", mAudioBitRate, maxAudioBitRate);
+        mAudioBitRate = maxAudioBitRate;
+    }
+}
+
+void StagefrightRecorder::clipAudioSampleRate() {
+    LOGV("clipAudioSampleRate: encoder %d", mAudioEncoder);
+
+    int minSampleRate =
+            mEncoderProfiles->getAudioEncoderParamByName(
+                "enc.aud.hz.min", mAudioEncoder);
+    if (mSampleRate < minSampleRate) {
+        LOGW("Intended audio sample rate (%d) is too small"
+            " and will be set to (%d)", mSampleRate, minSampleRate);
+        mSampleRate = minSampleRate;
+    }
+
+    int maxSampleRate =
+            mEncoderProfiles->getAudioEncoderParamByName(
+                "enc.aud.hz.max", mAudioEncoder);
+    if (mSampleRate > maxSampleRate) {
+        LOGW("Intended audio sample rate (%d) is too large"
+            " and will be set to (%d)", mSampleRate, maxSampleRate);
+        mSampleRate = maxSampleRate;
+    }
+}
+
+void StagefrightRecorder::clipNumberOfAudioChannels() {
+    LOGV("clipNumberOfAudioChannels: encoder %d", mAudioEncoder);
+
+    int minChannels =
+            mEncoderProfiles->getAudioEncoderParamByName(
+                "enc.aud.ch.min", mAudioEncoder);
+    if (mAudioChannels < minChannels) {
+        LOGW("Intended number of audio channels (%d) is too small"
+            " and will be set to (%d)", mAudioChannels, minChannels);
+        mAudioChannels = minChannels;
+    }
+
+    int maxChannels =
+            mEncoderProfiles->getAudioEncoderParamByName(
+                "enc.aud.ch.max", mAudioEncoder);
+    if (mAudioChannels > maxChannels) {
+        LOGW("Intended number of audio channels (%d) is too large"
+            " and will be set to (%d)", mAudioChannels, maxChannels);
+        mAudioChannels = maxChannels;
+    }
+}
+
 void StagefrightRecorder::clipVideoFrameHeight() {
     LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder);
     int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
@@ -1198,18 +1268,23 @@
 }
 
 status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
-    sp<MediaSource> audioEncoder;
+    status_t status = BAD_VALUE;
+    if (OK != (status = checkAudioEncoderCapabilities())) {
+        return status;
+    }
+
     switch(mAudioEncoder) {
         case AUDIO_ENCODER_AMR_NB:
         case AUDIO_ENCODER_AMR_WB:
         case AUDIO_ENCODER_AAC:
-            audioEncoder = createAudioSource();
             break;
+
         default:
             LOGE("Unsupported audio encoder: %d", mAudioEncoder);
             return UNKNOWN_ERROR;
     }
 
+    sp<MediaSource> audioEncoder = createAudioSource();
     if (audioEncoder == NULL) {
         return UNKNOWN_ERROR;
     }
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 36a15a8..72225db 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -123,6 +123,7 @@
     status_t startMPEG2TSRecording();
     sp<MediaSource> createAudioSource();
     status_t checkVideoEncoderCapabilities();
+    status_t checkAudioEncoderCapabilities();
     status_t setupCameraSource(sp<CameraSource> *cameraSource);
     status_t setupAudioEncoder(const sp<MediaWriter>& writer);
     status_t setupVideoEncoder(
@@ -158,6 +159,9 @@
     void clipVideoFrameRate();
     void clipVideoFrameWidth();
     void clipVideoFrameHeight();
+    void clipAudioBitRate();
+    void clipAudioSampleRate();
+    void clipNumberOfAudioChannels();
 
     StagefrightRecorder(const StagefrightRecorder &);
     StagefrightRecorder &operator=(const StagefrightRecorder &);
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
index c4f3764..c20e279 100644
--- a/media/libmediaplayerservice/nuplayer/Android.mk
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -2,17 +2,20 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=                       \
+        HTTPLiveSource.cpp              \
         NuPlayer.cpp                    \
         NuPlayerDecoder.cpp             \
         NuPlayerDriver.cpp              \
         NuPlayerRenderer.cpp            \
         NuPlayerStreamListener.cpp      \
         DecoderWrapper.cpp              \
+        StreamingSource.cpp             \
 
 LOCAL_C_INCLUDES := \
         $(TOP)/frameworks/base/include/media/stagefright/openmax        \
 	$(TOP)/frameworks/base/media/libstagefright/include             \
         $(TOP)/frameworks/base/media/libstagefright/mpeg2ts             \
+        $(TOP)/frameworks/base/media/libstagefright/httplive            \
 
 LOCAL_MODULE:= libstagefright_nuplayer
 
diff --git a/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp b/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
index 89a5e69..802d1fb 100644
--- a/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
+++ b/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
@@ -151,6 +151,7 @@
             const sp<AMessage> &notify);
 
     void start();
+    void stop();
     void readMore(bool flush = false);
 
 protected:
@@ -166,6 +167,9 @@
     sp<MediaSource> mDecoder;
     sp<AMessage> mNotify;
     bool mEOS;
+    bool mSentFormat;
+
+    void sendFormatChange();
 
     DISALLOW_EVIL_CONSTRUCTORS(WrapperReader);
 };
@@ -174,7 +178,8 @@
         const sp<MediaSource> &decoder, const sp<AMessage> &notify)
     : mDecoder(decoder),
       mNotify(notify),
-      mEOS(false) {
+      mEOS(false),
+      mSentFormat(false) {
 }
 
 DecoderWrapper::WrapperReader::~WrapperReader() {
@@ -185,6 +190,10 @@
     readMore();
 }
 
+void DecoderWrapper::WrapperReader::stop() {
+    CHECK_EQ(mDecoder->stop(), (status_t)OK);
+}
+
 void DecoderWrapper::WrapperReader::readMore(bool flush) {
     if (!flush && mEOS) {
         return;
@@ -215,12 +224,17 @@
             MediaBuffer *src;
             status_t err = mDecoder->read(&src, &options);
 
-            sp<AMessage> notify = mNotify->dup();
-
-            sp<AMessage> realNotify;
-            CHECK(notify->findMessage("real-notify", &realNotify));
-
             if (err == OK) {
+                if (!mSentFormat) {
+                    sendFormatChange();
+                    mSentFormat = true;
+                }
+
+                sp<AMessage> notify = mNotify->dup();
+
+                sp<AMessage> realNotify;
+                CHECK(notify->findMessage("real-notify", &realNotify));
+
                 realNotify->setInt32("what", ACodec::kWhatDrainThisBuffer);
 
                 sp<ABuffer> dst = new ABuffer(src->range_length());
@@ -236,12 +250,23 @@
                 dst->meta()->setInt64("timeUs", timeUs);
 
                 realNotify->setObject("buffer", dst);
+
+                notify->post();
+            } else if (err == INFO_FORMAT_CHANGED) {
+                sendFormatChange();
+
+                readMore(false /* flush */);
             } else {
+                sp<AMessage> notify = mNotify->dup();
+
+                sp<AMessage> realNotify;
+                CHECK(notify->findMessage("real-notify", &realNotify));
+
                 realNotify->setInt32("what", ACodec::kWhatEOS);
                 mEOS = true;
-            }
 
-            notify->post();
+                notify->post();
+            }
             break;
         }
 
@@ -251,6 +276,58 @@
     }
 }
 
+void DecoderWrapper::WrapperReader::sendFormatChange() {
+    sp<AMessage> notify = mNotify->dup();
+
+    sp<AMessage> realNotify;
+    CHECK(notify->findMessage("real-notify", &realNotify));
+
+    realNotify->setInt32("what", ACodec::kWhatOutputFormatChanged);
+
+    sp<MetaData> meta = mDecoder->getFormat();
+
+    const char *mime;
+    CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+    realNotify->setString("mime", mime);
+
+    if (!strncasecmp("audio/", mime, 6)) {
+        int32_t numChannels;
+        CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
+
+        int32_t sampleRate;
+        CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+
+        realNotify->setInt32("channel-count", numChannels);
+        realNotify->setInt32("sample-rate", sampleRate);
+    } else {
+        CHECK(!strncasecmp("video/", mime, 6));
+
+        int32_t width, height;
+        CHECK(meta->findInt32(kKeyWidth, &width));
+        CHECK(meta->findInt32(kKeyHeight, &height));
+
+        realNotify->setInt32("width", width);
+        realNotify->setInt32("height", height);
+
+        int32_t cropLeft, cropTop, cropRight, cropBottom;
+        if (!meta->findRect(
+                    kKeyCropRect,
+                    &cropLeft, &cropTop, &cropRight, &cropBottom)) {
+            cropLeft = 0;
+            cropTop = 0;
+            cropRight = width - 1;
+            cropBottom = height - 1;
+        }
+
+        realNotify->setRect("crop", cropLeft, cropTop, cropRight, cropBottom);
+    }
+
+    notify->post();
+
+    mSentFormat = true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 DecoderWrapper::DecoderWrapper()
@@ -291,6 +368,10 @@
             onSetup(msg);
             break;
 
+        case kWhatShutdown:
+            onShutdown();
+            break;
+
         case kWhatInputDataRequested:
         {
             postFillBuffer();
@@ -327,24 +408,33 @@
 
         case kWhatFillBufferDone:
         {
-            CHECK_GT(mNumPendingDecodes, 0);
-            --mNumPendingDecodes;
-
-            if (mFlushing) {
-                completeFlushIfPossible();
-                break;
-            }
-
             sp<AMessage> notify;
             CHECK(msg->findMessage("real-notify", &notify));
 
-            sp<AMessage> reply =
-                new AMessage(kWhatOutputBufferDrained, id());
+            int32_t what;
+            CHECK(notify->findInt32("what", &what));
 
-            notify->setMessage("reply", reply);
+            if (what == ACodec::kWhatDrainThisBuffer) {
+                CHECK_GT(mNumPendingDecodes, 0);
+                --mNumPendingDecodes;
+
+                sp<AMessage> reply =
+                    new AMessage(kWhatOutputBufferDrained, id());
+
+                notify->setMessage("reply", reply);
+
+                ++mNumOutstandingOutputBuffers;
+            } else if (what == ACodec::kWhatEOS) {
+                CHECK_GT(mNumPendingDecodes, 0);
+                --mNumPendingDecodes;
+
+                if (mFlushing) {
+                    completeFlushIfPossible();
+                    break;
+                }
+            }
+
             notify->post();
-
-            ++mNumOutstandingOutputBuffers;
             break;
         }
 
@@ -424,6 +514,25 @@
     ++mNumPendingDecodes;
 }
 
+void DecoderWrapper::onShutdown() {
+    mReaderLooper->stop();
+    mReaderLooper.clear();
+
+    mReader->stop();
+    mReader.clear();
+
+    mSource.clear();
+
+    mNumOutstandingInputBuffers = 0;
+    mNumOutstandingOutputBuffers = 0;
+    mNumPendingDecodes = 0;
+    mFlushing = false;
+
+    sp<AMessage> notify = mNotify->dup();
+    notify->setInt32("what", ACodec::kWhatShutdownCompleted);
+    notify->post();
+}
+
 void DecoderWrapper::postFillBuffer() {
     sp<AMessage> notify = mNotify->dup();
     notify->setInt32("what", ACodec::kWhatFillThisBuffer);
diff --git a/media/libmediaplayerservice/nuplayer/DecoderWrapper.h b/media/libmediaplayerservice/nuplayer/DecoderWrapper.h
index 883b356..b9be12c 100644
--- a/media/libmediaplayerservice/nuplayer/DecoderWrapper.h
+++ b/media/libmediaplayerservice/nuplayer/DecoderWrapper.h
@@ -66,6 +66,7 @@
     bool mFlushing;
 
     void onSetup(const sp<AMessage> &msg);
+    void onShutdown();
     void onFlush();
     void onResume();
 
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
new file mode 100644
index 0000000..6bf6dd3
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "HTTPLiveSource"
+#include <utils/Log.h>
+
+#include "HTTPLiveSource.h"
+
+#include "ATSParser.h"
+#include "AnotherPacketSource.h"
+#include "LiveDataSource.h"
+#include "LiveSession.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+NuPlayer::HTTPLiveSource::HTTPLiveSource(const char *url)
+    : mURL(url),
+      mEOS(false),
+      mOffset(0) {
+}
+
+NuPlayer::HTTPLiveSource::~HTTPLiveSource() {
+    mLiveSession->disconnect();
+    mLiveLooper->stop();
+}
+
+void NuPlayer::HTTPLiveSource::start() {
+    mLiveLooper = new ALooper;
+    mLiveLooper->setName("http live");
+    mLiveLooper->start();
+
+    mLiveSession = new LiveSession;
+    mLiveLooper->registerHandler(mLiveSession);
+
+    mLiveSession->connect(mURL.c_str());
+
+    mTSParser = new ATSParser;
+}
+
+sp<MetaData> NuPlayer::HTTPLiveSource::getFormat(bool audio) {
+    ATSParser::SourceType type =
+        audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO;
+
+    sp<AnotherPacketSource> source =
+        static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+
+    if (source == NULL) {
+        return NULL;
+    }
+
+    return source->getFormat();
+}
+
+bool NuPlayer::HTTPLiveSource::feedMoreTSData() {
+    if (mEOS) {
+        return false;
+    }
+
+    sp<LiveDataSource> source =
+        static_cast<LiveDataSource *>(mLiveSession->getDataSource().get());
+
+    for (int32_t i = 0; i < 50; ++i) {
+        char buffer[188];
+        ssize_t n = source->readAtNonBlocking(mOffset, buffer, sizeof(buffer));
+
+        if (n == -EWOULDBLOCK) {
+            break;
+        } else if (n < 0) {
+            LOGI("input data EOS reached.");
+            mTSParser->signalEOS(n);
+            mEOS = true;
+            break;
+        } else {
+            if (buffer[0] == 0x00) {
+                // XXX legacy
+                mTSParser->signalDiscontinuity(
+                        buffer[1] == 0x00
+                            ? ATSParser::DISCONTINUITY_SEEK
+                            : ATSParser::DISCONTINUITY_FORMATCHANGE);
+            } else {
+                mTSParser->feedTSPacket(buffer, sizeof(buffer));
+            }
+
+            mOffset += n;
+        }
+    }
+
+    return true;
+}
+
+status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
+        bool audio, sp<ABuffer> *accessUnit) {
+    ATSParser::SourceType type =
+        audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO;
+
+    sp<AnotherPacketSource> source =
+        static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+
+    if (source == NULL) {
+        return -EWOULDBLOCK;
+    }
+
+    status_t finalResult;
+    if (!source->hasBufferAvailable(&finalResult)) {
+        return finalResult == OK ? -EWOULDBLOCK : finalResult;
+    }
+
+    return source->dequeueAccessUnit(accessUnit);
+}
+
+status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) {
+    return mLiveSession->getDuration(durationUs);
+}
+
+status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
+    // We need to make sure we're not seeking until we have seen the very first
+    // PTS timestamp in the whole stream (from the beginning of the stream).
+    while (!mTSParser->PTSTimeDeltaEstablished() && feedMoreTSData()) {
+        usleep(100000);
+    }
+
+    mLiveSession->seekTo(seekTimeUs);
+
+    return OK;
+}
+
+bool NuPlayer::HTTPLiveSource::isSeekable() {
+    return mLiveSession->isSeekable();
+}
+
+}  // namespace android
+
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
new file mode 100644
index 0000000..f3f539a
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HTTP_LIVE_SOURCE_H_
+
+#define HTTP_LIVE_SOURCE_H_
+
+#include "NuPlayer.h"
+#include "NuPlayerSource.h"
+
+namespace android {
+
+struct ATSParser;
+struct LiveSession;
+
+struct NuPlayer::HTTPLiveSource : public NuPlayer::Source {
+    HTTPLiveSource(const char *url);
+
+    virtual void start();
+
+    // Returns true iff more data was available, false on EOS.
+    virtual bool feedMoreTSData();
+
+    virtual sp<MetaData> getFormat(bool audio);
+    virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+
+    virtual status_t getDuration(int64_t *durationUs);
+    virtual status_t seekTo(int64_t seekTimeUs);
+    virtual bool isSeekable();
+
+protected:
+    virtual ~HTTPLiveSource();
+
+private:
+    AString mURL;
+    bool mEOS;
+    off64_t mOffset;
+    sp<ALooper> mLiveLooper;
+    sp<LiveSession> mLiveSession;
+    sp<ATSParser> mTSParser;
+
+    DISALLOW_EVIL_CONSTRUCTORS(HTTPLiveSource);
+};
+
+}  // namespace android
+
+#endif  // HTTP_LIVE_SOURCE_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 403029a..7f534c0 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -19,10 +19,17 @@
 #include <utils/Log.h>
 
 #include "NuPlayer.h"
-#include "NuPlayerDecoder.h"
-#include "NuPlayerRenderer.h"
-#include "NuPlayerStreamListener.h"
 
+#include "HTTPLiveSource.h"
+#include "NuPlayerDecoder.h"
+#include "NuPlayerDriver.h"
+#include "NuPlayerRenderer.h"
+#include "NuPlayerSource.h"
+#include "StreamingSource.h"
+
+#include "ATSParser.h"
+
+#include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -36,26 +43,35 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 NuPlayer::NuPlayer()
-    : mEOS(false),
-      mAudioEOS(false),
+    : mAudioEOS(false),
       mVideoEOS(false),
+      mScanSourcesPending(false),
+      mScanSourcesGeneration(0),
       mFlushingAudio(NONE),
-      mFlushingVideo(NONE) {
+      mFlushingVideo(NONE),
+      mResetInProgress(false),
+      mResetPostponed(false) {
 }
 
 NuPlayer::~NuPlayer() {
 }
 
-void NuPlayer::setListener(const wp<MediaPlayerBase> &listener) {
-    mListener = listener;
+void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
+    mDriver = driver;
 }
 
 void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
     sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
 
-    source->incStrong(this);
-    msg->setPointer("source", source.get());  // XXX unsafe.
+    msg->setObject("source", new StreamingSource(source));
+    msg->post();
+}
 
+void NuPlayer::setDataSource(
+        const char *url, const KeyedVector<String8, String8> *headers) {
+    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
+
+    msg->setObject("source", new HTTPLiveSource(url));
     msg->post();
 }
 
@@ -75,28 +91,62 @@
     (new AMessage(kWhatStart, id()))->post();
 }
 
+void NuPlayer::pause() {
+    // XXX to be implemented
+}
+
+void NuPlayer::resume() {
+    // XXX to be implemented
+}
+
+void NuPlayer::resetAsync() {
+    (new AMessage(kWhatReset, id()))->post();
+}
+
+void NuPlayer::seekToAsync(int64_t seekTimeUs) {
+    sp<AMessage> msg = new AMessage(kWhatSeek, id());
+    msg->setInt64("seekTimeUs", seekTimeUs);
+    msg->post();
+}
+
+// static
+bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
+    switch (state) {
+        case FLUSHING_DECODER:
+            if (needShutdown != NULL) {
+                *needShutdown = false;
+            }
+            return true;
+
+        case FLUSHING_DECODER_SHUTDOWN:
+            if (needShutdown != NULL) {
+                *needShutdown = true;
+            }
+            return true;
+
+        default:
+            return false;
+    }
+}
+
 void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
     switch (msg->what()) {
         case kWhatSetDataSource:
         {
-            LOGI("kWhatSetDataSource");
+            LOGV("kWhatSetDataSource");
 
             CHECK(mSource == NULL);
 
-            void *ptr;
-            CHECK(msg->findPointer("source", &ptr));
+            sp<RefBase> obj;
+            CHECK(msg->findObject("source", &obj));
 
-            mSource = static_cast<IStreamSource *>(ptr);
-            mSource->decStrong(this);
-
-            mStreamListener = new NuPlayerStreamListener(mSource, id());
-            mTSParser = new ATSParser;
+            mSource = static_cast<Source *>(obj.get());
             break;
         }
 
         case kWhatSetVideoSurface:
         {
-            LOGI("kWhatSetVideoSurface");
+            LOGV("kWhatSetVideoSurface");
 
             sp<RefBase> obj;
             CHECK(msg->findObject("surface", &obj));
@@ -107,7 +157,7 @@
 
         case kWhatSetAudioSink:
         {
-            LOGI("kWhatSetAudioSink");
+            LOGV("kWhatSetAudioSink");
 
             sp<RefBase> obj;
             CHECK(msg->findObject("sink", &obj));
@@ -118,7 +168,12 @@
 
         case kWhatStart:
         {
-            mStreamListener->start();
+            LOGV("kWhatStart");
+
+            mAudioEOS = false;
+            mVideoEOS = false;
+
+            mSource->start();
 
             mRenderer = new Renderer(
                     mAudioSink,
@@ -126,26 +181,42 @@
 
             looper()->registerHandler(mRenderer);
 
-            (new AMessage(kWhatScanSources, id()))->post();
+            postScanSources();
             break;
         }
 
         case kWhatScanSources:
         {
+            int32_t generation;
+            CHECK(msg->findInt32("generation", &generation));
+            if (generation != mScanSourcesGeneration) {
+                // Drop obsolete msg.
+                break;
+            }
+
+            mScanSourcesPending = false;
+
+            LOGV("scanning sources haveAudio=%d, haveVideo=%d",
+                 mAudioDecoder != NULL, mVideoDecoder != NULL);
+
             instantiateDecoder(false, &mVideoDecoder);
 
             if (mAudioSink != NULL) {
                 instantiateDecoder(true, &mAudioDecoder);
             }
 
-            if (mEOS) {
+            if (!mSource->feedMoreTSData()) {
+                if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
+                    // We're not currently decoding anything (no audio or
+                    // video tracks found) and we just ran out of input data.
+                    notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
+                }
                 break;
             }
 
-            feedMoreTSData();
-
             if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
                 msg->post(100000ll);
+                mScanSourcesPending = true;
             }
             break;
         }
@@ -165,39 +236,93 @@
                 status_t err = feedDecoderInputData(
                         audio, codecRequest);
 
-                if (err == -EWOULDBLOCK && !mEOS) {
-                    feedMoreTSData();
-                    msg->post();
+                if (err == -EWOULDBLOCK) {
+                    if (mSource->feedMoreTSData()) {
+                        msg->post();
+                    }
                 }
             } else if (what == ACodec::kWhatEOS) {
                 mRenderer->queueEOS(audio, ERROR_END_OF_STREAM);
             } else if (what == ACodec::kWhatFlushCompleted) {
+                bool needShutdown;
+
                 if (audio) {
-                    CHECK_EQ((int)mFlushingAudio, (int)FLUSHING_DECODER);
+                    CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
                     mFlushingAudio = FLUSHED;
                 } else {
-                    CHECK_EQ((int)mFlushingVideo, (int)FLUSHING_DECODER);
+                    CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
                     mFlushingVideo = FLUSHED;
                 }
 
-                LOGI("decoder %s flush completed", audio ? "audio" : "video");
+                LOGV("decoder %s flush completed", audio ? "audio" : "video");
 
-                if (mFlushingAudio == FLUSHED && mFlushingVideo == FLUSHED) {
-                    LOGI("both audio and video are flushed now.");
+                if (needShutdown) {
+                    LOGV("initiating %s decoder shutdown",
+                         audio ? "audio" : "video");
 
-                    mRenderer->signalTimeDiscontinuity();
+                    (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
 
-                    if (mAudioDecoder != NULL) {
-                        mAudioDecoder->signalResume();
+                    if (audio) {
+                        mFlushingAudio = SHUTTING_DOWN_DECODER;
+                    } else {
+                        mFlushingVideo = SHUTTING_DOWN_DECODER;
                     }
-
-                    if (mVideoDecoder != NULL) {
-                        mVideoDecoder->signalResume();
-                    }
-
-                    mFlushingAudio = NONE;
-                    mFlushingVideo = NONE;
                 }
+
+                finishFlushIfPossible();
+            } else if (what == ACodec::kWhatOutputFormatChanged) {
+                if (audio) {
+                    int32_t numChannels;
+                    CHECK(codecRequest->findInt32("channel-count", &numChannels));
+
+                    int32_t sampleRate;
+                    CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
+
+                    LOGV("Audio output format changed to %d Hz, %d channels",
+                         sampleRate, numChannels);
+
+                    mAudioSink->close();
+                    CHECK_EQ(mAudioSink->open(sampleRate, numChannels), (status_t)OK);
+                    mAudioSink->start();
+
+                    mRenderer->signalAudioSinkChanged();
+                } else {
+                    // video
+
+                    int32_t width, height;
+                    CHECK(codecRequest->findInt32("width", &width));
+                    CHECK(codecRequest->findInt32("height", &height));
+
+                    int32_t cropLeft, cropTop, cropRight, cropBottom;
+                    CHECK(codecRequest->findRect(
+                                "crop",
+                                &cropLeft, &cropTop, &cropRight, &cropBottom));
+
+                    LOGV("Video output format changed to %d x %d "
+                         "(crop: %d, %d, %d, %d)",
+                         width, height,
+                         cropLeft, cropTop, cropRight, cropBottom);
+
+                    notifyListener(
+                            MEDIA_SET_VIDEO_SIZE,
+                            cropRight - cropLeft + 1,
+                            cropBottom - cropTop + 1);
+                }
+            } else if (what == ACodec::kWhatShutdownCompleted) {
+                LOGV("%s shutdown completed", audio ? "audio" : "video");
+                if (audio) {
+                    mAudioDecoder.clear();
+
+                    CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
+                    mFlushingAudio = SHUT_DOWN;
+                } else {
+                    mVideoDecoder.clear();
+
+                    CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
+                    mFlushingVideo = SHUT_DOWN;
+                }
+
+                finishFlushIfPossible();
             } else {
                 CHECK_EQ((int)what, (int)ACodec::kWhatDrainThisBuffer);
 
@@ -222,19 +347,29 @@
                     mVideoEOS = true;
                 }
 
-                LOGI("reached %s EOS", audio ? "audio" : "video");
+                LOGV("reached %s EOS", audio ? "audio" : "video");
 
                 if ((mAudioEOS || mAudioDecoder == NULL)
                         && (mVideoEOS || mVideoDecoder == NULL)) {
                     notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
                 }
+            } else if (what == Renderer::kWhatPosition) {
+                int64_t positionUs;
+                CHECK(msg->findInt64("positionUs", &positionUs));
+
+                if (mDriver != NULL) {
+                    sp<NuPlayerDriver> driver = mDriver.promote();
+                    if (driver != NULL) {
+                        driver->notifyPosition(positionUs);
+                    }
+                }
             } else {
                 CHECK_EQ(what, (int32_t)Renderer::kWhatFlushComplete);
 
                 int32_t audio;
                 CHECK(msg->findInt32("audio", &audio));
 
-                LOGI("renderer %s flush completed.", audio ? "audio" : "video");
+                LOGV("renderer %s flush completed.", audio ? "audio" : "video");
             }
             break;
         }
@@ -244,114 +379,135 @@
             break;
         }
 
+        case kWhatReset:
+        {
+            LOGV("kWhatReset");
+
+            if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
+                // We're currently flushing, postpone the reset until that's
+                // completed.
+
+                LOGV("postponing reset");
+
+                mResetPostponed = true;
+                break;
+            }
+
+            if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
+                finishReset();
+                break;
+            }
+
+            if (mAudioDecoder != NULL) {
+                flushDecoder(true /* audio */, true /* needShutdown */);
+            }
+
+            if (mVideoDecoder != NULL) {
+                flushDecoder(false /* audio */, true /* needShutdown */);
+            }
+
+            mResetInProgress = true;
+            break;
+        }
+
+        case kWhatSeek:
+        {
+            int64_t seekTimeUs;
+            CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
+
+            LOGV("kWhatSeek seekTimeUs=%lld us (%.2f secs)",
+                 seekTimeUs, seekTimeUs / 1E6);
+
+            mSource->seekTo(seekTimeUs);
+
+            if (mDriver != NULL) {
+                sp<NuPlayerDriver> driver = mDriver.promote();
+                if (driver != NULL) {
+                    driver->notifySeekComplete();
+                }
+            }
+
+            break;
+        }
+
         default:
             TRESPASS();
             break;
     }
 }
 
-void NuPlayer::feedMoreTSData() {
-    CHECK(!mEOS);
+void NuPlayer::finishFlushIfPossible() {
+    if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
+        return;
+    }
 
-    for (int32_t i = 0; i < 10; ++i) {
-        char buffer[188];
-        ssize_t n = mStreamListener->read(buffer, sizeof(buffer));
+    if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
+        return;
+    }
 
-        if (n == 0) {
-            LOGI("input data EOS reached.");
-            mTSParser->signalEOS(ERROR_END_OF_STREAM);
-            mEOS = true;
-            break;
-        } else if (n == INFO_DISCONTINUITY) {
-            mTSParser->signalDiscontinuity(ATSParser::DISCONTINUITY_SEEK);
-        } else if (n < 0) {
-            CHECK_EQ(n, -EWOULDBLOCK);
-            break;
-        } else {
-            if (buffer[0] == 0x00) {
-                // XXX legacy
-                mTSParser->signalDiscontinuity(ATSParser::DISCONTINUITY_SEEK);
-            } else {
-                mTSParser->feedTSPacket(buffer, sizeof(buffer));
-            }
+    LOGV("both audio and video are flushed now.");
+
+    mRenderer->signalTimeDiscontinuity();
+
+    if (mAudioDecoder != NULL) {
+        mAudioDecoder->signalResume();
+    }
+
+    if (mVideoDecoder != NULL) {
+        mVideoDecoder->signalResume();
+    }
+
+    mFlushingAudio = NONE;
+    mFlushingVideo = NONE;
+
+    if (mResetInProgress) {
+        LOGV("reset completed");
+
+        mResetInProgress = false;
+        finishReset();
+    } else if (mResetPostponed) {
+        (new AMessage(kWhatReset, id()))->post();
+        mResetPostponed = false;
+    } else if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
+        postScanSources();
+    }
+}
+
+void NuPlayer::finishReset() {
+    CHECK(mAudioDecoder == NULL);
+    CHECK(mVideoDecoder == NULL);
+
+    mRenderer.clear();
+    mSource.clear();
+
+    if (mDriver != NULL) {
+        sp<NuPlayerDriver> driver = mDriver.promote();
+        if (driver != NULL) {
+            driver->notifyResetComplete();
         }
     }
 }
 
-status_t NuPlayer::dequeueNextAccessUnit(
-        ATSParser::SourceType *type, sp<ABuffer> *accessUnit) {
-    accessUnit->clear();
-
-    status_t audioErr = -EWOULDBLOCK;
-    int64_t audioTimeUs;
-
-    sp<AnotherPacketSource> audioSource =
-        static_cast<AnotherPacketSource *>(
-                mTSParser->getSource(ATSParser::MPEG2ADTS_AUDIO).get());
-
-    if (audioSource != NULL) {
-        audioErr = audioSource->nextBufferTime(&audioTimeUs);
+void NuPlayer::postScanSources() {
+    if (mScanSourcesPending) {
+        return;
     }
 
-    status_t videoErr = -EWOULDBLOCK;
-    int64_t videoTimeUs;
+    sp<AMessage> msg = new AMessage(kWhatScanSources, id());
+    msg->setInt32("generation", mScanSourcesGeneration);
+    msg->post();
 
-    sp<AnotherPacketSource> videoSource =
-        static_cast<AnotherPacketSource *>(
-                mTSParser->getSource(ATSParser::AVC_VIDEO).get());
-
-    if (videoSource != NULL) {
-        videoErr = videoSource->nextBufferTime(&videoTimeUs);
-    }
-
-    if (audioErr == -EWOULDBLOCK || videoErr == -EWOULDBLOCK) {
-        return -EWOULDBLOCK;
-    }
-
-    if (audioErr != OK && videoErr != OK) {
-        return audioErr;
-    }
-
-    if (videoErr != OK || (audioErr == OK && audioTimeUs < videoTimeUs)) {
-        *type = ATSParser::MPEG2ADTS_AUDIO;
-        return audioSource->dequeueAccessUnit(accessUnit);
-    } else {
-        *type = ATSParser::AVC_VIDEO;
-        return videoSource->dequeueAccessUnit(accessUnit);
-    }
+    mScanSourcesPending = true;
 }
 
-status_t NuPlayer::dequeueAccessUnit(
-        ATSParser::SourceType type, sp<ABuffer> *accessUnit) {
-    sp<AnotherPacketSource> source =
-        static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
-
-    if (source == NULL) {
-        return -EWOULDBLOCK;
-    }
-
-    status_t finalResult;
-    if (!source->hasBufferAvailable(&finalResult)) {
-        return finalResult == OK ? -EWOULDBLOCK : finalResult;
-    }
-
-    return source->dequeueAccessUnit(accessUnit);
-}
-
-status_t NuPlayer::instantiateDecoder(
-        bool audio, sp<Decoder> *decoder) {
+status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
     if (*decoder != NULL) {
         return OK;
     }
 
-    ATSParser::SourceType type =
-        audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO;
+    sp<MetaData> meta = mSource->getFormat(audio);
 
-    sp<AnotherPacketSource> source =
-        static_cast<AnotherPacketSource *>(
-                mTSParser->getSource(type).get());
-
-    if (source == NULL) {
+    if (meta == NULL) {
         return -EWOULDBLOCK;
     }
 
@@ -362,19 +518,14 @@
     *decoder = new Decoder(notify, audio ? NULL : mSurface);
     looper()->registerHandler(*decoder);
 
-    const sp<MetaData> &meta = source->getFormat();
     (*decoder)->configure(meta);
 
-    if (audio) {
-        int32_t sampleRate;
-        int32_t channelCount;
-        CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
-        CHECK(meta->findInt32(kKeyChannelCount, &channelCount));
-
-        channelCount = 2;  // XXX
-
-        CHECK_EQ(mAudioSink->open(sampleRate, channelCount), (status_t)OK);
-        mAudioSink->start();
+    int64_t durationUs;
+    if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
+        sp<NuPlayerDriver> driver = mDriver.promote();
+        if (driver != NULL) {
+            driver->notifyDuration(durationUs);
+        }
     }
 
     return OK;
@@ -384,45 +535,30 @@
     sp<AMessage> reply;
     CHECK(msg->findMessage("reply", &reply));
 
-    if ((audio && mFlushingAudio == FLUSHING_DECODER)
-            || (!audio && mFlushingVideo == FLUSHING_DECODER)) {
+    if ((audio && IsFlushingState(mFlushingAudio))
+            || (!audio && IsFlushingState(mFlushingVideo))) {
         reply->setInt32("err", INFO_DISCONTINUITY);
         reply->post();
         return OK;
     }
 
     sp<ABuffer> accessUnit;
-    status_t err = dequeueAccessUnit(
-            audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO,
-            &accessUnit);
+    status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
 
     if (err == -EWOULDBLOCK) {
         return err;
     } else if (err != OK) {
         if (err == INFO_DISCONTINUITY) {
-            LOGI("%s discontinuity", audio ? "audio" : "video");
-            (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
-            mRenderer->flush(audio);
+            int32_t type;
+            CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
 
-            if (audio) {
-                CHECK(mFlushingAudio == NONE
-                        || mFlushingAudio == AWAITING_DISCONTINUITY);
-                mFlushingAudio = FLUSHING_DECODER;
-                if (mFlushingVideo == NONE) {
-                    mFlushingVideo = (mVideoDecoder != NULL)
-                        ? AWAITING_DISCONTINUITY
-                        : FLUSHED;
-                }
-            } else {
-                CHECK(mFlushingVideo == NONE
-                        || mFlushingVideo == AWAITING_DISCONTINUITY);
-                mFlushingVideo = FLUSHING_DECODER;
-                if (mFlushingAudio == NONE) {
-                    mFlushingAudio = (mAudioDecoder != NULL)
-                        ? AWAITING_DISCONTINUITY
-                        : FLUSHED;
-                }
-            }
+            bool formatChange =
+                type == ATSParser::DISCONTINUITY_FORMATCHANGE;
+
+            LOGV("%s discontinuity (formatChange=%d)",
+                 audio ? "audio" : "video", formatChange);
+
+            flushDecoder(audio, formatChange);
         }
 
         reply->setInt32("err", err);
@@ -430,12 +566,12 @@
         return OK;
     }
 
-    LOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
+    // LOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
 
 #if 0
     int64_t mediaTimeUs;
     CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
-    LOGI("feeding %s input buffer at media time %.2f secs",
+    LOGV("feeding %s input buffer at media time %.2f secs",
          audio ? "audio" : "video",
          mediaTimeUs / 1E6);
 #endif
@@ -447,7 +583,7 @@
 }
 
 void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
-    LOGV("renderBuffer %s", audio ? "audio" : "video");
+    // LOGV("renderBuffer %s", audio ? "audio" : "video");
 
     sp<AMessage> reply;
     CHECK(msg->findMessage("reply", &reply));
@@ -461,17 +597,53 @@
 }
 
 void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
-    if (mListener == NULL) {
+    if (mDriver == NULL) {
         return;
     }
 
-    sp<MediaPlayerBase> listener = mListener.promote();
+    sp<NuPlayerDriver> driver = mDriver.promote();
 
-    if (listener == NULL) {
+    if (driver == NULL) {
         return;
     }
 
-    listener->sendEvent(msg, ext1, ext2);
+    driver->sendEvent(msg, ext1, ext2);
+}
+
+void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
+    // Make sure we don't continue to scan sources until we finish flushing.
+    ++mScanSourcesGeneration;
+    mScanSourcesPending = false;
+
+    (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
+    mRenderer->flush(audio);
+
+    FlushStatus newStatus =
+        needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
+
+    if (audio) {
+        CHECK(mFlushingAudio == NONE
+                || mFlushingAudio == AWAITING_DISCONTINUITY);
+
+        mFlushingAudio = newStatus;
+
+        if (mFlushingVideo == NONE) {
+            mFlushingVideo = (mVideoDecoder != NULL)
+                ? AWAITING_DISCONTINUITY
+                : FLUSHED;
+        }
+    } else {
+        CHECK(mFlushingVideo == NONE
+                || mFlushingVideo == AWAITING_DISCONTINUITY);
+
+        mFlushingVideo = newStatus;
+
+        if (mFlushingAudio == NONE) {
+            mFlushingAudio = (mAudioDecoder != NULL)
+                ? AWAITING_DISCONTINUITY
+                : FLUSHED;
+        }
+    }
 }
 
 }  // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 9a5a6c4..339b628 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -21,33 +21,47 @@
 #include <media/MediaPlayerInterface.h>
 #include <media/stagefright/foundation/AHandler.h>
 
-#include "ATSParser.h"
-#include "AnotherPacketSource.h"
-
 namespace android {
 
 struct ACodec;
 struct MetaData;
+struct NuPlayerDriver;
 
 struct NuPlayer : public AHandler {
     NuPlayer();
 
-    void setListener(const wp<MediaPlayerBase> &listener);
+    void setDriver(const wp<NuPlayerDriver> &driver);
 
     void setDataSource(const sp<IStreamSource> &source);
+
+    void setDataSource(
+            const char *url, const KeyedVector<String8, String8> *headers);
+
     void setVideoSurface(const sp<Surface> &surface);
     void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink);
     void start();
 
+    void pause();
+    void resume();
+
+    // Will notify the driver through "notifyResetComplete" once finished.
+    void resetAsync();
+
+    // Will notify the driver through "notifySeekComplete" once finished.
+    void seekToAsync(int64_t seekTimeUs);
+
 protected:
     virtual ~NuPlayer();
 
     virtual void onMessageReceived(const sp<AMessage> &msg);
 
 private:
-    struct Renderer;
     struct Decoder;
+    struct HTTPLiveSource;
     struct NuPlayerStreamListener;
+    struct Renderer;
+    struct Source;
+    struct StreamingSource;
 
     enum {
         kWhatSetDataSource,
@@ -59,47 +73,55 @@
         kWhatVideoNotify,
         kWhatAudioNotify,
         kWhatRendererNotify,
+        kWhatReset,
+        kWhatSeek,
     };
 
-    wp<MediaPlayerBase> mListener;
-    sp<IStreamSource> mSource;
+    wp<NuPlayerDriver> mDriver;
+    sp<Source> mSource;
     sp<Surface> mSurface;
     sp<MediaPlayerBase::AudioSink> mAudioSink;
-    sp<NuPlayerStreamListener> mStreamListener;
-    sp<ATSParser> mTSParser;
     sp<Decoder> mVideoDecoder;
     sp<Decoder> mAudioDecoder;
     sp<Renderer> mRenderer;
 
-    bool mEOS;
     bool mAudioEOS;
     bool mVideoEOS;
 
+    bool mScanSourcesPending;
+    int32_t mScanSourcesGeneration;
+
     enum FlushStatus {
         NONE,
         AWAITING_DISCONTINUITY,
         FLUSHING_DECODER,
-        FLUSHED
+        FLUSHING_DECODER_SHUTDOWN,
+        SHUTTING_DOWN_DECODER,
+        FLUSHED,
+        SHUT_DOWN,
     };
 
     FlushStatus mFlushingAudio;
     FlushStatus mFlushingVideo;
+    bool mResetInProgress;
+    bool mResetPostponed;
 
-    status_t instantiateDecoder(
-            bool audio, sp<Decoder> *decoder);
+    status_t instantiateDecoder(bool audio, sp<Decoder> *decoder);
 
     status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);
     void renderBuffer(bool audio, const sp<AMessage> &msg);
 
-    status_t dequeueNextAccessUnit(
-            ATSParser::SourceType *type, sp<ABuffer> *accessUnit);
-
-    status_t dequeueAccessUnit(
-            ATSParser::SourceType type, sp<ABuffer> *accessUnit);
-
-    void feedMoreTSData();
     void notifyListener(int msg, int ext1, int ext2);
 
+    void finishFlushIfPossible();
+
+    void flushDecoder(bool audio, bool needShutdown);
+
+    static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL);
+
+    void finishReset();
+    void postScanSources();
+
     DISALLOW_EVIL_CONSTRUCTORS(NuPlayer);
 };
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index d1ed222..761dfa4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -25,6 +25,7 @@
 
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/ACodec.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
@@ -123,6 +124,13 @@
         msg->setInt32("sample-rate", sampleRate);
     }
 
+    int32_t maxInputSize;
+    if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
+        msg->setInt32("max-input-size", maxInputSize);
+    }
+
+    mCSDIndex = 0;
+
     uint32_t type;
     const void *data;
     size_t size;
@@ -228,13 +236,6 @@
 #endif
     }
 
-    int32_t maxInputSize;
-    if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
-        msg->setInt32("max-input-size", maxInputSize);
-    }
-
-    mCSDIndex = 0;
-
     return msg;
 }
 
@@ -282,5 +283,14 @@
     }
 }
 
+void NuPlayer::Decoder::initiateShutdown() {
+    if (mCodec != NULL) {
+        mCodec->initiateShutdown();
+    } else {
+        CHECK(mWrapper != NULL);
+        mWrapper->initiateShutdown();
+    }
+}
+
 }  // namespace android
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index 77800be..3874cfe 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -24,14 +24,17 @@
 
 namespace android {
 
+struct ABuffer;
 struct DecoderWrapper;
 
 struct NuPlayer::Decoder : public AHandler {
     Decoder(const sp<AMessage> &notify, const sp<Surface> &surface = NULL);
 
     void configure(const sp<MetaData> &meta);
+
     void signalFlush();
     void signalResume();
+    void initiateShutdown();
 
 protected:
     virtual ~Decoder();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index b79251a..ac19a2f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -22,12 +22,18 @@
 
 #include "NuPlayer.h"
 
+#include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 
 namespace android {
 
 NuPlayerDriver::NuPlayerDriver()
-    : mLooper(new ALooper) {
+    : mResetInProgress(false),
+      mDurationUs(-1),
+      mPositionUs(-1),
+      mLooper(new ALooper),
+      mState(UNINITIALIZED),
+      mStartupSeekTimeUs(-1) {
     mLooper->setName("NuPlayerDriver Looper");
 
     mLooper->start(
@@ -38,7 +44,7 @@
     mPlayer = new NuPlayer;
     mLooper->registerHandler(mPlayer);
 
-    mPlayer->setListener(this);
+    mPlayer->setDriver(this);
 }
 
 NuPlayerDriver::~NuPlayerDriver() {
@@ -51,7 +57,13 @@
 
 status_t NuPlayerDriver::setDataSource(
         const char *url, const KeyedVector<String8, String8> *headers) {
-    return INVALID_OPERATION;
+    CHECK_EQ((int)mState, (int)UNINITIALIZED);
+
+    mPlayer->setDataSource(url, headers);
+
+    mState = STOPPED;
+
+    return OK;
 }
 
 status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
@@ -59,8 +71,12 @@
 }
 
 status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
+    CHECK_EQ((int)mState, (int)UNINITIALIZED);
+
     mPlayer->setDataSource(source);
 
+    mState = STOPPED;
+
     return OK;
 }
 
@@ -75,40 +91,135 @@
 }
 
 status_t NuPlayerDriver::prepareAsync() {
+    sendEvent(MEDIA_PREPARED);
+
     return OK;
 }
 
 status_t NuPlayerDriver::start() {
-    mPlayer->start();
+    switch (mState) {
+        case UNINITIALIZED:
+            return INVALID_OPERATION;
+        case STOPPED:
+        {
+            mPlayer->start();
+
+            if (mStartupSeekTimeUs >= 0) {
+                mPlayer->seekToAsync(mStartupSeekTimeUs);
+                mStartupSeekTimeUs = -1;
+            }
+            break;
+        }
+        case PLAYING:
+            return OK;
+        default:
+        {
+            CHECK_EQ((int)mState, (int)PAUSED);
+
+            mPlayer->resume();
+            break;
+        }
+    }
+
+    mState = PLAYING;
 
     return OK;
 }
 
 status_t NuPlayerDriver::stop() {
-    return OK;
+    return pause();
 }
 
 status_t NuPlayerDriver::pause() {
+    switch (mState) {
+        case UNINITIALIZED:
+            return INVALID_OPERATION;
+        case STOPPED:
+            return OK;
+        case PLAYING:
+            mPlayer->pause();
+            break;
+        default:
+        {
+            CHECK_EQ((int)mState, (int)PAUSED);
+            return OK;
+        }
+    }
+
+    mState = PAUSED;
+
     return OK;
 }
 
 bool NuPlayerDriver::isPlaying() {
-    return false;
+    return mState == PLAYING;
 }
 
 status_t NuPlayerDriver::seekTo(int msec) {
-    return INVALID_OPERATION;
+    int64_t seekTimeUs = msec * 1000ll;
+
+    switch (mState) {
+        case UNINITIALIZED:
+            return INVALID_OPERATION;
+        case STOPPED:
+        {
+            mStartupSeekTimeUs = seekTimeUs;
+            break;
+        }
+        case PLAYING:
+        case PAUSED:
+        {
+            mPlayer->seekToAsync(seekTimeUs);
+            break;
+        }
+
+        default:
+            TRESPASS();
+            break;
+    }
+
+    return OK;
 }
 
 status_t NuPlayerDriver::getCurrentPosition(int *msec) {
-    return INVALID_OPERATION;
+    Mutex::Autolock autoLock(mLock);
+
+    if (mPositionUs < 0) {
+        *msec = 0;
+    } else {
+        *msec = (mPositionUs + 500ll) / 1000;
+    }
+
+    return OK;
 }
 
 status_t NuPlayerDriver::getDuration(int *msec) {
-    return INVALID_OPERATION;
+    Mutex::Autolock autoLock(mLock);
+
+    if (mDurationUs < 0) {
+        *msec = 0;
+    } else {
+        *msec = (mDurationUs + 500ll) / 1000;
+    }
+
+    return OK;
 }
 
 status_t NuPlayerDriver::reset() {
+    Mutex::Autolock autoLock(mLock);
+    mResetInProgress = true;
+
+    mPlayer->resetAsync();
+
+    while (mResetInProgress) {
+        mCondition.wait(mLock);
+    }
+
+    mDurationUs = -1;
+    mPositionUs = -1;
+    mState = UNINITIALIZED;
+    mStartupSeekTimeUs = -1;
+
     return OK;
 }
 
@@ -133,4 +244,25 @@
     return INVALID_OPERATION;
 }
 
+void NuPlayerDriver::notifyResetComplete() {
+    Mutex::Autolock autoLock(mLock);
+    CHECK(mResetInProgress);
+    mResetInProgress = false;
+    mCondition.broadcast();
+}
+
+void NuPlayerDriver::notifyDuration(int64_t durationUs) {
+    Mutex::Autolock autoLock(mLock);
+    mDurationUs = durationUs;
+}
+
+void NuPlayerDriver::notifyPosition(int64_t positionUs) {
+    Mutex::Autolock autoLock(mLock);
+    mPositionUs = positionUs;
+}
+
+void NuPlayerDriver::notifySeekComplete() {
+    sendEvent(MEDIA_SEEK_COMPLETE);
+}
+
 }  // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 245f1dd..e3a5de4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -54,13 +54,39 @@
     virtual status_t getMetadata(
             const media::Metadata::Filter& ids, Parcel *records);
 
+    void notifyResetComplete();
+    void notifyDuration(int64_t durationUs);
+    void notifyPosition(int64_t positionUs);
+    void notifySeekComplete();
+
 protected:
     virtual ~NuPlayerDriver();
 
 private:
+    Mutex mLock;
+    Condition mCondition;
+
+    // The following are protected through "mLock"
+    // >>>
+    bool mResetInProgress;
+    int64_t mDurationUs;
+    int64_t mPositionUs;
+    // <<<
+
     sp<ALooper> mLooper;
     sp<NuPlayer> mPlayer;
 
+    enum State {
+        UNINITIALIZED,
+        STOPPED,
+        PLAYING,
+        PAUSED
+    };
+
+    State mState;
+
+    int64_t mStartupSeekTimeUs;
+
     DISALLOW_EVIL_CONSTRUCTORS(NuPlayerDriver);
 };
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 855bc0a..5833697 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -22,6 +22,7 @@
 
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
 
 namespace android {
 
@@ -39,7 +40,9 @@
       mAnchorTimeRealUs(-1),
       mFlushingAudio(false),
       mFlushingVideo(false),
-      mSyncQueues(true) {
+      mHasAudio(mAudioSink != NULL),
+      mHasVideo(true),
+      mSyncQueues(mHasAudio && mHasVideo) {
 }
 
 NuPlayer::Renderer::~Renderer() {
@@ -87,7 +90,7 @@
     CHECK(mVideoQueue.empty());
     mAnchorTimeMediaUs = -1;
     mAnchorTimeRealUs = -1;
-    mSyncQueues = true;
+    mSyncQueues = mHasAudio && mHasVideo;
 }
 
 void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
@@ -142,6 +145,12 @@
             break;
         }
 
+        case kWhatAudioSinkChanged:
+        {
+            onAudioSinkChanged();
+            break;
+        }
+
         default:
             TRESPASS();
             break;
@@ -163,6 +172,10 @@
     msg->post(10000);
 }
 
+void NuPlayer::Renderer::signalAudioSinkChanged() {
+    (new AMessage(kWhatAudioSinkChanged, id()))->post();
+}
+
 void NuPlayer::Renderer::onDrainAudioQueue() {
     uint32_t numFramesPlayed;
     CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
@@ -236,6 +249,8 @@
         numBytesAvailableToWrite -= copy;
         mNumFramesWritten += copy / mAudioSink->frameSize();
     }
+
+    notifyPosition();
 }
 
 void NuPlayer::Renderer::postDrainVideoQueue() {
@@ -264,7 +279,7 @@
         if (mAnchorTimeMediaUs < 0) {
             delayUs = 0;
 
-            if (mAudioSink == NULL) {
+            if (!mHasAudio) {
                 mAnchorTimeMediaUs = mediaTimeUs;
                 mAnchorTimeRealUs = ALooper::GetNowUs();
             }
@@ -309,6 +324,8 @@
     entry->mNotifyConsumed->post();
     mVideoQueue.erase(mVideoQueue.begin());
     entry = NULL;
+
+    notifyPosition();
 }
 
 void NuPlayer::Renderer::notifyEOS(bool audio) {
@@ -492,5 +509,24 @@
     return true;
 }
 
+void NuPlayer::Renderer::onAudioSinkChanged() {
+    CHECK(!mDrainAudioQueuePending);
+    mNumFramesWritten = 0;
+}
+
+void NuPlayer::Renderer::notifyPosition() {
+    if (mAnchorTimeRealUs < 0 || mAnchorTimeMediaUs < 0) {
+        return;
+    }
+
+    int64_t nowUs = ALooper::GetNowUs();
+    int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
+
+    sp<AMessage> notify = mNotify->dup();
+    notify->setInt32("what", kWhatPosition);
+    notify->setInt64("positionUs", positionUs);
+    notify->post();
+}
+
 }  // namespace android
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 834ddc5..dbf3ecff 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -22,6 +22,8 @@
 
 namespace android {
 
+struct ABuffer;
+
 struct NuPlayer::Renderer : public AHandler {
     Renderer(const sp<MediaPlayerBase::AudioSink> &sink,
              const sp<AMessage> &notify);
@@ -37,9 +39,12 @@
 
     void signalTimeDiscontinuity();
 
+    void signalAudioSinkChanged();
+
     enum {
         kWhatEOS,
         kWhatFlushComplete,
+        kWhatPosition,
     };
 
 protected:
@@ -54,6 +59,7 @@
         kWhatQueueBuffer,
         kWhatQueueEOS,
         kWhatFlush,
+        kWhatAudioSinkChanged,
     };
 
     struct QueueEntry {
@@ -81,6 +87,8 @@
     bool mFlushingAudio;
     bool mFlushingVideo;
 
+    bool mHasAudio;
+    bool mHasVideo;
     bool mSyncQueues;
 
     void onDrainAudioQueue();
@@ -92,9 +100,11 @@
     void onQueueBuffer(const sp<AMessage> &msg);
     void onQueueEOS(const sp<AMessage> &msg);
     void onFlush(const sp<AMessage> &msg);
+    void onAudioSinkChanged();
 
     void notifyEOS(bool audio);
     void notifyFlushComplete(bool audio);
+    void notifyPosition();
 
     void flushQueue(List<QueueEntry> *queue);
     bool dropBufferWhileFlushing(bool audio, const sp<AMessage> &msg);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
new file mode 100644
index 0000000..5e55487
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NUPLAYER_SOURCE_H_
+
+#define NUPLAYER_SOURCE_H_
+
+#include "NuPlayer.h"
+
+namespace android {
+
+struct ABuffer;
+
+struct NuPlayer::Source : public RefBase {
+    Source() {}
+
+    virtual void start() = 0;
+
+    // Returns true iff more data was available, false on EOS.
+    virtual bool feedMoreTSData() = 0;
+
+    virtual sp<MetaData> getFormat(bool audio) = 0;
+
+    virtual status_t dequeueAccessUnit(
+            bool audio, sp<ABuffer> *accessUnit) = 0;
+
+    virtual status_t getDuration(int64_t *durationUs) {
+        return INVALID_OPERATION;
+    }
+
+    virtual status_t seekTo(int64_t seekTimeUs) {
+        return INVALID_OPERATION;
+    }
+
+    virtual bool isSeekable() {
+        return false;
+    }
+
+protected:
+    virtual ~Source() {}
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(Source);
+};
+
+}  // namespace android
+
+#endif  // NUPLAYER_SOURCE_H_
+
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
index 92642a8..a23beb7 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
@@ -22,6 +22,8 @@
 
 #include <binder/MemoryDealer.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
 
 namespace android {
 
@@ -62,7 +64,10 @@
 
     if (mSendDataNotification) {
         mSendDataNotification = false;
-        (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
+
+        if (mTargetID != 0) {
+            (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
+        }
     }
 }
 
@@ -80,7 +85,10 @@
 
     if (mSendDataNotification) {
         mSendDataNotification = false;
-        (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
+
+        if (mTargetID != 0) {
+            (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
+        }
     }
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
new file mode 100644
index 0000000..b85ac9f
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "StreamingSource"
+#include <utils/Log.h>
+
+#include "StreamingSource.h"
+
+#include "ATSParser.h"
+#include "AnotherPacketSource.h"
+#include "NuPlayerStreamListener.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+NuPlayer::StreamingSource::StreamingSource(const sp<IStreamSource> &source)
+    : mSource(source),
+      mEOS(false) {
+}
+
+NuPlayer::StreamingSource::~StreamingSource() {
+}
+
+void NuPlayer::StreamingSource::start() {
+    mStreamListener = new NuPlayerStreamListener(mSource, 0);
+    mTSParser = new ATSParser;
+
+    mStreamListener->start();
+}
+
+bool NuPlayer::StreamingSource::feedMoreTSData() {
+    if (mEOS) {
+        return false;
+    }
+
+    for (int32_t i = 0; i < 10; ++i) {
+        char buffer[188];
+        ssize_t n = mStreamListener->read(buffer, sizeof(buffer));
+
+        if (n == 0) {
+            LOGI("input data EOS reached.");
+            mTSParser->signalEOS(ERROR_END_OF_STREAM);
+            mEOS = true;
+            break;
+        } else if (n == INFO_DISCONTINUITY) {
+            mTSParser->signalDiscontinuity(ATSParser::DISCONTINUITY_SEEK);
+        } else if (n < 0) {
+            CHECK_EQ(n, -EWOULDBLOCK);
+            break;
+        } else {
+            if (buffer[0] == 0x00) {
+                // XXX legacy
+                mTSParser->signalDiscontinuity(
+                        buffer[1] == 0x00
+                            ? ATSParser::DISCONTINUITY_SEEK
+                            : ATSParser::DISCONTINUITY_FORMATCHANGE);
+            } else {
+                mTSParser->feedTSPacket(buffer, sizeof(buffer));
+            }
+        }
+    }
+
+    return true;
+}
+
+sp<MetaData> NuPlayer::StreamingSource::getFormat(bool audio) {
+    ATSParser::SourceType type =
+        audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO;
+
+    sp<AnotherPacketSource> source =
+        static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+
+    if (source == NULL) {
+        return NULL;
+    }
+
+    return source->getFormat();
+}
+
+status_t NuPlayer::StreamingSource::dequeueAccessUnit(
+        bool audio, sp<ABuffer> *accessUnit) {
+    ATSParser::SourceType type =
+        audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO;
+
+    sp<AnotherPacketSource> source =
+        static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+
+    if (source == NULL) {
+        return -EWOULDBLOCK;
+    }
+
+    status_t finalResult;
+    if (!source->hasBufferAvailable(&finalResult)) {
+        return finalResult == OK ? -EWOULDBLOCK : finalResult;
+    }
+
+    return source->dequeueAccessUnit(accessUnit);
+}
+
+}  // namespace android
+
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.h b/media/libmediaplayerservice/nuplayer/StreamingSource.h
new file mode 100644
index 0000000..7abce84
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STREAMING_SOURCE_H_
+
+#define STREAMING_SOURCE_H_
+
+#include "NuPlayer.h"
+#include "NuPlayerSource.h"
+
+namespace android {
+
+struct ABuffer;
+struct ATSParser;
+
+struct NuPlayer::StreamingSource : public NuPlayer::Source {
+    StreamingSource(const sp<IStreamSource> &source);
+
+    virtual void start();
+
+    // Returns true iff more data was available, false on EOS.
+    virtual bool feedMoreTSData();
+
+    virtual sp<MetaData> getFormat(bool audio);
+    virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+
+protected:
+    virtual ~StreamingSource();
+
+private:
+    sp<IStreamSource> mSource;
+    bool mEOS;
+    sp<NuPlayerStreamListener> mStreamListener;
+    sp<ATSParser> mTSParser;
+
+    DISALLOW_EVIL_CONSTRUCTORS(StreamingSource);
+};
+
+}  // namespace android
+
+#endif  // STREAMING_SOURCE_H_
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 77276ab..dfb4e00 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -299,7 +299,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 ACodec::ACodec()
-    : mNode(NULL) {
+    : mNode(NULL),
+      mSentFormat(false) {
     mUninitializedState = new UninitializedState(this);
     mLoadedToIdleState = new LoadedToIdleState(this);
     mIdleToExecutingState = new IdleToExecutingState(this);
@@ -980,6 +981,103 @@
     }
 }
 
+void ACodec::sendFormatChange() {
+    sp<AMessage> notify = mNotify->dup();
+    notify->setInt32("what", kWhatOutputFormatChanged);
+
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = kPortIndexOutput;
+
+    CHECK_EQ(mOMX->getParameter(
+                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
+             (status_t)OK);
+
+    CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
+
+    switch (def.eDomain) {
+        case OMX_PortDomainVideo:
+        {
+            OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
+
+            notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
+            notify->setInt32("width", videoDef->nFrameWidth);
+            notify->setInt32("height", videoDef->nFrameHeight);
+
+            OMX_CONFIG_RECTTYPE rect;
+            InitOMXParams(&rect);
+            rect.nPortIndex = kPortIndexOutput;
+
+            if (mOMX->getConfig(
+                        mNode, OMX_IndexConfigCommonOutputCrop,
+                        &rect, sizeof(rect)) != OK) {
+                rect.nLeft = 0;
+                rect.nTop = 0;
+                rect.nWidth = videoDef->nFrameWidth;
+                rect.nHeight = videoDef->nFrameHeight;
+            }
+
+            CHECK_GE(rect.nLeft, 0);
+            CHECK_GE(rect.nTop, 0);
+            CHECK_GE(rect.nWidth, 0u);
+            CHECK_GE(rect.nHeight, 0u);
+            CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
+            CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
+
+            notify->setRect(
+                    "crop",
+                    rect.nLeft,
+                    rect.nTop,
+                    rect.nLeft + rect.nWidth - 1,
+                    rect.nTop + rect.nHeight - 1);
+
+            if (mNativeWindow != NULL) {
+                android_native_rect_t crop;
+                crop.left = rect.nLeft;
+                crop.top = rect.nTop;
+                crop.right = rect.nLeft + rect.nWidth - 1;
+                crop.bottom = rect.nTop + rect.nHeight - 1;
+
+                CHECK_EQ(0, native_window_set_crop(
+                            mNativeWindow.get(), &crop));
+            }
+            break;
+        }
+
+        case OMX_PortDomainAudio:
+        {
+            OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
+            CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
+
+            OMX_AUDIO_PARAM_PCMMODETYPE params;
+            InitOMXParams(&params);
+            params.nPortIndex = kPortIndexOutput;
+
+            CHECK_EQ(mOMX->getParameter(
+                        mNode, OMX_IndexParamAudioPcm,
+                        &params, sizeof(params)),
+                     (status_t)OK);
+
+            CHECK(params.nChannels == 1 || params.bInterleaved);
+            CHECK_EQ(params.nBitPerSample, 16u);
+            CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
+            CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
+
+            notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
+            notify->setInt32("channel-count", params.nChannels);
+            notify->setInt32("sample-rate", params.nSamplingRate);
+            break;
+        }
+
+        default:
+            TRESPASS();
+    }
+
+    notify->post();
+
+    mSentFormat = true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
@@ -1082,7 +1180,7 @@
 bool ACodec::BaseState::onOMXEvent(
         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
     if (event != OMX_EventError) {
-        LOGI("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
+        LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
              mCodec->mComponentName.c_str(), event, data1, data2);
 
         return false;
@@ -1157,6 +1255,9 @@
     if (!msg->findObject("buffer", &obj)) {
         CHECK(msg->findInt32("err", &err));
 
+        LOGV("[%s] saw error %d instead of an input buffer",
+             mCodec->mComponentName.c_str(), err);
+
         obj.clear();
     }
 
@@ -1302,6 +1403,10 @@
                     info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
                 }
             } else {
+                if (!mCodec->mSentFormat) {
+                    mCodec->sendFormatChange();
+                }
+
                 if (mCodec->mNativeWindow == NULL) {
                     info->mData->setRange(rangeOffset, rangeLength);
                 }
@@ -1517,7 +1622,7 @@
 }
 
 void ACodec::LoadedToIdleState::stateEntered() {
-    LOGI("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
+    LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
 
     CHECK_EQ(allocateBuffers(), (status_t)OK);
 }
@@ -1574,7 +1679,7 @@
 }
 
 void ACodec::IdleToExecutingState::stateEntered() {
-    LOGI("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
+    LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
 }
 
 bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
@@ -1658,7 +1763,7 @@
 }
 
 void ACodec::ExecutingState::stateEntered() {
-    LOGI("[%s] Now Executing", mCodec->mComponentName.c_str());
+    LOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
 
     mCodec->processDeferredMessages();
 }
@@ -1714,7 +1819,7 @@
         {
             CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
 
-            if (data2 == OMX_IndexParamPortDefinition) {
+            if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
                 CHECK_EQ(mCodec->mOMX->sendCommand(
                             mCodec->mNode,
                             OMX_CommandPortDisable, kPortIndexOutput),
@@ -1726,6 +1831,8 @@
                 }
 
                 mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
+            } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
+                mCodec->mSentFormat = false;
             } else {
                 LOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
                      mCodec->mComponentName.c_str(), data2);
@@ -1784,7 +1891,7 @@
 }
 
 void ACodec::OutputPortSettingsChangedState::stateEntered() {
-    LOGI("[%s] Now handling output port settings change",
+    LOGV("[%s] Now handling output port settings change",
          mCodec->mComponentName.c_str());
 }
 
@@ -1813,6 +1920,8 @@
             } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
                 CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
 
+                mCodec->mSentFormat = false;
+
                 LOGV("[%s] Output port now reenabled.",
                         mCodec->mComponentName.c_str());
 
@@ -1865,7 +1974,9 @@
 }
 
 void ACodec::ExecutingToIdleState::stateEntered() {
-    LOGI("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
+    LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
+
+    mCodec->mSentFormat = false;
 }
 
 bool ACodec::ExecutingToIdleState::onOMXEvent(
@@ -1947,7 +2058,7 @@
 }
 
 void ACodec::IdleToLoadedState::stateEntered() {
-    LOGI("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
+    LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
 }
 
 bool ACodec::IdleToLoadedState::onOMXEvent(
@@ -1958,7 +2069,7 @@
             CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
             CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
 
-            LOGI("[%s] Now Loaded", mCodec->mComponentName.c_str());
+            LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
 
             CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
 
@@ -1992,12 +2103,12 @@
 }
 
 void ACodec::ErrorState::stateEntered() {
-    LOGI("[%s] Now in ErrorState", mCodec->mComponentName.c_str());
+    LOGV("[%s] Now in ErrorState", mCodec->mComponentName.c_str());
 }
 
 bool ACodec::ErrorState::onOMXEvent(
         OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
-    LOGI("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2);
+    LOGV("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2);
     return true;
 }
 
@@ -2008,7 +2119,7 @@
 }
 
 void ACodec::FlushingState::stateEntered() {
-    LOGI("[%s] Now Flushing", mCodec->mComponentName.c_str());
+    LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
 
     mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
 }
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 7613d04..4cfe28e 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -33,8 +33,6 @@
 #include "UDPPusher.h"
 
 #include <binder/IPCThreadState.h>
-#include <binder/MemoryDealer.h>
-#include <media/IStreamSource.h>
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/AudioPlayer.h>
@@ -54,6 +52,7 @@
 #include "include/LiveSession.h"
 
 #define USE_SURFACE_ALLOC 1
+#define FRAME_DROP_FREQ 7
 
 namespace android {
 
@@ -161,245 +160,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-struct QueueDataSource;
-
-struct QueueListener : public BnStreamListener {
-    QueueListener(QueueDataSource *owner)
-        : mOwner(owner) {
-    }
-
-    void clearOwner();
-
-    virtual void queueBuffer(size_t index, size_t size);
-
-    virtual void issueCommand(
-            Command cmd, bool synchronous, const sp<AMessage> &msg);
-
-private:
-    Mutex mLock;
-
-    QueueDataSource *mOwner;
-
-    DISALLOW_EVIL_CONSTRUCTORS(QueueListener);
-};
-
-struct QueueDataSource : public DataSource {
-    QueueDataSource(const sp<IStreamSource> &source);
-
-    virtual status_t initCheck() const;
-
-    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
-
-    virtual void queueBuffer(size_t index, size_t size);
-
-    virtual void issueCommand(
-            IStreamListener::Command cmd,
-            bool synchronous,
-            const sp<AMessage> &msg);
-
-protected:
-    virtual ~QueueDataSource();
-
-private:
-    enum {
-        kNumBuffers = 16
-    };
-
-    struct QueueEntry {
-        bool mIsCommand;
-
-        IStreamListener::Command mCommand;
-        sp<AMessage> mCommandMessage;
-
-        size_t mIndex;
-        size_t mOffset;
-        size_t mSize;
-    };
-
-    Mutex mLock;
-    Condition mCondition;
-
-    sp<IStreamSource> mSource;
-    sp<QueueListener> mListener;
-    sp<MemoryDealer> mDealer;
-    Vector<sp<IMemory> > mBuffers;
-
-    List<QueueEntry> mQueue;
-
-    off64_t mPosition;
-    bool mEOS;
-
-    DISALLOW_EVIL_CONSTRUCTORS(QueueDataSource);
-};
-
-QueueDataSource::QueueDataSource(const sp<IStreamSource> &source)
-    : mSource(source),
-      mPosition(0),
-      mEOS(false) {
-    mListener = new QueueListener(this);
-    mSource->setListener(mListener);
-
-    static const size_t kBufferSize = (8192 / 188) * 188;
-
-    mDealer = new MemoryDealer(kNumBuffers * kBufferSize);
-    for (size_t i = 0; i < kNumBuffers; ++i) {
-        sp<IMemory> mem = mDealer->allocate(kBufferSize);
-        CHECK(mem != NULL);
-
-        mBuffers.push(mem);
-    }
-    mSource->setBuffers(mBuffers);
-
-    for (size_t i = 0; i < kNumBuffers; ++i) {
-        mSource->onBufferAvailable(i);
-    }
-}
-
-QueueDataSource::~QueueDataSource() {
-    Mutex::Autolock autoLock(mLock);
-
-    mListener->clearOwner();
-}
-
-status_t QueueDataSource::initCheck() const {
-    return OK;
-}
-
-ssize_t QueueDataSource::readAt(off64_t offset, void *data, size_t size) {
-    if (offset != mPosition) {
-        return -EPIPE;
-    }
-
-    Mutex::Autolock autoLock(mLock);
-
-    if (mEOS) {
-        return ERROR_END_OF_STREAM;
-    }
-
-    size_t sizeDone = 0;
-
-    while (sizeDone < size) {
-        while (mQueue.empty()) {
-            mCondition.wait(mLock);
-        }
-
-        QueueEntry &entry = *mQueue.begin();
-
-        if (entry.mIsCommand) {
-            switch (entry.mCommand) {
-                case IStreamListener::EOS:
-                {
-                    mEOS = true;
-
-                    if (sizeDone > 0) {
-                        offset += sizeDone;
-                        return sizeDone;
-                    } else {
-                        return ERROR_END_OF_STREAM;
-                    }
-                    break;
-                }
-
-                case IStreamListener::DISCONTINUITY:
-                {
-                    CHECK_EQ(size, 188u);
-                    CHECK_EQ(sizeDone, 0u);
-
-                    memset(data, 0, size);
-                    sizeDone = size;
-                    break;
-                }
-
-                default:
-                    break;
-            }
-
-            mQueue.erase(mQueue.begin());
-            continue;
-        }
-
-        size_t copy = size - sizeDone;
-        if (copy > entry.mSize) {
-            copy = entry.mSize;
-        }
-
-        memcpy((uint8_t *)data + sizeDone,
-               (const uint8_t *)mBuffers.itemAt(entry.mIndex)->pointer()
-                    + entry.mOffset,
-               copy);
-
-        entry.mSize -= copy;
-        entry.mOffset += copy;
-        sizeDone += copy;
-
-        if (entry.mSize == 0) {
-            mSource->onBufferAvailable(entry.mIndex);
-            mQueue.erase(mQueue.begin());
-        }
-    }
-
-    mPosition += sizeDone;
-
-    return sizeDone;
-}
-
-void QueueDataSource::queueBuffer(size_t index, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-
-    CHECK_LT(index, mBuffers.size());
-    CHECK_LE(size, mBuffers.itemAt(index)->size());
-
-    QueueEntry entry;
-    entry.mIsCommand = false;
-    entry.mIndex = index;
-    entry.mSize = size;
-    entry.mOffset = 0;
-
-    mQueue.push_back(entry);
-    mCondition.signal();
-}
-
-void QueueDataSource::issueCommand(
-        IStreamListener::Command cmd,
-        bool synchronous,
-        const sp<AMessage> &msg) {
-    Mutex::Autolock autoLock(mLock);
-
-    CHECK(!synchronous);
-
-    QueueEntry entry;
-    entry.mIsCommand = true;
-    entry.mCommand = cmd;
-    entry.mCommandMessage = msg;
-    mQueue.push_back(entry);
-
-    mCondition.signal();
-}
-
-void QueueListener::clearOwner() {
-    Mutex::Autolock autoLock(mLock);
-    mOwner = NULL;
-}
-
-void QueueListener::queueBuffer(size_t index, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-    if (mOwner == NULL) {
-        return;
-    }
-    mOwner->queueBuffer(index, size);
-}
-
-void QueueListener::issueCommand(
-        Command cmd, bool synchronous, const sp<AMessage> &msg) {
-    Mutex::Autolock autoLock(mLock);
-    if (mOwner == NULL) {
-        return;
-    }
-    mOwner->issueCommand(cmd, synchronous, msg);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
 AwesomePlayer::AwesomePlayer()
     : mQueueStarted(false),
       mTimeSource(NULL),
@@ -419,6 +179,8 @@
     mStreamDoneEventPending = false;
     mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
     mBufferingEventPending = false;
+    mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
+    mVideoEventPending = false;
 
     mCheckAudioStatusEvent = new AwesomeEvent(
             this, &AwesomePlayer::onCheckAudioStatus);
@@ -445,6 +207,8 @@
     mStreamDoneEventPending = false;
     mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
     mAudioStatusEventPending = false;
+    mQueue.cancelEvent(mVideoLagEvent->eventID());
+    mVideoLagEventPending = false;
 
     if (!keepBufferingGoing) {
         mQueue.cancelEvent(mBufferingEvent->eventID());
@@ -511,14 +275,7 @@
 }
 
 status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
-    Mutex::Autolock autoLock(mLock);
-
-    reset_l();
-
-    sp<DataSource> dataSource = new QueueDataSource(source);
-    sp<MediaExtractor> extractor = new MPEG2TSExtractor(dataSource);
-
-    return setDataSource_l(extractor);
+    return INVALID_OPERATION;
 }
 
 status_t AwesomePlayer::setDataSource_l(
@@ -605,11 +362,15 @@
 }
 
 void AwesomePlayer::reset() {
+    LOGI("reset");
+
     Mutex::Autolock autoLock(mLock);
     reset_l();
 }
 
 void AwesomePlayer::reset_l() {
+    LOGI("reset_l");
+
     if (mDecryptHandle != NULL) {
             mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
                     Playback::STOP, 0);
@@ -632,6 +393,10 @@
         }
     }
 
+    if (mFlags & PREPARING) {
+        LOGI("waiting until preparation is completes.");
+    }
+
     while (mFlags & PREPARING) {
         mPreparedCondition.wait(mLock);
     }
@@ -655,6 +420,8 @@
     }
     mAudioSource.clear();
 
+    LOGI("audio source cleared");
+
     mTimeSource = NULL;
 
     delete mAudioPlayer;
@@ -695,6 +462,8 @@
         IPCThreadState::self()->flushCommands();
     }
 
+    LOGI("video source cleared");
+
     mDurationUs = -1;
     mFlags = 0;
     mExtractorFlags = 0;
@@ -711,6 +480,8 @@
     mFileSource.clear();
 
     mBitrate = -1;
+
+    LOGI("reset_l completed");
 }
 
 void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
@@ -763,6 +534,28 @@
     }
 }
 
+void AwesomePlayer::onVideoLagUpdate() {
+    Mutex::Autolock autoLock(mLock);
+    if (!mVideoLagEventPending) {
+        return;
+    }
+    mVideoLagEventPending = false;
+
+    int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
+    int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
+
+    if (videoLateByUs > 300000ll) {
+        LOGV("video late by %lld ms.", videoLateByUs / 1000ll);
+
+        notifyListener_l(
+                MEDIA_INFO,
+                MEDIA_INFO_VIDEO_TRACK_LAGGING,
+                videoLateByUs / 1000ll);
+    }
+
+    postVideoLagEvent_l();
+}
+
 void AwesomePlayer::onBufferingUpdate() {
     Mutex::Autolock autoLock(mLock);
     if (!mBufferingEventPending) {
@@ -1021,6 +814,10 @@
     if (mVideoSource != NULL) {
         // Kick off video playback
         postVideoEvent_l();
+
+        if (mAudioSource != NULL && mVideoSource != NULL) {
+            postVideoLagEvent_l();
+        }
     }
 
     if (deferredAudioSeek) {
@@ -1489,7 +1286,7 @@
 
     if (mFlags & FIRST_FRAME) {
         mFlags &= ~FIRST_FRAME;
-
+        mSinceLastDropped = 0;
         mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
     }
 
@@ -1517,12 +1314,16 @@
     if (latenessUs > 40000) {
         // We're more than 40ms late.
         LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
+        if ( mSinceLastDropped > FRAME_DROP_FREQ)
+        {
+            LOGV("we're late by %lld us (%.2f secs) dropping one after %d frames", latenessUs, latenessUs / 1E6, mSinceLastDropped);
+            mSinceLastDropped = 0;
+            mVideoBuffer->release();
+            mVideoBuffer = NULL;
 
-        mVideoBuffer->release();
-        mVideoBuffer = NULL;
-
-        postVideoEvent_l();
-        return;
+            postVideoEvent_l();
+            return;
+        }
     }
 
     if (latenessUs < -10000) {
@@ -1539,6 +1340,7 @@
     }
 
     if (mVideoRenderer != NULL) {
+        mSinceLastDropped++;
         mVideoRenderer->render(mVideoBuffer);
     }
 
@@ -1575,6 +1377,14 @@
     mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
 }
 
+void AwesomePlayer::postVideoLagEvent_l() {
+    if (mVideoLagEventPending) {
+        return;
+    }
+    mVideoLagEventPending = true;
+    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
+}
+
 void AwesomePlayer::postCheckAudioStatusEvent_l() {
     if (mAudioStatusEventPending) {
         return;
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 2f3353b..b1c6b18 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -573,7 +573,7 @@
 }
 
 status_t CameraSource::stop() {
-    LOGV("stop");
+    LOGD("stop: E");
     Mutex::Autolock autoLock(mLock);
     mStarted = false;
     mFrameAvailableCondition.signal();
@@ -581,9 +581,11 @@
     int64_t token = IPCThreadState::self()->clearCallingIdentity();
     releaseQueuedFrames();
     while (!mFramesBeingEncoded.empty()) {
-        LOGI("Waiting for outstanding frames being encoded: %d",
+        if (NO_ERROR !=
+            mFrameCompleteCondition.waitRelative(mLock, 3000000000LL)) {
+            LOGW("Timed out waiting for outstanding frames being encoded: %d",
                 mFramesBeingEncoded.size());
-        mFrameCompleteCondition.wait(mLock);
+        }
     }
     stopCameraRecording();
     releaseCamera();
@@ -601,6 +603,7 @@
     }
 
     CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
+    LOGD("stop: X");
     return OK;
 }
 
@@ -666,7 +669,11 @@
     {
         Mutex::Autolock autoLock(mLock);
         while (mStarted && mFramesReceived.empty()) {
-            mFrameAvailableCondition.wait(mLock);
+            if (NO_ERROR !=
+                mFrameAvailableCondition.waitRelative(mLock, 3000000000LL)) {
+                LOGW("Timed out waiting for incoming camera video frames: %lld us",
+                    mLastFrameTimestampUs);
+            }
         }
         if (!mStarted) {
             return OK;
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 0b158be..31b6ec9 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -76,7 +76,7 @@
     mVideoWidth = videoSize.width;
     mVideoHeight = videoSize.height;
 
-    if (trySettingPreviewSize(videoSize.width, videoSize.height)) {
+    if (trySettingVideoSize(videoSize.width, videoSize.height)) {
         mUseStillCameraForTimeLapse = false;
     } else {
         // TODO: Add a check to see that mTimeBetweenTimeLapseFrameCaptureUs is greater
@@ -115,29 +115,39 @@
     }
 }
 
-bool CameraSourceTimeLapse::trySettingPreviewSize(int32_t width, int32_t height) {
-    LOGV("trySettingPreviewSize: %dx%d", width, height);
+bool CameraSourceTimeLapse::trySettingVideoSize(int32_t width, int32_t height) {
+    LOGV("trySettingVideoSize: %dx%d", width, height);
     int64_t token = IPCThreadState::self()->clearCallingIdentity();
     String8 s = mCamera->getParameters();
 
     CameraParameters params(s);
     Vector<Size> supportedSizes;
-    params.getSupportedPreviewSizes(supportedSizes);
+    params.getSupportedVideoSizes(supportedSizes);
+    bool videoOutputSupported = false;
+    if (supportedSizes.size() == 0) {
+        params.getSupportedPreviewSizes(supportedSizes);
+    } else {
+        videoOutputSupported = true;
+    }
 
-    bool previewSizeSupported = false;
+    bool videoSizeSupported = false;
     for (uint32_t i = 0; i < supportedSizes.size(); ++i) {
         int32_t pictureWidth = supportedSizes[i].width;
         int32_t pictureHeight = supportedSizes[i].height;
 
         if ((pictureWidth == width) && (pictureHeight == height)) {
-            previewSizeSupported = true;
+            videoSizeSupported = true;
         }
     }
 
     bool isSuccessful = false;
-    if (previewSizeSupported) {
-        LOGV("Video size (%d, %d) is a supported preview size", width, height);
-        params.setPreviewSize(width, height);
+    if (videoSizeSupported) {
+        LOGV("Video size (%d, %d) is supported", width, height);
+        if (videoOutputSupported) {
+            params.setVideoSize(width, height);
+        } else {
+            params.setPreviewSize(width, height);
+        }
         if (mCamera->setParameters(params.flatten()) == OK) {
             isSuccessful = true;
         } else {
@@ -337,7 +347,8 @@
 }
 
 void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
-    if (!mUseStillCameraForTimeLapse) {
+    if (!mUseStillCameraForTimeLapse &&
+        mCamera != NULL) {
         mCamera->releaseRecordingFrame(frame);
     }
 }
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 9610f90..00a4dd5e 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -228,22 +228,47 @@
 
     off64_t pos = *inout_pos;
     bool valid = false;
+
+    const size_t kMaxReadBytes = 1024;
+    const size_t kMaxBytesChecked = 128 * 1024;
+    uint8_t buf[kMaxReadBytes];
+    ssize_t bytesToRead = kMaxReadBytes;
+    ssize_t totalBytesRead = 0;
+    ssize_t remainingBytes = 0;
+    bool reachEOS = false;
+    uint8_t *tmp = buf;
+
     do {
-        if (pos >= *inout_pos + 128 * 1024) {
+        if (pos >= *inout_pos + kMaxBytesChecked) {
             // Don't scan forever.
             LOGV("giving up at offset %ld", pos);
             break;
         }
 
-        uint8_t tmp[4];
-        if (source->readAt(pos, tmp, 4) != 4) {
-            break;
+        if (remainingBytes < 4) {
+            if (reachEOS) {
+                break;
+            } else {
+                memcpy(buf, tmp, remainingBytes);
+                bytesToRead = kMaxReadBytes - remainingBytes;
+                totalBytesRead = source->readAt(pos, buf + remainingBytes, bytesToRead);
+                if (totalBytesRead <= 0) {
+                    break;
+                }
+                reachEOS = (totalBytesRead != bytesToRead);
+                totalBytesRead += remainingBytes;
+                remainingBytes = totalBytesRead;
+                tmp = buf;
+                continue;
+            }
         }
 
         uint32_t header = U32_AT(tmp);
 
         if (match_header != 0 && (header & kMask) != (match_header & kMask)) {
             ++pos;
+            ++tmp;
+            --remainingBytes;
             continue;
         }
 
@@ -253,6 +278,8 @@
                     header, &frame_size,
                     &sample_rate, &num_channels, &bitrate)) {
             ++pos;
+            ++tmp;
+            --remainingBytes;
             continue;
         }
 
@@ -303,6 +330,8 @@
         }
 
         ++pos;
+        ++tmp;
+        --remainingBytes;
     } while (!valid);
 
     return valid;
@@ -614,6 +643,7 @@
         { kKeyAuthor, "TXT", "TEXT" },
         { kKeyCDTrackNumber, "TRK", "TRCK" },
         { kKeyDiscNumber, "TPA", "TPOS" },
+        { kKeyCompilation, "TCP", "TCMP" },
     };
     static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
 
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index d3c7445..bafa243 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -959,6 +959,13 @@
             uint16_t width = U16_AT(&buffer[6 + 18]);
             uint16_t height = U16_AT(&buffer[6 + 20]);
 
+            // The video sample is not stand-compliant if it has invalid dimension.
+            // Use some default width and height value, and
+            // let the decoder figure out the actual width and height (and thus
+            // be prepared for INFO_FOMRAT_CHANGED event).
+            if (width == 0)  width  = 352;
+            if (height == 0) height = 288;
+
             // printf("*** coding='%s' width=%d height=%d\n",
             //        chunk, width, height);
 
@@ -1385,6 +1392,17 @@
             metadataKey = kKeyGenre;
             break;
         }
+        case FOURCC('c', 'p', 'i', 'l'):
+        {
+            if (size == 9 && flags == 21) {
+                char tmp[16];
+                sprintf(tmp, "%d",
+                        (int)buffer[size - 1]);
+
+                mFileMetaData->setCString(kKeyCompilation, tmp);
+            }
+            break;
+        }
         case FOURCC('t', 'r', 'k', 'n'):
         {
             if (size == 16 && flags == 0) {
diff --git a/media/libstagefright/MediaBuffer.cpp b/media/libstagefright/MediaBuffer.cpp
index cbccd31..a8fadf2 100644
--- a/media/libstagefright/MediaBuffer.cpp
+++ b/media/libstagefright/MediaBuffer.cpp
@@ -26,17 +26,10 @@
 #include <media/stagefright/MetaData.h>
 
 #include <ui/GraphicBuffer.h>
+#include <sys/atomics.h>
 
 namespace android {
 
-// XXX make this truly atomic.
-static int atomic_add(int *value, int delta) {
-    int prev_value = *value;
-    *value += delta;
-
-    return prev_value;
-}
-
 MediaBuffer::MediaBuffer(void *data, size_t size)
     : mObserver(NULL),
       mNextBuffer(NULL),
@@ -84,7 +77,7 @@
         return;
     }
 
-    int prevCount = atomic_add(&mRefCount, -1);
+    int prevCount = __atomic_dec(&mRefCount);
     if (prevCount == 1) {
         if (mObserver == NULL) {
             delete this;
@@ -104,7 +97,7 @@
 }
 
 void MediaBuffer::add_ref() {
-    atomic_add(&mRefCount, 1);
+    (void) __atomic_inc(&mRefCount);
 }
 
 void *MediaBuffer::data() const {
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 110fb03..9017921 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -319,7 +319,7 @@
 
 void NuCachedSource2::restartPrefetcherIfNecessary_l(
         bool ignoreLowWaterThreshold) {
-    static const size_t kGrayArea = 256 * 1024;
+    static const size_t kGrayArea = 1024 * 1024;
 
     if (mFetching || mFinalStatus != OK) {
         return;
@@ -348,7 +348,7 @@
 ssize_t NuCachedSource2::readAt(off64_t offset, void *data, size_t size) {
     Mutex::Autolock autoSerializer(mSerializer);
 
-    LOGV("readAt offset %ld, size %d", offset, size);
+    LOGV("readAt offset %lld, size %d", offset, size);
 
     Mutex::Autolock autoLock(mLock);
 
@@ -408,13 +408,13 @@
 }
 
 ssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) {
-    LOGV("readInternal offset %ld size %d", offset, size);
+    LOGV("readInternal offset %lld size %d", offset, size);
 
     Mutex::Autolock autoLock(mLock);
 
     if (offset < mCacheOffset
             || offset >= (off64_t)(mCacheOffset + mCache->totalSize())) {
-        static const off64_t kPadding = 32768;
+        static const off64_t kPadding = 256 * 1024;
 
         // In the presence of multiple decoded streams, once of them will
         // trigger this seek request, the other one will request data "nearby"
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index 4ce7265..653c85e 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -158,6 +158,9 @@
         request.append(" HTTP/1.1\r\n");
         request.append("Host: ");
         request.append(mHost);
+        if (mPort != 80) {
+            request.append(StringPrintf(":%u", mPort).c_str());
+        }
         request.append("\r\n");
 
         if (offset != 0) {
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 69ab75a..e516cb4 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -235,7 +235,9 @@
         sp<OMXCodec> codec = mTarget.promote();
 
         if (codec.get() != NULL) {
+            Mutex::Autolock autoLock(codec->mLock);
             codec->on_message(msg);
+            codec.clear();
         }
     }
 
@@ -1506,7 +1508,7 @@
 OMXCodec::~OMXCodec() {
     mSource.clear();
 
-    CHECK(mState == LOADED || mState == ERROR);
+    CHECK(mState == LOADED || mState == ERROR || mState == LOADED_TO_IDLE);
 
     status_t err = mOMX->freeNode(mNode);
     CHECK_EQ(err, (status_t)OK);
@@ -1536,7 +1538,9 @@
     }
 
     err = allocateBuffers();
-    CHECK_EQ(err, (status_t)OK);
+    if (err != (status_t)OK) {
+        return err;
+    }
 
     if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
         err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
@@ -1843,8 +1847,6 @@
 }
 
 void OMXCodec::on_message(const omx_message &msg) {
-    Mutex::Autolock autoLock(mLock);
-
     switch (msg.type) {
         case omx_message::EVENT:
         {
@@ -3359,7 +3361,15 @@
     }
 
     while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
-        mBufferFilled.wait(mLock);
+        if (mIsEncoder) {
+            if (NO_ERROR != mBufferFilled.waitRelative(mLock, 3000000000LL)) {
+                LOGW("Timed out waiting for buffers from video encoder: %d/%d",
+                    countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
+                    countBuffersWeOwn(mPortBuffers[kPortIndexOutput]));
+            }
+        } else {
+            mBufferFilled.wait(mLock);
+        }
     }
 
     if (mState == ERROR) {
@@ -3913,6 +3923,8 @@
 
             if (!mIsEncoder) {
                 OMX_CONFIG_RECTTYPE rect;
+                InitOMXParams(&rect);
+                rect.nPortIndex = kPortIndexOutput;
                 status_t err =
                         mOMX->getConfig(
                             mNode, OMX_IndexConfigCommonOutputCrop,
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 4b8a014..cf622af 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -660,6 +660,9 @@
     } kMap[] = {
         { "TITLE", kKeyTitle },
         { "ARTIST", kKeyArtist },
+        { "ALBUMARTIST", kKeyAlbumArtist },
+        { "ALBUM ARTIST", kKeyAlbumArtist },
+        { "COMPILATION", kKeyCompilation },
         { "ALBUM", kKeyAlbum },
         { "COMPOSER", kKeyComposer },
         { "GENRE", kKeyGenre },
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 86e0e73..39b0021 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -131,9 +131,7 @@
         if (status != OK) {
             return status;
         }
-    } else if (mRetriever->setDataSource(path) == OK
-            && mRetriever->setMode(
-                METADATA_MODE_METADATA_RETRIEVAL_ONLY) == OK) {
+    } else if (mRetriever->setDataSource(path) == OK) {
         const char *value;
         if ((value = mRetriever->extractMetadata(
                         METADATA_KEY_MIMETYPE)) != NULL) {
@@ -156,6 +154,7 @@
             { "year", METADATA_KEY_YEAR },
             { "duration", METADATA_KEY_DURATION },
             { "writer", METADATA_KEY_WRITER },
+            { "compilation", METADATA_KEY_COMPILATION },
         };
         static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
 
@@ -181,9 +180,7 @@
     }
     lseek64(fd, 0, SEEK_SET);
 
-    if (mRetriever->setDataSource(fd, 0, size) == OK
-            && mRetriever->setMode(
-                METADATA_MODE_FRAME_CAPTURE_ONLY) == OK) {
+    if (mRetriever->setDataSource(fd, 0, size) == OK) {
         sp<IMemory> mem = mRetriever->extractAlbumArt();
 
         if (mem != NULL) {
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index ee3eefc..600de7c 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -238,7 +238,7 @@
             (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
     CHECK(converter.isValid());
 
-    converter.convert(
+    err = converter.convert(
             (const uint8_t *)buffer->data() + buffer->range_offset(),
             width, height,
             crop_left, crop_top, crop_right, crop_bottom,
@@ -252,6 +252,13 @@
 
     decoder->stop();
 
+    if (err != OK) {
+        LOGE("Colorconverter failed to convert frame.");
+
+        delete frame;
+        frame = NULL;
+    }
+
     return frame;
 }
 
@@ -259,11 +266,6 @@
         int64_t timeUs, int option) {
 
     LOGV("getFrameAtTime: %lld us option: %d", timeUs, option);
-    if (0 == (mMode & METADATA_MODE_FRAME_CAPTURE_ONLY)) {
-        LOGV("captureFrame disabled by mode (0x%08x)", mMode);
-
-        return NULL;
-    }
 
     if (mExtractor.get() == NULL) {
         LOGV("no extractor.");
@@ -317,12 +319,6 @@
 MediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() {
     LOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO");
 
-    if (0 == (mMode & METADATA_MODE_METADATA_RETRIEVAL_ONLY)) {
-        LOGV("extractAlbumArt/metadata retrieval disabled by mode");
-
-        return NULL;
-    }
-
     if (mExtractor == NULL) {
         return NULL;
     }
@@ -341,12 +337,6 @@
 }
 
 const char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
-    if (0 == (mMode & METADATA_MODE_METADATA_RETRIEVAL_ONLY)) {
-        LOGV("extractAlbumArt/metadata retrieval disabled by mode");
-
-        return NULL;
-    }
-
     if (mExtractor == NULL) {
         return NULL;
     }
@@ -387,6 +377,7 @@
         { kKeyTitle, METADATA_KEY_TITLE },
         { kKeyYear, METADATA_KEY_YEAR },
         { kKeyWriter, METADATA_KEY_WRITER },
+        { kKeyCompilation, METADATA_KEY_COMPILATION },
     };
     static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
 
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index 2fe5e18..fa12cf0 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "avc_utils"
+#include <utils/Log.h>
+
 #include "include/avc_utils.h"
 
 #include <media/stagefright/foundation/ABitReader.h>
diff --git a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
index 0f08f6e..38778fb 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
@@ -132,7 +132,10 @@
     }
 
     MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle);
-    CHECK_EQ(mode, actualMode);
+    if (mode != actualMode) {
+        PVCleanUpVideoDecoder(mHandle);
+        return UNKNOWN_ERROR;
+    }
 
     PVSetPostProcType((VideoDecControls *) mHandle, 0);
 
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 600f040..d518c97 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -16,6 +16,7 @@
 
 #include <media/stagefright/ColorConverter.h>
 #include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaErrors.h>
 
 namespace android {
 
@@ -72,7 +73,7 @@
     return mCropBottom - mCropTop + 1;
 }
 
-void ColorConverter::convert(
+status_t ColorConverter::convert(
         const void *srcBits,
         size_t srcWidth, size_t srcHeight,
         size_t srcCropLeft, size_t srcCropTop,
@@ -81,7 +82,9 @@
         size_t dstWidth, size_t dstHeight,
         size_t dstCropLeft, size_t dstCropTop,
         size_t dstCropRight, size_t dstCropBottom) {
-    CHECK_EQ(mDstFormat, OMX_COLOR_Format16bitRGB565);
+    if (mDstFormat != OMX_COLOR_Format16bitRGB565) {
+        return ERROR_UNSUPPORTED;
+    }
 
     BitmapParams src(
             const_cast<void *>(srcBits),
@@ -93,21 +96,23 @@
             dstWidth, dstHeight,
             dstCropLeft, dstCropTop, dstCropRight, dstCropBottom);
 
+    status_t err;
+
     switch (mSrcFormat) {
         case OMX_COLOR_FormatYUV420Planar:
-            convertYUV420Planar(src, dst);
+            err = convertYUV420Planar(src, dst);
             break;
 
         case OMX_COLOR_FormatCbYCrY:
-            convertCbYCrY(src, dst);
+            err = convertCbYCrY(src, dst);
             break;
 
         case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
-            convertQCOMYUV420SemiPlanar(src, dst);
+            err = convertQCOMYUV420SemiPlanar(src, dst);
             break;
 
         case OMX_COLOR_FormatYUV420SemiPlanar:
-            convertYUV420SemiPlanar(src, dst);
+            err = convertYUV420SemiPlanar(src, dst);
             break;
 
         default:
@@ -116,17 +121,21 @@
             break;
         }
     }
+
+    return err;
 }
 
-void ColorConverter::convertCbYCrY(
+status_t ColorConverter::convertCbYCrY(
         const BitmapParams &src, const BitmapParams &dst) {
     // XXX Untested
 
     uint8_t *kAdjustedClip = initClip();
 
-    CHECK((src.mCropLeft & 1) == 0);
-    CHECK_EQ(src.cropWidth(), dst.cropWidth());
-    CHECK_EQ(src.cropHeight(), dst.cropHeight());
+    if (!((src.mCropLeft & 1) == 0
+        && src.cropWidth() == dst.cropWidth()
+        && src.cropHeight() == dst.cropHeight())) {
+        return ERROR_UNSUPPORTED;
+    }
 
     uint32_t *dst_ptr = (uint32_t *)dst.mBits
         + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2;
@@ -172,16 +181,20 @@
         src_ptr += src.mWidth * 2;
         dst_ptr += dst.mWidth / 2;
     }
+
+    return OK;
 }
 
-void ColorConverter::convertYUV420Planar(
+status_t ColorConverter::convertYUV420Planar(
         const BitmapParams &src, const BitmapParams &dst) {
-    uint8_t *kAdjustedClip = initClip();
+    if (!((dst.mWidth & 3) == 0
+            && (src.mCropLeft & 1) == 0
+            && src.cropWidth() == dst.cropWidth()
+            && src.cropHeight() == dst.cropHeight())) {
+        return ERROR_UNSUPPORTED;
+    }
 
-    CHECK((dst.mWidth & 3) == 0);
-    CHECK((src.mCropLeft & 1) == 0);
-    CHECK_EQ(src.cropWidth(), dst.cropWidth());
-    CHECK_EQ(src.cropHeight(), dst.cropHeight());
+    uint8_t *kAdjustedClip = initClip();
 
     uint32_t *dst_ptr = (uint32_t *)dst.mBits
         + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2;
@@ -259,16 +272,20 @@
 
         dst_ptr += dst.mWidth / 2;
     }
+
+    return OK;
 }
 
-void ColorConverter::convertQCOMYUV420SemiPlanar(
+status_t ColorConverter::convertQCOMYUV420SemiPlanar(
         const BitmapParams &src, const BitmapParams &dst) {
     uint8_t *kAdjustedClip = initClip();
 
-    CHECK((dst.mWidth & 3) == 0);
-    CHECK((src.mCropLeft & 1) == 0);
-    CHECK_EQ(src.cropWidth(), dst.cropWidth());
-    CHECK_EQ(src.cropHeight(), dst.cropHeight());
+    if (!((dst.mWidth & 3) == 0
+            && (src.mCropLeft & 1) == 0
+            && src.cropWidth() == dst.cropWidth()
+            && src.cropHeight() == dst.cropHeight())) {
+        return ERROR_UNSUPPORTED;
+    }
 
     uint32_t *dst_ptr = (uint32_t *)dst.mBits
         + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2;
@@ -324,18 +341,22 @@
 
         dst_ptr += dst.mWidth / 2;
     }
+
+    return OK;
 }
 
-void ColorConverter::convertYUV420SemiPlanar(
+status_t ColorConverter::convertYUV420SemiPlanar(
         const BitmapParams &src, const BitmapParams &dst) {
     // XXX Untested
 
     uint8_t *kAdjustedClip = initClip();
 
-    CHECK((dst.mWidth & 3) == 0);
-    CHECK((src.mCropLeft & 1) == 0);
-    CHECK_EQ(src.cropWidth(), dst.cropWidth());
-    CHECK_EQ(src.cropHeight(), dst.cropHeight());
+    if (!((dst.mWidth & 3) == 0
+            && (src.mCropLeft & 1) == 0
+            && src.cropWidth() == dst.cropWidth()
+            && src.cropHeight() == dst.cropHeight())) {
+        return ERROR_UNSUPPORTED;
+    }
 
     uint32_t *dst_ptr = (uint32_t *)dst.mBits
         + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2;
@@ -391,6 +412,8 @@
 
         dst_ptr += dst.mWidth / 2;
     }
+
+    return OK;
 }
 
 uint8_t *ColorConverter::initClip() {
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 7da9cb8..b592c3f 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -171,6 +171,18 @@
     item->u.refValue = obj.get();
 }
 
+void AMessage::setRect(
+        const char *name,
+        int32_t left, int32_t top, int32_t right, int32_t bottom) {
+    Item *item = allocateItem(name);
+    item->mType = kTypeRect;
+
+    item->u.rectValue.mLeft = left;
+    item->u.rectValue.mTop = top;
+    item->u.rectValue.mRight = right;
+    item->u.rectValue.mBottom = bottom;
+}
+
 bool AMessage::findString(const char *name, AString *value) const {
     const Item *item = findItem(name, kTypeString);
     if (item) {
@@ -198,6 +210,22 @@
     return false;
 }
 
+bool AMessage::findRect(
+        const char *name,
+        int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
+    const Item *item = findItem(name, kTypeRect);
+    if (item == NULL) {
+        return false;
+    }
+
+    *left = item->u.rectValue.mLeft;
+    *top = item->u.rectValue.mTop;
+    *right = item->u.rectValue.mRight;
+    *bottom = item->u.rectValue.mBottom;
+
+    return true;
+}
+
 void AMessage::post(int64_t delayUs) {
     extern ALooperRoster gLooperRoster;
 
@@ -224,13 +252,22 @@
             }
 
             case kTypeObject:
-            case kTypeMessage:
             {
                 to->u.refValue = from->u.refValue;
                 to->u.refValue->incStrong(msg.get());
                 break;
             }
 
+            case kTypeMessage:
+            {
+                sp<AMessage> copy =
+                    static_cast<AMessage *>(from->u.refValue)->dup();
+
+                to->u.refValue = copy.get();
+                to->u.refValue->incStrong(msg.get());
+                break;
+            }
+
             default:
             {
                 to->u = from->u;
diff --git a/media/libstagefright/httplive/LiveDataSource.cpp b/media/libstagefright/httplive/LiveDataSource.cpp
index 25e2902..5f5c6d4 100644
--- a/media/libstagefright/httplive/LiveDataSource.cpp
+++ b/media/libstagefright/httplive/LiveDataSource.cpp
@@ -54,7 +54,8 @@
     return mBufferQueue.size();
 }
 
-ssize_t LiveDataSource::readAt(off64_t offset, void *data, size_t size) {
+ssize_t LiveDataSource::readAtNonBlocking(
+        off64_t offset, void *data, size_t size) {
     Mutex::Autolock autoLock(mLock);
 
     if (offset != mOffset) {
@@ -62,6 +63,36 @@
         return -EPIPE;
     }
 
+    size_t totalAvailable = 0;
+    for (List<sp<ABuffer> >::iterator it = mBufferQueue.begin();
+         it != mBufferQueue.end(); ++it) {
+        sp<ABuffer> buffer = *it;
+
+        totalAvailable += buffer->size();
+
+        if (totalAvailable >= size) {
+            break;
+        }
+    }
+
+    if (totalAvailable < size) {
+        return mFinalResult == OK ? -EWOULDBLOCK : mFinalResult;
+    }
+
+    return readAt_l(offset, data, size);
+}
+
+ssize_t LiveDataSource::readAt(off64_t offset, void *data, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+    return readAt_l(offset, data, size);
+}
+
+ssize_t LiveDataSource::readAt_l(off64_t offset, void *data, size_t size) {
+    if (offset != mOffset) {
+        LOGE("Attempt at reading non-sequentially from LiveDataSource.");
+        return -EPIPE;
+    }
+
     size_t sizeDone = 0;
 
     while (sizeDone < size) {
diff --git a/media/libstagefright/httplive/LiveDataSource.h b/media/libstagefright/httplive/LiveDataSource.h
index a489ec6..b7be637 100644
--- a/media/libstagefright/httplive/LiveDataSource.h
+++ b/media/libstagefright/httplive/LiveDataSource.h
@@ -33,6 +33,7 @@
     virtual status_t initCheck() const;
 
     virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+    ssize_t readAtNonBlocking(off64_t offset, void *data, size_t size);
 
     void queueBuffer(const sp<ABuffer> &buffer);
     void queueEOS(status_t finalResult);
@@ -53,6 +54,8 @@
 
     FILE *mBackupFile;
 
+    ssize_t readAt_l(off64_t offset, void *data, size_t size);
+
     DISALLOW_EVIL_CONSTRUCTORS(LiveDataSource);
 };
 
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 62567be..5979be6 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -157,9 +157,16 @@
 
         mBandwidthItems.sort(SortByBandwidth);
 
-        if (mBandwidthItems.size() > 1) {
-            // XXX Remove the lowest bitrate stream for now...
-            mBandwidthItems.removeAt(0);
+        char value[PROPERTY_VALUE_MAX];
+        if (property_get("media.httplive.disable-nuplayer", value, NULL)
+                && (!strcasecmp(value, "true") || !strcmp(value, "1"))) {
+            // The "legacy" player cannot deal with audio format changes,
+            // some streams use different audio encoding parameters for
+            // their lowest bandwidth stream.
+            if (mBandwidthItems.size() > 1) {
+                // XXX Remove the lowest bitrate stream for now...
+                mBandwidthItems.removeAt(0);
+            }
         }
     }
 
@@ -179,9 +186,9 @@
 
     if (!strncasecmp(url, "file://", 7)) {
         source = new FileSource(url + 7);
+    } else if (strncasecmp(url, "http://", 7)) {
+        return ERROR_UNSUPPORTED;
     } else {
-        CHECK(!strncasecmp(url, "http://", 7));
-
         status_t err = mHTTPDataSource->connect(url);
 
         if (err != OK) {
@@ -222,7 +229,7 @@
                 bufferRemaining);
 
         if (n < 0) {
-            return err;
+            return n;
         }
 
         if (n == 0) {
@@ -333,6 +340,7 @@
 void LiveSession::onDownloadNext() {
     size_t bandwidthIndex = getBandwidthIndex();
 
+rinse_repeat:
     int64_t nowUs = ALooper::GetNowUs();
 
     if (mLastPlaylistFetchTimeUs < 0
@@ -349,7 +357,11 @@
         bool firstTime = (mPlaylist == NULL);
 
         mPlaylist = fetchPlaylist(url.c_str());
-        CHECK(mPlaylist != NULL);
+        if (mPlaylist == NULL) {
+            LOGE("failed to load playlist at url '%s'", url.c_str());
+            mDataSource->queueEOS(ERROR_IO);
+            return;
+        }
 
         if (firstTime) {
             Mutex::Autolock autoLock(mLock);
@@ -374,6 +386,7 @@
     }
 
     bool explicitDiscontinuity = false;
+    bool bandwidthChanged = false;
 
     if (mSeekTimeUs >= 0) {
         int32_t targetDuration;
@@ -384,10 +397,24 @@
             int64_t index = seekTimeSecs / targetDuration;
 
             if (index >= 0 && index < mPlaylist->size()) {
-                mSeqNumber = firstSeqNumberInPlaylist + index;
-                mDataSource->reset();
+                int32_t newSeqNumber = firstSeqNumberInPlaylist + index;
 
-                explicitDiscontinuity = true;
+                if (newSeqNumber != mSeqNumber) {
+                    LOGI("seeking to seq no %d", newSeqNumber);
+
+                    mSeqNumber = newSeqNumber;
+
+                    mDataSource->reset();
+
+                    // reseting the data source will have had the
+                    // side effect of discarding any previously queued
+                    // bandwidth change discontinuity.
+                    // Therefore we'll need to treat these explicit
+                    // discontinuities as involving a bandwidth change
+                    // even if they aren't directly.
+                    explicitDiscontinuity = true;
+                    bandwidthChanged = true;
+                }
             }
         }
 
@@ -411,13 +438,25 @@
 
     if (mSeqNumber < firstSeqNumberInPlaylist
             || mSeqNumber > lastSeqNumberInPlaylist) {
+        if (mSeqNumber < firstSeqNumberInPlaylist
+                && mPrevBandwidthIndex != (ssize_t)bandwidthIndex) {
+            // Go back to the previous bandwidth.
+
+            LOGI("new bandwidth does not have the sequence number "
+                 "we're looking for, switching back to previous bandwidth");
+
+            mLastPlaylistFetchTimeUs = -1;
+            bandwidthIndex = mPrevBandwidthIndex;
+            goto rinse_repeat;
+        }
+
         if (!mPlaylist->isComplete()
                 && mSeqNumber > lastSeqNumberInPlaylist
                 && mNumRetries < kMaxNumRetries) {
             ++mNumRetries;
 
             mLastPlaylistFetchTimeUs = -1;
-            postMonitorQueue(1000000ll);
+            postMonitorQueue(3000000ll);
             return;
         }
 
@@ -446,7 +485,13 @@
 
     sp<ABuffer> buffer;
     status_t err = fetchFile(uri.c_str(), &buffer);
-    CHECK_EQ(err, (status_t)OK);
+    if (err != OK) {
+        LOGE("failed to fetch .ts segment at url '%s'", uri.c_str());
+        mDataSource->queueEOS(err);
+        return;
+    }
+
+    CHECK(buffer != NULL);
 
     CHECK_EQ((status_t)OK,
              decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer));
@@ -460,13 +505,25 @@
         return;
     }
 
-    if (explicitDiscontinuity
-            || (mPrevBandwidthIndex >= 0
-                && (size_t)mPrevBandwidthIndex != bandwidthIndex)) {
+    if ((size_t)mPrevBandwidthIndex != bandwidthIndex) {
+        bandwidthChanged = true;
+    }
+
+    if (mPrevBandwidthIndex < 0) {
+        // Don't signal a bandwidth change at the very beginning of
+        // playback.
+        bandwidthChanged = false;
+    }
+
+    if (explicitDiscontinuity || bandwidthChanged) {
         // Signal discontinuity.
 
+        LOGI("queueing discontinuity (explicit=%d, bandwidthChanged=%d)",
+             explicitDiscontinuity, bandwidthChanged);
+
         sp<ABuffer> tmp = new ABuffer(188);
         memset(tmp->data(), 0, tmp->size());
+        tmp->data()[1] = bandwidthChanged;
 
         mDataSource->queueBuffer(tmp);
     }
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index d4a29c0..95f6741 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "M3UParser"
+#include <utils/Log.h>
+
 #include "include/M3UParser.h"
 
 #include <media/stagefright/foundation/AMessage.h>
@@ -80,14 +84,18 @@
     out->clear();
 
     if (strncasecmp("http://", baseURL, 7)
+            && strncasecmp("https://", baseURL, 8)
             && strncasecmp("file://", baseURL, 7)) {
         // Base URL must be absolute
         return false;
     }
 
-    if (!strncasecmp("http://", url, 7)) {
+    if (!strncasecmp("http://", url, 7) || !strncasecmp("https://", url, 8)) {
         // "url" is already an absolute URL, ignore base URL.
         out->setTo(url);
+
+        LOGV("base:'%s', url:'%s' => '%s'", baseURL, url, out->c_str());
+
         return true;
     }
 
@@ -108,6 +116,8 @@
         out->append(url);
     }
 
+    LOGV("base:'%s', url:'%s' => '%s'", baseURL, url, out->c_str());
+
     return true;
 }
 
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 0c67432..130ad82 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -151,6 +151,7 @@
 
     uint32_t mFlags;
     uint32_t mExtractorFlags;
+    uint32_t mSinceLastDropped;
 
     int64_t mTimeSourceDeltaUs;
     int64_t mVideoTimeUs;
@@ -172,6 +173,8 @@
     bool mBufferingEventPending;
     sp<TimedEventQueue::Event> mCheckAudioStatusEvent;
     bool mAudioStatusEventPending;
+    sp<TimedEventQueue::Event> mVideoLagEvent;
+    bool mVideoLagEventPending;
 
     sp<TimedEventQueue::Event> mAsyncPrepareEvent;
     Condition mPreparedCondition;
@@ -183,6 +186,7 @@
     void postBufferingEvent_l();
     void postStreamDoneEvent_l(status_t status);
     void postCheckAudioStatusEvent_l();
+    void postVideoLagEvent_l();
     status_t play_l();
 
     MediaBuffer *mVideoBuffer;
@@ -232,6 +236,7 @@
     void onPrepareAsyncEvent();
     void abortPrepare(status_t err);
     void finishAsyncPrepare_l();
+    void onVideoLagUpdate();
 
     bool getCachedDuration_l(int64_t *durationUs, bool *eos);
 
diff --git a/media/libstagefright/include/LiveSession.h b/media/libstagefright/include/LiveSession.h
index 50c0a99..41f5ad0 100644
--- a/media/libstagefright/include/LiveSession.h
+++ b/media/libstagefright/include/LiveSession.h
@@ -49,8 +49,8 @@
 
 private:
     enum {
-        kMaxNumQueuedFragments = 2,
-        kMaxNumRetries         = 3,
+        kMaxNumQueuedFragments = 3,
+        kMaxNumRetries         = 5,
     };
 
     static const int64_t kMaxPlaylistAgeUs;
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 78719c1..aa320fc 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -55,8 +55,8 @@
 
     enum {
         kPageSize            = 65536,
-        kHighWaterThreshold  = 5 * 1024 * 1024,
-        kLowWaterThreshold   = 1024 * 1024,
+        kHighWaterThreshold  = 20 * 1024 * 1024,
+        kLowWaterThreshold   = 4 * 1024 * 1024,
 
         // Read data after a 15 sec timeout whether we're actively
         // fetching or not.
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index e0ac49f..eca9ed6 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -118,6 +118,9 @@
     virtual status_t read(
             MediaBuffer **buffer, const ReadOptions *options);
 
+protected:
+    virtual ~MatroskaSource();
+
 private:
     enum Type {
         AVC,
@@ -131,8 +134,13 @@
     BlockIterator mBlockIter;
     size_t mNALSizeLen;  // for type AVC
 
+    List<MediaBuffer *> mPendingFrames;
+
     status_t advance();
 
+    status_t readBlock();
+    void clearPendingFrames();
+
     MatroskaSource(const MatroskaSource &);
     MatroskaSource &operator=(const MatroskaSource &);
 };
@@ -168,6 +176,10 @@
     }
 }
 
+MatroskaSource::~MatroskaSource() {
+    clearPendingFrames();
+}
+
 status_t MatroskaSource::start(MetaData *params) {
     mBlockIter.reset();
 
@@ -175,6 +187,8 @@
 }
 
 status_t MatroskaSource::stop() {
+    clearPendingFrames();
+
     return OK;
 }
 
@@ -256,6 +270,214 @@
     return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
 }
 
+static size_t clz(uint8_t x) {
+    size_t numLeadingZeroes = 0;
+
+    while (!(x & 0x80)) {
+        ++numLeadingZeroes;
+        x = x << 1;
+    }
+
+    return numLeadingZeroes;
+}
+
+void MatroskaSource::clearPendingFrames() {
+    while (!mPendingFrames.empty()) {
+        MediaBuffer *frame = *mPendingFrames.begin();
+        mPendingFrames.erase(mPendingFrames.begin());
+
+        frame->release();
+        frame = NULL;
+    }
+}
+
+#define BAIL(err) \
+    do {                        \
+        if (bigbuf) {           \
+            bigbuf->release();  \
+            bigbuf = NULL;      \
+        }                       \
+                                \
+        return err;             \
+    } while (0)
+
+status_t MatroskaSource::readBlock() {
+    CHECK(mPendingFrames.empty());
+
+    if (mBlockIter.eos()) {
+        return ERROR_END_OF_STREAM;
+    }
+
+    const mkvparser::Block *block = mBlockIter.block();
+
+    size_t size = block->GetSize();
+    int64_t timeUs = mBlockIter.blockTimeUs();
+    int32_t isSync = block->IsKey();
+
+    MediaBuffer *bigbuf = new MediaBuffer(size);
+
+    long res = block->Read(
+            mExtractor->mReader, (unsigned char *)bigbuf->data());
+
+    if (res != 0) {
+        bigbuf->release();
+        bigbuf = NULL;
+
+        return ERROR_END_OF_STREAM;
+    }
+
+    mBlockIter.advance();
+
+    bigbuf->meta_data()->setInt64(kKeyTime, timeUs);
+    bigbuf->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
+
+    unsigned lacing = (block->Flags() >> 1) & 3;
+
+    if (lacing == 0) {
+        mPendingFrames.push_back(bigbuf);
+        return OK;
+    }
+
+    LOGV("lacing = %u, size = %d", lacing, size);
+
+    const uint8_t *data = (const uint8_t *)bigbuf->data();
+    // hexdump(data, size);
+
+    if (size == 0) {
+        BAIL(ERROR_MALFORMED);
+    }
+
+    unsigned numFrames = (unsigned)data[0] + 1;
+    ++data;
+    --size;
+
+    Vector<uint64_t> frameSizes;
+
+    switch (lacing) {
+        case 1:  // Xiph
+        {
+            for (size_t i = 0; i < numFrames - 1; ++i) {
+                size_t frameSize = 0;
+                uint8_t byte;
+                do {
+                    if (size == 0) {
+                        BAIL(ERROR_MALFORMED);
+                    }
+                    byte = data[0];
+                    ++data;
+                    --size;
+
+                    frameSize += byte;
+                } while (byte == 0xff);
+
+                frameSizes.push(frameSize);
+            }
+
+            break;
+        }
+
+        case 2:  // fixed-size
+        {
+            if ((size % numFrames) != 0) {
+                BAIL(ERROR_MALFORMED);
+            }
+
+            size_t frameSize = size / numFrames;
+            for (size_t i = 0; i < numFrames - 1; ++i) {
+                frameSizes.push(frameSize);
+            }
+
+            break;
+        }
+
+        case 3:  // EBML
+        {
+            uint64_t lastFrameSize = 0;
+            for (size_t i = 0; i < numFrames - 1; ++i) {
+                uint8_t byte;
+
+                if (size == 0) {
+                    BAIL(ERROR_MALFORMED);
+                }
+                byte = data[0];
+                ++data;
+                --size;
+
+                size_t numLeadingZeroes = clz(byte);
+
+                uint64_t frameSize = byte & ~(0x80 >> numLeadingZeroes);
+                for (size_t j = 0; j < numLeadingZeroes; ++j) {
+                    if (size == 0) {
+                        BAIL(ERROR_MALFORMED);
+                    }
+
+                    frameSize = frameSize << 8;
+                    frameSize |= data[0];
+                    ++data;
+                    --size;
+                }
+
+                if (i == 0) {
+                    frameSizes.push(frameSize);
+                } else {
+                    size_t shift =
+                        7 - numLeadingZeroes + 8 * numLeadingZeroes;
+
+                    int64_t delta =
+                        (int64_t)frameSize - (1ll << (shift - 1)) + 1;
+
+                    frameSize = lastFrameSize + delta;
+
+                    frameSizes.push(frameSize);
+                }
+
+                lastFrameSize = frameSize;
+            }
+            break;
+        }
+
+        default:
+            TRESPASS();
+    }
+
+#if 0
+    AString out;
+    for (size_t i = 0; i < frameSizes.size(); ++i) {
+        if (i > 0) {
+            out.append(", ");
+        }
+        out.append(StringPrintf("%llu", frameSizes.itemAt(i)));
+    }
+    LOGV("sizes = [%s]", out.c_str());
+#endif
+
+    for (size_t i = 0; i < frameSizes.size(); ++i) {
+        uint64_t frameSize = frameSizes.itemAt(i);
+
+        if (size < frameSize) {
+            BAIL(ERROR_MALFORMED);
+        }
+
+        MediaBuffer *mbuf = new MediaBuffer(frameSize);
+        mbuf->meta_data()->setInt64(kKeyTime, timeUs);
+        mbuf->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
+        memcpy(mbuf->data(), data, frameSize);
+        mPendingFrames.push_back(mbuf);
+
+        data += frameSize;
+        size -= frameSize;
+    }
+
+    size_t offset = bigbuf->range_length() - size;
+    bigbuf->set_range(offset, size);
+
+    mPendingFrames.push_back(bigbuf);
+
+    return OK;
+}
+
+#undef BAIL
+
 status_t MatroskaSource::read(
         MediaBuffer **out, const ReadOptions *options) {
     *out = NULL;
@@ -263,17 +485,38 @@
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
     if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+        clearPendingFrames();
         mBlockIter.seek(seekTimeUs);
     }
 
 again:
-    if (mBlockIter.eos()) {
-        return ERROR_END_OF_STREAM;
+    while (mPendingFrames.empty()) {
+        status_t err = readBlock();
+
+        if (err != OK) {
+            clearPendingFrames();
+
+            return err;
+        }
     }
 
-    const mkvparser::Block *block = mBlockIter.block();
-    size_t size = block->GetSize();
-    int64_t timeUs = mBlockIter.blockTimeUs();
+    MediaBuffer *frame = *mPendingFrames.begin();
+    mPendingFrames.erase(mPendingFrames.begin());
+
+    size_t size = frame->range_length();
+
+    if (mType != AVC) {
+        *out = frame;
+
+        return OK;
+    }
+
+    if (size < mNALSizeLen) {
+        frame->release();
+        frame = NULL;
+
+        return ERROR_MALFORMED;
+    }
 
     // In the case of AVC content, each NAL unit is prefixed by
     // mNALSizeLen bytes of length. We want to prefix the data with
@@ -283,73 +526,54 @@
     static const size_t kPadding = 3;
 
     MediaBuffer *buffer = new MediaBuffer(size + kPadding);
+
+    int64_t timeUs;
+    CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
+    int32_t isSync;
+    CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
+
     buffer->meta_data()->setInt64(kKeyTime, timeUs);
-    buffer->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
+    buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
 
-    long res = block->Read(
-            mExtractor->mReader, (unsigned char *)buffer->data() + kPadding);
-
-    if (res != 0) {
-        return ERROR_END_OF_STREAM;
-    }
+    memcpy((uint8_t *)buffer->data() + kPadding,
+           (const uint8_t *)frame->data() + frame->range_offset(),
+           size);
 
     buffer->set_range(kPadding, size);
 
-    if (mType == AVC) {
-        CHECK_GE(size, mNALSizeLen);
+    frame->release();
+    frame = NULL;
 
-        uint8_t *data = (uint8_t *)buffer->data();
+    uint8_t *data = (uint8_t *)buffer->data();
 
-        size_t NALsize;
-        switch (mNALSizeLen) {
-            case 1: NALsize = data[kPadding]; break;
-            case 2: NALsize = U16_AT(&data[kPadding]); break;
-            case 3: NALsize = U24_AT(&data[kPadding]); break;
-            case 4: NALsize = U32_AT(&data[kPadding]); break;
-            default:
-                TRESPASS();
-        }
-
-        CHECK_GE(size, NALsize + mNALSizeLen);
-        if (size > NALsize + mNALSizeLen) {
-            LOGW("discarding %d bytes of data.", size - NALsize - mNALSizeLen);
-        }
-
-        // actual data starts at &data[kPadding + mNALSizeLen]
-
-        memcpy(&data[mNALSizeLen - 1], "\x00\x00\x00\x01", 4);
-        buffer->set_range(mNALSizeLen - 1, NALsize + 4);
-    } else if (mType == AAC) {
-        // There's strange junk at the beginning...
-
-        const uint8_t *data = (const uint8_t *)buffer->data() + kPadding;
-
-        // hexdump(data, size);
-
-        size_t offset = 0;
-        while (offset < size && data[offset] != 0x21) {
-            ++offset;
-        }
-
-        if (size == offset) {
-            buffer->release();
-
-            mBlockIter.advance();
-            goto again;
-        }
-
-        buffer->set_range(kPadding + offset, size - offset);
+    size_t NALsize;
+    switch (mNALSizeLen) {
+        case 1: NALsize = data[kPadding]; break;
+        case 2: NALsize = U16_AT(&data[kPadding]); break;
+        case 3: NALsize = U24_AT(&data[kPadding]); break;
+        case 4: NALsize = U32_AT(&data[kPadding]); break;
+        default:
+            TRESPASS();
     }
 
+    if (size < NALsize + mNALSizeLen) {
+        buffer->release();
+        buffer = NULL;
+
+        return ERROR_MALFORMED;
+    }
+
+    if (size > NALsize + mNALSizeLen) {
+        LOGW("discarding %d bytes of data.", size - NALsize - mNALSizeLen);
+    }
+
+    // actual data starts at &data[kPadding + mNALSizeLen]
+
+    memcpy(&data[mNALSizeLen - 1], "\x00\x00\x00\x01", 4);
+    buffer->set_range(mNALSizeLen - 1, NALsize + 4);
+
     *out = buffer;
 
-#if 0
-    hexdump((const uint8_t *)buffer->data() + buffer->range_offset(),
-            buffer->range_length());
-#endif
-
-    mBlockIter.advance();
-
     return OK;
 }
 
diff --git a/media/libstagefright/matroska/mkvparser.cpp b/media/libstagefright/matroska/mkvparser.cpp
index 455b1d6..7448d96 100644
--- a/media/libstagefright/matroska/mkvparser.cpp
+++ b/media/libstagefright/matroska/mkvparser.cpp
@@ -4474,6 +4474,9 @@
     return ((m_flags & static_cast<unsigned char>(1 << 7)) != 0);

 }

 

+unsigned char Block::Flags() const {

+    return m_flags;

+}

 

 void Block::SetKey(bool bKey)

 {

diff --git a/media/libstagefright/matroska/mkvparser.hpp b/media/libstagefright/matroska/mkvparser.hpp
index c46d349..f7d8948 100644
--- a/media/libstagefright/matroska/mkvparser.hpp
+++ b/media/libstagefright/matroska/mkvparser.hpp
@@ -80,6 +80,8 @@
     bool IsKey() const;

     void SetKey(bool);

 

+    unsigned char Flags() const;

+

     long long GetOffset() const;

     long GetSize() const;

     long Read(IMkvReader*, unsigned char*) const;

diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index de6346b..d8ab080 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -56,6 +56,10 @@
 
     int64_t convertPTSToTimestamp(uint64_t PTS);
 
+    bool PTSTimeDeltaEstablished() const {
+        return mFirstPTSValid;
+    }
+
 private:
     ATSParser *mParser;
     unsigned mProgramMapPID;
@@ -284,7 +288,7 @@
     : mProgram(program),
       mElementaryPID(elementaryPID),
       mStreamType(streamType),
-      mBuffer(new ABuffer(128 * 1024)),
+      mBuffer(new ABuffer(192 * 1024)),
       mPayloadStarted(false),
       mQueue(streamType == 0x1b
               ? ElementaryStreamQueue::H264 : ElementaryStreamQueue::AAC) {
@@ -334,7 +338,7 @@
 
             if (mStreamType == 0x1b && mSource != NULL) {
                 // Don't signal discontinuities on audio streams.
-                mSource->queueDiscontinuity();
+                mSource->queueDiscontinuity(type);
             }
             break;
         }
@@ -347,8 +351,7 @@
             mQueue.clear(!isASeek);
 
             if (mSource != NULL) {
-                mSource->clear();
-                mSource->queueDiscontinuity();
+                mSource->queueDiscontinuity(type);
             }
             break;
         }
@@ -561,6 +564,10 @@
             // After a discontinuity we invalidate the queue's format
             // and won't enqueue any access units to the source until
             // the queue has reestablished the new format.
+
+            if (mSource->getFormat() == NULL) {
+                mSource->setFormat(mQueue.getFormat());
+            }
             mSource->queueAccessUnit(accessUnit);
         }
     }
@@ -730,4 +737,12 @@
     return NULL;
 }
 
+bool ATSParser::PTSTimeDeltaEstablished() {
+    if (mPrograms.isEmpty()) {
+        return false;
+    }
+
+    return mPrograms.editItemAt(0)->PTSTimeDeltaEstablished();
+}
+
 }  // namespace android
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index ef78c77..fe31981 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -50,6 +50,8 @@
     };
     sp<MediaSource> getSource(SourceType type);
 
+    bool PTSTimeDeltaEstablished();
+
 protected:
     virtual ~ATSParser();
 
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index 7a1d5b0..0ad883b 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -33,6 +33,11 @@
       mEOSResult(OK) {
 }
 
+void AnotherPacketSource::setFormat(const sp<MetaData> &meta) {
+    CHECK(mFormat == NULL);
+    mFormat = meta;
+}
+
 AnotherPacketSource::~AnotherPacketSource() {
 }
 
@@ -61,9 +66,11 @@
         mBuffers.erase(mBuffers.begin());
 
         int32_t discontinuity;
-        if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)
-                && discontinuity) {
-            buffer->clear();
+        if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) {
+
+            if (discontinuity == ATSParser::DISCONTINUITY_FORMATCHANGE) {
+                mFormat.clear();
+            }
 
             return INFO_DISCONTINUITY;
         }
@@ -88,8 +95,11 @@
         mBuffers.erase(mBuffers.begin());
 
         int32_t discontinuity;
-        if (buffer->meta()->findInt32("discontinuity", &discontinuity)
-                && discontinuity) {
+        if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
+            if (discontinuity == ATSParser::DISCONTINUITY_FORMATCHANGE) {
+                mFormat.clear();
+            }
+
             return INFO_DISCONTINUITY;
         } else {
             int64_t timeUs;
@@ -125,22 +135,30 @@
     mCondition.signal();
 }
 
-void AnotherPacketSource::queueDiscontinuity() {
+void AnotherPacketSource::queueDiscontinuity(
+        ATSParser::DiscontinuityType type) {
     sp<ABuffer> buffer = new ABuffer(0);
-    buffer->meta()->setInt32("discontinuity", true);
+    buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
 
     Mutex::Autolock autoLock(mLock);
 
+#if 0
+    if (type == ATSParser::DISCONTINUITY_SEEK
+            || type == ATSParser::DISCONTINUITY_FORMATCHANGE) {
+        // XXX Fix this: This will also clear any pending discontinuities,
+        // If there's a pending DISCONTINUITY_FORMATCHANGE and the new
+        // discontinuity is "just" a DISCONTINUITY_SEEK, this will effectively
+        // downgrade the type of discontinuity received by the client.
+
+        mBuffers.clear();
+        mEOSResult = OK;
+    }
+#endif
+
     mBuffers.push_back(buffer);
     mCondition.signal();
 }
 
-void AnotherPacketSource::clear() {
-    Mutex::Autolock autoLock(mLock);
-    mBuffers.clear();
-    mEOSResult = OK;
-}
-
 void AnotherPacketSource::signalEOS(status_t result) {
     CHECK(result != OK);
 
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index 2bc7404..6fe93f8 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -23,6 +23,8 @@
 #include <utils/threads.h>
 #include <utils/List.h>
 
+#include "ATSParser.h"
+
 namespace android {
 
 struct ABuffer;
@@ -30,6 +32,8 @@
 struct AnotherPacketSource : public MediaSource {
     AnotherPacketSource(const sp<MetaData> &meta);
 
+    void setFormat(const sp<MetaData> &meta);
+
     virtual status_t start(MetaData *params = NULL);
     virtual status_t stop();
     virtual sp<MetaData> getFormat();
@@ -42,11 +46,9 @@
     status_t nextBufferTime(int64_t *timeUs);
 
     void queueAccessUnit(const sp<ABuffer> &buffer);
-    void queueDiscontinuity();
+    void queueDiscontinuity(ATSParser::DiscontinuityType type);
     void signalEOS(status_t result);
 
-    void clear();
-
     status_t dequeueAccessUnit(sp<ABuffer> *buffer);
 
 protected:
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 4e7759d..73efdfe 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -225,6 +225,14 @@
 
             mFormat = MakeAACCodecSpecificData(
                     profile, sampling_freq_index, channel_configuration);
+
+            int32_t sampleRate;
+            int32_t numChannels;
+            CHECK(mFormat->findInt32(kKeySampleRate, &sampleRate));
+            CHECK(mFormat->findInt32(kKeyChannelCount, &numChannels));
+
+            LOGI("found AAC codec config (%d Hz, %d channels)",
+                 sampleRate, numChannels);
         } else {
             // profile_ObjectType, sampling_frequency_index, private_bits,
             // channel_configuration, original_copy, home
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 4e9920b..3638f41 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -86,6 +86,9 @@
         mQueueChanged.signal();
     }
 
+    // Don't call join on myself
+    CHECK(mThread != pthread_self());
+
     void *dummy;
     pthread_join(mThread, &dummy);
 }
@@ -246,9 +249,12 @@
 
     status_t err = instance->freeNode(mMaster);
 
-    index = mDispatchers.indexOfKey(node);
-    CHECK(index >= 0);
-    mDispatchers.removeItemsAt(index);
+    {
+        Mutex::Autolock autoLock(mLock);
+        index = mDispatchers.indexOfKey(node);
+        CHECK(index >= 0);
+        mDispatchers.removeItemsAt(index);
+    }
 
     return err;
 }
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 547fbab..77917b3 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -265,15 +265,17 @@
     const char *s = value.c_str() + 4;
     char *end;
     double from = strtod(s, &end);
-    CHECK_GT(end, s);
-    CHECK_EQ(*end, '-');
+
+    if (end == s || *end != '-') {
+        return false;
+    }
 
     s = end + 1;
     double to = strtod(s, &end);
-    CHECK_GT(end, s);
-    CHECK_EQ(*end, '\0');
 
-    CHECK_GE(to, from);
+    if (end == s || *end != '\0' || to < from) {
+        return false;
+    }
 
     *durationUs = (int64_t)((to - from) * 1E6);
 
diff --git a/media/libstagefright/yuv/Android.mk b/media/libstagefright/yuv/Android.mk
index 0794ad1..7697e3c 100644
--- a/media/libstagefright/yuv/Android.mk
+++ b/media/libstagefright/yuv/Android.mk
@@ -10,4 +10,6 @@
 
 LOCAL_MODULE:= libstagefright_yuv
 
+LOCAL_PRELINK_MODULE := false
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
index e285847..70dc340 100644
--- a/media/mtp/Android.mk
+++ b/media/mtp/Android.mk
@@ -37,13 +37,14 @@
                   MtpStringBuffer.cpp                   \
                   MtpStorage.cpp                        \
                   MtpUtils.cpp                          \
-                  PtpCursor.cpp                         \
 
 LOCAL_MODULE:= libmtp
 
 LOCAL_CFLAGS := -DMTP_DEVICE -DMTP_HOST
 
-include $(BUILD_STATIC_LIBRARY)
+LOCAL_SHARED_LIBRARIES := libutils libcutils libusbhost libbinder
+
+include $(BUILD_SHARED_LIBRARY)
 
 endif
 
@@ -67,7 +68,6 @@
                   MtpStringBuffer.cpp                   \
                   MtpStorage.cpp                        \
                   MtpUtils.cpp                          \
-                  PtpCursor.cpp                         \
 
 LOCAL_MODULE:= libmtp
 
diff --git a/media/mtp/MtpClient.cpp b/media/mtp/MtpClient.cpp
index ceb6a43..c830540 100644
--- a/media/mtp/MtpClient.cpp
+++ b/media/mtp/MtpClient.cpp
@@ -29,12 +29,8 @@
 #include <errno.h>
 
 #include <usbhost/usbhost.h>
-#include <linux/version.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
-#include <linux/usb/ch9.h>
-#else
-#include <linux/usb_ch9.h>
-#endif
+
+struct usb_device;
 
 namespace android {
 
@@ -194,20 +190,13 @@
                 return mDone;
             }
 
-            struct usb_endpoint *ep_in = usb_endpoint_open(device, ep_in_desc);
-            struct usb_endpoint *ep_out = usb_endpoint_open(device, ep_out_desc);
-            struct usb_endpoint *ep_intr = usb_endpoint_open(device, ep_intr_desc);
-
             if (usb_device_claim_interface(device, interface->bInterfaceNumber)) {
                 LOGE("usb_device_claim_interface failed errno: %d\n", errno);
-                usb_endpoint_close(ep_in);
-                usb_endpoint_close(ep_out);
-                usb_endpoint_close(ep_intr);
                 return mDone;
             }
 
             MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber,
-                        ep_in, ep_out, ep_intr);
+                        ep_in_desc, ep_out_desc, ep_intr_desc);
             mDeviceList.add(mtpDevice);
             mtpDevice->initialize();
             deviceAdded(mtpDevice);
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index eac1f7e..801edb0 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -391,15 +391,19 @@
 #endif // MTP_DEVICE
 
 #ifdef MTP_HOST
-int MtpDataPacket::read(struct usb_endpoint *ep) {
+int MtpDataPacket::read(struct usb_request *request) {
     // first read the header
-    int length = transfer(ep, mBuffer, mBufferSize);
+    request->buffer = mBuffer;
+    request->buffer_length = mBufferSize;
+    int length = transfer(request);
     if (length >= MTP_CONTAINER_HEADER_SIZE) {
         // look at the length field to see if the data spans multiple packets
         uint32_t totalLength = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
         while (totalLength > length) {
             allocate(length + mAllocationIncrement);
-            int ret = transfer(ep, mBuffer + length, mAllocationIncrement);
+            request->buffer = mBuffer + length;
+            request->buffer_length = mAllocationIncrement;
+            int ret = transfer(request);
             if (ret >= 0)
                 length += ret;
             else {
@@ -413,10 +417,12 @@
     return length;
 }
 
-int MtpDataPacket::readData(struct usb_endpoint *ep, void* buffer, int length) {
+int MtpDataPacket::readData(struct usb_request *request, void* buffer, int length) {
     int read = 0;
     while (read < length) {
-        int ret = transfer(ep, (char *)buffer + read, length - read);
+        request->buffer = (char *)buffer + read;
+        request->buffer_length = length - read;
+        int ret = transfer(request);
         if (ret < 0) {
             return ret;
         }
@@ -426,8 +432,8 @@
 }
 
 // Queue a read request.  Call readDataWait to wait for result
-int MtpDataPacket::readDataAsync(struct usb_endpoint *ep, void* buffer, int length) {
-    if (usb_endpoint_queue(ep, buffer, length)) {
+int MtpDataPacket::readDataAsync(struct usb_request *req) {
+    if (usb_request_queue(req)) {
         LOGE("usb_endpoint_queue failed, errno: %d", errno);
         return -1;
     }
@@ -435,39 +441,49 @@
 }
 
 // Wait for result of readDataAsync
-int MtpDataPacket::readDataWait(struct usb_endpoint *ep) {
-    int ep_num;
-    return usb_endpoint_wait(usb_endpoint_get_device(ep), &ep_num);
+int MtpDataPacket::readDataWait(struct usb_device *device) {
+    struct usb_request *req = usb_request_wait(device);
+    return (req ? req->actual_length : -1);
 }
 
-int MtpDataPacket::readDataHeader(struct usb_endpoint *ep) {
-    int length = transfer(ep, mBuffer, usb_endpoint_max_packet(ep));
+int MtpDataPacket::readDataHeader(struct usb_request *request) {
+    request->buffer = mBuffer;
+    request->buffer_length = request->max_packet_size;
+    int length = transfer(request);
     if (length >= 0)
         mPacketSize = length;
     return length;
 }
 
-int MtpDataPacket::writeDataHeader(struct usb_endpoint *ep, uint32_t length) {
+int MtpDataPacket::writeDataHeader(struct usb_request *request, uint32_t length) {
     MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
     MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
-    int ret = transfer(ep, mBuffer, MTP_CONTAINER_HEADER_SIZE);
+    request->buffer = mBuffer;
+    request->buffer_length = MTP_CONTAINER_HEADER_SIZE;
+    int ret = transfer(request);
     return (ret < 0 ? ret : 0);
 }
 
-int MtpDataPacket::write(struct usb_endpoint *ep) {
+int MtpDataPacket::write(struct usb_request *request) {
     MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
     MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
 
     // send header separately from data
-    int ret = transfer(ep, mBuffer, MTP_CONTAINER_HEADER_SIZE);
-    if (ret == MTP_CONTAINER_HEADER_SIZE)
-        ret = transfer(ep, mBuffer + MTP_CONTAINER_HEADER_SIZE,
-                        mPacketSize - MTP_CONTAINER_HEADER_SIZE);
+    request->buffer = mBuffer;
+    request->buffer_length = MTP_CONTAINER_HEADER_SIZE;
+    int ret = transfer(request);
+    if (ret == MTP_CONTAINER_HEADER_SIZE) {
+        request->buffer = mBuffer + MTP_CONTAINER_HEADER_SIZE;
+        request->buffer_length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
+        ret = transfer(request);
+    }
     return (ret < 0 ? ret : 0);
 }
 
-int MtpDataPacket::write(struct usb_endpoint *ep, void* buffer, uint32_t length) {
-    int ret = transfer(ep, buffer, length);
+int MtpDataPacket::write(struct usb_request *request, void* buffer, uint32_t length) {
+    request->buffer = buffer;
+    request->buffer_length = length;
+    int ret = transfer(request);
     return (ret < 0 ? ret : 0);
 }
 
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 3ae6226..577cea1 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -20,6 +20,9 @@
 #include "MtpPacket.h"
 #include "mtp.h"
 
+struct usb_device;
+struct usb_request;
+
 namespace android {
 
 class MtpStringBuffer;
@@ -100,15 +103,15 @@
 #endif
 
 #ifdef MTP_HOST
-    int                 read(struct usb_endpoint *ep);
-    int                 readData(struct usb_endpoint *ep, void* buffer, int length);
-    int                 readDataAsync(struct usb_endpoint *ep, void* buffer, int length);
-    int                 readDataWait(struct usb_endpoint *ep);
-    int                 readDataHeader(struct usb_endpoint *ep);
+    int                 read(struct usb_request *request);
+    int                 readData(struct usb_request *request, void* buffer, int length);
+    int                 readDataAsync(struct usb_request *req);
+    int                 readDataWait(struct usb_device *device);
+    int                 readDataHeader(struct usb_request *ep);
 
-    int                 writeDataHeader(struct usb_endpoint *ep, uint32_t length);
-    int                 write(struct usb_endpoint *ep);
-    int                 write(struct usb_endpoint *ep, void* buffer, uint32_t length);
+    int                 writeDataHeader(struct usb_request *ep, uint32_t length);
+    int                 write(struct usb_request *ep);
+    int                 write(struct usb_request *ep, void* buffer, uint32_t length);
 #endif
 
     inline bool         hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; }
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index e058a5a..d22c72f 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -39,25 +39,35 @@
 namespace android {
 
 MtpDevice::MtpDevice(struct usb_device* device, int interface,
-            struct usb_endpoint *ep_in, struct usb_endpoint *ep_out,
-            struct usb_endpoint *ep_intr)
+            const struct usb_endpoint_descriptor *ep_in,
+            const struct usb_endpoint_descriptor *ep_out,
+            const struct usb_endpoint_descriptor *ep_intr)
     :   mDevice(device),
         mInterface(interface),
-        mEndpointIn(ep_in),
-        mEndpointOut(ep_out),
-        mEndpointIntr(ep_intr),
+        mRequestIn1(NULL),
+        mRequestIn2(NULL),
+        mRequestOut(NULL),
+        mRequestIntr(NULL),
         mDeviceInfo(NULL),
         mID(usb_device_get_unique_id(device)),
         mSessionID(0),
         mTransactionID(0),
         mReceivedResponse(false)
 {
+    mRequestIn1 = usb_request_new(device, ep_in);
+    mRequestIn2 = usb_request_new(device, ep_in);
+    mRequestOut = usb_request_new(device, ep_out);
+    mRequestIntr = usb_request_new(device, ep_intr);
 }
 
 MtpDevice::~MtpDevice() {
     close();
     for (int i = 0; i < mDeviceProperties.size(); i++)
         delete mDeviceProperties[i];
+    usb_request_free(mRequestIn1);
+    usb_request_free(mRequestIn2);
+    usb_request_free(mRequestOut);
+    usb_request_free(mRequestIntr);
 }
 
 void MtpDevice::initialize() {
@@ -325,7 +335,7 @@
         while (remaining > 0) {
             int count = read(srcFD, buffer, sizeof(buffer));
             if (count > 0) {
-                int written = mData.write(mEndpointOut, buffer, count);
+                int written = mData.write(mRequestOut, buffer, count);
                 // FIXME check error
                 remaining -= count;
             } else {
@@ -441,7 +451,7 @@
     mRequest.reset();
     mRequest.setParameter(1, handle);
     if (sendRequest(MTP_OPERATION_GET_OBJECT)
-            && mData.readDataHeader(mEndpointIn)) {
+            && mData.readDataHeader(mRequestIn1)) {
         uint32_t length = mData.getContainerLength();
         if (length < MTP_CONTAINER_HEADER_SIZE)
             goto fail;
@@ -461,20 +471,22 @@
 
         // USB reads greater than 16K don't work
         char buffer1[16384], buffer2[16384];
-        char* readBuffer = buffer1;
-        char* writeBuffer = NULL;
+        mRequestIn1->buffer = buffer1;
+        mRequestIn2->buffer = buffer2;
+        struct usb_request* req = mRequestIn1;
+        void* writeBuffer = NULL;
         int writeLength = 0;
 
         while (remaining > 0 || writeBuffer) {
             if (remaining > 0) {
                 // queue up a read request
-                int readSize = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
-                if (mData.readDataAsync(mEndpointIn, readBuffer, readSize)) {
+                req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
+                if (mData.readDataAsync(req)) {
                     LOGE("readDataAsync failed");
                     goto fail;
                 }
             } else {
-                readBuffer = NULL;
+                req = NULL;
             }
 
             if (writeBuffer) {
@@ -482,23 +494,23 @@
                 if (write(fd, writeBuffer, writeLength) != writeLength) {
                     LOGE("write failed");
                     // wait for pending read before failing
-                    if (readBuffer)
-                        mData.readDataWait(mEndpointIn);
+                    if (req)
+                        mData.readDataWait(mDevice);
                     goto fail;
                 }
                 writeBuffer = NULL;
             }
 
             // wait for read to complete
-            if (readBuffer) {
-                int read = mData.readDataWait(mEndpointIn);
+            if (req) {
+                int read = mData.readDataWait(mDevice);
                 if (read < 0)
                     goto fail;
 
-                writeBuffer = readBuffer;
+                writeBuffer = req->buffer;
                 writeLength = read;
                 remaining -= read;
-                readBuffer = (readBuffer == buffer1 ? buffer2 : buffer1);
+                req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
             }
         }
 
@@ -518,7 +530,7 @@
     mRequest.setOperationCode(operation);
     if (mTransactionID > 0)
         mRequest.setTransactionID(mTransactionID++);
-    int ret = mRequest.write(mEndpointOut);
+    int ret = mRequest.write(mRequestOut);
     mRequest.dump();
     return (ret > 0);
 }
@@ -527,14 +539,14 @@
     LOGV("sendData\n");
     mData.setOperationCode(mRequest.getOperationCode());
     mData.setTransactionID(mRequest.getTransactionID());
-    int ret = mData.write(mEndpointOut);
+    int ret = mData.write(mRequestOut);
     mData.dump();
     return (ret > 0);
 }
 
 bool MtpDevice::readData() {
     mData.reset();
-    int ret = mData.read(mEndpointIn);
+    int ret = mData.read(mRequestIn1);
     LOGV("readData returned %d\n", ret);
     if (ret >= MTP_CONTAINER_HEADER_SIZE) {
         if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
@@ -557,7 +569,7 @@
 bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
     mData.setOperationCode(operation);
     mData.setTransactionID(mRequest.getTransactionID());
-    return (!mData.writeDataHeader(mEndpointOut, dataLength));
+    return (!mData.writeDataHeader(mRequestOut, dataLength));
 }
 
 MtpResponseCode MtpDevice::readResponse() {
@@ -566,7 +578,7 @@
         mReceivedResponse = false;
         return mResponse.getResponseCode();
     }
-    int ret = mResponse.read(mEndpointIn);
+    int ret = mResponse.read(mRequestIn1);
     if (ret >= MTP_CONTAINER_HEADER_SIZE) {
         mResponse.dump();
         return mResponse.getResponseCode();
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index 67bb85f..d0a0fb3 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -25,6 +25,8 @@
 #include <utils/threads.h>
 
 struct usb_device;
+struct usb_request;
+struct usb_endpoint_descriptor;
 
 namespace android {
 
@@ -36,9 +38,10 @@
 private:
     struct usb_device*      mDevice;
     int                     mInterface;
-    struct usb_endpoint*    mEndpointIn;
-    struct usb_endpoint*    mEndpointOut;
-    struct usb_endpoint*    mEndpointIntr;
+    struct usb_request*     mRequestIn1;
+    struct usb_request*     mRequestIn2;
+    struct usb_request*     mRequestOut;
+    struct usb_request*     mRequestIntr;
     MtpDeviceInfo*          mDeviceInfo;
     MtpPropertyList         mDeviceProperties;
 
@@ -61,8 +64,9 @@
 
 public:
                             MtpDevice(struct usb_device* device, int interface,
-                                    struct usb_endpoint *ep_in, struct usb_endpoint *ep_out,
-                                    struct usb_endpoint *ep_intr);
+                                    const struct usb_endpoint_descriptor *ep_in,
+                                    const struct usb_endpoint_descriptor *ep_out,
+                                    const struct usb_endpoint_descriptor *ep_intr);
     virtual                 ~MtpDevice();
 
     inline int              getID() const { return mID; }
diff --git a/media/mtp/MtpEventPacket.cpp b/media/mtp/MtpEventPacket.cpp
index fc74542..d2fca42 100644
--- a/media/mtp/MtpEventPacket.cpp
+++ b/media/mtp/MtpEventPacket.cpp
@@ -27,6 +27,8 @@
 
 #include "MtpEventPacket.h"
 
+#include <usbhost/usbhost.h>
+
 namespace android {
 
 MtpEventPacket::MtpEventPacket()
@@ -52,9 +54,10 @@
 #endif
 
 #ifdef MTP_HOST
-    // read our buffer from the given endpoint
-int MtpEventPacket::read(struct usb_endpoint *ep) {
-    int ret = transfer(ep, mBuffer, mBufferSize);
+int MtpEventPacket::read(struct usb_request *request) {
+    request->buffer = mBuffer;
+    request->buffer_length = mBufferSize;
+    int ret = transfer(request);
      if (ret >= 0)
         mPacketSize = ret;
     else
diff --git a/media/mtp/MtpEventPacket.h b/media/mtp/MtpEventPacket.h
index 30ae869..660baad 100644
--- a/media/mtp/MtpEventPacket.h
+++ b/media/mtp/MtpEventPacket.h
@@ -34,8 +34,8 @@
 #endif
 
 #ifdef MTP_HOST
-    // read our buffer from the given endpoint
-    int                 read(struct usb_endpoint *ep);
+    // read our buffer with the given request
+    int                 read(struct usb_request *request);
 #endif
 
     inline MtpEventCode     getEventCode() const { return getContainerCode(); }
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index a885249..d3f2cb4 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -152,13 +152,13 @@
 }
 
 #ifdef MTP_HOST
-int MtpPacket::transfer(struct usb_endpoint *ep, void* buffer, int length) {
-    if (usb_endpoint_queue(ep, buffer, length)) {
+int MtpPacket::transfer(struct usb_request* request) {
+    if (usb_request_queue(request)) {
         LOGE("usb_endpoint_queue failed, errno: %d", errno);
         return -1;
     }
-    int ep_num;
-    return usb_endpoint_wait(usb_endpoint_get_device(ep), &ep_num);
+    request = usb_request_wait(request->dev);
+    return (request ? request->actual_length : -1);
 }
 #endif
 
diff --git a/media/mtp/MtpPacket.h b/media/mtp/MtpPacket.h
index 73963a3..0ffb1d3 100644
--- a/media/mtp/MtpPacket.h
+++ b/media/mtp/MtpPacket.h
@@ -19,7 +19,7 @@
 
 #include "MtpTypes.h"
 
-struct usb_endpoint;
+struct usb_request;
 
 namespace android {
 
@@ -57,7 +57,7 @@
     void                setParameter(int index, uint32_t value);
 
 #ifdef MTP_HOST
-    int                 transfer(struct usb_endpoint *ep, void* buffer, int length);
+    int                 transfer(struct usb_request* request);
 #endif
 
 protected:
diff --git a/media/mtp/MtpRequestPacket.cpp b/media/mtp/MtpRequestPacket.cpp
index 8ece580..0e58e01 100644
--- a/media/mtp/MtpRequestPacket.cpp
+++ b/media/mtp/MtpRequestPacket.cpp
@@ -22,6 +22,8 @@
 
 #include "MtpRequestPacket.h"
 
+#include <usbhost/usbhost.h>
+
 namespace android {
 
 MtpRequestPacket::MtpRequestPacket()
@@ -45,11 +47,13 @@
 
 #ifdef MTP_HOST
     // write our buffer to the given endpoint (host mode)
-int MtpRequestPacket::write(struct usb_endpoint *ep)
+int MtpRequestPacket::write(struct usb_request *request)
 {
     putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
     putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_COMMAND);
-    return transfer(ep, mBuffer, mPacketSize);
+    request->buffer = mBuffer;
+    request->buffer_length = mPacketSize;
+    return transfer(request);
 }
 #endif
 
diff --git a/media/mtp/MtpRequestPacket.h b/media/mtp/MtpRequestPacket.h
index df518f2..1201f11 100644
--- a/media/mtp/MtpRequestPacket.h
+++ b/media/mtp/MtpRequestPacket.h
@@ -20,6 +20,8 @@
 #include "MtpPacket.h"
 #include "mtp.h"
 
+struct usb_request;
+
 namespace android {
 
 class MtpRequestPacket : public MtpPacket {
@@ -35,7 +37,7 @@
 
 #ifdef MTP_HOST
     // write our buffer to the given endpoint
-    int                 write(struct usb_endpoint *ep);
+    int                 write(struct usb_request *request);
 #endif
 
     inline MtpOperationCode    getOperationCode() const { return getContainerCode(); }
diff --git a/media/mtp/MtpResponsePacket.cpp b/media/mtp/MtpResponsePacket.cpp
index 3ef714e..c2b41e4 100644
--- a/media/mtp/MtpResponsePacket.cpp
+++ b/media/mtp/MtpResponsePacket.cpp
@@ -22,6 +22,8 @@
 
 #include "MtpResponsePacket.h"
 
+#include <usbhost/usbhost.h>
+
 namespace android {
 
 MtpResponsePacket::MtpResponsePacket()
@@ -42,9 +44,10 @@
 #endif
 
 #ifdef MTP_HOST
-    // read our buffer from the given endpoint
-int MtpResponsePacket::read(struct usb_endpoint *ep) {
-    int ret = transfer(ep, mBuffer, mBufferSize);
+int MtpResponsePacket::read(struct usb_request *request) {
+    request->buffer = mBuffer;
+    request->buffer_length = mBufferSize;
+    int ret = transfer(request);
      if (ret >= 0)
         mPacketSize = ret;
     else
diff --git a/media/mtp/MtpResponsePacket.h b/media/mtp/MtpResponsePacket.h
index 373f8f9..592ad4a 100644
--- a/media/mtp/MtpResponsePacket.h
+++ b/media/mtp/MtpResponsePacket.h
@@ -34,8 +34,8 @@
 #endif
 
 #ifdef MTP_HOST
-    // read our buffer from the given endpoint
-    int                 read(struct usb_endpoint *ep);
+    // read our buffer with the given request
+    int                 read(struct usb_request *request);
 #endif
 
     inline MtpResponseCode      getResponseCode() const { return getContainerCode(); }
diff --git a/media/mtp/PtpCursor.cpp b/media/mtp/PtpCursor.cpp
deleted file mode 100644
index 7294cef..0000000
--- a/media/mtp/PtpCursor.cpp
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "PtpCursor"
-
-#include "MtpDebug.h"
-#include "MtpClient.h"
-#include "PtpCursor.h"
-#include "MtpDevice.h"
-#include "MtpDeviceInfo.h"
-#include "MtpObjectInfo.h"
-#include "MtpStorageInfo.h"
-
-
-#include "binder/CursorWindow.h"
-
-namespace android {
-
-/* Device Column IDs */
-/* These must match the values in PtpCursor.java */
-#define DEVICE_ROW_ID           1
-#define DEVICE_MANUFACTURER     2
-#define DEVICE_MODEL            3
-
-/* Storage Column IDs */
-/* These must match the values in PtpCursor.java */
-#define STORAGE_ROW_ID          101
-#define STORAGE_IDENTIFIER      102
-#define STORAGE_DESCRIPTION     103
-
-/* Object Column IDs */
-/* These must match the values in PtpCursor.java */
-#define OBJECT_ROW_ID               201
-#define OBJECT_STORAGE_ID           202
-#define OBJECT_FORMAT               203
-#define OBJECT_PROTECTION_STATUS    204
-#define OBJECT_SIZE                 205
-#define OBJECT_THUMB_FORMAT         206
-#define OBJECT_THUMB_SIZE           207
-#define OBJECT_THUMB_WIDTH          208
-#define OBJECT_THUMB_HEIGHT         209
-#define OBJECT_IMAGE_WIDTH          210
-#define OBJECT_IMAGE_HEIGHT         211
-#define OBJECT_IMAGE_DEPTH          212
-#define OBJECT_PARENT               213
-#define OBJECT_ASSOCIATION_TYPE     214
-#define OBJECT_ASSOCIATION_DESC     215
-#define OBJECT_SEQUENCE_NUMBER      216
-#define OBJECT_NAME                 217
-#define OBJECT_DATE_CREATED         218
-#define OBJECT_DATE_MODIFIED        219
-#define OBJECT_KEYWORDS             220
-#define OBJECT_THUMB                221
-
-PtpCursor::PtpCursor(MtpClient* client, int queryType, int deviceID,
-                MtpStorageID storageID, MtpObjectHandle objectID,
-                int columnCount, int* columns)
-        :   mClient(client),
-            mQueryType(queryType),
-            mDeviceID(deviceID),
-            mStorageID(storageID),
-            mQbjectID(objectID),
-            mColumnCount(columnCount),
-            mColumns(NULL)
-{
-    if (columns) {
-        mColumns = new int[columnCount];
-        memcpy(mColumns, columns, columnCount * sizeof(int));
-    }
-}
-
-PtpCursor::~PtpCursor() {
-    delete[] mColumns;
-}
-
-int PtpCursor::fillWindow(CursorWindow* window, int startPos) {
-    LOGD("PtpCursor::fillWindow mQueryType: %d\n", mQueryType);
-
-    switch (mQueryType) {
-        case DEVICE:
-            return fillDevices(window, startPos);
-        case DEVICE_ID:
-            return fillDevice(window, startPos);
-        case STORAGE:
-            return fillStorages(window, startPos);
-        case STORAGE_ID:
-            return fillStorage(window, startPos);
-        case OBJECT:
-            return fillObjects(window, 0, startPos);
-        case OBJECT_ID:
-            return fillObject(window, startPos);
-        case STORAGE_CHILDREN:
-            return fillObjects(window, -1, startPos);
-        case OBJECT_CHILDREN:
-            return fillObjects(window, mQbjectID, startPos);
-        default:
-            LOGE("PtpCursor::fillWindow: unknown query type %d\n", mQueryType);
-            return 0;
-    }
-}
-
-int PtpCursor::fillDevices(CursorWindow* window, int startPos) {
-    int count = 0;
-    MtpDeviceList& deviceList = mClient->getDeviceList();
-    for (int i = 0; i < deviceList.size(); i++) {
-        MtpDevice* device = deviceList[i];
-        if (fillDevice(window, device, startPos)) {
-            count++;
-            startPos++;
-        } else {
-            break;
-        }
-    }
-    return count;
-}
-
-int PtpCursor::fillDevice(CursorWindow* window, int startPos) {
-    MtpDevice* device = mClient->getDevice(mDeviceID);
-    if (device && fillDevice(window, device, startPos))
-        return 1;
-    else
-        return 0;
-}
-
-int PtpCursor::fillStorages(CursorWindow* window, int startPos) {
-    int count = 0;
-    MtpDevice* device = mClient->getDevice(mDeviceID);
-    if (!device)
-        return 0;
-    MtpStorageIDList* storageIDs = device->getStorageIDs();
-    if (!storageIDs)
-        return 0;
-
-    for (int i = 0; i < storageIDs->size(); i++) {
-        MtpStorageID storageID = (*storageIDs)[i];
-        if (fillStorage(window, device, storageID, startPos)) {
-            count++;
-            startPos++;
-        } else {
-            break;
-        }
-    }
-    delete storageIDs;
-    return count;
-}
-
-int PtpCursor::fillStorage(CursorWindow* window, int startPos) {
-    MtpDevice* device = mClient->getDevice(mDeviceID);
-    if (device && fillStorage(window, device, mStorageID, startPos))
-        return 1;
-    else
-        return 0;
-}
-
-int PtpCursor::fillObjects(CursorWindow* window, int parent, int startPos) {
-    int count = 0;
-    MtpDevice* device = mClient->getDevice(mDeviceID);
-    if (!device)
-        return 0;
-    MtpObjectHandleList* handles = device->getObjectHandles(mStorageID, 0, parent);
-    if (!handles)
-        return 0;
-
-    for (int i = 0; i < handles->size(); i++) {
-        MtpObjectHandle handle = (*handles)[i];
-        if (fillObject(window, device, handle, startPos)) {
-            count++;
-            startPos++;
-        } else {
-            break;
-        }
-    }
-    delete handles;
-    return count;
-}
-
-int PtpCursor::fillObject(CursorWindow* window, int startPos) {
-    MtpDevice* device = mClient->getDevice(mDeviceID);
-    if (device && fillObject(window, device, mQbjectID, startPos))
-        return 1;
-    else
-        return 0;
-}
-
-bool PtpCursor::fillDevice(CursorWindow* window, MtpDevice* device, int row) {
-    MtpDeviceInfo* deviceInfo = device->getDeviceInfo();
-    if (!deviceInfo)
-        return false;
-    if (!prepareRow(window))
-        return false;
-
-    for (int i = 0; i < mColumnCount; i++) {
-        switch (mColumns[i]) {
-            case DEVICE_ROW_ID:
-                if (!putLong(window, device->getID(), row, i))
-                    return false;
-                 break;
-            case DEVICE_MANUFACTURER:
-                if (!putString(window, deviceInfo->mManufacturer, row, i))
-                    return false;
-                 break;
-            case DEVICE_MODEL:
-                if (!putString(window, deviceInfo->mModel, row, i))
-                    return false;
-                 break;
-            default:
-                LOGE("fillDevice: unknown column %d\n", mColumns[i]);
-                return false;
-        }
-    }
-
-    return true;
-}
-
-bool PtpCursor::fillStorage(CursorWindow* window, MtpDevice* device,
-        MtpStorageID storageID, int row) {
-
-LOGD("fillStorage %d\n", storageID);
-
-    MtpStorageInfo* storageInfo = device->getStorageInfo(storageID);
-    if (!storageInfo)
-        return false;
-    if (!prepareRow(window)) {
-        delete storageInfo;
-        return false;
-    }
-
-    const char* text;
-    for (int i = 0; i < mColumnCount; i++) {
-        switch (mColumns[i]) {
-            case STORAGE_ROW_ID:
-                if (!putLong(window, storageID, row, i))
-                    goto fail;
-                 break;
-            case STORAGE_IDENTIFIER:
-                text = storageInfo->mVolumeIdentifier;
-                if (!text || !text[0])
-                    text = "Camera Storage";
-                if (!putString(window, text, row, i))
-                    goto fail;
-                 break;
-            case STORAGE_DESCRIPTION:
-                text = storageInfo->mStorageDescription;
-                if (!text || !text[0])
-                    text = "Storage Description";
-                if (!putString(window, text, row, i))
-                    goto fail;
-                 break;
-            default:
-                LOGE("fillStorage: unknown column %d\n", mColumns[i]);
-                goto fail;
-        }
-    }
-
-    delete storageInfo;
-    return true;
-
-fail:
-    delete storageInfo;
-    return false;
-}
-
-bool PtpCursor::fillObject(CursorWindow* window, MtpDevice* device,
-        MtpObjectHandle objectID, int row) {
-
-    MtpObjectInfo* objectInfo = device->getObjectInfo(objectID);
-    if (!objectInfo)
-        return false;
-    // objectInfo->print();
-    if (!prepareRow(window)) {
-        delete objectInfo;
-        return false;
-    }
-
-    for (int i = 0; i < mColumnCount; i++) {
-        switch (mColumns[i]) {
-            case OBJECT_ROW_ID:
-                if (!putLong(window, objectID, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_STORAGE_ID:
-                if (!putLong(window, objectInfo->mStorageID, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_FORMAT:
-                if (!putLong(window, objectInfo->mFormat, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_PROTECTION_STATUS:
-                if (!putLong(window, objectInfo->mProtectionStatus, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_SIZE:
-                if (!putLong(window, objectInfo->mCompressedSize, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_THUMB_FORMAT:
-                if (!putLong(window, objectInfo->mThumbFormat, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_THUMB_SIZE:
-                if (!putLong(window, objectInfo->mThumbCompressedSize, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_THUMB_WIDTH:
-                if (!putLong(window, objectInfo->mThumbPixWidth, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_THUMB_HEIGHT:
-                if (!putLong(window, objectInfo->mThumbPixHeight, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_IMAGE_WIDTH:
-                if (!putLong(window, objectInfo->mImagePixWidth, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_IMAGE_HEIGHT:
-                if (!putLong(window, objectInfo->mImagePixHeight, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_IMAGE_DEPTH:
-                if (!putLong(window, objectInfo->mImagePixDepth, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_PARENT:
-                if (!putLong(window, objectInfo->mParent, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_ASSOCIATION_TYPE:
-                if (!putLong(window, objectInfo->mAssociationType, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_ASSOCIATION_DESC:
-                if (!putLong(window, objectInfo->mAssociationDesc, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_SEQUENCE_NUMBER:
-                if (!putLong(window, objectInfo->mSequenceNumber, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_NAME:
-                if (!putString(window, objectInfo->mName, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_DATE_CREATED:
-                if (!putLong(window, objectInfo->mDateCreated, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_DATE_MODIFIED:
-                if (!putLong(window, objectInfo->mDateModified, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_KEYWORDS:
-                if (!putString(window, objectInfo->mKeywords, row, i))
-                    goto fail;
-                 break;
-            case OBJECT_THUMB:
-                if (!putThumbnail(window, objectID, objectInfo->mFormat, row, i))
-                    goto fail;
-                break;
-            default:
-                LOGE("fillObject: unknown column %d\n", mColumns[i]);
-                goto fail;
-        }
-    }
-
-    delete objectInfo;
-    return true;
-
-fail:
-    delete objectInfo;
-    return false;
-}
-
-bool PtpCursor::prepareRow(CursorWindow* window) {
-    if (!window->setNumColumns(mColumnCount)) {
-        LOGE("Failed to change column count from %d to %d", window->getNumColumns(), mColumnCount);
-        return false;
-    }
-    field_slot_t * fieldDir = window->allocRow();
-    if (!fieldDir) {
-        LOGE("Failed allocating fieldDir");
-        return false;
-    }
-    return true;
-}
-
-
-bool PtpCursor::putLong(CursorWindow* window, int64_t value, int row, int column) {
-    if (!window->putLong(row, column, value)) {
-        window->freeLastRow();
-        LOGE("Failed allocating space for a long in column %d", column);
-        return false;
-    }
-    return true;
-}
-
-bool PtpCursor::putString(CursorWindow* window, const char* text, int row, int column) {
-    int size = strlen(text) + 1;
-    int offset = window->alloc(size);
-    if (!offset) {
-        window->freeLastRow();
-        LOGE("Failed allocating %u bytes for text/blob %s", size, text);
-        return false;
-    }
-    window->copyIn(offset, (const uint8_t*)text, size);
-
-    // This must be updated after the call to alloc(), since that
-    // may move the field around in the window
-    field_slot_t * fieldSlot = window->getFieldSlot(row, column);
-    fieldSlot->type = FIELD_TYPE_STRING;
-    fieldSlot->data.buffer.offset = offset;
-    fieldSlot->data.buffer.size = size;
-    return true;
-}
-
-bool PtpCursor::putThumbnail(CursorWindow* window, MtpObjectHandle objectID,
-                            MtpObjectFormat format, int row, int column) {
-    MtpDevice* device = mClient->getDevice(mDeviceID);
-    void* thumbnail;
-    int size, offset;
-    if (format == MTP_FORMAT_ASSOCIATION) {
-        thumbnail = NULL;
-        size = offset = 0;
-    } else {
-        thumbnail = device->getThumbnail(objectID, size);
-
-        LOGV("putThumbnail: %p, size: %d\n", thumbnail, size);
-        offset = window->alloc(size);
-        if (!offset) {
-            window->freeLastRow();
-            LOGE("Failed allocating %u bytes for thumbnail", size);
-            return false;
-        }
-    }
-    if (thumbnail)
-        window->copyIn(offset, (const uint8_t*)thumbnail, size);
-
-    // This must be updated after the call to alloc(), since that
-    // may move the field around in the window
-    field_slot_t * fieldSlot = window->getFieldSlot(row, column);
-    fieldSlot->type = FIELD_TYPE_BLOB;
-    fieldSlot->data.buffer.offset = offset;
-    fieldSlot->data.buffer.size = size;
-    return true;
-}
-
-} // namespace android
diff --git a/media/mtp/PtpCursor.h b/media/mtp/PtpCursor.h
deleted file mode 100644
index 38a1d47..0000000
--- a/media/mtp/PtpCursor.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _PTP_CURSOR_H
-#define _PTP_CURSOR_H
-
-#include "MtpTypes.h"
-
-namespace android {
-
-class CursorWindow;
-
-class PtpCursor {
-private:
-    enum {
-        DEVICE              = 1,
-        DEVICE_ID           = 2,
-        STORAGE             = 3,
-        STORAGE_ID          = 4,
-        OBJECT              = 5,
-        OBJECT_ID           = 6,
-        STORAGE_CHILDREN    = 7,
-        OBJECT_CHILDREN     = 8,
-    };
-
-    MtpClient*      mClient;
-    int             mQueryType;
-    int             mDeviceID;
-    MtpStorageID    mStorageID;
-    MtpObjectHandle mQbjectID;
-    int             mColumnCount;
-    int*            mColumns;
-
-public:
-                PtpCursor(MtpClient* client, int queryType, int deviceID,
-                        MtpStorageID storageID, MtpObjectHandle objectID,
-                        int columnCount, int* columns);
-    virtual     ~PtpCursor();
-
-    int         fillWindow(CursorWindow* window, int startPos);
-
-private:
-    int         fillDevices(CursorWindow* window, int startPos);
-    int         fillDevice(CursorWindow* window, int startPos);
-    int         fillStorages(CursorWindow* window, int startPos);
-    int         fillStorage(CursorWindow* window, int startPos);
-    int         fillObjects(CursorWindow* window, int parent, int startPos);
-    int         fillObject(CursorWindow* window, int startPos);
-
-    bool        fillDevice(CursorWindow* window, MtpDevice* device, int startPos);
-    bool        fillStorage(CursorWindow* window, MtpDevice* device,
-                        MtpStorageID storageID, int row);
-    bool        fillObject(CursorWindow* window, MtpDevice* device,
-                        MtpObjectHandle objectID, int row);
-
-    bool        prepareRow(CursorWindow* window);
-    bool        putLong(CursorWindow* window, int64_t value, int row, int column);
-    bool        putString(CursorWindow* window, const char* text, int row, int column);
-    bool        putThumbnail(CursorWindow* window, MtpObjectHandle objectID,
-                            MtpObjectFormat format, int row, int column);
-};
-
-}; // namespace android
-
-#endif // _PTP_CURSOR_H
diff --git a/media/tests/CameraBrowser/Android.mk b/media/tests/CameraBrowser/Android.mk
deleted file mode 100644
index 295b3e6..0000000
--- a/media/tests/CameraBrowser/Android.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := CameraBrowser
-
-include $(BUILD_PACKAGE)
diff --git a/media/tests/CameraBrowser/AndroidManifest.xml b/media/tests/CameraBrowser/AndroidManifest.xml
deleted file mode 100644
index 1b1c146..0000000
--- a/media/tests/CameraBrowser/AndroidManifest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.camerabrowser">
-
-    <uses-permission android:name="android.permission.ACCESS_USB" />
-
-    <application android:label="@string/app_label">
-        <activity android:name="CameraBrowser" android:label="Camera Browser">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="StorageBrowser" />
-        <activity android:name="ObjectBrowser" />
-        <activity android:name="ObjectViewer" />
-
-        <receiver android:name="UsbReceiver">
-            <intent-filter>
-                <action android:name="android.hardware.action.USB_CAMERA_ATTACHED" />
-                <data android:scheme="content"/>
-            </intent-filter>
-        </receiver>
-
-    </application>
-
-
-</manifest>
diff --git a/media/tests/CameraBrowser/res/layout/object_info.xml b/media/tests/CameraBrowser/res/layout/object_info.xml
deleted file mode 100644
index a0499f2..0000000
--- a/media/tests/CameraBrowser/res/layout/object_info.xml
+++ /dev/null
@@ -1,169 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/object_info"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content">
-    <TableRow>
-        <TextView android:id="@+id/name_label"
-            android:text="@string/name_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/name"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <TextView android:id="@+id/size_label"
-            android:text="@string/size_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/size"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <TextView android:id="@+id/format_label"
-            android:text="@string/format_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/format"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <TextView android:id="@+id/thumb_width_label"
-            android:text="@string/thumb_width_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/thumb_width"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <TextView android:id="@+id/thumb_height_label"
-            android:text="@string/thumb_height_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/thumb_height"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <TextView android:id="@+id/thumb_size_label"
-            android:text="@string/thumb_size_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/thumb_size"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <TextView android:id="@+id/width_label"
-            android:text="@string/width_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/width"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <TextView android:id="@+id/height_label"
-            android:text="@string/height_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/height"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <TextView android:id="@+id/depth_label"
-            android:text="@string/depth_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/depth"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <TextView android:id="@+id/sequence_label"
-            android:text="@string/sequence_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/sequence"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <TextView android:id="@+id/created_label"
-            android:text="@string/created_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/created"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <TextView android:id="@+id/modified_label"
-            android:text="@string/modified_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/modified"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <TextView android:id="@+id/keywords_label"
-            android:text="@string/keywords_label"
-            android:layout_gravity="right"
-            android:layout_marginRight="8dip"
-            style="@style/info_label" />
-
-        <TextView android:id="@+id/keywords"
-            style="@style/info_value" />
-    </TableRow>
-    <TableRow>
-        <ImageView android:id="@+id/thumbnail" />
-    </TableRow>
-    <TableRow>
-        <Button android:id="@+id/import_button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/import_label">
-        </Button>
-        <Button android:id="@+id/delete_button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/delete_label">
-        </Button>
-    </TableRow>
-</TableLayout>
-
diff --git a/media/tests/CameraBrowser/res/layout/object_list.xml b/media/tests/CameraBrowser/res/layout/object_list.xml
deleted file mode 100644
index 30c18bb..0000000
--- a/media/tests/CameraBrowser/res/layout/object_list.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="horizontal"
-    android:layout_width="fill_parent" 
-    android:layout_height="fill_parent">
-    
-    <ImageView android:id="@+id/thumbnail"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
-
-    <TextView android:id="@+id/name"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textAppearance="?android:attr/textAppearanceLarge"
-        android:gravity="center_vertical"
-        android:paddingLeft="6dip"
-        android:minHeight="?android:attr/listPreferredItemHeight" />
-</LinearLayout>
diff --git a/media/tests/CameraBrowser/res/values/strings.xml b/media/tests/CameraBrowser/res/values/strings.xml
deleted file mode 100644
index 932aaec..0000000
--- a/media/tests/CameraBrowser/res/values/strings.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources>
-    <string name="app_label">Camera Browser</string>
-
-    <!-- for object info -->
-    <string name="name_label">Name: </string>
-    <string name="size_label">Size: </string>
-    <string name="format_label">Format: </string>
-    <string name="thumb_width_label">Thumb Width: </string>
-    <string name="thumb_height_label">Thumb Height: </string>
-    <string name="thumb_size_label">Thumb Size: </string>
-    <string name="width_label">Width: </string>
-    <string name="height_label">Height: </string>
-    <string name="depth_label">Depth: </string>
-    <string name="sequence_label">Sequence: </string>
-    <string name="created_label">Created: </string>
-    <string name="modified_label">Modified: </string>
-    <string name="keywords_label">Keywords: </string>
-
-    <!-- button labels -->
-    <string name="import_label">Import</string>
-    <string name="delete_label">Delete</string>
-
-    <!-- toasts -->
-    <string name="object_saved_message">Object saved</string>
-    <string name="save_failed_message">Could not save object</string>
-    <string name="object_deleted_message">Object deleted</string>
-    <string name="delete_failed_message">Could not delete object</string>
-    <string name="start_activity_failed_message">Import succeeded, but could not display object</string>
-
-</resources>
diff --git a/media/tests/CameraBrowser/res/values/styles.xml b/media/tests/CameraBrowser/res/values/styles.xml
deleted file mode 100644
index c869985..0000000
--- a/media/tests/CameraBrowser/res/values/styles.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources>
-    <style name="info_label">
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:textSize">14sp</item>
-        <item name="android:textStyle">bold</item>
-        <item name="android:paddingRight">4dip</item>
-    </style>
-
-    <style name="info_value">
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:textSize">14sp</item>
-        <item name="android:textStyle">normal</item>
-    </style>
-
-</resources>
-
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowser.java
deleted file mode 100644
index 0942d1f..0000000
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/CameraBrowser.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camerabrowser;
-
-import android.app.ListActivity;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.provider.Ptp;
-import android.util.Log;
-import android.view.View;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.SimpleCursorAdapter;
-
- /**
- * A list view displaying all connected cameras.
- */
-public class CameraBrowser extends ListActivity {
-
-    private static final String TAG = "CameraBrowser";
-
-    private ListAdapter mAdapter;
-    private ContentResolver mResolver;
-    private DeviceObserver mDeviceObserver;
-    private Cursor mCursor;
-
-    private class DeviceObserver extends ContentObserver {
-        DeviceObserver(Handler handler) {
-            super(handler);
-        }
-
-        @Override
-        public void onChange(boolean selfChange) {
-            Log.d(TAG, "DeviceObserver.onChange");
-            if (mCursor != null) {
-                mCursor.requery();
-            }
-        }
-    }
-
-    private static final String[] DEVICE_COLUMNS =
-         new String[] { Ptp.Device._ID, Ptp.Device.MANUFACTURER, Ptp.Device.MODEL };
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mResolver = getContentResolver();
-        mDeviceObserver = new DeviceObserver(new Handler());
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-
-        Cursor c = getContentResolver().query(Ptp.Device.CONTENT_URI,
-                DEVICE_COLUMNS, null, null, null);
-        Log.d(TAG, "query returned " + c);
-        startManagingCursor(c);
-        mCursor = c;
-
-        // Map Cursor columns to views defined in simple_list_item_2.xml
-        mAdapter = new SimpleCursorAdapter(this,
-                android.R.layout.simple_list_item_2, c,
-                        new String[] { Ptp.Device.MANUFACTURER, Ptp.Device.MODEL },
-                        new int[] { android.R.id.text1, android.R.id.text2 });
-        setListAdapter(mAdapter);
-
-        // register for changes to the device list
-        mResolver.registerContentObserver(Ptp.Device.CONTENT_URI, true, mDeviceObserver);
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        mResolver.unregisterContentObserver(mDeviceObserver);
-    }
-
-    @Override
-    protected void onListItemClick(ListView l, View v, int position, long id) {
-        Intent intent = new Intent(this, StorageBrowser.class);
-        intent.putExtra("device", (int)mAdapter.getItemId(position));
-        startActivity(intent);
-    }
-}
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/DeviceDisconnectedReceiver.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/DeviceDisconnectedReceiver.java
deleted file mode 100644
index d5e433b..0000000
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/DeviceDisconnectedReceiver.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camerabrowser;
-
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.hardware.UsbManager;
-import android.net.Uri;
-
-public class DeviceDisconnectedReceiver extends BroadcastReceiver {
-
-    private final Activity mActivity;
-    private final int mDeviceID;
-
-    public DeviceDisconnectedReceiver(Activity activity, int deviceID) {
-        mActivity = activity;
-        mDeviceID = deviceID;
-
-     IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_CAMERA_DETACHED);
-     filter.addDataScheme("content");
-     activity.registerReceiver(this, filter);
-    }
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        // close our activity if the device it is displaying is disconnected
-        Uri uri = intent.getData();
-        int id = Integer.parseInt(uri.getPathSegments().get(1));
-        if (id == mDeviceID) {
-            mActivity.finish();
-        }
-    }
-}
\ No newline at end of file
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
deleted file mode 100644
index 40c5978..0000000
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camerabrowser;
-
-import android.app.ListActivity;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.media.MtpConstants;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.Ptp;
-import android.util.Log;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.ResourceCursorAdapter;
-import android.widget.TextView;
-
- /**
- * A list view displaying all objects within a container (folder or storage unit).
- */
-public class ObjectBrowser extends ListActivity {
-
-    private static final String TAG = "ObjectBrowser";
-
-    private Cursor mCursor;
-    private ObjectCursorAdapter mAdapter;
-    private int mDeviceID;
-    private long mStorageID;
-    private long mObjectID;
-    private DeviceDisconnectedReceiver mDisconnectedReceiver;
-
-    private static final String[] OBJECT_COLUMNS =
-        new String[] { Ptp.Object._ID, Ptp.Object.NAME, Ptp.Object.FORMAT, Ptp.Object.THUMB };
-
-    static final int ID_COLUMN = 0;
-    static final int NAME_COLUMN = 1;
-    static final int FORMAT_COLUMN = 2;
-    static final int THUMB_COLUMN = 3;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mDeviceID = getIntent().getIntExtra("device", 0);
-        mStorageID = getIntent().getLongExtra("storage", 0);
-        mObjectID = getIntent().getLongExtra("object", 0);
-        mDisconnectedReceiver = new DeviceDisconnectedReceiver(this, mDeviceID);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-
-        if (mDeviceID != 0 && mStorageID != 0) {
-            Cursor c;
-            Uri uri;
-            if (mObjectID == 0) {
-                uri = Ptp.Object.getContentUriForStorageChildren(mDeviceID, mStorageID);
-            } else {
-                uri = Ptp.Object.getContentUriForObjectChildren(mDeviceID, mObjectID);
-            }
-            Log.d(TAG, "query " + uri);
-            c = getContentResolver().query(uri, OBJECT_COLUMNS, null, null, null);
-            startManagingCursor(c);
-            mCursor = c;
-
-            // Map Cursor columns to views defined in simple_list_item_1.xml
-            mAdapter = new ObjectCursorAdapter(this, c);
-            setListAdapter(mAdapter);
-        }
-    }
-
-    @Override
-    protected void onDestroy() {
-        unregisterReceiver(mDisconnectedReceiver);
-        super.onDestroy();
-    }
-
-    @Override
-    protected void onListItemClick(ListView l, View v, int position, long id) {
-        long rowID = mAdapter.getItemId(position);
-        Cursor c = getContentResolver().query(
-                        Ptp.Object.getContentUri(mDeviceID, rowID),
-                        OBJECT_COLUMNS, null, null, null);
-        Log.d(TAG, "query returned " + c + " count: " + c.getCount());
-        long format = 0;
-        if (c != null && c.getCount() == 1) {
-            c.moveToFirst();
-            long rowId = c.getLong(ID_COLUMN);
-            String name = c.getString(NAME_COLUMN);
-            format = c.getLong(FORMAT_COLUMN);
-            Log.d(TAG, "rowId: " + rowId + " name: " + name + " format: " + format);
-        }
-        if (format == MtpConstants.FORMAT_ASSOCIATION) {
-            Intent intent = new Intent(this, ObjectBrowser.class);
-            intent.putExtra("device", mDeviceID);
-            intent.putExtra("storage", mStorageID);
-            intent.putExtra("object", rowID);
-            startActivity(intent);
-        } else {
-            Intent intent = new Intent(this, ObjectViewer.class);
-            intent.putExtra("device", mDeviceID);
-            intent.putExtra("storage", mStorageID);
-            intent.putExtra("object", rowID);
-            startActivity(intent);
-        }
-    }
-
-    private class ObjectCursorAdapter extends ResourceCursorAdapter {
-
-        public ObjectCursorAdapter(Context context, Cursor c) {
-            super(context, R.layout.object_list, c);
-        }
-
-        @Override
-        public void bindView(View view, Context context, Cursor cursor) {
-            ImageView thumbView = (ImageView)view.findViewById(R.id.thumbnail);
-            TextView nameView = (TextView)view.findViewById(R.id.name);
-
-            // get the thumbnail
-            byte[] thumbnail = cursor.getBlob(THUMB_COLUMN);
-            if (thumbnail != null) {
-                Bitmap bitmap = BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length);
-                if (bitmap != null) {
-                    thumbView.setImageBitmap(bitmap);
-                }
-            }
-
-            // get the name
-            String name = cursor.getString(NAME_COLUMN);
-            if (name == null) {
-                name = "";
-            }
-            nameView.setText(name);
-        }
-    }
-}
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
deleted file mode 100644
index d53dbff..0000000
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camerabrowser;
-
-import android.app.Activity;
-import android.content.ActivityNotFoundException;
-import android.content.ContentValues;
-import android.content.Intent;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Environment;
-import android.provider.Ptp;
-import android.util.Log;
-import android.view.View;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import java.io.File;
-import java.util.Date;
-
-/**
- * A view to display the properties of an object.
- */
-public class ObjectViewer extends Activity implements View.OnClickListener {
-
-    private static final String TAG = "ObjectViewer";
-
-    private int mDeviceID;
-    private long mStorageID;
-    private long mObjectID;
-    private String mFileName;
-    private Button mImportButton;
-    private Button mDeleteButton;
-    private DeviceDisconnectedReceiver mDisconnectedReceiver;
-
-    private static final String[] OBJECT_COLUMNS =
-        new String[] {  Ptp.Object._ID,
-                        Ptp.Object.NAME,
-                        Ptp.Object.SIZE,
-                        Ptp.Object.THUMB_WIDTH,
-                        Ptp.Object.THUMB_HEIGHT,
-                        Ptp.Object.THUMB_SIZE,
-                        Ptp.Object.IMAGE_WIDTH,
-                        Ptp.Object.IMAGE_HEIGHT,
-                        Ptp.Object.IMAGE_DEPTH,
-                        Ptp.Object.SEQUENCE_NUMBER,
-                        Ptp.Object.DATE_CREATED,
-                        Ptp.Object.DATE_MODIFIED,
-                        Ptp.Object.KEYWORDS,
-                        Ptp.Object.THUMB,
-                        Ptp.Object.FORMAT,
-                        };
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        setContentView(R.layout.object_info);
-
-        mImportButton = (Button)findViewById(R.id.import_button);
-        mImportButton.setOnClickListener(this);
-        mDeleteButton = (Button)findViewById(R.id.delete_button);
-        mDeleteButton.setOnClickListener(this);
-
-        mDeviceID = getIntent().getIntExtra("device", 0);
-        mStorageID = getIntent().getLongExtra("storage", 0);
-        mObjectID = getIntent().getLongExtra("object", 0);
-        mDisconnectedReceiver = new DeviceDisconnectedReceiver(this, mDeviceID);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-
-        if (mDeviceID != 0 && mObjectID != 0) {
-        Cursor c = getContentResolver().query(
-                        Ptp.Object.getContentUri(mDeviceID, mObjectID),
-                        OBJECT_COLUMNS, null, null, null);
-            c.moveToFirst();
-            TextView view = (TextView)findViewById(R.id.name);
-            mFileName = c.getString(1);
-            view.setText(mFileName);
-            view = (TextView)findViewById(R.id.size);
-            view.setText(Long.toString(c.getLong(2)));
-            view = (TextView)findViewById(R.id.thumb_width);
-            view.setText(Long.toString(c.getLong(3)));
-            view = (TextView)findViewById(R.id.thumb_height);
-            view.setText(Long.toString(c.getLong(4)));
-            view = (TextView)findViewById(R.id.thumb_size);
-            view.setText(Long.toString(c.getLong(5)));
-            view = (TextView)findViewById(R.id.width);
-            view.setText(Long.toString(c.getLong(6)));
-            view = (TextView)findViewById(R.id.height);
-            view.setText(Long.toString(c.getLong(7)));
-            view = (TextView)findViewById(R.id.depth);
-            view.setText(Long.toString(c.getLong(8)));
-            view = (TextView)findViewById(R.id.sequence);
-            view.setText(Long.toString(c.getLong(9)));
-            view = (TextView)findViewById(R.id.created);
-            Date date = new Date(c.getLong(10) * 1000);
-            view.setText(date.toString());
-            view = (TextView)findViewById(R.id.modified);
-            date = new Date(c.getLong(11) * 1000);
-            view.setText(date.toString());
-            view = (TextView)findViewById(R.id.keywords);
-            view.setText(c.getString(12));
-            byte[] thumbnail = c.getBlob(13);
-            if (thumbnail != null) {
-                ImageView thumbView = (ImageView)findViewById(R.id.thumbnail);
-                Bitmap bitmap = BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length);
-                if (bitmap != null) {
-                    thumbView.setImageBitmap(bitmap);
-                }
-            }
-            view = (TextView)findViewById(R.id.format);
-            view.setText(Long.toHexString(c.getLong(14)).toUpperCase());
-        }
-    }
-
-    @Override
-    protected void onDestroy() {
-        unregisterReceiver(mDisconnectedReceiver);
-        super.onDestroy();
-    }
-
-    private void importObject() {
-        // copy file to /mnt/sdcard/imported/<filename>
-        File dest = Environment.getExternalStorageDirectory();
-        dest = new File(dest, "imported");
-        dest.mkdirs();
-        dest = new File(dest, mFileName);
-
-        Uri requestUri = Ptp.Object.getContentUriForImport(mDeviceID, mObjectID,
-                dest.getAbsolutePath());
-        Uri resultUri = getContentResolver().insert(requestUri, new ContentValues());
-        Log.d(TAG, "save returned " + resultUri);
-
-        if (resultUri != null) {
-            Toast.makeText(this, R.string.object_saved_message, Toast.LENGTH_SHORT).show();
-            Intent intent = new Intent(Intent.ACTION_VIEW, resultUri);
-            try {
-                startActivity(intent);
-            } catch (ActivityNotFoundException e) {
-                Toast.makeText(this, R.string.start_activity_failed_message, Toast.LENGTH_SHORT).show();
-            }
-        } else {
-            Toast.makeText(this, R.string.save_failed_message, Toast.LENGTH_SHORT).show();
-        }
-    }
-
-    private void deleteObject() {
-        Uri uri = Ptp.Object.getContentUri(mDeviceID, mObjectID);
-
-        Log.d(TAG, "deleting " + uri);
-
-        int result = getContentResolver().delete(uri, null, null);
-        if (result > 0) {
-            Toast.makeText(this, R.string.object_deleted_message, Toast.LENGTH_SHORT).show();
-            finish();
-        } else {
-            Toast.makeText(this, R.string.delete_failed_message, Toast.LENGTH_SHORT).show();
-        }
-    }
-
-    public void onClick(View v) {
-        if (v == mImportButton) {
-            importObject();
-        } else if (v == mDeleteButton) {
-            deleteObject();
-        }
-    }
-}
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java
deleted file mode 100644
index 62187b0..0000000
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camerabrowser;
-
-import android.app.ListActivity;
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.Ptp;
-import android.util.Log;
-import android.view.View;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.SimpleCursorAdapter;
-
-/**
- * A list view displaying all storage units on a device.
- */
-public class StorageBrowser extends ListActivity {
-
-    private static final String TAG = "StorageBrowser";
-
-    private ListAdapter mAdapter;
-    private int mDeviceID;
-    private DeviceDisconnectedReceiver mDisconnectedReceiver;
-
-    private static final String[] STORAGE_COLUMNS =
-        new String[] { Ptp.Storage._ID, Ptp.Storage.DESCRIPTION };
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mDeviceID = getIntent().getIntExtra("device", 0);
-        mDisconnectedReceiver = new DeviceDisconnectedReceiver(this, mDeviceID);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-
-        if (mDeviceID != 0) {
-            Cursor c = getContentResolver().query(Ptp.Storage.getContentUri(mDeviceID),
-                    STORAGE_COLUMNS, null, null, null);
-            Log.d(TAG, "query returned " + c);
-            startManagingCursor(c);
-
-            // Map Cursor columns to views defined in simple_list_item_1.xml
-            mAdapter = new SimpleCursorAdapter(this,
-                    android.R.layout.simple_list_item_1, c,
-                            new String[] { Ptp.Storage.DESCRIPTION },
-                            new int[] { android.R.id.text1, android.R.id.text2 });
-            setListAdapter(mAdapter);
-        }
-    }
-
-    @Override
-    protected void onDestroy() {
-        unregisterReceiver(mDisconnectedReceiver);
-        super.onDestroy();
-    }
-
-    @Override
-    protected void onListItemClick(ListView l, View v, int position, long id) {
-        Intent intent = new Intent(this, ObjectBrowser.class);
-        intent.putExtra("device", mDeviceID);
-        intent.putExtra("storage", mAdapter.getItemId(position));
-        startActivity(intent);
-    }
-}
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/UsbReceiver.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/UsbReceiver.java
deleted file mode 100644
index 07e5a23..0000000
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/UsbReceiver.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camerabrowser;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.BroadcastReceiver;
-import android.hardware.UsbManager;
-import android.net.Uri;
-import android.util.Log;
-
-public class UsbReceiver extends BroadcastReceiver
-{
-    private static final String TAG = "UsbReceiver";
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        Log.d(TAG, "onReceive " + intent);
-        if (UsbManager.ACTION_USB_CAMERA_ATTACHED.equals(intent.getAction())) {
-            Uri uri = intent.getData();
-            intent = new Intent(context, StorageBrowser.class);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            try {
-                // TODO - add a wrapper to Mtp.Device for this
-                int id = Integer.parseInt(uri.getPathSegments().get(1));
-                intent.putExtra("device", id);
-                context.startActivity(intent);
-            } catch (NumberFormatException e) {
-                Log.e(TAG, "bad device Uri " + uri);
-            }
-        }
-    }
-}
diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml
index 5c20811..2253eb2 100644
--- a/media/tests/MediaFrameworkTest/AndroidManifest.xml
+++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml
@@ -25,7 +25,8 @@
     <application>    
         <uses-library android:name="android.test.runner" />
         <activity android:label="@string/app_name"
-                android:name="MediaFrameworkTest">         
+                android:name="MediaFrameworkTest"
+                android:screenOrientation="landscape">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER"/>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java
index 95dbb97..6ded74d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java
@@ -202,7 +202,6 @@
         }
         String value = null;
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
-        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         try {
             retriever.setDataSource(meta_data_file[fileIndex][0]);
         } catch(Exception e) {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
index a0c72e6..a66db05 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
@@ -31,13 +31,12 @@
    
     // Test album art extraction.
     @MediumTest
-    public static void testAlbumArt() throws Exception {
-        Log.v(TAG, "testAlbumArt starts.");
+    public static void testGetEmbeddedPicture() throws Exception {
+        Log.v(TAG, "testGetEmbeddedPicture starts.");
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
         boolean supportWMA = MediaProfileReader.getWMAEnable();
         boolean hasFailed = false;
         boolean supportWMV = MediaProfileReader.getWMVEnable();
-        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         for (int i = 0, n = MediaNames.ALBUMART_TEST_FILES.length; i < n; ++i) {
             try {
                 Log.v(TAG, "File " + i + ": " + MediaNames.ALBUMART_TEST_FILES[i]);
@@ -48,13 +47,13 @@
                     continue;
                 }
                 retriever.setDataSource(MediaNames.ALBUMART_TEST_FILES[i]);
-                byte[] albumArt = retriever.extractAlbumArt();
+                byte[] albumArt = retriever.getEmbeddedPicture();
 
                 // TODO:
                 // A better test would be to compare the retrieved album art with the
                 // known result.
                 if (albumArt == null) {  // Do we have expect in JUnit?
-                    Log.e(TAG, "Fails to extract album art for " + MediaNames.ALBUMART_TEST_FILES[i]);
+                    Log.e(TAG, "Fails to get embedded picture for " + MediaNames.ALBUMART_TEST_FILES[i]);
                     hasFailed = true;
                 }
             } catch(Exception e) {
@@ -64,7 +63,7 @@
             Thread.yield();  // Don't be evil
         }
         retriever.release();
-        Log.v(TAG, "testAlbumArt completes.");
+        Log.v(TAG, "testGetEmbeddedPicture completes.");
         assertTrue(!hasFailed);
     }
 
@@ -116,7 +115,6 @@
         boolean supportWMV = MediaProfileReader.getWMVEnable();
         boolean hasFailed = false;
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
-        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         for(int i = 0, n = MediaNames.METADATA_RETRIEVAL_TEST_FILES.length; i < n; ++i) {
             try {
                 Log.v(TAG, "File " + i + ": " + MediaNames.METADATA_RETRIEVAL_TEST_FILES[i]);
@@ -170,7 +168,6 @@
     public static void testBasicAbnormalMethodCallSequence() {
         boolean hasFailed = false;
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
-        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         if (retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM) != null) {
             Log.e(TAG, "No album metadata expected, but is available");
             hasFailed = true;
@@ -186,7 +183,6 @@
     @MediumTest
     public static void testSetDataSource() {
         MediaMetadataRetriever retriever = new MediaMetadataRetriever();
-        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         boolean hasFailed = false;
 
         // Null pointer argument
@@ -253,7 +249,6 @@
         assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null);
 
         // Do not capture frame or retrieve metadata
-        retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY & MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         retriever.setDataSource(MediaNames.TEST_PATH_1);
         if (retriever.getFrameAtTime(-1) != null) {
             Log.e(TAG, "No frame expected, but is available");
@@ -265,12 +260,10 @@
         }
 
         // Capture frame only
-        retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
         retriever.setDataSource(MediaNames.TEST_PATH_1);
         assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) == null);
 
         // Retriever metadata only
-        retriever.setMode(MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         retriever.setDataSource(MediaNames.TEST_PATH_1);
         if (retriever.getFrameAtTime(-1) != null) {
             Log.e(TAG, "No frame expected, but is available");
@@ -278,7 +271,6 @@
         }
 
         // Capture frame and retrieve metadata
-        retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY | MediaMetadataRetriever.MODE_GET_METADATA_ONLY);
         retriever.setDataSource(MediaNames.TEST_PATH_1);
         assertTrue(retriever.getFrameAtTime(-1) != null);
         assertTrue(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS) != null);
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 7acce02..386cc5d 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -895,7 +895,7 @@
     dp->refs--;
     dp->numTotalConfigs = 0;
     delete [] dp->configs;
-    clearTLS();
+
     return res;
 }
 
@@ -1231,6 +1231,27 @@
     return result;
 }
 
+static void loseCurrent(egl_context_t * cur_c)
+{
+    if (cur_c) {
+        egl_surface_t * cur_r = get_surface(cur_c->read);
+        egl_surface_t * cur_d = get_surface(cur_c->draw);
+
+        // by construction, these are either 0 or valid (possibly terminated)
+        // it should be impossible for these to be invalid
+        ContextRef _cur_c(cur_c);
+        SurfaceRef _cur_r(cur_r);
+        SurfaceRef _cur_d(cur_d);
+
+        cur_c->read = NULL;
+        cur_c->draw = NULL;
+
+        _cur_c.release();
+        _cur_r.release();
+        _cur_d.release();
+    }
+}
+
 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
                             EGLSurface read, EGLContext ctx)
 {
@@ -1259,13 +1280,9 @@
 
     // these are the current objects structs
     egl_context_t * cur_c = get_context(getContext());
-    egl_surface_t * cur_r = NULL;
-    egl_surface_t * cur_d = NULL;
     
     if (ctx != EGL_NO_CONTEXT) {
         c = get_context(ctx);
-        cur_r = get_surface(c->read);
-        cur_d = get_surface(c->draw);
         impl_ctx = c->context;
     } else {
         // no context given, use the implementation of the current context
@@ -1311,30 +1328,21 @@
     }
 
     if (result == EGL_TRUE) {
-        // by construction, these are either 0 or valid (possibly terminated)
-        // it should be impossible for these to be invalid
-        ContextRef _cur_c(cur_c);
-        SurfaceRef _cur_r(cur_r);
-        SurfaceRef _cur_d(cur_d);
 
-        // cur_c has to be valid here (but could be terminated)
+        loseCurrent(cur_c);
+
         if (ctx != EGL_NO_CONTEXT) {
             setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
             setContext(ctx);
             _c.acquire();
+            _r.acquire();
+            _d.acquire();
+            c->read = read;
+            c->draw = draw;
         } else {
             setGLHooksThreadSpecific(&gHooksNoContext);
             setContext(EGL_NO_CONTEXT);
         }
-        _cur_c.release();
-
-        _r.acquire();
-        _cur_r.release();
-        if (c) c->read = read;
-
-        _d.acquire();
-        _cur_d.release();
-        if (c) c->draw = draw;
     }
     return result;
 }
@@ -1721,6 +1729,9 @@
 
 EGLBoolean eglReleaseThread(void)
 {
+    // If there is context bound to the thread, release it
+    loseCurrent(get_context(getContext()));
+
     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
index 743dbf1..6312970 100644
--- a/opengl/tests/hwc/Android.mk
+++ b/opengl/tests/hwc/Android.mk
@@ -1,7 +1,40 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= hwc_stress.cpp
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE:= libhwcTest
+LOCAL_SRC_FILES:= hwcTestLib.cpp
+LOCAL_C_INCLUDES += system/extras/tests/include \
+    bionic \
+    bionic/libstdc++/include \
+    external/stlport/stlport \
+    frameworks/base/opengl/tests \
+    frameworks/base/opengl/tests/include \
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+LOCAL_SHARED_LIBRARIES += libcutils libutils libstlport
+LOCAL_STATIC_LIBRARIES += libglTest
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= hwcStress.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
@@ -12,12 +45,18 @@
 
 LOCAL_STATIC_LIBRARIES := \
     libtestUtil \
+    libglTest \
+    libhwcTest \
 
 LOCAL_C_INCLUDES += \
     system/extras/tests/include \
     hardware/libhardware/include \
+    frameworks/base/opengl/tests \
+    frameworks/base/opengl/tests/include \
 
-LOCAL_MODULE:= hwc_stress
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+LOCAL_MODULE:= hwcStress
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativestresstest
 
 LOCAL_MODULE_TAGS := tests
@@ -25,3 +64,93 @@
 LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
 include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= hwcRects.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libEGL \
+    libGLESv2 \
+    libui \
+    libhardware \
+
+LOCAL_STATIC_LIBRARIES := \
+    libtestUtil \
+    libglTest \
+    libhwcTest \
+
+LOCAL_C_INCLUDES += \
+    system/extras/tests/include \
+    hardware/libhardware/include \
+    frameworks/base/opengl/tests \
+    frameworks/base/opengl/tests/include \
+
+LOCAL_MODULE:= hwcRects
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativeutil
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= hwcColorEquiv.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libEGL \
+    libGLESv2 \
+    libui \
+    libhardware \
+
+LOCAL_STATIC_LIBRARIES := \
+    libtestUtil \
+    libglTest \
+    libhwcTest \
+
+LOCAL_C_INCLUDES += \
+    system/extras/tests/include \
+    hardware/libhardware/include \
+    frameworks/base/opengl/tests \
+    frameworks/base/opengl/tests/include \
+
+LOCAL_MODULE:= hwcColorEquiv
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativeutil
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= hwcCommit.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libEGL \
+    libGLESv2 \
+    libui \
+    libhardware \
+
+LOCAL_STATIC_LIBRARIES := \
+    libtestUtil \
+    libglTest \
+    libhwcTest \
+
+LOCAL_C_INCLUDES += \
+    system/extras/tests/include \
+    hardware/libhardware/include \
+    frameworks/base/opengl/tests \
+    frameworks/base/opengl/tests/include \
+
+LOCAL_MODULE:= hwcCommit
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativebenchmark
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+include $(BUILD_NATIVE_TEST)
diff --git a/opengl/tests/hwc/hwcColorEquiv.cpp b/opengl/tests/hwc/hwcColorEquiv.cpp
new file mode 100644
index 0000000..1d03948
--- /dev/null
+++ b/opengl/tests/hwc/hwcColorEquiv.cpp
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Hardware Composer Color Equivalence
+ *
+ * Synopsis
+ *   hwc_colorequiv [options] eFmt
+ *
+ *     options:
+         -v - verbose
+ *       -s <0.##, 0.##, 0.##> - Start color (default: <0.0, 0.0, 0.0>
+ *       -e <0.##, 0.##, 0.##> - Ending color (default: <1.0, 1.0, 1.0>
+ *       -r fmt - reference graphic format
+ *       -D #.## - End of test delay
+ *
+ *     graphic formats:
+ *       RGBA8888 (reference frame default)
+ *       RGBX8888
+ *       RGB888
+ *       RGB565
+ *       BGRA8888
+ *       RGBA5551
+ *       RGBA4444
+ *       YV12
+ *
+ * Description
+ *   Renders a horizontal blend in two frames.  The first frame is rendered
+ *   in the upper third of the display and is called the reference frame.
+ *   The second frame is displayed in the middle third and is called the
+ *   equivalence frame.  The primary purpose of this utility is to verify
+ *   that the colors produced in the reference and equivalence frames are
+ *   the same.  The colors are the same when the colors are the same
+ *   vertically between the reference and equivalence frames.
+ *
+ *   By default the reference frame is rendered through the use of the
+ *   RGBA8888 graphic format.  The -r option can be used to specify a
+ *   non-default reference frame graphic format.  The graphic format of
+ *   the equivalence frame is determined by a single required positional
+ *   parameter.  Intentionally there is no default for the graphic format
+ *   of the equivalence frame.
+ *
+ *   The horizontal blend in the reference frame is produced from a linear
+ *   interpolation from a start color (default: <0.0, 0.0, 0.0> on the left
+ *   side to an end color (default <1.0, 1.0, 1.0> on the right side.  Where
+ *   possible the equivalence frame is rendered with the equivalent color
+ *   from the reference frame.  A color of black is used in the equivalence
+ *   frame for cases where an equivalent color does not exist.
+ */
+
+#include <algorithm>
+#include <assert.h>
+#include <cerrno>
+#include <cmath>
+#include <cstdlib>
+#include <ctime>
+#include <libgen.h>
+#include <sched.h>
+#include <sstream>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <vector>
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+#define LOG_TAG "hwcColorEquivTest"
+#include <utils/Log.h>
+#include <testUtil.h>
+
+#include <hardware/hwcomposer.h>
+
+#include "hwcTestLib.h"
+
+using namespace std;
+using namespace android;
+
+// Defaults for command-line options
+const bool defaultVerbose = false;
+const ColorFract defaultStartColor(0.0, 0.0, 0.0);
+const ColorFract defaultEndColor(1.0, 1.0, 1.0);
+const char *defaultRefFormat = "RGBA8888";
+const float defaultEndDelay = 2.0; // Default delay after rendering graphics
+
+// Defines
+#define MAXSTR               100
+#define MAXCMD               200
+#define BITSPERBYTE            8 // TODO: Obtain from <values.h>, once
+                                 // it has been added
+
+#define CMD_STOP_FRAMEWORK   "stop 2>&1"
+#define CMD_START_FRAMEWORK  "start 2>&1"
+
+// Macros
+#define NUMA(a) (sizeof(a) / sizeof(a [0])) // Num elements in an array
+#define MEMCLR(addr, size) do { \
+        memset((addr), 0, (size)); \
+    } while (0)
+
+// Globals
+static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
+        GraphicBuffer::USAGE_SW_WRITE_RARELY;
+static hwc_composer_device_t *hwcDevice;
+static EGLDisplay dpy;
+static EGLSurface surface;
+static EGLint width, height;
+
+// Functions prototypes
+void init(void);
+void printSyntax(const char *cmd);
+
+// Command-line option settings
+static bool verbose = defaultVerbose;
+static ColorFract startRefColor = defaultStartColor;
+static ColorFract endRefColor = defaultEndColor;
+static float endDelay = defaultEndDelay;
+static const struct hwcTestGraphicFormat *refFormat
+    = hwcTestGraphicFormatLookup(defaultRefFormat);
+static const struct hwcTestGraphicFormat *equivFormat;
+
+/*
+ * Main
+ *
+ * Performs the following high-level sequence of operations:
+ *
+ *   1. Command-line parsing
+ *
+ *   2. Stop framework
+ *
+ *   3. Initialization
+ *
+ *   4. Create Hardware Composer description of reference and equivalence frames
+ *
+ *   5. Have Hardware Composer render the reference and equivalence frames
+ *
+ *   6. Delay for amount of time given by endDelay
+ *
+ *   7. Start framework
+ */
+int
+main(int argc, char *argv[])
+{
+    int rv, opt;
+    bool error;
+    char *chptr;
+    unsigned int pass;
+    char cmd[MAXCMD];
+    string str;
+
+    testSetLogCatTag(LOG_TAG);
+
+    assert(refFormat != NULL);
+
+    testSetLogCatTag(LOG_TAG);
+
+    // Parse command line arguments
+    while ((opt = getopt(argc, argv, "vs:e:r:D:?h")) != -1) {
+        switch (opt) {
+          case 'D': // End of test delay
+                    // Delay between completion of final pass and restart
+                    // of framework
+            endDelay = strtod(optarg, &chptr);
+            if ((*chptr != '\0') || (endDelay < 0.0)) {
+                testPrintE("Invalid command-line specified end of test delay "
+                           "of: %s", optarg);
+                exit(1);
+            }
+            break;
+
+          case 's': // Starting reference color
+            str = optarg;
+            while (optind < argc) {
+                if (*argv[optind] == '-') { break; }
+                char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
+                if ((endChar == '>') || (endChar == ']')) { break; }
+                str += " " + string(argv[optind++]);
+            }
+            {
+                istringstream in(str);
+                startRefColor = hwcTestParseColor(in, error);
+                // Any parse error or characters not used by parser
+                if (error
+                    || (((unsigned int) in.tellg() != in.str().length())
+                        && (in.tellg() != (streampos) -1))) {
+                    testPrintE("Invalid command-line specified start "
+                               "reference color of: %s", str.c_str());
+                    exit(2);
+                }
+            }
+            break;
+
+          case 'e': // Ending reference color
+            str = optarg;
+            while (optind < argc) {
+                if (*argv[optind] == '-') { break; }
+                char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
+                if ((endChar == '>') || (endChar == ']')) { break; }
+                str += " " + string(argv[optind++]);
+            }
+            {
+                istringstream in(str);
+                endRefColor = hwcTestParseColor(in, error);
+                // Any parse error or characters not used by parser
+                if (error
+                    || (((unsigned int) in.tellg() != in.str().length())
+                        && (in.tellg() != (streampos) -1))) {
+                    testPrintE("Invalid command-line specified end "
+                               "reference color of: %s", str.c_str());
+                    exit(3);
+                }
+            }
+            break;
+
+          case 'r': // Reference graphic format
+            refFormat = hwcTestGraphicFormatLookup(optarg);
+            if (refFormat == NULL) {
+                testPrintE("Unkown command-line specified reference graphic "
+                           "format of: %s", optarg);
+                printSyntax(basename(argv[0]));
+                exit(4);
+            }
+            break;
+
+          case 'v': // Verbose
+            verbose = true;
+            break;
+
+          case 'h': // Help
+          case '?':
+          default:
+            printSyntax(basename(argv[0]));
+            exit(((optopt == 0) || (optopt == '?')) ? 0 : 5);
+        }
+    }
+
+    // Expect a single positional parameter, which specifies the
+    // equivalence graphic format.
+    if (argc != (optind + 1)) {
+        testPrintE("Expected a single command-line postional parameter");
+        printSyntax(basename(argv[0]));
+        exit(6);
+    }
+    equivFormat = hwcTestGraphicFormatLookup(argv[optind]);
+    if (equivFormat == NULL) {
+        testPrintE("Unkown command-line specified equivalence graphic "
+                   "format of: %s", argv[optind]);
+        printSyntax(basename(argv[0]));
+        exit(7);
+    }
+
+    testPrintI("refFormat: %u %s", refFormat->format, refFormat->desc);
+    testPrintI("equivFormat: %u %s", equivFormat->format, equivFormat->desc);
+    testPrintI("startRefColor: %s", ((string) startRefColor).c_str());
+    testPrintI("endRefColor: %s", ((string) endRefColor).c_str());
+    testPrintI("endDelay: %f", endDelay);
+
+    // Stop framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
+        exit(8);
+    }
+    testExecCmd(cmd);
+    testDelay(1.0); // TODO - needs means to query whether asynchronous stop
+                    // framework operation has completed.  For now, just wait
+                    // a long time.
+
+    init();
+
+    // Use the upper third of the display for the reference frame and
+    // the middle third for the equivalence frame.
+    unsigned int refHeight = height / 3;
+    unsigned int refPosY = 0; // Reference frame Y position
+    unsigned int refPosX = 0; // Reference frame X position
+    unsigned int refWidth = width - refPosX;
+    if ((refWidth & refFormat->wMod) != 0) {
+        refWidth += refFormat->wMod - (refWidth % refFormat->wMod);
+    }
+    unsigned int equivHeight = height / 3;
+    unsigned int equivPosY = refHeight; // Equivalence frame Y position
+    unsigned int equivPosX = 0;         // Equivalence frame X position
+    unsigned int equivWidth = width - equivPosX;
+    if ((equivWidth & equivFormat->wMod) != 0) {
+        equivWidth += equivFormat->wMod - (equivWidth % equivFormat->wMod);
+    }
+
+    // Create reference and equivalence graphic buffers
+    const unsigned int numFrames = 2;
+    sp<GraphicBuffer> refFrame;
+    refFrame = new GraphicBuffer(refWidth, refHeight,
+                                 refFormat->format, texUsage);
+    if ((rv = refFrame->initCheck()) != NO_ERROR) {
+        testPrintE("refFrame initCheck failed, rv: %i", rv);
+        testPrintE("  width %u height: %u format: %u %s", refWidth, refHeight,
+                   refFormat->format,
+                   hwcTestGraphicFormat2str(refFormat->format));
+        exit(9);
+    }
+    testPrintI("refFrame width: %u height: %u format: %u %s",
+               refWidth, refHeight, refFormat->format,
+               hwcTestGraphicFormat2str(refFormat->format));
+
+    sp<GraphicBuffer> equivFrame;
+    equivFrame = new GraphicBuffer(equivWidth, equivHeight,
+                                   equivFormat->format, texUsage);
+    if ((rv = refFrame->initCheck()) != NO_ERROR) {
+        testPrintE("refFrame initCheck failed, rv: %i", rv);
+        testPrintE("  width %u height: %u format: %u %s", refWidth, refHeight,
+                   refFormat->format,
+                   hwcTestGraphicFormat2str(refFormat->format));
+        exit(10);
+    }
+    testPrintI("equivFrame width: %u height: %u format: %u %s",
+               equivWidth, equivHeight, equivFormat->format,
+               hwcTestGraphicFormat2str(equivFormat->format));
+
+    // Fill the frames with a horizontal blend
+    hwcTestFillColorHBlend(refFrame.get(), refFormat->format,
+                           startRefColor, endRefColor);
+    hwcTestFillColorHBlend(equivFrame.get(), refFormat->format,
+                           startRefColor, endRefColor);
+
+    hwc_layer_list_t *list;
+    size_t size = sizeof(hwc_layer_list) + numFrames * sizeof(hwc_layer_t);
+    if ((list = (hwc_layer_list_t *) calloc(1, size)) == NULL) {
+        testPrintE("Allocate list failed");
+        exit(11);
+    }
+    list->flags = HWC_GEOMETRY_CHANGED;
+    list->numHwLayers = numFrames;
+
+    hwc_layer_t *layer = &list->hwLayers[0];
+    layer->handle = refFrame->handle;
+    layer->blending = HWC_BLENDING_NONE;
+    layer->sourceCrop.left = 0;
+    layer->sourceCrop.top = 0;
+    layer->sourceCrop.right = width;
+    layer->sourceCrop.bottom = refHeight;
+    layer->displayFrame.left = 0;
+    layer->displayFrame.top = 0;
+    layer->displayFrame.right = width;
+    layer->displayFrame.bottom = refHeight;
+    layer->visibleRegionScreen.numRects = 1;
+    layer->visibleRegionScreen.rects = &layer->displayFrame;
+
+    layer++;
+    layer->handle = equivFrame->handle;
+    layer->blending = HWC_BLENDING_NONE;
+    layer->sourceCrop.left = 0;
+    layer->sourceCrop.top = 0;
+    layer->sourceCrop.right = width;
+    layer->sourceCrop.bottom = equivHeight;
+    layer->displayFrame.left = 0;
+    layer->displayFrame.top = refHeight;
+    layer->displayFrame.right = width;
+    layer->displayFrame.bottom = layer->displayFrame.top + equivHeight;
+    layer->visibleRegionScreen.numRects = 1;
+    layer->visibleRegionScreen.rects = &layer->displayFrame;
+
+    // Perform prepare operation
+    if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(list); }
+    hwcDevice->prepare(hwcDevice, list);
+    if (verbose) {
+        testPrintI("Post Prepare:");
+        hwcTestDisplayListPrepareModifiable(list);
+    }
+
+    // Turn off the geometry changed flag
+    list->flags &= ~HWC_GEOMETRY_CHANGED;
+
+    if (verbose) {hwcTestDisplayListHandles(list); }
+    hwcDevice->set(hwcDevice, dpy, surface, list);
+
+    testDelay(endDelay);
+
+    // Start framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
+        exit(12);
+    }
+    testExecCmd(cmd);
+
+    return 0;
+}
+
+void init(void)
+{
+    // Seed pseudo random number generator
+    // Seeding causes fill horizontal blend to fill the pad area with
+    // a deterministic set of values.
+    srand48(0);
+
+    hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
+
+    hwcTestOpenHwc(&hwcDevice);
+}
+
+void printSyntax(const char *cmd)
+{
+    testPrintE("  %s [options] graphicFormat", cmd);
+    testPrintE("    options:");
+    testPrintE("      -s <0.##, 0.##, 0.##> - Starting reference color");
+    testPrintE("      -e <0.##, 0.##, 0.##> - Ending reference color");
+    testPrintE("      -r format - Reference graphic format");
+    testPrintE("      -D #.## - End of test delay");
+    testPrintE("      -v Verbose");
+    testPrintE("");
+    testPrintE("    graphic formats:");
+    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+        testPrintE("      %s", hwcTestGraphicFormat[n1].desc);
+    }
+}
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
new file mode 100644
index 0000000..66ccdae
--- /dev/null
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -0,0 +1,1562 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Hardware Composer Commit Points
+ *
+ * Synopsis
+ *   hwcCommit [options] graphicFormat ...
+ *     options:
+ *       -s [width, height] - Starting dimension
+ *       -v - Verbose
+ *
+ *      graphic formats:
+ *        RGBA8888 (reference frame default)
+ *        RGBX8888
+ *        RGB888
+ *        RGB565
+ *        BGRA8888
+ *        RGBA5551
+ *        RGBA4444
+ *        YV12
+ *
+ * Description
+ *   The Hardware Composer (HWC) Commit test is a benchmark that
+ *   discovers the points at which the HWC will commit to rendering an
+ *   overlay(s).  Before rendering a set of overlays, the HWC is shown
+ *   the list through a prepare call.  During the prepare call the HWC
+ *   is able to examine the list and specify which overlays it is able
+ *   to handle.  The overlays that it can't handle are typically composited
+ *   by a higher level (e.g. Surface Flinger) and then the original list
+ *   plus a composit of what HWC passed on are provided back to the HWC
+ *   for rendering.
+ *
+ *   Once an implementation of the HWC has been shipped, a regression would
+ *   likely occur if a latter implementation started passing on conditions
+ *   that it used to commit to.  The primary purpose of this benchmark
+ *   is the automated discovery of the commit points, where an implementation
+ *   is on the edge between committing and not committing.  These are commonly
+ *   referred to as commit points.  Between implementations changes to the
+ *   commit points are allowed, as long as they improve what the HWC commits
+ *   to.  Once an implementation of the HWC is shipped, the commit points are
+ *   not allowed to regress in future implementations.
+ *
+ *   This benchmark takes a sampling and then adjusts until it finds a
+ *   commit point.  It doesn't exhaustively check all possible conditions,
+ *   which do to the number of combinations would be impossible.  Instead
+ *   it starts its search from a starting dimension, that can be changed
+ *   via the -s option.  The search is also bounded by a set of search
+ *   limits, that are hard-coded into a structure of constants named
+ *   searchLimits.  Results that happen to reach a searchLimit are prefixed
+ *   with >=, so that it is known that the value could possibly be larger.
+ *
+ *   Measurements are made for each of the graphic formats specified as
+ *   positional parameters on the command-line.  If no graphic formats
+ *   are specified on the command line, then by default measurements are
+ *   made and reported for each of the known graphic format.
+ */
+
+#include <algorithm>
+#include <assert.h>
+#include <cerrno>
+#include <cmath>
+#include <cstdlib>
+#include <ctime>
+#include <iomanip>
+#include <istream>
+#include <libgen.h>
+#include <list>
+#include <sched.h>
+#include <sstream>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <vector>
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+#define LOG_TAG "hwcCommitTest"
+#include <utils/Log.h>
+#include <testUtil.h>
+
+#include <hardware/hwcomposer.h>
+
+#include <glTestLib.h>
+#include <hwc/hwcTestLib.h>
+
+using namespace std;
+using namespace android;
+
+// Defaults
+const HwcTestDim defaultStartDim = HwcTestDim(100, 100);
+const bool defaultVerbose = false;
+
+const uint32_t   defaultFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+const int32_t    defaultTransform = 0;
+const uint32_t   defaultBlend = HWC_BLENDING_NONE;
+const ColorFract defaultColor(0.5, 0.5, 0.5);
+const float      defaultAlpha = 1.0; // Opaque
+const HwcTestDim defaultSourceDim(1, 1);
+const struct hwc_rect defaultSourceCrop = {0, 0, 1, 1};
+const struct hwc_rect defaultDisplayFrame = {0, 0, 100, 100};
+
+// Global Constants
+const uint32_t printFieldWidth = 2;
+const struct searchLimits {
+    uint32_t   numOverlays;
+    HwcTestDim sourceCrop;
+} searchLimits = {
+    10,
+    HwcTestDim(3000, 2000),
+};
+const struct transformType {
+    const char *desc;
+    uint32_t id;
+} transformType[] = {
+    {"fliph",  HWC_TRANSFORM_FLIP_H},
+    {"flipv",  HWC_TRANSFORM_FLIP_V},
+    {"rot90",  HWC_TRANSFORM_ROT_90},
+    {"rot180", HWC_TRANSFORM_ROT_180},
+    {"rot270", HWC_TRANSFORM_ROT_270},
+};
+const struct blendType {
+    const char *desc;
+    uint32_t id;
+} blendType[] = {
+    {"none", HWC_BLENDING_NONE},
+    {"premult", HWC_BLENDING_PREMULT},
+    {"coverage", HWC_BLENDING_COVERAGE},
+};
+
+// Defines
+#define MAXCMD               200
+#define CMD_STOP_FRAMEWORK   "stop 2>&1"
+#define CMD_START_FRAMEWORK  "start 2>&1"
+
+// Macros
+#define NUMA(a) (sizeof(a) / sizeof(a [0])) // Num elements in an array
+
+// Local types
+class Rectangle {
+public:
+    Rectangle(uint32_t graphicFormat = defaultFormat,
+              HwcTestDim dfDim = HwcTestDim(1, 1),
+              HwcTestDim sDim = HwcTestDim(1, 1));
+    void setSourceDim(HwcTestDim dim);
+
+    uint32_t     format;
+    uint32_t     transform;
+    int32_t      blend;
+    ColorFract   color;
+    float        alpha;
+    HwcTestDim   sourceDim;
+    struct hwc_rect   sourceCrop;
+    struct hwc_rect   displayFrame;
+};
+
+class Range {
+public:
+    Range(void) : _l(0), _u(0) {}
+    Range(uint32_t lower, uint32_t upper) : _l(lower), _u(upper) {}
+    uint32_t lower(void) { return _l; }
+    uint32_t upper(void) { return _u; }
+
+    operator string();
+
+private:
+    uint32_t _l; // lower
+    uint32_t _u; // upper
+};
+
+Range::operator string()
+{
+    ostringstream out;
+
+    out << '[' << _l << ", " << _u << ']';
+
+    return out.str();
+}
+
+class Rational {
+public:
+    Rational(void) : _n(0), _d(1) {}
+    Rational(uint32_t n, uint32_t d) : _n(n), _d(d) {}
+    uint32_t numerator(void) { return _n; }
+    uint32_t denominator(void) { return _d; }
+    void setNumerator(uint32_t numerator) { _n = numerator; }
+
+    bool operator==(const Rational& other) const;
+    bool operator!=(const Rational& other) const { return !(*this == other); }
+    bool operator<(const Rational& other) const;
+    bool operator>(const Rational& other) const {
+        return (!(*this == other) && !(*this < other));
+    }
+    static void double2Rational(double f, Range nRange, Range dRange,
+                               Rational& lower, Rational& upper);
+        
+    operator string() const;
+    operator double() const { return (double) _n / (double) _d; }
+
+
+private:
+    uint32_t _n;
+    uint32_t _d;
+};
+
+// Globals
+static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
+        GraphicBuffer::USAGE_SW_WRITE_RARELY;
+static hwc_composer_device_t *hwcDevice;
+static EGLDisplay dpy;
+static EGLSurface surface;
+static EGLint width, height;
+static size_t maxHeadingLen;
+static vector<string> formats;
+
+// Measurements
+struct meas {
+    uint32_t format;
+    uint32_t startDimOverlays;
+    uint32_t maxNonOverlapping;
+    uint32_t maxOverlapping;
+    list<uint32_t> transforms;
+    list<uint32_t> blends;
+    struct displayFrame {
+        uint32_t minWidth;
+        uint32_t minHeight;
+        HwcTestDim minDim;
+        uint32_t maxWidth;
+        uint32_t maxHeight;
+        HwcTestDim maxDim;
+    } df;
+    struct sourceCrop {
+        uint32_t minWidth;
+        uint32_t minHeight;
+        HwcTestDim minDim;
+        uint32_t maxWidth;
+        uint32_t maxHeight;
+        HwcTestDim maxDim;
+        Rational hScale;
+        HwcTestDim hScaleBestDf;
+        HwcTestDim hScaleBestSc;
+        Rational vScale;
+        HwcTestDim vScaleBestDf;
+        HwcTestDim vScaleBestSc;
+    } sc;
+    vector<uint32_t> overlapBlendNone;
+    vector<uint32_t> overlapBlendPremult;
+    vector<uint32_t> overlapBlendCoverage;
+};
+vector<meas> measurements;
+
+// Function prototypes
+uint32_t numOverlays(list<Rectangle>& rectList);
+uint32_t maxOverlays(uint32_t format, bool allowOverlap);
+list<uint32_t> supportedTransforms(uint32_t format);
+list<uint32_t> supportedBlends(uint32_t format);
+uint32_t dfMinWidth(uint32_t format);
+uint32_t dfMinHeight(uint32_t format);
+uint32_t dfMaxWidth(uint32_t format);
+uint32_t dfMaxHeight(uint32_t format);
+HwcTestDim dfMinDim(uint32_t format);
+HwcTestDim dfMaxDim(uint32_t format);
+uint32_t scMinWidth(uint32_t format, const HwcTestDim& dfDim);
+uint32_t scMinHeight(uint32_t format, const HwcTestDim& dfDim);
+uint32_t scMaxWidth(uint32_t format, const HwcTestDim& dfDim);
+uint32_t scMaxHeight(uint32_t format, const HwcTestDim& dfDim);
+HwcTestDim scMinDim(uint32_t format, const HwcTestDim& dfDim);
+HwcTestDim scMaxDim(uint32_t format, const HwcTestDim& dfDim);
+Rational scHScale(uint32_t format,
+                  const HwcTestDim& dfMin, const HwcTestDim& dfMax,
+                  const HwcTestDim& scMin, const HwcTestDim& scMax,
+                  HwcTestDim& outBestDf, HwcTestDim& outBestSc);
+Rational scVScale(uint32_t format,
+                  const HwcTestDim& dfMin, const HwcTestDim& dfMax,
+                  const HwcTestDim& scMin, const HwcTestDim& scMax,
+                  HwcTestDim& outBestDf, HwcTestDim& outBestSc);
+uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat,
+                        uint32_t backgroundBlend, uint32_t foregroundBlend);
+string transformList2str(const list<uint32_t>& transformList);
+string blendList2str(const list<uint32_t>& blendList);
+void init(void);
+void printFormatHeadings(size_t indent);
+void printOverlapLine(size_t indent, const string formatStr,
+                      const vector<uint32_t>& results);
+void printSyntax(const char *cmd);
+
+// Command-line option settings
+static bool verbose = defaultVerbose;
+static HwcTestDim startDim = defaultStartDim;
+
+/*
+ * Main
+ *
+ * Performs the following high-level sequence of operations:
+ *
+ *   1. Command-line parsing
+ *
+ *   2. Form a list of command-line specified graphic formats.  If
+ *      no formats are specified, then form a list of all known formats.
+ *
+ *   3. Stop framework
+ *      Only one user at a time is allowed to use the HWC.  Surface
+ *      Flinger uses the HWC and is part of the framework.  Need to
+ *      stop the framework so that Surface Flinger will stop using
+ *      the HWC.
+ *   
+ *   4. Initialization
+ *
+ *   5. For each graphic format in the previously formed list perform
+ *      measurements on that format and report the results.
+ *
+ *   6. Start framework
+ */
+int
+main(int argc, char *argv[])
+{
+    int     rv, opt;
+    char   *chptr;
+    bool    error;
+    string  str;
+    char cmd[MAXCMD];
+    list<Rectangle> rectList;
+
+    testSetLogCatTag(LOG_TAG);
+
+    // Parse command line arguments
+    while ((opt = getopt(argc, argv, "s:v?h")) != -1) {
+        switch (opt) {
+
+          case 's': // Start Dimension
+            // Use arguments until next starts with a dash
+            // or current ends with a > or ]
+            str = optarg;
+            while (optind < argc) {
+                if (*argv[optind] == '-') { break; }
+                char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
+                if ((endChar == '>') || (endChar == ']')) { break; }
+                str += " " + string(argv[optind++]);
+            }
+            {
+                istringstream in(str);
+                startDim = hwcTestParseDim(in, error);
+                // Any parse error or characters not used by parser
+                if (error
+                    || (((unsigned int) in.tellg() != in.str().length())
+                        && (in.tellg() != (streampos) -1))) {
+                    testPrintE("Invalid command-line specified start "
+                               "dimension of: %s", str.c_str());
+                    exit(8);
+                }
+            }
+            break;
+
+          case 'v': // Verbose
+            verbose = true;
+            break;
+
+          case 'h': // Help
+          case '?':
+          default:
+            printSyntax(basename(argv[0]));
+            exit(((optopt == 0) || (optopt == '?')) ? 0 : 11);
+        }
+    }
+
+    // Positional parameters
+    // Positional parameters provide the names of graphic formats that
+    // measurements are to be made on.  Measurements are made on all
+    // known graphic formats when no positional parameters are provided.
+    if (optind == argc) {
+        // No command-line specified graphic formats
+        // Add all graphic formats to the list of formats to be measured
+        for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+            formats.push_back(hwcTestGraphicFormat[n1].desc);
+        }
+    } else {
+        // Add names of command-line specified graphic formats to the
+        // list of formats to be tested
+        for (; argv[optind] != NULL; optind++) {
+            formats.push_back(argv[optind]);
+        }
+    }
+
+    // Determine length of longest specified graphic format.
+    // This value is used for output formating
+    for (vector<string>::iterator it = formats.begin();
+         it != formats.end(); ++it) {
+         maxHeadingLen = max(maxHeadingLen, it->length());
+    }
+
+    // Stop framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
+        exit(14);
+    }
+    testExecCmd(cmd);
+    testDelay(1.0); // TODO - needs means to query whether asynchronous stop
+                    // framework operation has completed.  For now, just wait
+                    // a long time.
+
+    testPrintI("startDim: %s", ((string) startDim).c_str());
+
+    init();
+
+    // For each of the graphic formats
+    for (vector<string>::iterator itFormat = formats.begin();
+         itFormat != formats.end(); ++itFormat) {
+
+        // Locate hwcTestLib structure that describes this format
+        const struct hwcTestGraphicFormat *format;
+        format = hwcTestGraphicFormatLookup((*itFormat).c_str());
+        if (format == NULL) {
+            testPrintE("Unknown graphic format of: %s", (*itFormat).c_str());
+            exit(1);
+        }
+
+        // Display format header
+        testPrintI("format: %s", format->desc);
+
+        // Create area to hold the measurements
+        struct meas meas;
+        struct meas *measPtr;
+        meas.format = format->format;
+        measurements.push_back(meas);
+        measPtr = &measurements[measurements.size() - 1];
+
+        // Start dimension num overlays
+        Rectangle rect(format->format, startDim);
+        rectList.clear();
+        rectList.push_back(rect);
+        measPtr->startDimOverlays = numOverlays(rectList);
+        testPrintI("  startDimOverlays: %u", measPtr->startDimOverlays);
+
+        // Skip the rest of the measurements, when the start dimension
+        // doesn't produce an overlay
+        if (measPtr->startDimOverlays == 0) { continue; }
+
+        // Max Overlays
+        measPtr->maxNonOverlapping = maxOverlays(format->format, false);
+        testPrintI("  max nonOverlapping overlays: %s%u",
+                   (measPtr->maxNonOverlapping == searchLimits.numOverlays)
+                       ? ">= " : "",
+                   measPtr->maxNonOverlapping);
+        measPtr->maxOverlapping = maxOverlays(format->format, true);
+        testPrintI("  max Overlapping overlays: %s%u",
+                   (measPtr->maxOverlapping == searchLimits.numOverlays)
+                       ? ">= " : "",
+                   measPtr->maxOverlapping);
+
+        // Transforms and blends
+        measPtr->transforms = supportedTransforms(format->format);
+        testPrintI("  transforms: %s",
+                   transformList2str(measPtr->transforms).c_str());
+        measPtr->blends = supportedBlends(format->format);
+        testPrintI("  blends: %s",
+                   blendList2str(measPtr->blends).c_str());
+
+        // Display frame measurements
+        measPtr->df.minWidth = dfMinWidth(format->format);
+        testPrintI("  dfMinWidth: %u", measPtr->df.minWidth);
+
+        measPtr->df.minHeight = dfMinHeight(format->format);
+        testPrintI("  dfMinHeight: %u", measPtr->df.minHeight);
+
+        measPtr->df.maxWidth = dfMaxWidth(format->format);
+        testPrintI("  dfMaxWidth: %u", measPtr->df.maxWidth);
+
+        measPtr->df.maxHeight = dfMaxHeight(format->format);
+        testPrintI("  dfMaxHeight: %u", measPtr->df.maxHeight);
+
+        measPtr->df.minDim = dfMinDim(format->format);
+        testPrintI("  dfMinDim: %s", ((string) measPtr->df.minDim).c_str());
+
+        measPtr->df.maxDim = dfMaxDim(format->format);
+        testPrintI("  dfMaxDim: %s", ((string) measPtr->df.maxDim).c_str());
+
+        // Source crop measurements
+        measPtr->sc.minWidth = scMinWidth(format->format, measPtr->df.minDim);
+        testPrintI("  scMinWidth: %u", measPtr->sc.minWidth);
+
+        measPtr->sc.minHeight = scMinHeight(format->format, measPtr->df.minDim);
+        testPrintI("  scMinHeight: %u", measPtr->sc.minHeight);
+
+        measPtr->sc.maxWidth = scMaxWidth(format->format, measPtr->df.maxDim);
+        testPrintI("  scMaxWidth: %s%u", (measPtr->sc.maxWidth
+                   == searchLimits.sourceCrop.width()) ? ">= " : "",
+                   measPtr->sc.maxWidth);
+
+        measPtr->sc.maxHeight = scMaxHeight(format->format, measPtr->df.maxDim);
+        testPrintI("  scMaxHeight: %s%u", (measPtr->sc.maxHeight
+                   == searchLimits.sourceCrop.height()) ? ">= " : "",
+                   measPtr->sc.maxHeight);
+
+        measPtr->sc.minDim = scMinDim(format->format, measPtr->df.minDim);
+        testPrintI("  scMinDim: %s", ((string) measPtr->sc.minDim).c_str());
+
+        measPtr->sc.maxDim = scMaxDim(format->format, measPtr->df.maxDim);
+        testPrintI("  scMaxDim: %s%s", ((measPtr->sc.maxDim.width()
+                         >= searchLimits.sourceCrop.width())
+                         || (measPtr->sc.maxDim.width() >=
+                         searchLimits.sourceCrop.height())) ? ">= " : "",
+                   ((string) measPtr->sc.maxDim).c_str());
+
+        measPtr->sc.hScale = scHScale(format->format,
+                                      measPtr->df.minDim, measPtr->df.maxDim,
+                                      measPtr->sc.minDim, measPtr->sc.maxDim,
+                                      measPtr->sc.hScaleBestDf,
+                                      measPtr->sc.hScaleBestSc);
+        testPrintI("  scHScale: %s%f",
+                   (measPtr->sc.hScale
+                       >= Rational(searchLimits.sourceCrop.width(),
+                                   measPtr->df.minDim.width())) ? ">= " : "",
+                   (double) measPtr->sc.hScale);
+        testPrintI("    HScale Best Display Frame: %s",
+                   ((string) measPtr->sc.hScaleBestDf).c_str());
+        testPrintI("    HScale Best Source Crop: %s",
+                   ((string) measPtr->sc.hScaleBestSc).c_str());
+
+        measPtr->sc.vScale = scVScale(format->format,
+                                      measPtr->df.minDim, measPtr->df.maxDim,
+                                      measPtr->sc.minDim, measPtr->sc.maxDim,
+                                      measPtr->sc.vScaleBestDf,
+                                      measPtr->sc.vScaleBestSc);
+        testPrintI("  scVScale: %s%f",
+                   (measPtr->sc.vScale
+                       >= Rational(searchLimits.sourceCrop.height(),
+                                   measPtr->df.minDim.height())) ? ">= " : "",
+                   (double) measPtr->sc.vScale);
+        testPrintI("    VScale Best Display Frame: %s",
+                   ((string) measPtr->sc.vScaleBestDf).c_str());
+        testPrintI("    VScale Best Source Crop: %s",
+                   ((string) measPtr->sc.vScaleBestSc).c_str());
+
+        // Overlap two graphic formats and different blends
+        // Results displayed after all overlap measurments with
+        // current format in the foreground
+        // TODO: make measurments with background blend other than
+        //       none.  All of these measurements are done with a
+        //       background blend of HWC_BLENDING_NONE, with the
+        //       blend type of the foregound being varied.
+        uint32_t foregroundFormat = format->format;
+        for (vector<string>::iterator it = formats.begin();
+             it != formats.end(); ++it) {
+            uint32_t num;
+
+            const struct hwcTestGraphicFormat *backgroundFormatPtr
+                = hwcTestGraphicFormatLookup((*it).c_str());
+            uint32_t backgroundFormat = backgroundFormatPtr->format;
+
+            num = numOverlapping(backgroundFormat, foregroundFormat,
+                                 HWC_BLENDING_NONE, HWC_BLENDING_NONE);
+            measPtr->overlapBlendNone.push_back(num);
+
+            num = numOverlapping(backgroundFormat, foregroundFormat,
+                                 HWC_BLENDING_NONE, HWC_BLENDING_PREMULT);
+            measPtr->overlapBlendPremult.push_back(num);
+
+            num = numOverlapping(backgroundFormat, foregroundFormat,
+                                 HWC_BLENDING_NONE, HWC_BLENDING_COVERAGE);
+            measPtr->overlapBlendCoverage.push_back(num);
+        }
+
+    }
+
+    // Display overlap results
+    size_t indent = 2;
+    testPrintI("overlapping blend: none");
+    printFormatHeadings(indent);
+    for (vector<string>::iterator it = formats.begin();
+         it != formats.end(); ++it) {
+        printOverlapLine(indent, *it, measurements[it
+                         - formats.begin()].overlapBlendNone);
+    }
+    testPrintI("");
+
+    testPrintI("overlapping blend: premult");
+    printFormatHeadings(indent);
+    for (vector<string>::iterator it = formats.begin();
+         it != formats.end(); ++it) {
+        printOverlapLine(indent, *it, measurements[it
+                         - formats.begin()].overlapBlendPremult);
+    }
+    testPrintI("");
+
+    testPrintI("overlapping blend: coverage");
+    printFormatHeadings(indent);
+    for (vector<string>::iterator it = formats.begin();
+         it != formats.end(); ++it) {
+        printOverlapLine(indent, *it, measurements[it
+                         - formats.begin()].overlapBlendCoverage);
+    }
+    testPrintI("");
+
+    // Start framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
+        exit(21);
+    }
+    testExecCmd(cmd);
+
+    return 0;
+}
+
+// Determine the maximum number of overlays that are all of the same format
+// that the HWC will commit to.  If allowOverlap is true, then the rectangles
+// are laid out on a diagonal starting from the upper left corner.  With
+// each rectangle adjust one pixel to the right and one pixel down.
+// When allowOverlap is false, the rectangles are tiled in column major
+// order.  Note, column major ordering is used so that the initial rectangles
+// are all on different horizontal scan rows.  It is common that hardware
+// has limits on the number of objects it can handle on any single row.
+uint32_t maxOverlays(uint32_t format, bool allowOverlap)
+{
+    unsigned int max = 0;
+
+    for (unsigned int numRects = 1; numRects <= searchLimits.numOverlays;
+         numRects++) {
+        list<Rectangle> rectList;
+
+        for (unsigned int x = 0;
+             (x + startDim.width()) < (unsigned int) width;
+             x += (allowOverlap) ? 1 : startDim.width()) {
+            for (unsigned int y = 0;
+                 (y + startDim.height()) < (unsigned int) height;
+                 y += (allowOverlap) ? 1 : startDim.height()) {
+                Rectangle rect(format, startDim, startDim);
+                rect.displayFrame.left = x;
+                rect.displayFrame.top = y;
+                rect.displayFrame.right = x + startDim.width();
+                rect.displayFrame.bottom = y + startDim.height();
+
+                rectList.push_back(rect);
+
+                if (rectList.size() >= numRects) { break; }
+            }
+            if (rectList.size() >= numRects) { break; }
+        }
+
+        uint32_t num = numOverlays(rectList);
+        if (num > max) { max = num; }
+    }
+
+    return max;
+}
+
+// Measures what transforms (i.e. flip horizontal, rotate 180) are
+// supported by the specified format
+list<uint32_t> supportedTransforms(uint32_t format)
+{
+    list<uint32_t> rv;
+    list<Rectangle> rectList;
+    Rectangle rect(format, startDim);
+
+    // For each of the transform types
+    for (unsigned int idx = 0; idx < NUMA(transformType); idx++) {
+        unsigned int id = transformType[idx].id;
+
+        rect.transform = id;
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+
+        if (num == 1) {
+            rv.push_back(id);
+        }
+    }
+
+    return rv;
+}
+
+// Determines which types of blends (i.e. none, premult, coverage) are
+// supported by the specified format
+list<uint32_t> supportedBlends(uint32_t format)
+{
+    list<uint32_t> rv;
+    list<Rectangle> rectList;
+    Rectangle rect(format, startDim);
+
+    // For each of the blend types
+    for (unsigned int idx = 0; idx < NUMA(blendType); idx++) {
+        unsigned int id = blendType[idx].id;
+
+        rect.blend = id;
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+
+        if (num == 1) {
+            rv.push_back(id);
+        }
+    }
+
+    return rv;
+}
+
+// Determines the minimum width of any display frame of the given format
+// that the HWC will commit to.
+uint32_t dfMinWidth(uint32_t format)
+{
+    uint32_t w;
+    list<Rectangle> rectList;
+
+    for (w = 1; w <= startDim.width(); w++) {
+        HwcTestDim dim(w, startDim.height());
+        Rectangle rect(format, dim);
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return w;
+        }
+    }
+    if (w > startDim.width()) {
+        testPrintE("Failed to locate display frame min width");
+        exit(33);
+    }
+
+    return w;
+}
+
+// Display frame minimum height
+uint32_t dfMinHeight(uint32_t format)
+{
+    uint32_t h;
+    list<Rectangle> rectList;
+
+    for (h = 1; h <= startDim.height(); h++) {
+        HwcTestDim dim(startDim.width(), h);
+        Rectangle rect(format, dim);
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return h;
+        }
+    }
+    if (h > startDim.height()) {
+        testPrintE("Failed to locate display frame min height");
+        exit(34);
+    }
+
+    return h;
+}
+
+// Display frame maximum width
+uint32_t dfMaxWidth(uint32_t format)
+{
+    uint32_t w;
+    list<Rectangle> rectList;
+
+    for (w = width; w >= startDim.width(); w--) {
+        HwcTestDim dim(w, startDim.height());
+        Rectangle rect(format, dim);
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return w;
+        }
+    }
+    if (w < startDim.width()) {
+        testPrintE("Failed to locate display frame max width");
+        exit(35);
+    }
+
+    return w;
+}
+
+// Display frame maximum height
+uint32_t dfMaxHeight(uint32_t format)
+{
+    uint32_t h;
+
+    for (h = height; h >= startDim.height(); h--) {
+        HwcTestDim dim(startDim.width(), h);
+        Rectangle rect(format, dim);
+        list<Rectangle> rectList;
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return h;
+        }
+    }
+    if (h < startDim.height()) {
+        testPrintE("Failed to locate display frame max height");
+        exit(36);
+    }
+
+    return h;
+}
+
+// Determine the minimum number of pixels that the HWC will ever commit to.
+// Note, this might be different that dfMinWidth * dfMinHeight, in that this
+// function adjusts both the width and height from the starting dimension.
+HwcTestDim dfMinDim(uint32_t format)
+{
+    uint64_t bestMinPixels = 0;
+    HwcTestDim bestDim;
+    bool bestSet = false; // True when value has been assigned to
+                          // bestMinPixels and bestDim
+
+    bool origVerbose = verbose;  // Temporarily turn off verbose
+    verbose = false;
+    for (uint32_t w = 1; w <= startDim.width(); w++) {
+        for (uint32_t h = 1; h <= startDim.height(); h++) {
+            if (bestSet && ((w > bestMinPixels) || (h > bestMinPixels))) {
+                break;
+            }
+
+            HwcTestDim dim(w, h);
+            Rectangle rect(format, dim);
+            list<Rectangle> rectList;
+            rectList.push_back(rect);
+            uint32_t num = numOverlays(rectList);
+            if (num > 0) {
+                uint64_t pixels = dim.width() * dim.height();
+                if (!bestSet || (pixels < bestMinPixels)) {
+                    bestMinPixels = pixels;
+                    bestDim = dim;
+                    bestSet = true;
+                }
+            }
+        }
+    }
+    verbose = origVerbose;
+
+    if (!bestSet) {
+        testPrintE("Unable to locate display frame min dimension");
+        exit(20);
+    }
+
+    return bestDim;
+}
+
+// Display frame maximum dimension
+HwcTestDim dfMaxDim(uint32_t format)
+{
+    uint64_t bestMaxPixels = 0;
+    HwcTestDim bestDim;
+    bool bestSet = false; // True when value has been assigned to
+                          // bestMaxPixels and bestDim;
+
+    // Potentially increase benchmark performance by first checking
+    // for the common case of supporting a full display frame.
+    HwcTestDim dim(width, height);
+    Rectangle rect(format, dim);
+    list<Rectangle> rectList;
+    rectList.push_back(rect);
+    uint32_t num = numOverlays(rectList);
+    if (num == 1) { return dim; }
+
+    // TODO: Use a binary search
+    bool origVerbose = verbose;  // Temporarily turn off verbose
+    verbose = false;
+    for (uint32_t w = startDim.width(); w <= (uint32_t) width; w++) {
+        for (uint32_t h = startDim.height(); h <= (uint32_t) height; h++) {
+            if (bestSet && ((w * h) <= bestMaxPixels)) { continue; }
+
+            HwcTestDim dim(w, h);
+            Rectangle rect(format, dim);
+            list<Rectangle> rectList;
+            rectList.push_back(rect);
+            uint32_t num = numOverlays(rectList);
+            if (num > 0) {
+                uint64_t pixels = dim.width() * dim.height();
+                if (!bestSet || (pixels > bestMaxPixels)) {
+                    bestMaxPixels = pixels;
+                    bestDim = dim;
+                    bestSet = true;
+                }
+            }
+        }
+    }
+    verbose = origVerbose;
+
+    if (!bestSet) {
+        testPrintE("Unable to locate display frame max dimension");
+        exit(21);
+    }
+
+    return bestDim;
+}
+
+// Source crop minimum width
+uint32_t scMinWidth(uint32_t format, const HwcTestDim& dfDim)
+{
+    uint32_t w;
+    list<Rectangle> rectList;
+
+    // Source crop frame min width
+    for (w = 1; w <= dfDim.width(); w++) {
+        Rectangle rect(format, dfDim, HwcTestDim(w, dfDim.height()));
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return w;
+        }
+    }
+    testPrintE("Failed to locate source crop min width");
+    exit(35);
+}
+
+// Source crop minimum height
+uint32_t scMinHeight(uint32_t format, const HwcTestDim& dfDim)
+{
+    uint32_t h;
+    list<Rectangle> rectList;
+
+    for (h = 1; h <= dfDim.height(); h++) {
+        Rectangle rect(format, dfDim, HwcTestDim(dfDim.width(), h));
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return h;
+        }
+    }
+    testPrintE("Failed to locate source crop min height");
+    exit(36);
+}
+
+// Source crop maximum width
+uint32_t scMaxWidth(uint32_t format, const HwcTestDim& dfDim)
+{
+    uint32_t w;
+    list<Rectangle> rectList;
+
+    for (w = searchLimits.sourceCrop.width(); w >= dfDim.width(); w--) {
+        Rectangle rect(format, dfDim, HwcTestDim(w, dfDim.height()));
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return w;
+        }
+    }
+    testPrintE("Failed to locate source crop max width");
+    exit(35);
+}
+
+// Source crop maximum height
+uint32_t scMaxHeight(uint32_t format, const HwcTestDim& dfDim)
+{
+    uint32_t h;
+    list<Rectangle> rectList;
+
+    for (h = searchLimits.sourceCrop.height(); h >= dfDim.height(); h--) {
+        Rectangle rect(format, dfDim, HwcTestDim(dfDim.width(), h));
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return h;
+        }
+    }
+    testPrintE("Failed to locate source crop max height");
+    exit(36);
+}
+
+// Source crop minimum dimension
+// Discovers the source crop with the least number of pixels that the
+// HWC will commit to.  Note, this may be different from scMinWidth
+// * scMinHeight, in that this function searches for a combination of
+// width and height.  While the other routines always keep one of the
+// dimensions equal to the corresponding start dimension.
+HwcTestDim scMinDim(uint32_t format, const HwcTestDim& dfDim)
+{
+    uint64_t bestMinPixels = 0;
+    HwcTestDim bestDim;
+    bool bestSet = false; // True when value has been assigned to
+                          // bestMinPixels and bestDim
+
+    bool origVerbose = verbose;  // Temporarily turn off verbose
+    verbose = false;
+    for (uint32_t w = 1; w <= dfDim.width(); w++) {
+        for (uint32_t h = 1; h <= dfDim.height(); h++) {
+            if (bestSet && ((w > bestMinPixels) || (h > bestMinPixels))) {
+                break;
+            }
+
+            HwcTestDim dim(w, h);
+            Rectangle rect(format, dfDim, HwcTestDim(w, h));
+            list<Rectangle> rectList;
+            rectList.push_back(rect);
+            uint32_t num = numOverlays(rectList);
+            if (num > 0) {
+                uint64_t pixels = dim.width() * dim.height();
+                if (!bestSet || (pixels < bestMinPixels)) {
+                    bestMinPixels = pixels;
+                    bestDim = dim;
+                    bestSet = true;
+                }
+            }
+        }
+    }
+    verbose = origVerbose;
+
+    if (!bestSet) {
+        testPrintE("Unable to locate source crop min dimension");
+        exit(20);
+    }
+
+    return bestDim;
+}
+
+// Source crop maximum dimension
+HwcTestDim scMaxDim(uint32_t format, const HwcTestDim& dfDim)
+{
+    uint64_t bestMaxPixels = 0;
+    HwcTestDim bestDim;
+    bool bestSet = false; // True when value has been assigned to
+                          // bestMaxPixels and bestDim;
+
+    // Potentially increase benchmark performance by first checking
+    // for the common case of supporting the maximum checked source size
+    HwcTestDim dim = searchLimits.sourceCrop;
+    Rectangle rect(format, dfDim, searchLimits.sourceCrop);
+    list<Rectangle> rectList;
+    rectList.push_back(rect);
+    uint32_t num = numOverlays(rectList);
+    if (num == 1) { return dim; }
+
+    // TODO: Use a binary search
+    bool origVerbose = verbose;  // Temporarily turn off verbose
+    verbose = false;
+    for (uint32_t w = dfDim.width();
+         w <= searchLimits.sourceCrop.width(); w++) {
+        for (uint32_t h = dfDim.height();
+             h <= searchLimits.sourceCrop.height(); h++) {
+            if (bestSet && ((w * h) <= bestMaxPixels)) { continue; }
+
+            HwcTestDim dim(w, h);
+            Rectangle rect(format, dfDim, dim);
+            list<Rectangle> rectList;
+            rectList.push_back(rect);
+            uint32_t num = numOverlays(rectList);
+            if (num > 0) {
+                uint64_t pixels = dim.width() * dim.height();
+                if (!bestSet || (pixels > bestMaxPixels)) {
+                    bestMaxPixels = pixels;
+                    bestDim = dim;
+                    bestSet = true;
+                }
+            }
+        }
+    }
+    verbose = origVerbose;
+
+    if (!bestSet) {
+        testPrintE("Unable to locate source crop max dimension");
+        exit(21);
+    }
+
+    return bestDim;
+}
+
+// Source crop horizontal scale
+// Determines the maximum factor by which the source crop can be larger
+// that the display frame.  The commit point is discovered through a
+// binary search of rational numbers.  The numerator in each of the
+// rational numbers contains the dimension for the source crop, while
+// the denominator specifies the dimension for the display frame.  On
+// each pass of the binary search the mid-point between the greatest
+// point committed to (best) and the smallest point in which a commit
+// has failed is calculated.  This mid-point is then passed to a function
+// named double2Rational, which determines the closest rational numbers
+// just below and above the mid-point.  By default the lower rational
+// number is used for the scale factor on the next pass of the binary
+// search.  The upper value is only used when best is already equal
+// to the lower value.  This only occurs when the lower value has already
+// been tried.
+Rational scHScale(uint32_t format,
+                      const HwcTestDim& dfMin, const HwcTestDim& dfMax,
+                      const HwcTestDim& scMin, const HwcTestDim& scMax,
+                      HwcTestDim& outBestDf, HwcTestDim& outBestSc)
+{
+    HwcTestDim scDim, dfDim; // Source crop and display frame dimension
+    Rational best(0, 1), minBad;  // Current bounds for a binary search
+                                  // MinGood is set below the lowest
+                                  // possible scale.  The value of minBad,
+                                  // will be set by the first pass
+                                  // of the binary search.
+
+    // Perform the passes of the binary search
+    bool firstPass = true;
+    do {
+        // On first pass try the maximum scale within the search limits
+        if (firstPass) {
+            // Try the maximum possible scale, within the search limits
+            scDim = HwcTestDim(searchLimits.sourceCrop.width(), scMin.height());
+            dfDim = dfMin;
+        } else {
+            // Subsequent pass
+            // Halve the difference between best and minBad.
+            Rational lower, upper, selected;
+
+            // Try the closest ratio halfway between minBood and minBad;
+            // TODO: Avoid rounding issue by using Rational type for
+            //       midpoint.  For now will use double, which should
+            //       have more than sufficient resolution.
+            double mid = (double) best
+                         + ((double) minBad - (double) best) / 2.0;
+            Rational::double2Rational(mid,
+                            Range(scMin.width(), scMax.width()),
+                            Range(dfMin.width(), dfMax.width()),
+                            lower, upper);
+            if (((lower == best) && (upper == minBad))) {
+                return best;
+            }
+
+            // Use lower value unless its already been tried
+            selected = (lower != best) ? lower : upper;
+
+            // Assign the size of the source crop and display frame
+            // from the selected ratio of source crop to display frame.
+            scDim = HwcTestDim(selected.numerator(), scMin.height());
+            dfDim = HwcTestDim(selected.denominator(), dfMin.height());
+        }
+
+        // See if the HWC will commit to this combination
+        Rectangle rect(format, dfDim, scDim);
+        list<Rectangle> rectList;
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+
+        if (verbose) {
+            testPrintI("  scHscale num: %u scale: %f dfDim: %s scDim: %s",
+                       num, (float) Rational(scDim.width(), dfDim.width()),
+                       ((string) dfDim).c_str(), ((string) scDim).c_str());
+        }
+        if (num == 1) {
+            // HWC committed to the combination
+            // This is the best scale factor seen so far.  Report the
+            // dimensions to the caller, in case nothing better is seen.
+            outBestDf = dfDim;
+            outBestSc = scDim;
+
+            // Success on the first pass means the largest possible scale
+            // is supported, in which case no need to search any further.
+            if (firstPass) { return Rational(scDim.width(), dfDim.width()); }
+
+            // Update the lower bound of the binary search
+            best = Rational(scDim.width(), dfDim.width());
+        } else {
+            // HWC didn't commit to this combination, so update the
+            // upper bound of the binary search.
+            minBad = Rational(scDim.width(), dfDim.width());
+        }
+
+        firstPass = false;
+    } while (best != minBad);
+
+    return best;
+}
+
+// Source crop vertical scale
+// Determines the maximum factor by which the source crop can be larger
+// that the display frame.  The commit point is discovered through a
+// binary search of rational numbers.  The numerator in each of the
+// rational numbers contains the dimension for the source crop, while
+// the denominator specifies the dimension for the display frame.  On
+// each pass of the binary search the mid-point between the greatest
+// point committed to (best) and the smallest point in which a commit
+// has failed is calculated.  This mid-point is then passed to a function
+// named double2Rational, which determines the closest rational numbers
+// just below and above the mid-point.  By default the lower rational
+// number is used for the scale factor on the next pass of the binary
+// search.  The upper value is only used when best is already equal
+// to the lower value.  This only occurs when the lower value has already
+// been tried.
+Rational scVScale(uint32_t format,
+                      const HwcTestDim& dfMin, const HwcTestDim& dfMax,
+                      const HwcTestDim& scMin, const HwcTestDim& scMax,
+                      HwcTestDim& outBestDf, HwcTestDim& outBestSc)
+{
+    HwcTestDim scDim, dfDim; // Source crop and display frame dimension
+    Rational best(0, 1), minBad;  // Current bounds for a binary search
+                                  // MinGood is set below the lowest
+                                  // possible scale.  The value of minBad,
+                                  // will be set by the first pass
+                                  // of the binary search.
+
+    // Perform the passes of the binary search
+    bool firstPass = true;
+    do {
+        // On first pass try the maximum scale within the search limits
+        if (firstPass) {
+            // Try the maximum possible scale, within the search limits
+            scDim = HwcTestDim(scMin.width(), searchLimits.sourceCrop.height());
+            dfDim = dfMin;
+        } else {
+            // Subsequent pass
+            // Halve the difference between best and minBad.
+            Rational lower, upper, selected;
+
+            // Try the closest ratio halfway between minBood and minBad;
+            // TODO: Avoid rounding issue by using Rational type for
+            //       midpoint.  For now will use double, which should
+            //       have more than sufficient resolution.
+            double mid = (double) best
+                         + ((double) minBad - (double) best) / 2.0;
+            Rational::double2Rational(mid,
+                            Range(scMin.height(), scMax.height()),
+                            Range(dfMin.height(), dfMax.height()),
+                            lower, upper);
+            if (((lower == best) && (upper == minBad))) {
+                return best;
+            }
+
+            // Use lower value unless its already been tried
+            selected = (lower != best) ? lower : upper;
+
+            // Assign the size of the source crop and display frame
+            // from the selected ratio of source crop to display frame.
+            scDim = HwcTestDim(scMin.width(), selected.numerator());
+            dfDim = HwcTestDim(dfMin.width(), selected.denominator());
+        }
+
+        // See if the HWC will commit to this combination
+        Rectangle rect(format, dfDim, scDim);
+        list<Rectangle> rectList;
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+
+        if (verbose) {
+            testPrintI("  scHscale num: %u scale: %f dfDim: %s scDim: %s",
+                       num, (float) Rational(scDim.height(), dfDim.height()),
+                       ((string) dfDim).c_str(), ((string) scDim).c_str());
+        }
+        if (num == 1) {
+            // HWC committed to the combination
+            // This is the best scale factor seen so far.  Report the
+            // dimensions to the caller, in case nothing better is seen.
+            outBestDf = dfDim;
+            outBestSc = scDim;
+
+            // Success on the first pass means the largest possible scale
+            // is supported, in which case no need to search any further.
+            if (firstPass) { return Rational(scDim.height(), dfDim.height()); }
+
+            // Update the lower bound of the binary search
+            best = Rational(scDim.height(), dfDim.height());
+        } else {
+            // HWC didn't commit to this combination, so update the
+            // upper bound of the binary search.
+            minBad = Rational(scDim.height(), dfDim.height());
+        }
+
+        firstPass = false;
+    } while (best != minBad);
+
+    return best;
+}
+
+uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat,
+                        uint32_t backgroundBlend, uint32_t foregroundBlend)
+{
+    list<Rectangle> rectList;
+
+    Rectangle background(backgroundFormat, startDim, startDim);
+    background.blend = backgroundBlend;
+    rectList.push_back(background);
+
+    // TODO: Handle cases where startDim is so small that adding 5
+    //       causes frames not to overlap.
+    // TODO: Handle cases where startDim is so large that adding 5
+    //       cause a portion or all of the foreground displayFrame
+    //       to be off the display.
+    Rectangle foreground(foregroundFormat, startDim, startDim);
+    foreground.displayFrame.left += 5;
+    foreground.displayFrame.top += 5;
+    foreground.displayFrame.right += 5;
+    foreground.displayFrame.bottom += 5;
+    background.blend = foregroundBlend;
+    rectList.push_back(foreground);
+
+    uint32_t num = numOverlays(rectList);
+
+    return num;
+}
+
+Rectangle::Rectangle(uint32_t graphicFormat, HwcTestDim dfDim,
+                     HwcTestDim sDim) :
+    format(graphicFormat), transform(defaultTransform),
+    blend(defaultBlend), color(defaultColor), alpha(defaultAlpha),
+    sourceCrop(sDim), displayFrame(dfDim)
+{
+    // Set source dimension
+    // Can't use a base initializer, because the setting of format
+    // must be done before setting the sourceDimension.
+    setSourceDim(sDim);
+}
+
+void Rectangle::setSourceDim(HwcTestDim dim)
+{
+    this->sourceDim = dim;
+
+    const struct hwcTestGraphicFormat *attrib;
+    attrib = hwcTestGraphicFormatLookup(this->format);
+    if (attrib != NULL) {
+        if (sourceDim.width() % attrib->wMod) {
+            sourceDim.setWidth(sourceDim.width() + attrib->wMod
+            - (sourceDim.width() % attrib->wMod));
+        }
+        if (sourceDim.height() % attrib->hMod) {
+            sourceDim.setHeight(sourceDim.height() + attrib->hMod
+            - (sourceDim.height() % attrib->hMod));
+        }
+    }
+}
+
+// Rational member functions
+bool Rational::operator==(const Rational& other) const
+{
+    if (((uint64_t) _n * other._d)
+        == ((uint64_t) _d * other._n)) { return true; }
+
+    return false;
+}
+
+bool Rational::operator<(const Rational& other) const
+{
+    if (((uint64_t) _n * other._d)
+        < ((uint64_t) _d * other._n)) { return true; }
+
+    return false;
+}
+
+Rational::operator string() const
+{
+    ostringstream out;
+
+    out << _n << '/' << _d;
+
+    return out.str();
+}
+
+void Rational::double2Rational(double f, Range nRange, Range dRange,
+                    Rational& lower, Rational& upper)
+{
+    Rational bestLower(nRange.lower(), dRange.upper());
+    Rational bestUpper(nRange.upper(), dRange.lower());
+
+    // Search for a better solution
+    for (uint32_t d = dRange.lower(); d <= dRange.upper(); d++) {
+        Rational val(d * f, d);  // Lower, because double to int cast truncates
+
+        if ((val.numerator() < nRange.lower())
+            || (val.numerator() > nRange.upper())) { continue; }
+
+        if (((double) val > (double) bestLower) && ((double) val <= f)) {
+            bestLower = val;
+        } 
+
+        val.setNumerator(val.numerator() + 1);
+        if (val.numerator() > nRange.upper()) { continue; }
+
+        if (((double) val < (double) bestUpper) && ((double) val >= f)) {
+            bestUpper = val;
+        }
+    }
+
+    lower = bestLower;
+    upper = bestUpper;
+}
+
+// Local functions
+
+// Num Overlays
+// Given a list of rectangles, determine how many HWC will commit to render
+uint32_t numOverlays(list<Rectangle>& rectList)
+{
+    hwc_layer_list_t *hwcList;
+    list<sp<GraphicBuffer> > buffers;
+
+    hwcList = hwcTestCreateLayerList(rectList.size());
+    if (hwcList == NULL) {
+        testPrintE("numOverlays create hwcList failed");
+        exit(30);
+    }
+
+    hwc_layer_t *layer = &hwcList->hwLayers[0];
+    for (std::list<Rectangle>::iterator it = rectList.begin();
+         it != rectList.end(); ++it, ++layer) {
+        // Allocate the texture for the source frame
+        // and push it onto the buffers list, so that it
+        // stays in scope until a return from this function.
+        sp<GraphicBuffer> texture;
+        texture  = new GraphicBuffer(it->sourceDim.width(),
+                                     it->sourceDim.height(),
+                                     it->format, texUsage);
+        buffers.push_back(texture);
+
+        layer->handle = texture->handle;
+        layer->blending = it->blend;
+        layer->transform = it->transform;
+        layer->sourceCrop = it->sourceCrop;
+        layer->displayFrame = it->displayFrame;
+
+        layer->visibleRegionScreen.numRects = 1;
+        layer->visibleRegionScreen.rects = &layer->displayFrame;
+    }
+
+    // Perform prepare operation
+    if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(hwcList); }
+    hwcDevice->prepare(hwcDevice, hwcList);
+    if (verbose) {
+        testPrintI("Post Prepare:");
+        hwcTestDisplayListPrepareModifiable(hwcList);
+    }
+
+    // Count the number of overlays
+    uint32_t total = 0;
+    for (unsigned int n1 = 0; n1 < hwcList->numHwLayers; n1++) {
+        if (hwcList->hwLayers[n1].compositionType == HWC_OVERLAY) {
+            total++;
+        }
+    }
+
+    // Free the layer list and graphic buffers
+    hwcTestFreeLayerList(hwcList);
+
+    return total;
+}
+
+string transformList2str(const list<uint32_t>& transformList)
+{
+    ostringstream out;
+
+    for (list<uint32_t>::const_iterator it = transformList.begin();
+         it != transformList.end(); ++it) {
+        uint32_t id = *it;
+
+        if (it != transformList.begin()) {
+            out << ", ";
+        }
+        out << id;
+
+        for (unsigned int idx = 0; idx < NUMA(transformType); idx++) {
+            if (id == transformType[idx].id) {
+                out << " (" << transformType[idx].desc << ')';
+                break;
+            }
+        }
+    }
+
+    return out.str();
+}
+
+string blendList2str(const list<uint32_t>& blendList)
+{
+    ostringstream out;
+
+    for (list<uint32_t>::const_iterator it = blendList.begin();
+         it != blendList.end(); ++it) {
+        uint32_t id = *it;
+
+        if (it != blendList.begin()) {
+            out << ", ";
+        }
+        out << id;
+
+        for (unsigned int idx = 0; idx < NUMA(blendType); idx++) {
+            if (id == blendType[idx].id) {
+                out << " (" << blendType[idx].desc << ')';
+                break;
+            }
+        }
+    }
+
+    return out.str();
+}
+
+void init(void)
+{
+    srand48(0);
+
+    hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
+
+    hwcTestOpenHwc(&hwcDevice);
+}
+
+void printFormatHeadings(size_t indent)
+{
+    for (size_t row = 0; row <= maxHeadingLen; row++) {
+        ostringstream line;
+        for(vector<string>::iterator it = formats.begin();
+            it != formats.end(); ++it) {
+            if ((maxHeadingLen - row) <= it->length()) {
+                if (row != maxHeadingLen) {
+                    char ch = (*it)[it->length() - (maxHeadingLen - row)];
+                    line << ' ' << setw(printFieldWidth) << ch;
+                } else {
+                    line << ' ' << string(printFieldWidth, '-');
+                }
+            } else {
+               line << ' ' << setw(printFieldWidth) << "";
+            }
+        }
+        testPrintI("%*s%s", indent + maxHeadingLen, "",
+                   line.str().c_str());
+    }
+}
+
+void printOverlapLine(size_t indent, const string formatStr,
+                        const vector<uint32_t>& results)
+{
+    ostringstream line;
+
+    line << setw(indent + maxHeadingLen - formatStr.length()) << "";
+
+    line << formatStr;
+
+    for (vector<uint32_t>::const_iterator it = results.begin();
+         it != results.end(); ++it) {
+        line << ' ' << setw(printFieldWidth) << *it;
+    }
+
+    testPrintI("%s", line.str().c_str());
+}
+
+void printSyntax(const char *cmd)
+{
+    testPrintE("  %s [options] [graphicFormat] ...",
+               cmd);
+    testPrintE("    options:");
+    testPrintE("      -s [width, height] - start dimension");
+    testPrintE("      -v - Verbose");
+    testPrintE("");
+    testPrintE("    graphic formats:");
+    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+        testPrintE("      %s", hwcTestGraphicFormat[n1].desc);
+    }
+}
diff --git a/opengl/tests/hwc/hwcRects.cpp b/opengl/tests/hwc/hwcRects.cpp
new file mode 100644
index 0000000..523e3de
--- /dev/null
+++ b/opengl/tests/hwc/hwcRects.cpp
@@ -0,0 +1,577 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Hardware Composer Rectangles
+ *
+ * Synopsis
+ *   hwcRects [options] (graphicFormat displayFrame [attributes],)...
+ *     options:
+ *       -D #.## - End of test delay
+ *       -v - Verbose
+ *
+ *      graphic formats:
+ *        RGBA8888 (reference frame default)
+ *        RGBX8888
+ *        RGB888
+ *        RGB565
+ *        BGRA8888
+ *        RGBA5551
+ *        RGBA4444
+ *        YV12
+ *
+ *      displayFrame
+ *        [left, top, right, bottom]
+ *
+ *      attributes:
+ *        transform: none | fliph | flipv | rot90 | rot180 | rot270
+ *        blend: none | premult | coverage
+ *        color: [0.##, 0.##, 0.##]
+ *        alpha: 0.##
+ *        sourceDim: [width, height]
+ *        sourceCrop: [left, top, right, bottom]
+ *
+ *      Example:
+ *        # White YV12 rectangle, with overlapping turquoise
+ *        #  RGBA8888 rectangle at 30%% (alpha: 0.7) transparency
+ *        hwcRects -v -D 30.0 \
+ *          YV12 [50, 80, 200, 300] transform: none \
+ *            color: [1.0, 0.5, 0.5], \
+ *          RGBA8888 [100, 150, 300, 400] blend: coverage \
+ *            color: [0.251, 0.878, 0.816] alpha: 0.7 \
+ *            sourceDim: [50, 60] sourceCrop: [5, 8, 12, 15]
+ *
+ * Description
+ *   Constructs a Hardware Composer (HWC) list of frames from
+ *   command-line specified parameters.  Then sends it to the HWC
+ *   be rendered.  The intended purpose of this tool is as a means to
+ *   reproduce and succinctly specify an observed HWC operation, with
+ *   no need to modify/compile a program.
+ *
+ *   The command-line syntax consists of a few standard command-line
+ *   options and then a description of one or more frames.  The frame
+ *   descriptions are separated from one another via a comma.  The
+ *   beginning of a frame description requires the specification
+ *   of the graphic format and then the display frame rectangle where
+ *   the frame will be displayed.  The display frame rectangle is
+ *   specified as follows, with the right and bottom coordinates being
+ *   exclusive values:
+ *
+ *     [left, top, right, bottom]
+ *    
+ *   After these two required parameters each frame description can
+ *   specify 1 or more optional attributes.  The name of each optional
+ *   attribute is preceded by a colon.  The current implementation
+ *   then requires white space after the colon and then the value of
+ *   the attribute is specified.  See the synopsis section above for
+ *   a list of attributes and the format of their expected value.
+ */
+
+#include <algorithm>
+#include <assert.h>
+#include <cerrno>
+#include <cmath>
+#include <cstdlib>
+#include <ctime>
+#include <istream>
+#include <libgen.h>
+#include <list>
+#include <sched.h>
+#include <sstream>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+#define LOG_TAG "hwcRectsTest"
+#include <utils/Log.h>
+#include <testUtil.h>
+
+#include <hardware/hwcomposer.h>
+
+#include <glTestLib.h>
+#include <hwc/hwcTestLib.h>
+
+using namespace std;
+using namespace android;
+
+// Defaults
+const bool defaultVerbose = false;
+const float defaultEndDelay = 2.0; // Default delay after rendering graphics
+
+const uint32_t   defaultFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+const int32_t    defaultTransform = 0;
+const uint32_t   defaultBlend = HWC_BLENDING_NONE;
+const ColorFract defaultColor(0.5, 0.5, 0.5);
+const float      defaultAlpha = 1.0; // Opaque
+const HwcTestDim defaultSourceDim(1, 1);
+const struct hwc_rect defaultSourceCrop = {0, 0, 1, 1};
+const struct hwc_rect defaultDisplayFrame = {0, 0, 100, 100};
+
+// Defines
+#define MAXCMD               200
+#define CMD_STOP_FRAMEWORK   "stop 2>&1"
+#define CMD_START_FRAMEWORK  "start 2>&1"
+
+// Macros
+#define NUMA(a) (sizeof(a) / sizeof(a [0])) // Num elements in an array
+
+// Local types
+class Rectangle {
+public:
+    Rectangle() : format(defaultFormat), transform(defaultTransform),
+                  blend(defaultBlend), color(defaultColor),
+                  alpha(defaultAlpha), sourceDim(defaultSourceDim),
+                  sourceCrop(defaultSourceCrop),
+                  displayFrame(defaultDisplayFrame) {};
+
+    uint32_t     format;
+    uint32_t     transform;
+    int32_t      blend;
+    ColorFract   color;
+    float        alpha;
+    HwcTestDim   sourceDim;
+    struct hwc_rect   sourceCrop;
+    struct hwc_rect   displayFrame;
+
+    sp<GraphicBuffer> texture;
+};
+
+// Globals
+list<Rectangle> rectangle;
+static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
+        GraphicBuffer::USAGE_SW_WRITE_RARELY;
+static hwc_composer_device_t *hwcDevice;
+static EGLDisplay dpy;
+static EGLSurface surface;
+static EGLint width, height;
+
+// Function prototypes
+static Rectangle parseRect(string rectStr);
+void init(void);
+void printSyntax(const char *cmd);
+
+// Command-line option settings
+static bool verbose = defaultVerbose;
+static float endDelay = defaultEndDelay;
+
+/*
+ * Main
+ *
+ * Performs the following high-level sequence of operations:
+ *
+ *   1. Parse command-line options
+ *
+ *   2. Stop framework
+ *
+ *   3. Initialization
+ *
+ *   4. Parse frame descriptions
+ *
+ *   5. Create HWC list from frame descriptions
+ *
+ *   6. Have HWC render the list description of the frames
+ *
+ *   7. Delay for amount of time given by endDelay
+ *
+ *   8. Start framework
+ */
+int
+main(int argc, char *argv[])
+{
+    int     rv, opt;
+    char   *chptr;
+    bool    error;
+    string  str;
+    char cmd[MAXCMD];
+
+    testSetLogCatTag(LOG_TAG);
+
+    // Parse command line arguments
+    while ((opt = getopt(argc, argv, "D:v?h")) != -1) {
+        switch (opt) {
+          case 'D': // End of test delay
+            endDelay = strtod(optarg, &chptr);
+            if ((*chptr != '\0') || (endDelay < 0.0)) {
+                testPrintE("Invalid command-line specified end of test delay "
+                           "of: %s", optarg);
+                exit(1);
+            }
+            break;
+
+          case 'v': // Verbose
+            verbose = true;
+            break;
+
+          case 'h': // Help
+          case '?':
+          default:
+            printSyntax(basename(argv[0]));
+            exit(((optopt == 0) || (optopt == '?')) ? 0 : 2);
+        }
+    }
+
+    // Stop framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
+        exit(3);
+    }
+    testExecCmd(cmd);
+    testDelay(1.0); // TODO - needs means to query whether asyncronous stop
+                    // framework operation has completed.  For now, just wait
+                    // a long time.
+
+    init();
+
+    // Parse rectangle descriptions
+    int numOpen = 0; // Current number of unmatched <[
+    string rectDesc(""); // String description of a single rectangle
+    while (optind < argc) {
+        string argNext = string(argv[optind++]);
+
+        if (rectDesc.length()) { rectDesc += ' '; }
+        rectDesc += argNext;
+
+        // Count number of opening <[ and matching >]
+        // At this point not worried about an opening character being
+        // matched by it's corresponding closing character.  For example,
+        // "<1.0, 2.0]" is incorrect because the opening < should be matched
+        // with a closing >, instead of the closing ].  Such errors are
+        // detected when the actual value is parsed.
+        for (unsigned int n1 = 0; n1 < argNext.length(); n1++) {
+            switch(argNext[n1]) {
+              case '[':
+              case '<':
+                numOpen++;
+                break;
+
+              case ']':
+              case '>':
+                numOpen--;
+                break;
+            }
+
+            // Error anytime there is more closing then opening characters
+            if (numOpen < 0) {
+                testPrintI("Mismatched number of opening <[ with "
+                           "closing >] in: %s", rectDesc.c_str());
+                exit(4);
+            }
+        }
+
+        // Description of a rectangle is complete when all opening
+        // <[ are closed with >] and the string ends with a comma or
+        // there are no more args.
+        if ((numOpen == 0) && rectDesc.length()
+            && ((rectDesc[rectDesc.length() - 1] == ',')
+                || (optind == argc))) {
+            // Remove trailing comma if it is present
+            if (rectDesc[rectDesc.length() - 1] == ',') {
+                rectDesc.erase(rectDesc.length() - 1);
+            }
+
+            // Parse string description of rectangle
+            Rectangle rect = parseRect(rectDesc);
+
+            // Add to the list of rectangles
+            rectangle.push_back(rect);
+
+            // Prepare for description of another rectangle
+            rectDesc = string("");
+        }
+    }
+
+    // Create list of frames
+    hwc_layer_list_t *list;
+    list = hwcTestCreateLayerList(rectangle.size());
+    if (list == NULL) {
+        testPrintE("hwcTestCreateLayerList failed");
+        exit(5);
+    }
+
+    hwc_layer_t *layer = &list->hwLayers[0];
+    for (std::list<Rectangle>::iterator it = rectangle.begin();
+         it != rectangle.end(); ++it, ++layer) {
+        layer->handle = it->texture->handle;
+        layer->blending = it->blend;
+        layer->transform = it->transform;
+        layer->sourceCrop = it->sourceCrop;
+        layer->displayFrame = it->displayFrame;
+
+        layer->visibleRegionScreen.numRects = 1;
+        layer->visibleRegionScreen.rects = &layer->displayFrame;
+    }
+
+    // Perform prepare operation
+    if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(list); }
+    hwcDevice->prepare(hwcDevice, list);
+    if (verbose) {
+        testPrintI("Post Prepare:");
+        hwcTestDisplayListPrepareModifiable(list);
+    }
+
+    // Turn off the geometry changed flag
+    list->flags &= ~HWC_GEOMETRY_CHANGED;
+
+    // Perform the set operation(s)
+    if (verbose) {testPrintI("Set:"); }
+    if (verbose) { hwcTestDisplayListHandles(list); }
+    hwcDevice->set(hwcDevice, dpy, surface, list);
+
+    testDelay(endDelay);
+
+    // Start framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
+        exit(6);
+    }
+    testExecCmd(cmd);
+
+    return 0;
+}
+
+// Parse string description of rectangle and add it to list of rectangles
+// to be rendered.
+static Rectangle parseRect(string rectStr)
+{
+    int rv;
+    string str;
+    bool   error;
+    istringstream in(rectStr);
+    const struct hwcTestGraphicFormat *format;
+    Rectangle rect;
+    struct hwc_rect hwcRect;
+
+    // Graphic Format
+    in >> str;
+    if (!in) {
+        testPrintE("Error parsing format from: %s", rectStr.c_str());
+        exit(20);
+    }
+    format = hwcTestGraphicFormatLookup(str.c_str());
+    if (format == NULL) {
+        testPrintE("Unknown graphic format in: %s", rectStr.c_str());
+        exit(21);
+    }
+    rect.format = format->format;
+
+    // Display Frame
+    rect.displayFrame = hwcTestParseHwcRect(in, error);
+    if (error) {
+        testPrintE("Invalid display frame in: %s", rectStr.c_str());
+        exit(22);
+    }
+
+    // Set default sourceDim and sourceCrop based on size of display frame.
+    // Default is source size equal to the size of the display frame, with
+    // the source crop being the entire size of the source frame.
+    rect.sourceDim = HwcTestDim(rect.displayFrame.right
+                                     - rect.displayFrame.left,
+                                 rect.displayFrame.bottom
+                                     - rect.displayFrame.top);
+    rect.sourceCrop.left = 0;
+    rect.sourceCrop.top = 0;
+    rect.sourceCrop.right = rect.sourceDim.width();
+    rect.sourceCrop.bottom = rect.sourceDim.height();
+
+    // Optional settings
+    while ((in.tellg() < (streampos) in.str().length())
+           && (in.tellg() != (streampos) -1)) {
+        string attrName;
+
+        in >> attrName;
+        if (in.eof()) { break; }
+        if (!in) {
+            testPrintE("Error reading attribute name in: %s",
+                       rectStr.c_str());
+            exit(23);
+        }
+
+        // Transform
+        if (attrName == "transform:") { // Transform
+            string str;
+
+            in >> str;
+            if (str == "none") {
+                rect.transform = 0;
+            } else if (str == "fliph") {
+                rect.transform = HWC_TRANSFORM_FLIP_H;
+            } else if (str == "flipv") {
+                rect.transform = HWC_TRANSFORM_FLIP_V;
+            } else if (str == "rot90") {
+                rect.transform = HWC_TRANSFORM_ROT_90;
+            } else if (str == "rot180") {
+                rect.transform = HWC_TRANSFORM_ROT_180;
+            } else if (str == "rot270") {
+                rect.transform = HWC_TRANSFORM_ROT_270;
+            } else {
+                testPrintE("Unknown transform of \"%s\" in: %s", str.c_str(),
+                           rectStr.c_str());
+                exit(24);
+            }
+        } else if (attrName == "blend:") { // Blend
+            string str;
+
+            in >> str;
+            if (str == string("none")) {
+                rect.blend = HWC_BLENDING_NONE;
+            } else if (str == "premult") {
+                rect.blend = HWC_BLENDING_PREMULT;
+            } else if (str == "coverage") {
+                rect.blend = HWC_BLENDING_COVERAGE;
+            } else {
+                testPrintE("Unknown blend of \"%s\" in: %s", str.c_str(),
+                           rectStr.c_str());
+                exit(25);
+            }
+        } else if (attrName == "color:") { // Color
+            rect.color = hwcTestParseColor(in, error);
+            if (error) {
+                testPrintE("Error parsing color in: %s", rectStr.c_str());
+                exit(26);
+            }
+        } else if (attrName == "alpha:") { // Alpha
+            in >> rect.alpha;
+            if (!in) {
+                testPrintE("Error parsing value for alpha attribute in: %s",
+                           rectStr.c_str());
+                exit(27);
+            }
+        } else if (attrName == "sourceDim:") { // Source Dimension
+           rect.sourceDim = hwcTestParseDim(in, error);
+            if (error) {
+                testPrintE("Error parsing source dimenision in: %s",
+                           rectStr.c_str());
+                exit(28);
+            }
+        } else if (attrName == "sourceCrop:") { // Source Crop
+            rect.sourceCrop = hwcTestParseHwcRect(in, error);
+            if (error) {
+                testPrintE("Error parsing source crop in: %s",
+                           rectStr.c_str());
+                exit(29);
+            }
+        } else { // Unknown attribute
+            testPrintE("Unknown attribute of \"%s\" in: %s", attrName.c_str(),
+                       rectStr.c_str());
+            exit(30);
+        }
+    }
+
+    // Validate
+    if (((uint32_t) rect.sourceCrop.left >= rect.sourceDim.width())
+        || ((uint32_t) rect.sourceCrop.right > rect.sourceDim.width())
+        || ((uint32_t) rect.sourceCrop.top >= rect.sourceDim.height())
+        || ((uint32_t) rect.sourceCrop.bottom > rect.sourceDim.height())) {
+        testPrintE("Invalid source crop in: %s", rectStr.c_str());
+        exit(31);
+    }
+    if ((rect.displayFrame.left >= width)
+        || (rect.displayFrame.right > width)
+        || (rect.displayFrame.top >= height)
+        || (rect.displayFrame.bottom > height)) {
+        testPrintE("Invalid display frame in: %s", rectStr.c_str());
+        exit(32);
+    }
+    if ((rect.alpha < 0.0) || (rect.alpha > 1.0)) {
+        testPrintE("Invalid alpha in: %s", rectStr.c_str());
+        exit(33);
+    }
+
+    // Create source texture
+    rect.texture = new GraphicBuffer(rect.sourceDim.width(),
+                                     rect.sourceDim.height(),
+                                     rect.format, texUsage);
+    if ((rv = rect.texture->initCheck()) != NO_ERROR) {
+        testPrintE("source texture initCheck failed, rv: %i", rv);
+        testPrintE("  %s", rectStr.c_str());
+
+    }
+
+    // Fill with uniform color
+    hwcTestFillColor(rect.texture.get(), rect.color, rect.alpha);
+    if (verbose) {
+        testPrintI("    buf: %p handle: %p format: %s width: %u height: %u "
+                   "color: %s alpha: %f",
+                   rect.texture.get(), rect.texture->handle, format->desc,
+                   rect.sourceDim.width(), rect.sourceDim.height(),
+                   string(rect.color).c_str(), rect.alpha);
+    }
+
+    return rect;
+}
+
+void init(void)
+{
+    // Seed pseudo random number generator
+    // Needed so that the pad areas of frames are filled with a deterministic
+    // pseudo random value.
+    srand48(0);
+
+    hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
+
+    hwcTestOpenHwc(&hwcDevice);
+}
+
+void printSyntax(const char *cmd)
+{
+    testPrintE("  %s [options] (graphicFormat displayFrame [attributes],)...",
+               cmd);
+    testPrintE("    options:");
+    testPrintE("      -D End of test delay");
+    testPrintE("      -v Verbose");
+    testPrintE("");
+    testPrintE("    graphic formats:");
+    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+        testPrintE("      %s", hwcTestGraphicFormat[n1].desc);
+    }
+    testPrintE("");
+    testPrintE("    displayFrame");
+    testPrintE("      [left, top, right, bottom]");
+    testPrintE("");
+    testPrintE("    attributes:");
+    testPrintE("      transform: none | fliph | flipv | rot90 | rot180 "
+               " | rot270");
+    testPrintE("      blend: none | premult | coverage");
+    testPrintE("      color: [0.##, 0.##, 0.##]");
+    testPrintE("      alpha: 0.##");
+    testPrintE("      sourceDim: [width, height]");
+    testPrintE("      sourceCrop: [left, top, right, bottom]");
+    testPrintE("");
+    testPrintE("    Example:");
+    testPrintE("      # White YV12 rectangle, with overlapping turquoise ");
+    testPrintE("      #  RGBA8888 rectangle at 30%% (alpha: 0.7) transparency");
+    testPrintE("      %s -v -D 30.0 \\", cmd);
+    testPrintE("        YV12 [50, 80, 200, 300] transform: none \\");
+    testPrintE("          color: [1.0, 0.5, 0.5], \\");
+    testPrintE("        RGBA8888 [100, 150, 300, 400] blend: coverage \\");
+    testPrintE("          color: [0.251, 0.878, 0.816] alpha: 0.7 \\");
+    testPrintE("          sourceDim: [50, 60] sourceCrop: [5, 8, 12, 15]");
+}
diff --git a/opengl/tests/hwc/hwcStress.cpp b/opengl/tests/hwc/hwcStress.cpp
new file mode 100644
index 0000000..1cefb4b
--- /dev/null
+++ b/opengl/tests/hwc/hwcStress.cpp
@@ -0,0 +1,645 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Hardware Composer stress test
+ *
+ * Performs a pseudo-random (prandom) sequence of operations to the
+ * Hardware Composer (HWC), for a specified number of passes or for
+ * a specified period of time.  By default the period of time is FLT_MAX,
+ * so that the number of passes will take precedence.
+ *
+ * The passes are grouped together, where (pass / passesPerGroup) specifies
+ * which group a particular pass is in.  This causes every passesPerGroup
+ * worth of sequential passes to be within the same group.  Computationally
+ * intensive operations are performed just once at the beginning of a group
+ * of passes and then used by all the passes in that group.  This is done
+ * so as to increase both the average and peak rate of graphic operations,
+ * by moving computationally intensive operations to the beginning of a group.
+ * In particular, at the start of each group of passes a set of
+ * graphic buffers are created, then used by the first and remaining
+ * passes of that group of passes.
+ *
+ * The per-group initialization of the graphic buffers is performed
+ * by a function called initFrames.  This function creates an array
+ * of smart pointers to the graphic buffers, in the form of a vector
+ * of vectors.  The array is accessed in row major order, so each
+ * row is a vector of smart pointers.  All the pointers of a single
+ * row point to graphic buffers which use the same pixel format and
+ * have the same dimension, although it is likely that each one is
+ * filled with a different color.  This is done so that after doing
+ * the first HWC prepare then set call, subsequent set calls can
+ * be made with each of the layer handles changed to a different
+ * graphic buffer within the same row.  Since the graphic buffers
+ * in a particular row have the same pixel format and dimension,
+ * additional HWC set calls can be made, without having to perform
+ * an HWC prepare call.
+ *
+ * This test supports the following command-line options:
+ *
+ *   -v        Verbose
+ *   -s num    Starting pass
+ *   -e num    Ending pass
+ *   -p num    Execute the single pass specified by num
+ *   -n num    Number of set operations to perform after each prepare operation
+ *   -t float  Maximum time in seconds to execute the test
+ *   -d float  Delay in seconds performed after each set operation
+ *   -D float  Delay in seconds performed after the last pass is executed
+ *
+ * Typically the test is executed for a large range of passes.  By default
+ * passes 0 through 99999 (100,000 passes) are executed.  Although this test
+ * does not validate the generated image, at times it is useful to reexecute
+ * a particular pass and leave the displayed image on the screen for an
+ * extended period of time.  This can be done either by setting the -s
+ * and -e options to the desired pass, along with a large value for -D.
+ * This can also be done via the -p option, again with a large value for
+ * the -D options.
+ *
+ * So far this test only contains code to create graphic buffers with
+ * a continuous solid color.  Although this test is unable to validate the
+ * image produced, any image that contains other than rectangles of a solid
+ * color are incorrect.  Note that the rectangles may use a transparent
+ * color and have a blending operation that causes the color in overlapping
+ * rectangles to be mixed.  In such cases the overlapping portions may have
+ * a different color from the rest of the rectangle.
+ */
+
+#include <algorithm>
+#include <assert.h>
+#include <cerrno>
+#include <cmath>
+#include <cstdlib>
+#include <ctime>
+#include <libgen.h>
+#include <sched.h>
+#include <sstream>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <vector>
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+#define LOG_TAG "hwcStressTest"
+#include <utils/Log.h>
+#include <testUtil.h>
+
+#include <hardware/hwcomposer.h>
+
+#include <glTestLib.h>
+#include <hwc/hwcTestLib.h>
+
+using namespace std;
+using namespace android;
+
+const float maxSizeRatio = 1.3;  // Graphic buffers can be upto this munch
+                                 // larger than the default screen size
+const unsigned int passesPerGroup = 10; // A group of passes all use the same
+                                        // graphic buffers
+
+// Ratios at which rare and frequent conditions should be produced
+const float rareRatio = 0.1;
+const float freqRatio = 0.9;
+
+// Defaults for command-line options
+const bool defaultVerbose = false;
+const unsigned int defaultStartPass = 0;
+const unsigned int defaultEndPass = 99999;
+const unsigned int defaultPerPassNumSet = 10;
+const float defaultPerSetDelay = 0.0; // Default delay after each set
+                                      // operation.  Default delay of
+                                      // zero used so as to perform the
+                                      // the set operations as quickly
+                                      // as possible.
+const float defaultEndDelay = 2.0; // Default delay between completion of
+                                   // final pass and restart of framework
+const float defaultDuration = FLT_MAX; // A fairly long time, so that
+                                       // range of passes will have
+                                       // precedence
+
+// Command-line option settings
+static bool verbose = defaultVerbose;
+static unsigned int startPass = defaultStartPass;
+static unsigned int endPass = defaultEndPass;
+static unsigned int numSet = defaultPerPassNumSet;
+static float perSetDelay = defaultPerSetDelay;
+static float endDelay = defaultEndDelay;
+static float duration = defaultDuration;
+
+// Command-line mutual exclusion detection flags.
+// Corresponding flag set true once an option is used.
+bool eFlag, sFlag, pFlag;
+
+#define MAXSTR               100
+#define MAXCMD               200
+#define BITSPERBYTE            8 // TODO: Obtain from <values.h>, once
+                                 // it has been added
+
+#define CMD_STOP_FRAMEWORK   "stop 2>&1"
+#define CMD_START_FRAMEWORK  "start 2>&1"
+
+#define NUMA(a) (sizeof(a) / sizeof(a [0]))
+#define MEMCLR(addr, size) do { \
+        memset((addr), 0, (size)); \
+    } while (0)
+
+// File scope constants
+const unsigned int blendingOps[] = {
+    HWC_BLENDING_NONE,
+    HWC_BLENDING_PREMULT,
+    HWC_BLENDING_COVERAGE,
+};
+const unsigned int layerFlags[] = {
+    HWC_SKIP_LAYER,
+};
+const vector<unsigned int> vecLayerFlags(layerFlags,
+    layerFlags + NUMA(layerFlags));
+
+const unsigned int transformFlags[] = {
+    HWC_TRANSFORM_FLIP_H,
+    HWC_TRANSFORM_FLIP_V,
+    HWC_TRANSFORM_ROT_90,
+    // ROT_180 & ROT_270 intentionally not listed, because they
+    // they are formed from combinations of the flags already listed.
+};
+const vector<unsigned int> vecTransformFlags(transformFlags,
+    transformFlags + NUMA(transformFlags));
+
+// File scope globals
+static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
+        GraphicBuffer::USAGE_SW_WRITE_RARELY;
+static hwc_composer_device_t *hwcDevice;
+static EGLDisplay dpy;
+static EGLSurface surface;
+static EGLint width, height;
+static vector <vector <sp<GraphicBuffer> > > frames;
+
+// File scope prototypes
+void init(void);
+void initFrames(unsigned int seed);
+template <class T> vector<T> vectorRandSelect(const vector<T>& vec, size_t num);
+template <class T> T vectorOr(const vector<T>& vec);
+
+/*
+ * Main
+ *
+ * Performs the following high-level sequence of operations:
+ *
+ *   1. Command-line parsing
+ *
+ *   2. Initialization
+ *
+ *   3. For each pass:
+ *
+ *        a. If pass is first pass or in a different group from the
+ *           previous pass, initialize the array of graphic buffers.
+ *
+ *        b. Create a HWC list with room to specify a prandomly
+ *           selected number of layers.
+ *
+ *        c. Select a subset of the rows from the graphic buffer array,
+ *           such that there is a unique row to be used for each
+ *           of the layers in the HWC list.
+ *
+ *        d. Prandomly fill in the HWC list with handles
+ *           selected from any of the columns of the selected row.
+ *
+ *        e. Pass the populated list to the HWC prepare call.
+ *
+ *        f. Pass the populated list to the HWC set call.
+ *
+ *        g. If additional set calls are to be made, then for each
+ *           additional set call, select a new set of handles and
+ *           perform the set call.
+ */
+int
+main(int argc, char *argv[])
+{
+    int rv, opt;
+    char *chptr;
+    unsigned int pass;
+    char cmd[MAXCMD];
+    struct timeval startTime, currentTime, delta;
+
+    testSetLogCatTag(LOG_TAG);
+
+    // Parse command line arguments
+    while ((opt = getopt(argc, argv, "vp:d:D:n:s:e:t:?h")) != -1) {
+        switch (opt) {
+          case 'd': // Delay after each set operation
+            perSetDelay = strtod(optarg, &chptr);
+            if ((*chptr != '\0') || (perSetDelay < 0.0)) {
+                testPrintE("Invalid command-line specified per pass delay of: "
+                           "%s", optarg);
+                exit(1);
+            }
+            break;
+
+          case 'D': // End of test delay
+                    // Delay between completion of final pass and restart
+                    // of framework
+            endDelay = strtod(optarg, &chptr);
+            if ((*chptr != '\0') || (endDelay < 0.0)) {
+                testPrintE("Invalid command-line specified end of test delay "
+                           "of: %s", optarg);
+                exit(2);
+            }
+            break;
+
+          case 't': // Duration
+            duration = strtod(optarg, &chptr);
+            if ((*chptr != '\0') || (duration < 0.0)) {
+                testPrintE("Invalid command-line specified duration of: %s",
+                           optarg);
+                exit(3);
+            }
+            break;
+
+          case 'n': // Num set operations per pass
+            numSet = strtoul(optarg, &chptr, 10);
+            if (*chptr != '\0') {
+                testPrintE("Invalid command-line specified num set per pass "
+                           "of: %s", optarg);
+                exit(4);
+            }
+            break;
+
+          case 's': // Starting Pass
+            sFlag = true;
+            if (pFlag) {
+                testPrintE("Invalid combination of command-line options.");
+                testPrintE("  The -p option is mutually exclusive from the");
+                testPrintE("  -s and -e options.");
+                exit(5);
+            }
+            startPass = strtoul(optarg, &chptr, 10);
+            if (*chptr != '\0') {
+                testPrintE("Invalid command-line specified starting pass "
+                           "of: %s", optarg);
+                exit(6);
+            }
+            break;
+
+          case 'e': // Ending Pass
+            eFlag = true;
+            if (pFlag) {
+                testPrintE("Invalid combination of command-line options.");
+                testPrintE("  The -p option is mutually exclusive from the");
+                testPrintE("  -s and -e options.");
+                exit(7);
+            }
+            endPass = strtoul(optarg, &chptr, 10);
+            if (*chptr != '\0') {
+                testPrintE("Invalid command-line specified ending pass "
+                           "of: %s", optarg);
+                exit(8);
+            }
+            break;
+
+          case 'p': // Run a single specified pass
+            pFlag = true;
+            if (sFlag || eFlag) {
+                testPrintE("Invalid combination of command-line options.");
+                testPrintE("  The -p option is mutually exclusive from the");
+                testPrintE("  -s and -e options.");
+                exit(9);
+            }
+            startPass = endPass = strtoul(optarg, &chptr, 10);
+            if (*chptr != '\0') {
+                testPrintE("Invalid command-line specified pass of: %s",
+                           optarg);
+                exit(10);
+            }
+            break;
+
+          case 'v': // Verbose
+            verbose = true;
+            break;
+
+          case 'h': // Help
+          case '?':
+          default:
+            testPrintE("  %s [options]", basename(argv[0]));
+            testPrintE("    options:");
+            testPrintE("      -p Execute specified pass");
+            testPrintE("      -s Starting pass");
+            testPrintE("      -e Ending pass");
+            testPrintE("      -t Duration");
+            testPrintE("      -d Delay after each set operation");
+            testPrintE("      -D End of test delay");
+            testPrintE("      -n Num set operations per pass");
+            testPrintE("      -v Verbose");
+            exit(((optopt == 0) || (optopt == '?')) ? 0 : 11);
+        }
+    }
+    if (endPass < startPass) {
+        testPrintE("Unexpected ending pass before starting pass");
+        testPrintE("  startPass: %u endPass: %u", startPass, endPass);
+        exit(12);
+    }
+    if (argc != optind) {
+        testPrintE("Unexpected command-line postional argument");
+        testPrintE("  %s [-s start_pass] [-e end_pass] [-t duration]",
+            basename(argv[0]));
+        exit(13);
+    }
+    testPrintI("duration: %g", duration);
+    testPrintI("startPass: %u", startPass);
+    testPrintI("endPass: %u", endPass);
+    testPrintI("numSet: %u", numSet);
+
+    // Stop framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
+        exit(14);
+    }
+    testExecCmd(cmd);
+    testDelay(1.0); // TODO - need means to query whether asyncronous stop
+                    // framework operation has completed.  For now, just wait
+                    // a long time.
+
+    init();
+
+    // For each pass
+    gettimeofday(&startTime, NULL);
+    for (pass = startPass; pass <= endPass; pass++) {
+        // Stop if duration of work has already been performed
+        gettimeofday(&currentTime, NULL);
+        delta = tvDelta(&startTime, &currentTime);
+        if (tv2double(&delta) > duration) { break; }
+
+        // Regenerate a new set of test frames when this pass is
+        // either the first pass or is in a different group then
+        // the previous pass.  A group of passes are passes that
+        // all have the same quotient when their pass number is
+        // divided by passesPerGroup.
+        if ((pass == startPass)
+            || ((pass / passesPerGroup) != ((pass - 1) / passesPerGroup))) {
+            initFrames(pass / passesPerGroup);
+        }
+
+        testPrintI("==== Starting pass: %u", pass);
+
+        // Cause deterministic sequence of prandom numbers to be
+        // generated for this pass.
+        srand48(pass);
+
+        hwc_layer_list_t *list;
+        list = hwcTestCreateLayerList(testRandMod(frames.size()) + 1);
+        if (list == NULL) {
+            testPrintE("hwcTestCreateLayerList failed");
+            exit(20);
+        }
+
+        // Prandomly select a subset of frames to be used by this pass.
+        vector <vector <sp<GraphicBuffer> > > selectedFrames;
+        selectedFrames = vectorRandSelect(frames, list->numHwLayers);
+
+        // Any transform tends to create a layer that the hardware
+        // composer is unable to support and thus has to leave for
+        // SurfaceFlinger.  Place heavy bias on specifying no transforms.
+        bool noTransform = testRandFract() > rareRatio;
+
+        for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) {
+            unsigned int idx = testRandMod(selectedFrames[n1].size());
+            sp<GraphicBuffer> gBuf = selectedFrames[n1][idx];
+            hwc_layer_t *layer = &list->hwLayers[n1];
+            layer->handle = gBuf->handle;
+
+            layer->blending = blendingOps[testRandMod(NUMA(blendingOps))];
+            layer->flags = (testRandFract() > rareRatio) ? 0
+                : vectorOr(vectorRandSelect(vecLayerFlags,
+                           testRandMod(vecLayerFlags.size() + 1)));
+            layer->transform = (noTransform || testRandFract() > rareRatio) ? 0
+                : vectorOr(vectorRandSelect(vecTransformFlags,
+                           testRandMod(vecTransformFlags.size() + 1)));
+            layer->sourceCrop.left = testRandMod(gBuf->getWidth());
+            layer->sourceCrop.top = testRandMod(gBuf->getHeight());
+            layer->sourceCrop.right = layer->sourceCrop.left
+                + testRandMod(gBuf->getWidth() - layer->sourceCrop.left) + 1;
+            layer->sourceCrop.bottom = layer->sourceCrop.top
+                + testRandMod(gBuf->getHeight() - layer->sourceCrop.top) + 1;
+            layer->displayFrame.left = testRandMod(width);
+            layer->displayFrame.top = testRandMod(height);
+            layer->displayFrame.right = layer->displayFrame.left
+                + testRandMod(width - layer->displayFrame.left) + 1;
+            layer->displayFrame.bottom = layer->displayFrame.top
+                + testRandMod(height - layer->displayFrame.top) + 1;
+
+            // Increase the frequency that a scale factor of 1.0 from
+            // the sourceCrop to displayFrame occurs.  This is the
+            // most common scale factor used by applications and would
+            // be rarely produced by this stress test without this
+            // logic.
+            if (testRandFract() <= freqRatio) {
+                // Only change to scale factor to 1.0 if both the
+                // width and height will fit.
+                int sourceWidth = layer->sourceCrop.right
+                                  - layer->sourceCrop.left;
+                int sourceHeight = layer->sourceCrop.bottom
+                                   - layer->sourceCrop.top;
+                if (((layer->displayFrame.left + sourceWidth) <= width)
+                    && ((layer->displayFrame.top + sourceHeight) <= height)) {
+                    layer->displayFrame.right = layer->displayFrame.left
+                                                + sourceWidth;
+                    layer->displayFrame.bottom = layer->displayFrame.top
+                                                 + sourceHeight;
+                }
+            }
+
+            layer->visibleRegionScreen.numRects = 1;
+            layer->visibleRegionScreen.rects = &layer->displayFrame;
+        }
+
+        // Perform prepare operation
+        if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(list); }
+        hwcDevice->prepare(hwcDevice, list);
+        if (verbose) {
+            testPrintI("Post Prepare:");
+            hwcTestDisplayListPrepareModifiable(list);
+        }
+
+        // Turn off the geometry changed flag
+        list->flags &= ~HWC_GEOMETRY_CHANGED;
+
+        // Perform the set operation(s)
+        if (verbose) {testPrintI("Set:"); }
+        for (unsigned int n1 = 0; n1 < numSet; n1++) {
+            if (verbose) { hwcTestDisplayListHandles(list); }
+            hwcDevice->set(hwcDevice, dpy, surface, list);
+
+            // Prandomly select a new set of handles
+            for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) {
+                unsigned int idx = testRandMod(selectedFrames[n1].size());
+                sp<GraphicBuffer> gBuf = selectedFrames[n1][idx];
+                hwc_layer_t *layer = &list->hwLayers[n1];
+                layer->handle = (native_handle_t *) gBuf->handle;
+            }
+
+            testDelay(perSetDelay);
+        }
+
+        hwcTestFreeLayerList(list);
+        testPrintI("==== Completed pass: %u", pass);
+    }
+
+    testDelay(endDelay);
+
+    // Start framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
+        exit(21);
+    }
+    testExecCmd(cmd);
+
+    testPrintI("Successfully completed %u passes", pass - startPass);
+
+    return 0;
+}
+
+void init(void)
+{
+    srand48(0); // Defensively set pseudo random number generator.
+                // Should not need to set this, because a stress test
+                // sets the seed on each pass.  Defensively set it here
+                // so that future code that uses pseudo random numbers
+                // before the first pass will be deterministic.
+
+    hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
+
+    hwcTestOpenHwc(&hwcDevice);
+}
+
+/*
+ * Initialize Frames
+ *
+ * Creates an array of graphic buffers, within the global variable
+ * named frames.  The graphic buffers are contained within a vector of
+ * vectors.  All the graphic buffers in a particular row are of the same
+ * format and dimension.  Each graphic buffer is uniformly filled with a
+ * prandomly selected color.  It is likely that each buffer, even
+ * in the same row, will be filled with a unique color.
+ */
+void initFrames(unsigned int seed)
+{
+    int rv;
+    const size_t maxRows = 5;
+    const size_t minCols = 2;  // Need at least double buffering
+    const size_t maxCols = 4;  // One more than triple buffering
+
+    if (verbose) { testPrintI("initFrames seed: %u", seed); }
+    srand48(seed);
+    size_t rows = testRandMod(maxRows) + 1;
+
+    frames.clear();
+    frames.resize(rows);
+
+    for (unsigned int row = 0; row < rows; row++) {
+        // All frames within a row have to have the same format and
+        // dimensions.  Width and height need to be >= 1.
+        unsigned int formatIdx = testRandMod(NUMA(hwcTestGraphicFormat));
+        const struct hwcTestGraphicFormat *formatPtr
+            = &hwcTestGraphicFormat[formatIdx];
+        int format = formatPtr->format;
+
+        // Pick width and height, which must be >= 1 and the size
+        // mod the wMod/hMod value must be equal to 0.
+        size_t w = (width * maxSizeRatio) * testRandFract();
+        size_t h = (height * maxSizeRatio) * testRandFract();
+        w = max(1u, w);
+        h = max(1u, h);
+        if ((w % formatPtr->wMod) != 0) {
+            w += formatPtr->wMod - (w % formatPtr->wMod);
+        }
+        if ((h % formatPtr->hMod) != 0) {
+            h += formatPtr->hMod - (h % formatPtr->hMod);
+        }
+        if (verbose) {
+            testPrintI("  frame %u width: %u height: %u format: %u %s",
+                       row, w, h, format, hwcTestGraphicFormat2str(format));
+        }
+
+        size_t cols = testRandMod((maxCols + 1) - minCols) + minCols;
+        frames[row].resize(cols);
+        for (unsigned int col = 0; col < cols; col++) {
+            ColorFract color(testRandFract(), testRandFract(), testRandFract());
+            float alpha = testRandFract();
+
+            frames[row][col] = new GraphicBuffer(w, h, format, texUsage);
+            if ((rv = frames[row][col]->initCheck()) != NO_ERROR) {
+                testPrintE("GraphicBuffer initCheck failed, rv: %i", rv);
+                testPrintE("  frame %u width: %u height: %u format: %u %s",
+                           row, w, h, format, hwcTestGraphicFormat2str(format));
+                exit(80);
+            }
+
+            hwcTestFillColor(frames[row][col].get(), color, alpha);
+            if (verbose) {
+                testPrintI("    buf: %p handle: %p color: %s alpha: %f",
+                           frames[row][col].get(), frames[row][col]->handle,
+                           string(color).c_str(), alpha);
+            }
+        }
+    }
+}
+
+/*
+ * Vector Random Select
+ *
+ * Prandomly selects and returns num elements from vec.
+ */
+template <class T>
+vector<T> vectorRandSelect(const vector<T>& vec, size_t num)
+{
+    vector<T> rv = vec;
+
+    while (rv.size() > num) {
+        rv.erase(rv.begin() + testRandMod(rv.size()));
+    }
+
+    return rv;
+}
+
+/*
+ * Vector Or
+ *
+ * Or's togethen the values of each element of vec and returns the result.
+ */
+template <class T>
+T vectorOr(const vector<T>& vec)
+{
+    T rv = 0;
+
+    for (size_t n1 = 0; n1 < vec.size(); n1++) {
+        rv |= vec[n1];
+    }
+
+    return rv;
+}
diff --git a/opengl/tests/hwc/hwcTestLib.cpp b/opengl/tests/hwc/hwcTestLib.cpp
new file mode 100644
index 0000000..925405e
--- /dev/null
+++ b/opengl/tests/hwc/hwcTestLib.cpp
@@ -0,0 +1,1028 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Hardware Composer Test Library
+ * Utility library functions for use by the Hardware Composer test cases
+ */
+
+#include <sstream>
+#include <string>
+
+#include <arpa/inet.h> // For ntohl() and htonl()
+
+#include <hwc/hwcTestLib.h>
+
+// Defines
+#define NUMA(a) (sizeof(a) / sizeof(a [0]))
+
+// Function Prototypes
+static void printGLString(const char *name, GLenum s);
+static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE);
+static void checkGlError(const char* op);
+static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config);
+
+using namespace std;
+using namespace android;
+
+
+#define BITSPERBYTE            8 // TODO: Obtain from <values.h>, once
+                                 // it has been added
+
+// Initialize Display
+void hwcTestInitDisplay(bool verbose, EGLDisplay *dpy, EGLSurface *surface,
+    EGLint *width, EGLint *height)
+{
+    static EGLContext context;
+
+    int rv;
+
+    EGLBoolean returnValue;
+    EGLConfig myConfig = {0};
+    EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+    EGLint sConfigAttribs[] = {
+        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+        EGL_NONE };
+    EGLint majorVersion, minorVersion;
+
+    checkEglError("<init>");
+    *dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    checkEglError("eglGetDisplay");
+    if (*dpy == EGL_NO_DISPLAY) {
+        testPrintE("eglGetDisplay returned EGL_NO_DISPLAY");
+        exit(70);
+    }
+
+    returnValue = eglInitialize(*dpy, &majorVersion, &minorVersion);
+    checkEglError("eglInitialize", returnValue);
+    if (verbose) {
+        testPrintI("EGL version %d.%d", majorVersion, minorVersion);
+    }
+    if (returnValue != EGL_TRUE) {
+        testPrintE("eglInitialize failed");
+        exit(71);
+    }
+
+    EGLNativeWindowType window = android_createDisplaySurface();
+    if (window == NULL) {
+        testPrintE("android_createDisplaySurface failed");
+        exit(72);
+    }
+    returnValue = EGLUtils::selectConfigForNativeWindow(*dpy,
+        sConfigAttribs, window, &myConfig);
+    if (returnValue) {
+        testPrintE("EGLUtils::selectConfigForNativeWindow() returned %d",
+            returnValue);
+        exit(73);
+    }
+    checkEglError("EGLUtils::selectConfigForNativeWindow");
+
+    if (verbose) {
+        testPrintI("Chose this configuration:");
+        printEGLConfiguration(*dpy, myConfig);
+    }
+
+    *surface = eglCreateWindowSurface(*dpy, myConfig, window, NULL);
+    checkEglError("eglCreateWindowSurface");
+    if (*surface == EGL_NO_SURFACE) {
+        testPrintE("gelCreateWindowSurface failed.");
+        exit(74);
+    }
+
+    context = eglCreateContext(*dpy, myConfig, EGL_NO_CONTEXT, contextAttribs);
+    checkEglError("eglCreateContext");
+    if (context == EGL_NO_CONTEXT) {
+        testPrintE("eglCreateContext failed");
+        exit(75);
+    }
+    returnValue = eglMakeCurrent(*dpy, *surface, *surface, context);
+    checkEglError("eglMakeCurrent", returnValue);
+    if (returnValue != EGL_TRUE) {
+        testPrintE("eglMakeCurrent failed");
+        exit(76);
+    }
+    eglQuerySurface(*dpy, *surface, EGL_WIDTH, width);
+    checkEglError("eglQuerySurface");
+    eglQuerySurface(*dpy, *surface, EGL_HEIGHT, height);
+    checkEglError("eglQuerySurface");
+
+    if (verbose) {
+        testPrintI("Window dimensions: %d x %d", *width, *height);
+
+        printGLString("Version", GL_VERSION);
+        printGLString("Vendor", GL_VENDOR);
+        printGLString("Renderer", GL_RENDERER);
+        printGLString("Extensions", GL_EXTENSIONS);
+    }
+}
+
+// Open Hardware Composer Device
+void hwcTestOpenHwc(hwc_composer_device_t **hwcDevicePtr)
+{
+    int rv;
+    hw_module_t const *hwcModule;
+
+    if ((rv = hw_get_module(HWC_HARDWARE_MODULE_ID, &hwcModule)) != 0) {
+        testPrintE("hw_get_module failed, rv: %i", rv);
+        errno = -rv;
+        perror(NULL);
+        exit(77);
+    }
+    if ((rv = hwc_open(hwcModule, hwcDevicePtr)) != 0) {
+        testPrintE("hwc_open failed, rv: %i", rv);
+        errno = -rv;
+        perror(NULL);
+        exit(78);
+    }
+}
+
+// Color fraction class to string conversion
+ColorFract::operator string()
+{
+    ostringstream out;
+
+    out << '[' << this->c1() << ", "
+        << this->c2() << ", "
+        << this->c3() << ']';
+
+    return out.str();
+}
+
+// Dimension class to string conversion
+HwcTestDim::operator string()
+{
+    ostringstream out;
+
+    out << '[' << this->width() << ", "
+        << this->height() << ']';
+
+    return out.str();
+}
+
+// Dimension class to hwc_rect conversion
+HwcTestDim::operator hwc_rect() const
+{
+    hwc_rect rect;
+
+    rect.left = rect.top = 0;
+
+    rect.right = this->_w;
+    rect.bottom = this->_h;
+
+    return rect;
+}
+
+// Hardware Composer rectangle to string conversion
+string hwcTestRect2str(const struct hwc_rect& rect)
+{
+    ostringstream out;
+
+    out << '[';
+    out << rect.left << ", ";
+    out << rect.top << ", ";
+    out << rect.right << ", ";
+    out << rect.bottom;
+    out << ']';
+
+    return out.str();
+}
+
+// Parse HWC rectangle description of form [left, top, right, bottom]
+struct hwc_rect hwcTestParseHwcRect(istringstream& in, bool& error)
+{
+    struct hwc_rect rect;
+    char chStart, ch;
+
+    // Defensively specify that an error occurred.  Will clear
+    // error flag if all of parsing succeeds.
+    error = true;
+
+    // First character should be a [ or <
+    in >> chStart;
+    if (!in || ((chStart != '<') && (chStart != '['))) { return rect; }
+
+    // Left
+    in >> rect.left;
+    if (!in) { return rect; }
+    in >> ch;
+    if (!in || (ch != ',')) { return rect; }
+
+    // Top
+    in >> rect.top;
+    if (!in) { return rect; }
+    in >> ch;
+    if (!in || (ch != ',')) { return rect; }
+
+    // Right
+    in >> rect.right;
+    if (!in) { return rect; }
+    in >> ch;
+    if (!in || (ch != ',')) { return rect; }
+
+    // Bottom
+    in >> rect.bottom;
+    if (!in) { return rect; }
+
+    // Closing > or ]
+    in >> ch;
+    if (!in) { return rect; }
+    if (((chStart == '<') && (ch != '>'))
+        || ((chStart == '[') && (ch != ']'))) { return rect; }
+
+    // Validate right and bottom are greater than left and top
+    if ((rect.right <= rect.left) || (rect.bottom <= rect.top)) { return rect; }
+
+    // Made It, clear error indicator
+    error = false;
+
+    return rect;
+}
+
+// Parse dimension of form [width, height]
+HwcTestDim hwcTestParseDim(istringstream& in, bool& error)
+{
+    HwcTestDim dim;
+    char chStart, ch;
+    uint32_t val;
+
+    // Defensively specify that an error occurred.  Will clear
+    // error flag if all of parsing succeeds.
+    error = true;
+
+    // First character should be a [ or <
+    in >> chStart;
+    if (!in || ((chStart != '<') && (chStart != '['))) { return dim; }
+
+    // Width
+    in >> val;
+    if (!in) { return dim; }
+    dim.setWidth(val);
+    in >> ch;
+    if (!in || (ch != ',')) { return dim; }
+
+    // Height
+    in >> val;
+    if (!in) { return dim; }
+    dim.setHeight(val);
+
+    // Closing > or ]
+    in >> ch;
+    if (!in) { return dim; }
+    if (((chStart == '<') && (ch != '>'))
+        || ((chStart == '[') && (ch != ']'))) { return dim; }
+
+    // Validate width and height greater than 0
+    if ((dim.width() <= 0) || (dim.height() <= 0)) { return dim; }
+
+    // Made It, clear error indicator
+    error = false;
+    return dim;
+}
+
+// Parse fractional color of form [0.##, 0.##, 0.##]
+// Fractional values can be from 0.0 to 1.0 inclusive.  Note, integer
+// values of 0.0 and 1.0, which are non-fractional, are considered valid.
+// They are an exception, all other valid inputs are fractions.
+ColorFract hwcTestParseColor(istringstream& in, bool& error)
+{
+    ColorFract color;
+    char chStart, ch;
+    float c1, c2, c3;
+
+    // Defensively specify that an error occurred.  Will clear
+    // error flag if all of parsing succeeds.
+    error = true;
+
+    // First character should be a [ or <
+    in >> chStart;
+    if (!in || ((chStart != '<') && (chStart != '['))) { return color; }
+
+    // 1st Component
+    in >> c1;
+    if (!in) { return color; }
+    if ((c1 < 0.0) || (c1 > 1.0)) { return color; }
+    in >> ch;
+    if (!in || (ch != ',')) { return color; }
+
+    // 2nd Component
+    in >> c2;
+    if (!in) { return color; }
+    if ((c2 < 0.0) || (c2 > 1.0)) { return color; }
+    in >> ch;
+    if (!in || (ch != ',')) { return color; }
+
+    // 3rd Component
+    in >> c3;
+    if (!in) { return color; }
+    if ((c3 < 0.0) || (c3 > 1.0)) { return color; }
+
+    // Closing > or ]
+    in >> ch;
+    if (!in) { return color; }
+    if (((chStart == '<') && (ch != '>'))
+        || ((chStart == '[') && (ch != ']'))) { return color; }
+
+    // Are all the components fractional
+    if ((c1 < 0.0) || (c1 > 1.0)
+        || (c2 < 0.0) || (c2 > 1.0)
+        || (c3 < 0.0) || (c3 > 1.0)) { return color; }
+
+    // Made It, clear error indicator
+    error = false;
+
+    return ColorFract(c1, c2, c3);
+}
+
+// Look up and return pointer to structure with the characteristics
+// of the graphic format named by the desc parameter.  Search failure
+// indicated by the return of NULL.
+const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(const char *desc)
+{
+    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+        if (string(desc) == string(hwcTestGraphicFormat[n1].desc)) {
+            return &hwcTestGraphicFormat[n1];
+        }
+    }
+
+    return NULL;
+}
+
+// Look up and return pointer to structure with the characteristics
+// of the graphic format specified by the id parameter.  Search failure
+// indicated by the return of NULL.
+const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(uint32_t id)
+{
+    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+        if (id == hwcTestGraphicFormat[n1].format) {
+            return &hwcTestGraphicFormat[n1];
+        }
+    }
+
+    return NULL;
+}
+
+
+// Given the integer ID of a graphic format, return a pointer to
+// a string that describes the format.
+const char *hwcTestGraphicFormat2str(uint32_t format)
+{
+    const static char *unknown = "unknown";
+
+    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+        if (format == hwcTestGraphicFormat[n1].format) {
+            return hwcTestGraphicFormat[n1].desc;
+        }
+    }
+
+    return unknown;
+}
+
+/*
+ * hwcTestCreateLayerList
+ * Dynamically creates layer list with numLayers worth
+ * of hwLayers entries.
+ */
+hwc_layer_list_t *hwcTestCreateLayerList(size_t numLayers)
+{
+    hwc_layer_list_t *list;
+
+    size_t size = sizeof(hwc_layer_list) + numLayers * sizeof(hwc_layer_t);
+    if ((list = (hwc_layer_list_t *) calloc(1, size)) == NULL) {
+        return NULL;
+    }
+    list->flags = HWC_GEOMETRY_CHANGED;
+    list->numHwLayers = numLayers;
+
+    return list;
+}
+
+/*
+ * hwcTestFreeLayerList
+ * Frees memory previous allocated via hwcTestCreateLayerList().
+ */
+void hwcTestFreeLayerList(hwc_layer_list_t *list)
+{
+    free(list);
+}
+
+// Display the settings of the layer list pointed to by list
+void hwcTestDisplayList(hwc_layer_list_t *list)
+{
+    testPrintI("  flags: %#x%s", list->flags,
+               (list->flags & HWC_GEOMETRY_CHANGED) ? " GEOMETRY_CHANGED" : "");
+    testPrintI("  numHwLayers: %u", list->numHwLayers);
+
+    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
+        testPrintI("    layer %u compositionType: %#x%s%s", layer,
+                   list->hwLayers[layer].compositionType,
+                   (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
+                       ? " FRAMEBUFFER" : "",
+                   (list->hwLayers[layer].compositionType == HWC_OVERLAY)
+                       ? " OVERLAY" : "");
+
+        testPrintI("      hints: %#x",
+                   list->hwLayers[layer].hints,
+                   (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
+                       ? " TRIPLE_BUFFER" : "",
+                   (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
+                       ? " CLEAR_FB" : "");
+
+        testPrintI("      flags: %#x%s",
+                   list->hwLayers[layer].flags,
+                   (list->hwLayers[layer].flags & HWC_SKIP_LAYER)
+                       ? " SKIP_LAYER" : "");
+
+        testPrintI("      handle: %p",
+                   list->hwLayers[layer].handle);
+
+        // Intentionally skipped display of ROT_180 & ROT_270,
+        // which are formed from combinations of the other flags.
+        testPrintI("      transform: %#x%s%s%s",
+                   list->hwLayers[layer].transform,
+                   (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_H)
+                       ? " FLIP_H" : "",
+                   (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_V)
+                       ? " FLIP_V" : "",
+                   (list->hwLayers[layer].transform & HWC_TRANSFORM_ROT_90)
+                       ? " ROT_90" : "");
+
+        testPrintI("      blending: %#x%s%s%s",
+                   list->hwLayers[layer].blending,
+                   (list->hwLayers[layer].blending == HWC_BLENDING_NONE)
+                       ? " NONE" : "",
+                   (list->hwLayers[layer].blending == HWC_BLENDING_PREMULT)
+                       ? " PREMULT" : "",
+                   (list->hwLayers[layer].blending == HWC_BLENDING_COVERAGE)
+                       ? " COVERAGE" : "");
+
+        testPrintI("      sourceCrop: %s",
+                   hwcTestRect2str(list->hwLayers[layer].sourceCrop).c_str());
+        testPrintI("      displayFrame: %s",
+                   hwcTestRect2str(list->hwLayers[layer].displayFrame).c_str());
+        testPrintI("      scaleFactor: [%f, %f]",
+                   (float) (list->hwLayers[layer].sourceCrop.right
+                            - list->hwLayers[layer].sourceCrop.left)
+                       / (float) (list->hwLayers[layer].displayFrame.right
+                            - list->hwLayers[layer].displayFrame.left),
+                   (float) (list->hwLayers[layer].sourceCrop.bottom
+                            - list->hwLayers[layer].sourceCrop.top)
+                       / (float) (list->hwLayers[layer].displayFrame.bottom
+                            - list->hwLayers[layer].displayFrame.top));
+    }
+}
+
+/*
+ * Display List Prepare Modifiable
+ *
+ * Displays the portions of a list that are meant to be modified by
+ * a prepare call.
+ */
+void hwcTestDisplayListPrepareModifiable(hwc_layer_list_t *list)
+{
+    uint32_t numOverlays = 0;
+    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
+        if (list->hwLayers[layer].compositionType == HWC_OVERLAY) {
+            numOverlays++;
+        }
+        testPrintI("    layer %u compositionType: %#x%s%s", layer,
+                   list->hwLayers[layer].compositionType,
+                   (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
+                       ? " FRAMEBUFFER" : "",
+                   (list->hwLayers[layer].compositionType == HWC_OVERLAY)
+                       ? " OVERLAY" : "");
+        testPrintI("      hints: %#x%s%s",
+                   list->hwLayers[layer].hints,
+                   (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
+                       ? " TRIPLE_BUFFER" : "",
+                   (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
+                       ? " CLEAR_FB" : "");
+    }
+    testPrintI("    numOverlays: %u", numOverlays);
+}
+
+/*
+ * Display List Handles
+ *
+ * Displays the handles of all the graphic buffers in the list.
+ */
+void hwcTestDisplayListHandles(hwc_layer_list_t *list)
+{
+    const unsigned int maxLayersPerLine = 6;
+
+    ostringstream str("  layers:");
+    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
+        str << ' ' << list->hwLayers[layer].handle;
+        if (((layer % maxLayersPerLine) == (maxLayersPerLine - 1))
+            && (layer != list->numHwLayers - 1)) {
+            testPrintI("%s", str.str().c_str());
+            str.str("    ");
+        }
+    }
+    testPrintI("%s", str.str().c_str());
+}
+
+// Returns a uint32_t that contains a format specific representation of a
+// single pixel of the given color and alpha values.
+uint32_t hwcTestColor2Pixel(uint32_t format, ColorFract color, float alpha)
+{
+    const struct attrib {
+        uint32_t format;
+        bool   hostByteOrder;
+        size_t bytes;
+        size_t c1Offset;
+        size_t c1Size;
+        size_t c2Offset;
+        size_t c2Size;
+        size_t c3Offset;
+        size_t c3Size;
+        size_t aOffset;
+        size_t aSize;
+    } attributes[] = {
+        {HAL_PIXEL_FORMAT_RGBA_8888, false, 4,  0, 8,  8, 8, 16, 8, 24, 8},
+        {HAL_PIXEL_FORMAT_RGBX_8888, false, 4,  0, 8,  8, 8, 16, 8,  0, 0},
+        {HAL_PIXEL_FORMAT_RGB_888,   false, 3,  0, 8,  8, 8, 16, 8,  0, 0},
+        {HAL_PIXEL_FORMAT_RGB_565,   true,  2,  0, 5,  5, 6, 11, 5,  0, 0},
+        {HAL_PIXEL_FORMAT_BGRA_8888, false, 4, 16, 8,  8, 8,  0, 8, 24, 8},
+        {HAL_PIXEL_FORMAT_RGBA_5551, true , 2,  0, 5,  5, 5, 10, 5, 15, 1},
+        {HAL_PIXEL_FORMAT_RGBA_4444, false, 2, 12, 4,  0, 4,  4, 4,  8, 4},
+        {HAL_PIXEL_FORMAT_YV12,      true,  3, 16, 8,  8, 8,  0, 8,  0, 0},  
+    };
+
+    const struct attrib *attrib;
+    for (attrib = attributes; attrib < attributes + NUMA(attributes);
+         attrib++) {
+        if (attrib->format == format) { break; }
+    }
+    if (attrib >= attributes + NUMA(attributes)) {
+        testPrintE("colorFract2Pixel unsupported format of: %u", format);
+        exit(80);
+    }
+
+    uint32_t pixel;
+    pixel = htonl((uint32_t) round((((1 << attrib->c1Size) - 1) * color.c1()))
+         << ((sizeof(pixel) * BITSPERBYTE)
+             - (attrib->c1Offset + attrib->c1Size)));
+    pixel |= htonl((uint32_t) round((((1 << attrib->c2Size) - 1) * color.c2()))
+         << ((sizeof(pixel) * BITSPERBYTE)
+             - (attrib->c2Offset + attrib->c2Size)));
+    pixel |= htonl((uint32_t) round((((1 << attrib->c3Size) - 1) * color.c3()))
+         << ((sizeof(pixel) * BITSPERBYTE)
+             - (attrib->c3Offset + attrib->c3Size)));
+    if (attrib->aSize) {
+        pixel |= htonl((uint32_t) round((((1 << attrib->aSize) - 1) * alpha))
+             << ((sizeof(pixel) * BITSPERBYTE)
+                 - (attrib->aOffset + attrib->aSize)));
+    }
+    if (attrib->hostByteOrder) {
+        pixel = ntohl(pixel);
+        pixel >>= sizeof(pixel) * BITSPERBYTE - attrib->bytes * BITSPERBYTE;
+    }
+
+    return pixel;
+}
+
+// Sets the pixel at the given x and y coordinates to the color and alpha
+// value given by pixel.  The contents of pixel is format specific.  It's
+// value should come from a call to hwcTestColor2Pixel().
+void hwcTestSetPixel(GraphicBuffer *gBuf, unsigned char *buf,
+              uint32_t x, uint32_t y, uint32_t pixel)
+{
+
+    const struct attrib {
+        int format;
+        size_t bytes;
+    } attributes[] = {
+        {HAL_PIXEL_FORMAT_RGBA_8888,  4},
+        {HAL_PIXEL_FORMAT_RGBX_8888,  4},
+        {HAL_PIXEL_FORMAT_RGB_888,    3},
+        {HAL_PIXEL_FORMAT_RGB_565,    2},
+        {HAL_PIXEL_FORMAT_BGRA_8888,  4},
+        {HAL_PIXEL_FORMAT_RGBA_5551,  2},
+        {HAL_PIXEL_FORMAT_RGBA_4444,  2},
+    };
+
+    if (gBuf->getPixelFormat() == HAL_PIXEL_FORMAT_YV12) {
+        uint32_t yPlaneOffset, uPlaneOffset, vPlaneOffset;
+        uint32_t yPlaneStride = gBuf->getStride();
+        uint32_t uPlaneStride = ((gBuf->getStride() / 2) + 0xf) & ~0xf;
+        uint32_t vPlaneStride = uPlaneStride;
+        yPlaneOffset = 0;
+        vPlaneOffset = yPlaneOffset + yPlaneStride * gBuf->getHeight();
+        uPlaneOffset = vPlaneOffset
+                       + vPlaneStride * (gBuf->getHeight() / 2);
+        *(buf + yPlaneOffset + y * yPlaneStride + x) = pixel & 0xff;
+        *(buf + uPlaneOffset + (y / 2) * uPlaneStride + (x / 2))
+            = (pixel & 0xff00) >> 8;
+        *(buf + vPlaneOffset + (y / 2) * vPlaneStride + (x / 2))
+            = (pixel & 0xff0000) >> 16;
+
+        return;
+    }
+
+    const struct attrib *attrib;
+    for (attrib = attributes; attrib < attributes + NUMA(attributes);
+         attrib++) {
+        if (attrib->format == gBuf->getPixelFormat()) { break; }
+    }
+    if (attrib >= attributes + NUMA(attributes)) {
+        testPrintE("setPixel unsupported format of: %u",
+                   gBuf->getPixelFormat());
+        exit(90);
+    }
+
+    memmove(buf + ((gBuf->getStride() * attrib->bytes) * y)
+            + (attrib->bytes * x), &pixel, attrib->bytes);
+}
+
+// Fill a given graphic buffer with a uniform color and alpha
+void hwcTestFillColor(GraphicBuffer *gBuf, ColorFract color, float alpha)
+{
+    unsigned char* buf = NULL;
+    status_t err;
+    uint32_t pixel;
+
+    pixel = hwcTestColor2Pixel(gBuf->getPixelFormat(), color, alpha);
+
+    err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
+    if (err != 0) {
+        testPrintE("hwcTestFillColor lock failed: %d", err);
+        exit(100);
+    }
+
+    for (unsigned int x = 0; x < gBuf->getStride(); x++) {
+        for (unsigned int y = 0; y < gBuf->getHeight(); y++) {
+            uint32_t val = pixel;
+            hwcTestSetPixel(gBuf, buf, x, y, (x < gBuf->getWidth())
+                            ? pixel : testRand());
+        }
+    }
+
+    err = gBuf->unlock();
+    if (err != 0) {
+        testPrintE("hwcTestFillColor unlock failed: %d", err);
+        exit(101);
+    }
+}
+
+// Fill the given buffer with a horizontal blend of colors, with the left
+// side color given by startColor and the right side color given by
+// endColor.  The startColor and endColor values are specified in the format
+// given by colorFormat, which might be different from the format of the
+// graphic buffer.  When different, a color conversion is done when possible
+// to the graphic format of the graphic buffer.  A color of black is
+// produced for cases where the conversion is impossible (e.g. out of gamut
+// values).
+void hwcTestFillColorHBlend(GraphicBuffer *gBuf, uint32_t colorFormat,
+                            ColorFract startColor, ColorFract endColor)
+{
+    status_t err;
+    unsigned char* buf = NULL;
+    const uint32_t width = gBuf->getWidth();
+    const uint32_t height = gBuf->getHeight();
+    const uint32_t stride = gBuf->getStride();
+
+    err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
+    if (err != 0) {
+        testPrintE("hwcTestFillColorHBlend lock failed: %d", err);
+        exit(110);
+    }
+
+    for (unsigned int x = 0; x < stride; x++) {
+        uint32_t pixel;
+        if (x < width) {
+            ColorFract color(startColor.c1() + (endColor.c1() - startColor.c1())
+                                 * ((float) x / (float) (width - 1)),
+                             startColor.c2() + (endColor.c2() - startColor.c2())
+                                 * ((float) x / (float) (width - 1)),
+                             startColor.c3() + (endColor.c3() - startColor.c3())
+                                 * ((float) x / (float) (width - 1)));
+
+            // When formats differ, convert colors.
+            // Important to not convert when formats are the same, since
+            // out of gamut colors are always converted to black.
+            if (colorFormat != (uint32_t) gBuf->getPixelFormat()) {
+                hwcTestColorConvert(colorFormat, gBuf->getPixelFormat(), color);
+            }
+            pixel = hwcTestColor2Pixel(gBuf->getPixelFormat(), color, 1.0);
+        } else {
+            // Fill pad with random values
+            pixel = testRand();
+        }
+
+        for (unsigned int y = 0; y < height; y++) {
+            hwcTestSetPixel(gBuf, buf, x, y, pixel);
+        }
+    }
+
+    err = gBuf->unlock();
+    if (err != 0) {
+        testPrintE("hwcTestFillColorHBlend unlock failed: %d", err);
+        exit(111);
+    }
+}
+
+/*
+ * When possible, converts color specified as a full range value in
+ * the fromFormat, into an equivalent full range color in the toFormat.
+ * When conversion is impossible (e.g. out of gamut color) a color
+ * or black in the full range output format is produced.  The input
+ * color is given as a fractional color in the parameter named color.
+ * The produced color is written over the same parameter used to
+ * provide the input color.
+ *
+ * Each graphic format has 3 color components and each of these
+ * components has both a full and in gamut range.  This function uses
+ * a table that provides the full and in gamut ranges of each of the
+ * supported graphic formats.  The full range is given by members named
+ * c[123]Min to c[123]Max, while the in gamut range is given by members
+ * named c[123]Low to c[123]High.  In most cases the full and in gamut
+ * ranges are equivalent.  This occurs when the c[123]Min == c[123]Low and
+ * c[123]High == c[123]Max.
+ *
+ * The input and produced colors are both specified as a fractional amount
+ * of the full range.  The diagram below provides an overview of the
+ * conversion process.  The main steps are:
+ *
+ *   1. Produce black if the input color is out of gamut.
+ *
+ *   2. Convert the in gamut color into the fraction of the fromFromat
+ *      in gamut range.
+ *
+ *   3. Convert from the fraction of the in gamut from format range to
+ *      the fraction of the in gamut to format range.  Produce black
+ *      if an equivalent color does not exists.
+ *
+ *   4. Covert from the fraction of the in gamut to format to the
+ *      fraction of the full range to format.
+ *
+ *       From Format                 To Format
+ *    max           high            high        max
+ *    ----+                 +-----------+
+ *    high \               /             \      high
+ *    ------\-------------+               +-------->
+ *           \
+ *            \                   +--- black --+
+ *             \                 /              \
+ *              \               /                +-->
+ *    low        \             /                  low
+ *    -------- ---+-- black --+
+ *    min             low           low           min
+ *     ^               ^      ^      ^             ^
+ *     |               |      |      |             |
+ *     |               |      |      |             +-- fraction of full range
+ *     |               |      |      +-- fraction of valid range
+ *     |               |      +-- fromFormat to toFormat color conversion
+ *     |               +-- fraction of valid range
+ *     +-- fraction of full range
+ */
+void hwcTestColorConvert(uint32_t fromFormat, uint32_t toFormat,
+                  ColorFract& color)
+{
+    const struct attrib {
+        uint32_t     format;
+        bool         rgb;
+        bool         yuv;
+        int          c1Min, c1Low, c1High, c1Max;
+        int          c2Min, c2Low, c2High, c2Max;
+        int          c3Min, c3Low, c3High, c3Max;
+    } attributes[] = {
+        {HAL_PIXEL_FORMAT_RGBA_8888, true,  false,
+         0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
+        {HAL_PIXEL_FORMAT_RGBX_8888, true,  false,
+         0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
+        {HAL_PIXEL_FORMAT_RGB_888,   true,  false,
+         0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
+        {HAL_PIXEL_FORMAT_RGB_565,   true,  false,
+         0, 0, 31, 31, 0, 0, 63, 63, 0, 0, 31, 31},
+        {HAL_PIXEL_FORMAT_BGRA_8888, true,  false,
+         0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
+        {HAL_PIXEL_FORMAT_RGBA_5551, true,  false,
+         0, 0, 31, 31, 0, 0, 31, 31, 0, 0, 31, 31},
+        {HAL_PIXEL_FORMAT_RGBA_4444, true,  false,
+         0, 0, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15},
+        {HAL_PIXEL_FORMAT_YV12,      false, true,
+         0, 16, 235, 255, 0, 16, 240, 255, 0, 16, 240, 255},
+    };
+
+    const struct attrib *fromAttrib;
+    for (fromAttrib = attributes; fromAttrib < attributes + NUMA(attributes);
+         fromAttrib++) {
+        if (fromAttrib->format == fromFormat) { break; }
+    }
+    if (fromAttrib >= attributes + NUMA(attributes)) {
+        testPrintE("hwcTestColorConvert unsupported from format of: %u",
+                   fromFormat);
+        exit(120);
+    }
+
+    const struct attrib *toAttrib;
+    for (toAttrib = attributes; toAttrib < attributes + NUMA(attributes);
+         toAttrib++) {
+        if (toAttrib->format == toFormat) { break; }
+    }
+    if (toAttrib >= attributes + NUMA(attributes)) {
+        testPrintE("hwcTestColorConvert unsupported to format of: %u",
+                   toFormat);
+        exit(121);
+    }
+
+    // Produce black if any of the from components are outside the
+    // valid color range
+    float c1Val = fromAttrib->c1Min
+        + ((float) (fromAttrib->c1Max - fromAttrib->c1Min) * color.c1());
+    float c2Val = fromAttrib->c2Min
+        + ((float) (fromAttrib->c2Max - fromAttrib->c2Min) * color.c2());
+    float c3Val = fromAttrib->c3Min
+        + ((float) (fromAttrib->c3Max - fromAttrib->c3Min) * color.c3());
+    if ((c1Val < fromAttrib->c1Low) || (c1Val > fromAttrib->c1High)
+        || (c2Val < fromAttrib->c2Low) || (c2Val > fromAttrib->c2High)
+        || (c3Val < fromAttrib->c3Low) || (c3Val > fromAttrib->c3High)) {
+
+        // Return black
+        // Will use representation of black from RGBA8888 graphic format
+        // and recursively convert it to the requested graphic format.
+        color = ColorFract(0.0, 0.0, 0.0);
+        hwcTestColorConvert(HAL_PIXEL_FORMAT_RGBA_8888, toFormat, color);
+        return;
+    }
+
+    // Within from format, convert from fraction of full range
+    // to fraction of valid range
+    color = ColorFract((c1Val - fromAttrib->c1Low)
+                           / (fromAttrib->c1High - fromAttrib->c1Low),
+                       (c2Val - fromAttrib->c2Low)
+                           / (fromAttrib->c2High - fromAttrib->c2Low),
+                       (c3Val - fromAttrib->c3Low)
+                           / (fromAttrib->c3High - fromAttrib->c3Low));
+
+    // If needed perform RGB to YUV conversion
+    float wr = 0.2126, wg = 0.7152, wb = 0.0722; // ITU709 recommended constants
+    if (fromAttrib->rgb && toAttrib->yuv) {
+        float r = color.c1(), g = color.c2(), b = color.c3();
+        float y = wr * r + wg * g + wb * b;
+        float u = 0.5 * ((b - y) / (1.0 - wb)) + 0.5;
+        float v = 0.5 * ((r - y) / (1.0 - wr)) + 0.5;
+
+        // Produce black if color is outside the YUV gamut
+        if ((y < 0.0) || (y > 1.0)
+            || (u < 0.0) || (u > 1.0)
+            || (v < 0.0) || (v > 1.0)) {
+            y = 0.0;
+            u = v = 0.5;
+        }
+
+        color = ColorFract(y, u, v);
+    }
+
+    // If needed perform YUV to RGB conversion
+    // Equations determined from the ITU709 equations for RGB to YUV
+    // conversion, plus the following algebra:
+    //
+    //   u = 0.5 * ((b - y) / (1.0 - wb)) + 0.5
+    //   0.5 * ((b - y) / (1.0 - wb)) = u - 0.5
+    //   (b - y) / (1.0 - wb) = 2 * (u - 0.5)
+    //   b - y = 2 * (u - 0.5) * (1.0 - wb)
+    //   b = 2 * (u - 0.5) * (1.0 - wb) + y
+    //
+    //   v = 0.5 * ((r -y) / (1.0 - wr)) + 0.5
+    //   0.5 * ((r - y) / (1.0 - wr)) = v - 0.5
+    //   (r - y) / (1.0 - wr) = 2 * (v - 0.5)
+    //   r - y = 2 * (v - 0.5) * (1.0 - wr)
+    //   r = 2 * (v - 0.5) * (1.0 - wr) + y
+    //
+    //   y = wr * r + wg * g + wb * b
+    //   wr * r + wg * g + wb * b = y
+    //   wg * g = y - wr * r - wb * b
+    //   g = (y - wr * r - wb * b) / wg
+    if (fromAttrib->yuv && toAttrib->rgb) {
+        float y = color.c1(), u = color.c2(), v = color.c3();
+        float r = 2.0 * (v - 0.5) * (1.0 - wr) + y;
+        float b = 2.0 * (u - 0.5) * (1.0 - wb) + y;
+        float g = (y - wr * r - wb * b) / wg;
+
+        // Produce black if color is outside the RGB gamut
+        if ((r < 0.0) || (r > 1.0)
+            || (g < 0.0) || (g > 1.0)
+            || (b < 0.0) || (b > 1.0)) {
+            r = g = b = 0.0;
+        }
+
+        color = ColorFract(r, g, b);
+    }
+
+    // Within to format, convert from fraction of valid range
+    // to fraction of full range
+    c1Val = (toAttrib->c1Low
+        + (float) (toAttrib->c1High - toAttrib->c1Low) * color.c1());
+    c2Val = (toAttrib->c1Low
+        + (float) (toAttrib->c2High - toAttrib->c2Low) * color.c2());
+    c3Val = (toAttrib->c1Low
+        + (float) (toAttrib->c3High - toAttrib->c3Low) * color.c3());
+    color = ColorFract((float) (c1Val - toAttrib->c1Min)
+                           / (float) (toAttrib->c1Max - toAttrib->c1Min),
+                       (float) (c2Val - toAttrib->c2Min)
+                           / (float) (toAttrib->c2Max - toAttrib->c2Min),
+                       (float) (c3Val - toAttrib->c3Min)
+                           / (float) (toAttrib->c3Max - toAttrib->c3Min));
+}
+
+// TODO: Use PrintGLString, CechckGlError, and PrintEGLConfiguration
+//       from libglTest
+static void printGLString(const char *name, GLenum s)
+{
+    const char *v = (const char *) glGetString(s);
+
+    if (v == NULL) {
+        testPrintI("GL %s unknown", name);
+    } else {
+        testPrintI("GL %s = %s", name, v);
+    }
+}
+
+static void checkEglError(const char* op, EGLBoolean returnVal)
+{
+    if (returnVal != EGL_TRUE) {
+        testPrintE("%s() returned %d", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+            = eglGetError()) {
+        testPrintE("after %s() eglError %s (0x%x)",
+                   op, EGLUtils::strerror(error), error);
+    }
+}
+
+static void checkGlError(const char* op)
+{
+    for (GLint error = glGetError(); error; error
+            = glGetError()) {
+        testPrintE("after %s() glError (0x%x)", op, error);
+    }
+}
+
+static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config)
+{
+
+#define X(VAL) {VAL, #VAL}
+    struct {EGLint attribute; const char* name;} names[] = {
+    X(EGL_BUFFER_SIZE),
+    X(EGL_ALPHA_SIZE),
+    X(EGL_BLUE_SIZE),
+    X(EGL_GREEN_SIZE),
+    X(EGL_RED_SIZE),
+    X(EGL_DEPTH_SIZE),
+    X(EGL_STENCIL_SIZE),
+    X(EGL_CONFIG_CAVEAT),
+    X(EGL_CONFIG_ID),
+    X(EGL_LEVEL),
+    X(EGL_MAX_PBUFFER_HEIGHT),
+    X(EGL_MAX_PBUFFER_PIXELS),
+    X(EGL_MAX_PBUFFER_WIDTH),
+    X(EGL_NATIVE_RENDERABLE),
+    X(EGL_NATIVE_VISUAL_ID),
+    X(EGL_NATIVE_VISUAL_TYPE),
+    X(EGL_SAMPLES),
+    X(EGL_SAMPLE_BUFFERS),
+    X(EGL_SURFACE_TYPE),
+    X(EGL_TRANSPARENT_TYPE),
+    X(EGL_TRANSPARENT_RED_VALUE),
+    X(EGL_TRANSPARENT_GREEN_VALUE),
+    X(EGL_TRANSPARENT_BLUE_VALUE),
+    X(EGL_BIND_TO_TEXTURE_RGB),
+    X(EGL_BIND_TO_TEXTURE_RGBA),
+    X(EGL_MIN_SWAP_INTERVAL),
+    X(EGL_MAX_SWAP_INTERVAL),
+    X(EGL_LUMINANCE_SIZE),
+    X(EGL_ALPHA_MASK_SIZE),
+    X(EGL_COLOR_BUFFER_TYPE),
+    X(EGL_RENDERABLE_TYPE),
+    X(EGL_CONFORMANT),
+   };
+#undef X
+
+    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+        EGLint value = -1;
+        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute,
+                                              &value);
+        EGLint error = eglGetError();
+        if (returnVal && error == EGL_SUCCESS) {
+            testPrintI(" %s: %d (%#x)", names[j].name, value, value);
+        }
+    }
+    testPrintI("");
+}
diff --git a/opengl/tests/hwc/hwcTestLib.h b/opengl/tests/hwc/hwcTestLib.h
new file mode 100644
index 0000000..99ee608
--- /dev/null
+++ b/opengl/tests/hwc/hwcTestLib.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Hardware Composer Test Library Header
+ */
+
+#include <sstream>
+#include <string>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+#include <utils/Log.h>
+#include <testUtil.h>
+
+#include <hardware/hwcomposer.h>
+
+// Characteristics of known graphic formats
+const struct hwcTestGraphicFormat {
+    uint32_t format;
+    const char *desc;
+    uint32_t wMod, hMod; // Width/height mod this value must equal zero
+} hwcTestGraphicFormat[] = {
+    {HAL_PIXEL_FORMAT_RGBA_8888, "RGBA8888", 1, 1},
+    {HAL_PIXEL_FORMAT_RGBX_8888, "RGBX8888", 1, 1},
+    {HAL_PIXEL_FORMAT_RGB_888,   "RGB888",   1, 1},
+    {HAL_PIXEL_FORMAT_RGB_565,   "RGB565",   1, 1},
+    {HAL_PIXEL_FORMAT_BGRA_8888, "BGRA8888", 1, 1},
+    {HAL_PIXEL_FORMAT_RGBA_5551, "RGBA5551", 1, 1},
+    {HAL_PIXEL_FORMAT_RGBA_4444, "RGBA4444", 1, 1},
+    {HAL_PIXEL_FORMAT_YV12,      "YV12",     2, 2},
+};
+
+// Represent RGB color as fraction of color components.
+// Each of the color components are expected in the range [0.0, 1.0]
+class ColorFract {
+  public:
+    ColorFract(): _c1(0.0), _c2(0.0), _c3(0.0) {};
+    ColorFract(float c1, float c2, float c3): _c1(c1), _c2(c2), _c3(c3) {};
+    float c1(void) const { return _c1; }
+    float c2(void) const { return _c2; }
+    float c3(void) const { return _c3; }
+
+    operator std::string();
+
+  private:
+    float _c1;
+    float _c2;
+    float _c3;
+};
+
+// Represent RGB color as fraction of color components.
+// Each of the color components are expected in the range [0.0, 1.0]
+class ColorRGB {
+  public:
+    ColorRGB(): _r(0.0), _g(0.0), _b(0.0) {};
+    ColorRGB(float f): _r(f), _g(f), _b(f) {}; // Gray
+    ColorRGB(float r, float g, float b): _r(r), _g(g), _b(b) {};
+    float r(void) const { return _r; }
+    float g(void) const { return _g; }
+    float b(void) const { return _b; }
+
+  private:
+    float _r;
+    float _g;
+    float _b;
+};
+
+// Dimension - width and height of a rectanguler area
+class HwcTestDim {
+  public:
+    HwcTestDim(): _w(0), _h(0) {};
+    HwcTestDim(uint32_t w, uint32_t h) : _w(w), _h(h) {}
+    uint32_t width(void) const { return _w; }
+    uint32_t height(void) const { return _h; }
+    void setWidth(uint32_t w) { _w = w; }
+    void setHeight(uint32_t h) { _h = h; }
+
+    operator std::string();
+    operator hwc_rect() const;
+
+  private:
+    uint32_t _w;
+    uint32_t _h;
+};
+
+// Function Prototypes
+void hwcTestInitDisplay(bool verbose, EGLDisplay *dpy, EGLSurface *surface,
+    EGLint *width, EGLint *height);
+void hwcTestOpenHwc(hwc_composer_device_t **hwcDevicePtr);
+const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(const char *desc);
+const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(uint32_t id);
+const char *hwcTestGraphicFormat2str(uint32_t format);
+std::string hwcTestRect2str(const struct hwc_rect& rect);
+
+hwc_layer_list_t *hwcTestCreateLayerList(size_t numLayers);
+void hwcTestFreeLayerList(hwc_layer_list_t *list);
+void hwcTestDisplayList(hwc_layer_list_t *list);
+void hwcTestDisplayListPrepareModifiable(hwc_layer_list_t *list);
+void hwcTestDisplayListHandles(hwc_layer_list_t *list);
+
+uint32_t hwcTestColor2Pixel(uint32_t format, ColorFract color, float alpha);
+void hwcTestColorConvert(uint32_t fromFormat, uint32_t toFormat,
+                  ColorFract& color);
+void hwcTestSetPixel(android::GraphicBuffer *gBuf, unsigned char *buf,
+                     uint32_t x, uint32_t y, uint32_t pixel);
+void hwcTestFillColor(android::GraphicBuffer *gBuf, ColorFract color,
+                      float alpha);
+void hwcTestFillColorHBlend(android::GraphicBuffer *gBuf,
+                            uint32_t colorFormat,
+                            ColorFract startColor, ColorFract endColor);
+ColorFract hwcTestParseColor(std::istringstream& in, bool& error);
+struct hwc_rect hwcTestParseHwcRect(std::istringstream& in, bool& error);
+HwcTestDim hwcTestParseDim(std::istringstream& in, bool& error);
diff --git a/opengl/tests/hwc/hwc_stress.cpp b/opengl/tests/hwc/hwc_stress.cpp
deleted file mode 100644
index 580eb83..0000000
--- a/opengl/tests/hwc/hwc_stress.cpp
+++ /dev/null
@@ -1,1262 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/*
- * Hardware Composer stress test
- *
- * Performs a pseudo-random (prandom) sequence of operations to the
- * Hardware Composer (HWC), for a specified number of passes or for
- * a specified period of time.  By default the period of time is FLT_MAX,
- * so that the number of passes will take precedence.
- *
- * The passes are grouped together, where (pass / passesPerGroup) specifies
- * which group a particular pass is in.  This causes every passesPerGroup
- * worth of sequential passes to be within the same group.  Computationally
- * intensive operations are performed just once at the beginning of a group
- * of passes and then used by all the passes in that group.  This is done
- * so as to increase both the average and peak rate of graphic operations,
- * by moving computationally intensive operations to the beginning of a group.
- * In particular, at the start of each group of passes a set of
- * graphic buffers are created, then used by the first and remaining
- * passes of that group of passes.
- *
- * The per-group initialization of the graphic buffers is performed
- * by a function called initFrames.  This function creates an array
- * of smart pointers to the graphic buffers, in the form of a vector
- * of vectors.  The array is accessed in row major order, so each
- * row is a vector of smart pointers.  All the pointers of a single
- * row point to graphic buffers which use the same pixel format and
- * have the same dimension, although it is likely that each one is
- * filled with a different color.  This is done so that after doing
- * the first HWC prepare then set call, subsequent set calls can
- * be made with each of the layer handles changed to a different
- * graphic buffer within the same row.  Since the graphic buffers
- * in a particular row have the same pixel format and dimension,
- * additional HWC set calls can be made, without having to perform
- * an HWC prepare call.
- *
- * This test supports the following command-line options:
- *
- *   -v        Verbose
- *   -s num    Starting pass
- *   -e num    Ending pass
- *   -p num    Execute the single pass specified by num
- *   -n num    Number of set operations to perform after each prepare operation
- *   -t float  Maximum time in seconds to execute the test
- *   -d float  Delay in seconds performed after each set operation
- *   -D float  Delay in seconds performed after the last pass is executed
- *
- * Typically the test is executed for a large range of passes.  By default
- * passes 0 through 99999 (100,000 passes) are executed.  Although this test
- * does not validate the generated image, at times it is useful to reexecute
- * a particular pass and leave the displayed image on the screen for an
- * extended period of time.  This can be done either by setting the -s
- * and -e options to the desired pass, along with a large value for -D.
- * This can also be done via the -p option, again with a large value for
- * the -D options.
- *
- * So far this test only contains code to create graphic buffers with
- * a continuous solid color.  Although this test is unable to validate the
- * image produced, any image that contains other than rectangles of a solid
- * color are incorrect.  Note that the rectangles may use a transparent
- * color and have a blending operation that causes the color in overlapping
- * rectangles to be mixed.  In such cases the overlapping portions may have
- * a different color from the rest of the rectangle.
- */
-
-#include <algorithm>
-#include <assert.h>
-#include <cerrno>
-#include <cmath>
-#include <cstdlib>
-#include <ctime>
-#include <libgen.h>
-#include <sched.h>
-#include <sstream>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <vector>
-
-#include <arpa/inet.h> // For ntohl() and htonl()
-
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <ui/FramebufferNativeWindow.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/EGLUtils.h>
-
-#define LOG_TAG "hwcStressTest"
-#include <utils/Log.h>
-#include <testUtil.h>
-
-#include <hardware/hwcomposer.h>
-
-using namespace std;
-using namespace android;
-
-const float maxSizeRatio = 1.3;  // Graphic buffers can be upto this munch
-                                 // larger than the default screen size
-const unsigned int passesPerGroup = 10; // A group of passes all use the same
-                                        // graphic buffers
-
-// Ratios at which rare and frequent conditions should be produced
-const float rareRatio = 0.1;
-const float freqRatio = 0.9;
-
-// Defaults for command-line options
-const bool defaultVerbose = false;
-const unsigned int defaultStartPass = 0;
-const unsigned int defaultEndPass = 99999;
-const unsigned int defaultPerPassNumSet = 10;
-const float defaultPerSetDelay = 0.0; // Default delay after each set
-                                      // operation.  Default delay of
-                                      // zero used so as to perform the
-                                      // the set operations as quickly
-                                      // as possible.
-const float defaultEndDelay = 2.0; // Default delay between completion of
-                                   // final pass and restart of framework
-const float defaultDuration = FLT_MAX; // A fairly long time, so that
-                                       // range of passes will have
-                                       // precedence
-
-// Command-line option settings
-static bool verbose = defaultVerbose;
-static unsigned int startPass = defaultStartPass;
-static unsigned int endPass = defaultEndPass;
-static unsigned int numSet = defaultPerPassNumSet;
-static float perSetDelay = defaultPerSetDelay;
-static float endDelay = defaultEndDelay;
-static float duration = defaultDuration;
-
-// Command-line mutual exclusion detection flags.
-// Corresponding flag set true once an option is used.
-bool eFlag, sFlag, pFlag;
-
-#define MAXSTR               100
-#define MAXCMD               200
-#define BITSPERBYTE            8 // TODO: Obtain from <values.h>, once
-                                 // it has been added
-
-#define CMD_STOP_FRAMEWORK   "stop 2>&1"
-#define CMD_START_FRAMEWORK  "start 2>&1"
-
-#define NUMA(a) (sizeof(a) / sizeof(a [0]))
-#define MEMCLR(addr, size) do { \
-        memset((addr), 0, (size)); \
-    } while (0)
-
-// Represent RGB color as fraction of color components.
-// Each of the color components are expected in the range [0.0, 1.0]
-class RGBColor {
-  public:
-    RGBColor(): _r(0.0), _g(0.0), _b(0.0) {};
-    RGBColor(float f): _r(f), _g(f), _b(f) {}; // Gray
-    RGBColor(float r, float g, float b): _r(r), _g(g), _b(b) {};
-    float r(void) const { return _r; }
-    float g(void) const { return _g; }
-    float b(void) const { return _b; }
-
-  private:
-    float _r;
-    float _g;
-    float _b;
-};
-
-// Represent YUV color as fraction of color components.
-// Each of the color components are expected in the range [0.0, 1.0]
-class YUVColor {
-  public:
-    YUVColor(): _y(0.0), _u(0.0), _v(0.0) {};
-    YUVColor(float f): _y(f), _u(0.0), _v(0.0) {}; // Gray
-    YUVColor(float y, float u, float v): _y(y), _u(u), _v(v) {};
-    float y(void) const { return _y; }
-    float u(void) const { return _u; }
-    float v(void) const { return _v; }
-
-  private:
-    float _y;
-    float _u;
-    float _v;
-};
-
-// File scope constants
-static const struct graphicFormat {
-    unsigned int format;
-    const char *desc;
-    unsigned int wMod, hMod; // Width/height mod this value must equal zero
-} graphicFormat[] = {
-    {HAL_PIXEL_FORMAT_RGBA_8888, "RGBA8888", 1, 1},
-    {HAL_PIXEL_FORMAT_RGBX_8888, "RGBX8888", 1, 1},
-    {HAL_PIXEL_FORMAT_RGB_888, "RGB888", 1, 1},
-    {HAL_PIXEL_FORMAT_RGB_565, "RGB565", 1, 1},
-    {HAL_PIXEL_FORMAT_BGRA_8888, "BGRA8888", 1, 1},
-    {HAL_PIXEL_FORMAT_RGBA_5551, "RGBA5551", 1, 1},
-    {HAL_PIXEL_FORMAT_RGBA_4444, "RGBA4444", 1, 1},
-    {HAL_PIXEL_FORMAT_YV12, "YV12", 2, 2},
-};
-const unsigned int blendingOps[] = {
-    HWC_BLENDING_NONE,
-    HWC_BLENDING_PREMULT,
-    HWC_BLENDING_COVERAGE,
-};
-const unsigned int layerFlags[] = {
-    HWC_SKIP_LAYER,
-};
-const vector<unsigned int> vecLayerFlags(layerFlags,
-    layerFlags + NUMA(layerFlags));
-
-const unsigned int transformFlags[] = {
-    HWC_TRANSFORM_FLIP_H,
-    HWC_TRANSFORM_FLIP_V,
-    HWC_TRANSFORM_ROT_90,
-    // ROT_180 & ROT_270 intentionally not listed, because they
-    // they are formed from combinations of the flags already listed.
-};
-const vector<unsigned int> vecTransformFlags(transformFlags,
-    transformFlags + NUMA(transformFlags));
-
-// File scope globals
-static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
-        GraphicBuffer::USAGE_SW_WRITE_RARELY;
-static hw_module_t const *hwcModule;
-static hwc_composer_device_t *hwcDevice;
-static vector <vector <sp<GraphicBuffer> > > frames;
-static EGLDisplay dpy;
-static EGLContext context;
-static EGLSurface surface;
-static EGLint width, height;
-
-// File scope prototypes
-static void execCmd(const char *cmd);
-static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE);
-static void checkGlError(const char* op);
-static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config);
-static void printGLString(const char *name, GLenum s);
-static hwc_layer_list_t *createLayerList(size_t numLayers);
-static void freeLayerList(hwc_layer_list_t *list);
-static void fillColor(GraphicBuffer *gBuf, RGBColor color, float trans);
-static void fillColor(GraphicBuffer *gBuf, YUVColor color, float trans);
-void init(void);
-void initFrames(unsigned int seed);
-void displayList(hwc_layer_list_t *list);
-void displayListPrepareModifiable(hwc_layer_list_t *list);
-void displayListHandles(hwc_layer_list_t *list);
-const char *graphicFormat2str(unsigned int format);
-template <class T> vector<T> vectorRandSelect(const vector<T>& vec, size_t num);
-template <class T> T vectorOr(const vector<T>& vec);
-
-/*
- * Main
- *
- * Performs the following high-level sequence of operations:
- *
- *   1. Command-line parsing
- *
- *   2. Initialization
- *
- *   3. For each pass:
- *
- *        a. If pass is first pass or in a different group from the
- *           previous pass, initialize the array of graphic buffers.
- *
- *        b. Create a HWC list with room to specify a prandomly
- *           selected number of layers.
- *
- *        c. Select a subset of the rows from the graphic buffer array,
- *           such that there is a unique row to be used for each
- *           of the layers in the HWC list.
- *
- *        d. Prandomly fill in the HWC list with handles
- *           selected from any of the columns of the selected row.
- *
- *        e. Pass the populated list to the HWC prepare call.
- *
- *        f. Pass the populated list to the HWC set call.
- *
- *        g. If additional set calls are to be made, then for each
- *           additional set call, select a new set of handles and
- *           perform the set call.
- */
-int
-main(int argc, char *argv[])
-{
-    int rv, opt;
-    char *chptr;
-    unsigned int pass;
-    char cmd[MAXCMD];
-    struct timeval startTime, currentTime, delta;
-
-    testSetLogCatTag(LOG_TAG);
-
-    // Parse command line arguments
-    while ((opt = getopt(argc, argv, "vp:d:D:n:s:e:t:?h")) != -1) {
-        switch (opt) {
-          case 'd': // Delay after each set operation
-            perSetDelay = strtod(optarg, &chptr);
-            if ((*chptr != '\0') || (perSetDelay < 0.0)) {
-                testPrintE("Invalid command-line specified per pass delay of: "
-                           "%s", optarg);
-                exit(1);
-            }
-            break;
-
-          case 'D': // End of test delay
-                    // Delay between completion of final pass and restart
-                    // of framework
-            endDelay = strtod(optarg, &chptr);
-            if ((*chptr != '\0') || (endDelay < 0.0)) {
-                testPrintE("Invalid command-line specified end of test delay "
-                           "of: %s", optarg);
-                exit(2);
-            }
-            break;
-
-          case 't': // Duration
-            duration = strtod(optarg, &chptr);
-            if ((*chptr != '\0') || (duration < 0.0)) {
-                testPrintE("Invalid command-line specified duration of: %s",
-                           optarg);
-                exit(3);
-            }
-            break;
-
-          case 'n': // Num set operations per pass
-            numSet = strtoul(optarg, &chptr, 10);
-            if (*chptr != '\0') {
-                testPrintE("Invalid command-line specified num set per pass "
-                           "of: %s", optarg);
-                exit(4);
-            }
-            break;
-
-          case 's': // Starting Pass
-            sFlag = true;
-            if (pFlag) {
-                testPrintE("Invalid combination of command-line options.");
-                testPrintE("  The -p option is mutually exclusive from the");
-                testPrintE("  -s and -e options.");
-                exit(5);
-            }
-            startPass = strtoul(optarg, &chptr, 10);
-            if (*chptr != '\0') {
-                testPrintE("Invalid command-line specified starting pass "
-                           "of: %s", optarg);
-                exit(6);
-            }
-            break;
-
-          case 'e': // Ending Pass
-            eFlag = true;
-            if (pFlag) {
-                testPrintE("Invalid combination of command-line options.");
-                testPrintE("  The -p option is mutually exclusive from the");
-                testPrintE("  -s and -e options.");
-                exit(7);
-            }
-            endPass = strtoul(optarg, &chptr, 10);
-            if (*chptr != '\0') {
-                testPrintE("Invalid command-line specified ending pass "
-                           "of: %s", optarg);
-                exit(8);
-            }
-            break;
-
-          case 'p': // Run a single specified pass
-            pFlag = true;
-            if (sFlag || eFlag) {
-                testPrintE("Invalid combination of command-line options.");
-                testPrintE("  The -p option is mutually exclusive from the");
-                testPrintE("  -s and -e options.");
-                exit(9);
-            }
-            startPass = endPass = strtoul(optarg, &chptr, 10);
-            if (*chptr != '\0') {
-                testPrintE("Invalid command-line specified pass of: %s",
-                           optarg);
-                exit(10);
-            }
-            break;
-
-          case 'v': // Verbose
-            verbose = true;
-            break;
-
-          case 'h': // Help
-          case '?':
-          default:
-            testPrintE("  %s [options]", basename(argv[0]));
-            testPrintE("    options:");
-            testPrintE("      -p Execute specified pass");
-            testPrintE("      -s Starting pass");
-            testPrintE("      -e Ending pass");
-            testPrintE("      -t Duration");
-            testPrintE("      -d Delay after each set operation");
-            testPrintE("      -D End of test delay");
-            testPrintE("      -n Num set operations per pass");
-            testPrintE("      -v Verbose");
-            exit(((optopt == 0) || (optopt == '?')) ? 0 : 11);
-        }
-    }
-    if (endPass < startPass) {
-        testPrintE("Unexpected ending pass before starting pass");
-        testPrintE("  startPass: %u endPass: %u", startPass, endPass);
-        exit(12);
-    }
-    if (argc != optind) {
-        testPrintE("Unexpected command-line postional argument");
-        testPrintE("  %s [-s start_pass] [-e end_pass] [-t duration]",
-            basename(argv[0]));
-        exit(13);
-    }
-    testPrintI("duration: %g", duration);
-    testPrintI("startPass: %u", startPass);
-    testPrintI("endPass: %u", endPass);
-    testPrintI("numSet: %u", numSet);
-
-    // Stop framework
-    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
-    if (rv >= (signed) sizeof(cmd) - 1) {
-        testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
-        exit(14);
-    }
-    execCmd(cmd);
-    testDelay(1.0); // TODO - needs means to query whether asyncronous stop
-                    // framework operation has completed.  For now, just wait
-                    // a long time.
-
-    init();
-
-    // For each pass
-    gettimeofday(&startTime, NULL);
-    for (pass = startPass; pass <= endPass; pass++) {
-        // Stop if duration of work has already been performed
-        gettimeofday(&currentTime, NULL);
-        delta = tvDelta(&startTime, &currentTime);
-        if (tv2double(&delta) > duration) { break; }
-
-        // Regenerate a new set of test frames when this pass is
-        // either the first pass or is in a different group then
-        // the previous pass.  A group of passes are passes that
-        // all have the same quotient when their pass number is
-        // divided by passesPerGroup.
-        if ((pass == startPass)
-            || ((pass / passesPerGroup) != ((pass - 1) / passesPerGroup))) {
-            initFrames(pass / passesPerGroup);
-        }
-
-        testPrintI("==== Starting pass: %u", pass);
-
-        // Cause deterministic sequence of prandom numbers to be
-        // generated for this pass.
-        srand48(pass);
-
-        hwc_layer_list_t *list;
-        list = createLayerList(testRandMod(frames.size()) + 1);
-        if (list == NULL) {
-            testPrintE("createLayerList failed");
-            exit(20);
-        }
-
-        // Prandomly select a subset of frames to be used by this pass.
-        vector <vector <sp<GraphicBuffer> > > selectedFrames;
-        selectedFrames = vectorRandSelect(frames, list->numHwLayers);
-
-        // Any transform tends to create a layer that the hardware
-        // composer is unable to support and thus has to leave for
-        // SurfaceFlinger.  Place heavy bias on specifying no transforms.
-        bool noTransform = testRandFract() > rareRatio;
-
-        for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) {
-            unsigned int idx = testRandMod(selectedFrames[n1].size());
-            sp<GraphicBuffer> gBuf = selectedFrames[n1][idx];
-            hwc_layer_t *layer = &list->hwLayers[n1];
-            layer->handle = gBuf->handle;
-
-            layer->blending = blendingOps[testRandMod(NUMA(blendingOps))];
-            layer->flags = (testRandFract() > rareRatio) ? 0
-                : vectorOr(vectorRandSelect(vecLayerFlags,
-                           testRandMod(vecLayerFlags.size() + 1)));
-            layer->transform = (noTransform || testRandFract() > rareRatio) ? 0
-                : vectorOr(vectorRandSelect(vecTransformFlags,
-                           testRandMod(vecTransformFlags.size() + 1)));
-            layer->sourceCrop.left = testRandMod(gBuf->getWidth());
-            layer->sourceCrop.top = testRandMod(gBuf->getHeight());
-            layer->sourceCrop.right = layer->sourceCrop.left
-                + testRandMod(gBuf->getWidth() - layer->sourceCrop.left) + 1;
-            layer->sourceCrop.bottom = layer->sourceCrop.top
-                + testRandMod(gBuf->getHeight() - layer->sourceCrop.top) + 1;
-            layer->displayFrame.left = testRandMod(width);
-            layer->displayFrame.top = testRandMod(height);
-            layer->displayFrame.right = layer->displayFrame.left
-                + testRandMod(width - layer->displayFrame.left) + 1;
-            layer->displayFrame.bottom = layer->displayFrame.top
-                + testRandMod(height - layer->displayFrame.top) + 1;
-
-            // Increase the frequency that a scale factor of 1.0 from
-            // the sourceCrop to displayFrame occurs.  This is the
-            // most common scale factor used by applications and would
-            // be rarely produced by this stress test without this
-            // logic.
-            if (testRandFract() <= freqRatio) {
-                // Only change to scale factor to 1.0 if both the
-                // width and height will fit.
-                int sourceWidth = layer->sourceCrop.right
-                                  - layer->sourceCrop.left;
-                int sourceHeight = layer->sourceCrop.bottom
-                                   - layer->sourceCrop.top;
-                if (((layer->displayFrame.left + sourceWidth) <= width)
-                    && ((layer->displayFrame.top + sourceHeight) <= height)) {
-                    layer->displayFrame.right = layer->displayFrame.left
-                                                + sourceWidth;
-                    layer->displayFrame.bottom = layer->displayFrame.top
-                                                 + sourceHeight;
-                }
-            }
-
-            layer->visibleRegionScreen.numRects = 1;
-            layer->visibleRegionScreen.rects = &layer->displayFrame;
-        }
-
-        // Perform prepare operation
-        if (verbose) { testPrintI("Prepare:"); displayList(list); }
-        hwcDevice->prepare(hwcDevice, list);
-        if (verbose) {
-            testPrintI("Post Prepare:");
-            displayListPrepareModifiable(list);
-        }
-
-        // Turn off the geometry changed flag
-        list->flags &= ~HWC_GEOMETRY_CHANGED;
-
-        // Perform the set operation(s)
-        if (verbose) {testPrintI("Set:"); }
-        for (unsigned int n1 = 0; n1 < numSet; n1++) {
-            if (verbose) {displayListHandles(list); }
-            hwcDevice->set(hwcDevice, dpy, surface, list);
-
-            // Prandomly select a new set of handles
-            for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) {
-                unsigned int idx = testRandMod(selectedFrames[n1].size());
-                sp<GraphicBuffer> gBuf = selectedFrames[n1][idx];
-                hwc_layer_t *layer = &list->hwLayers[n1];
-                layer->handle = (native_handle_t *) gBuf->handle;
-            }
-
-            testDelay(perSetDelay);
-        }
-
-
-        freeLayerList(list);
-        testPrintI("==== Completed pass: %u", pass);
-    }
-
-    testDelay(endDelay);
-
-    // Start framework
-    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
-    if (rv >= (signed) sizeof(cmd) - 1) {
-        testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
-        exit(21);
-    }
-    execCmd(cmd);
-
-    testPrintI("Successfully completed %u passes", pass - startPass);
-
-    return 0;
-}
-
-/*
- * Execute Command
- *
- * Executes the command pointed to by cmd.  Output from the
- * executed command is captured and sent to LogCat Info.  Once
- * the command has finished execution, it's exit status is captured
- * and checked for an exit status of zero.  Any other exit status
- * causes diagnostic information to be printed and an immediate
- * testcase failure.
- */
-static void execCmd(const char *cmd)
-{
-    FILE *fp;
-    int rv;
-    int status;
-    char str[MAXSTR];
-
-    // Display command to be executed
-    testPrintI("cmd: %s", cmd);
-
-    // Execute the command
-    fflush(stdout);
-    if ((fp = popen(cmd, "r")) == NULL) {
-        testPrintE("execCmd popen failed, errno: %i", errno);
-        exit(30);
-    }
-
-    // Obtain and display each line of output from the executed command
-    while (fgets(str, sizeof(str), fp) != NULL) {
-        if ((strlen(str) > 1) && (str[strlen(str) - 1] == '\n')) {
-            str[strlen(str) - 1] = '\0';
-        }
-        testPrintI(" out: %s", str);
-    }
-
-    // Obtain and check return status of executed command.
-    // Fail on non-zero exit status
-    status = pclose(fp);
-    if (!(WIFEXITED(status) && (WEXITSTATUS(status) == 0))) {
-        testPrintE("Unexpected command failure");
-        testPrintE("  status: %#x", status);
-        if (WIFEXITED(status)) {
-            testPrintE("WEXITSTATUS: %i", WEXITSTATUS(status));
-        }
-        if (WIFSIGNALED(status)) {
-            testPrintE("WTERMSIG: %i", WTERMSIG(status));
-        }
-        exit(31);
-    }
-}
-
-static void checkEglError(const char* op, EGLBoolean returnVal) {
-    if (returnVal != EGL_TRUE) {
-        testPrintE("%s() returned %d", op, returnVal);
-    }
-
-    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
-            = eglGetError()) {
-        testPrintE("after %s() eglError %s (0x%x)",
-                   op, EGLUtils::strerror(error), error);
-    }
-}
-
-static void checkGlError(const char* op) {
-    for (GLint error = glGetError(); error; error
-            = glGetError()) {
-        testPrintE("after %s() glError (0x%x)", op, error);
-    }
-}
-
-static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
-
-#define X(VAL) {VAL, #VAL}
-    struct {EGLint attribute; const char* name;} names[] = {
-    X(EGL_BUFFER_SIZE),
-    X(EGL_ALPHA_SIZE),
-    X(EGL_BLUE_SIZE),
-    X(EGL_GREEN_SIZE),
-    X(EGL_RED_SIZE),
-    X(EGL_DEPTH_SIZE),
-    X(EGL_STENCIL_SIZE),
-    X(EGL_CONFIG_CAVEAT),
-    X(EGL_CONFIG_ID),
-    X(EGL_LEVEL),
-    X(EGL_MAX_PBUFFER_HEIGHT),
-    X(EGL_MAX_PBUFFER_PIXELS),
-    X(EGL_MAX_PBUFFER_WIDTH),
-    X(EGL_NATIVE_RENDERABLE),
-    X(EGL_NATIVE_VISUAL_ID),
-    X(EGL_NATIVE_VISUAL_TYPE),
-    X(EGL_SAMPLES),
-    X(EGL_SAMPLE_BUFFERS),
-    X(EGL_SURFACE_TYPE),
-    X(EGL_TRANSPARENT_TYPE),
-    X(EGL_TRANSPARENT_RED_VALUE),
-    X(EGL_TRANSPARENT_GREEN_VALUE),
-    X(EGL_TRANSPARENT_BLUE_VALUE),
-    X(EGL_BIND_TO_TEXTURE_RGB),
-    X(EGL_BIND_TO_TEXTURE_RGBA),
-    X(EGL_MIN_SWAP_INTERVAL),
-    X(EGL_MAX_SWAP_INTERVAL),
-    X(EGL_LUMINANCE_SIZE),
-    X(EGL_ALPHA_MASK_SIZE),
-    X(EGL_COLOR_BUFFER_TYPE),
-    X(EGL_RENDERABLE_TYPE),
-    X(EGL_CONFORMANT),
-   };
-#undef X
-
-    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
-        EGLint value = -1;
-        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
-        EGLint error = eglGetError();
-        if (returnVal && error == EGL_SUCCESS) {
-            testPrintI(" %s: %d (%#x)", names[j].name, value, value);
-        }
-    }
-    testPrintI("");
-}
-
-static void printGLString(const char *name, GLenum s)
-{
-    const char *v = (const char *) glGetString(s);
-
-    if (v == NULL) {
-        testPrintI("GL %s unknown", name);
-    } else {
-        testPrintI("GL %s = %s", name, v);
-    }
-}
-
-/*
- * createLayerList
- * dynamically creates layer list with numLayers worth
- * of hwLayers entries.
- */
-static hwc_layer_list_t *createLayerList(size_t numLayers)
-{
-    hwc_layer_list_t *list;
-
-    size_t size = sizeof(hwc_layer_list) + numLayers * sizeof(hwc_layer_t);
-    if ((list = (hwc_layer_list_t *) calloc(1, size)) == NULL) {
-        return NULL;
-    }
-    list->flags = HWC_GEOMETRY_CHANGED;
-    list->numHwLayers = numLayers;
-
-    return list;
-}
-
-/*
- * freeLayerList
- * Frees memory previous allocated via createLayerList().
- */
-static void freeLayerList(hwc_layer_list_t *list)
-{
-    free(list);
-}
-
-static void fillColor(GraphicBuffer *gBuf, RGBColor color, float trans)
-{
-    unsigned char* buf = NULL;
-    status_t err;
-    uint32_t pixel;
-
-    // RGB 2 YUV conversion ratios
-    const struct rgb2yuvRatios {
-        int format;
-        float weightRed;
-        float weightBlu;
-        float weightGrn;
-    } rgb2yuvRatios[] = {
-        { HAL_PIXEL_FORMAT_YV12, 0.299, 0.114, 0.587 },
-    };
-
-    const struct rgbAttrib {
-        int format;
-        bool   hostByteOrder;
-        size_t bytes;
-        size_t rOffset;
-        size_t rSize;
-        size_t gOffset;
-        size_t gSize;
-        size_t bOffset;
-        size_t bSize;
-        size_t aOffset;
-        size_t aSize;
-    } rgbAttributes[] = {
-        {HAL_PIXEL_FORMAT_RGBA_8888, false, 4,  0, 8,  8, 8, 16, 8, 24, 8},
-        {HAL_PIXEL_FORMAT_RGBX_8888, false, 4,  0, 8,  8, 8, 16, 8,  0, 0},
-        {HAL_PIXEL_FORMAT_RGB_888,   false, 3,  0, 8,  8, 8, 16, 8,  0, 0},
-        {HAL_PIXEL_FORMAT_RGB_565,   true,  2,  0, 5,  5, 6, 11, 5,  0, 0},
-        {HAL_PIXEL_FORMAT_BGRA_8888, false, 4, 16, 8,  8, 8,  0, 8, 24, 8},
-        {HAL_PIXEL_FORMAT_RGBA_5551, true , 2,  0, 5,  5, 5, 10, 5, 15, 1},
-        {HAL_PIXEL_FORMAT_RGBA_4444, false, 2, 12, 4,  0, 4,  4, 4,  8, 4},
-    };
-
-    // If YUV format, convert color and pass work to YUV color fill
-    for (unsigned int n1 = 0; n1 < NUMA(rgb2yuvRatios); n1++) {
-        if (gBuf->getPixelFormat() == rgb2yuvRatios[n1].format) {
-            float wr = rgb2yuvRatios[n1].weightRed;
-            float wb = rgb2yuvRatios[n1].weightBlu;
-            float wg = rgb2yuvRatios[n1].weightGrn;
-            float y = wr * color.r() + wb * color.b() + wg * color.g();
-            float u = 0.5 * ((color.b() - y) / (1 - wb)) + 0.5;
-            float v = 0.5 * ((color.r() - y) / (1 - wr)) + 0.5;
-            YUVColor yuvColor(y, u, v);
-            fillColor(gBuf, yuvColor, trans);
-            return;
-        }
-    }
-
-    const struct rgbAttrib *attrib;
-    for (attrib = rgbAttributes; attrib < rgbAttributes + NUMA(rgbAttributes);
-         attrib++) {
-        if (attrib->format == gBuf->getPixelFormat()) { break; }
-    }
-    if (attrib >= rgbAttributes + NUMA(rgbAttributes)) {
-        testPrintE("fillColor rgb unsupported format of: %u",
-        gBuf->getPixelFormat());
-        exit(50);
-    }
-
-    pixel = htonl((uint32_t) (((1 << attrib->rSize) - 1) * color.r())
-         << ((sizeof(pixel) * BITSPERBYTE)
-             - (attrib->rOffset + attrib->rSize)));
-    pixel |= htonl((uint32_t) (((1 << attrib->gSize) - 1) * color.g())
-         << ((sizeof(pixel) * BITSPERBYTE)
-             - (attrib->gOffset + attrib->gSize)));
-    pixel |= htonl((uint32_t) (((1 << attrib->bSize) - 1) * color.b())
-         << ((sizeof(pixel) * BITSPERBYTE)
-             - (attrib->bOffset + attrib->bSize)));
-    if (attrib->aSize) {
-        pixel |= htonl((uint32_t) (((1 << attrib->aSize) - 1) * trans)
-             << ((sizeof(pixel) * BITSPERBYTE)
-                 - (attrib->aOffset + attrib->aSize)));
-    }
-    if (attrib->hostByteOrder) {
-        pixel = ntohl(pixel);
-        pixel >>= sizeof(pixel) * BITSPERBYTE - attrib->bytes * BITSPERBYTE;
-    }
-
-    err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
-    if (err != 0) {
-        testPrintE("fillColor rgb lock failed: %d", err);
-        exit(51);
-    }
-
-    for (unsigned int row = 0; row < gBuf->getHeight(); row++) {
-        for (unsigned int col = 0; col < gBuf->getWidth(); col++) {
-          memmove(buf, &pixel, attrib->bytes);
-          buf += attrib->bytes;
-        }
-        for (unsigned int pad = 0;
-             pad < (gBuf->getStride() - gBuf->getWidth()) * attrib->bytes;
-             pad++) {
-            *buf++ = testRandMod(256);
-        }
-    }
-
-    err = gBuf->unlock();
-    if (err != 0) {
-        testPrintE("fillColor rgb unlock failed: %d", err);
-        exit(52);
-    }
-}
-
-static void fillColor(GraphicBuffer *gBuf, YUVColor color, float trans)
-{
-    unsigned char* buf = NULL;
-    status_t err;
-    unsigned int width = gBuf->getWidth();
-    unsigned int height = gBuf->getHeight();
-
-    const struct yuvAttrib {
-        int format;
-        bool   planar;
-        unsigned int uSubSampX;
-        unsigned int uSubSampY;
-        unsigned int vSubSampX;
-        unsigned int vSubSampY;
-    } yuvAttributes[] = {
-        { HAL_PIXEL_FORMAT_YV12, true, 2, 2, 2, 2},
-    };
-
-    const struct yuvAttrib *attrib;
-    for (attrib = yuvAttributes; attrib < yuvAttributes + NUMA(yuvAttributes);
-         attrib++) {
-        if (attrib->format == gBuf->getPixelFormat()) { break; }
-    }
-    if (attrib >= yuvAttributes + NUMA(yuvAttributes)) {
-        testPrintE("fillColor yuv unsupported format of: %u",
-        gBuf->getPixelFormat());
-        exit(60);
-    }
-
-    assert(attrib->planar == true); // So far, only know how to handle planar
-
-    err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
-    if (err != 0) {
-        testPrintE("fillColor lock failed: %d", err);
-        exit(61);
-    }
-
-    // Fill in Y component
-    for (unsigned int row = 0; row < height; row++) {
-        for (unsigned int col = 0; col < width; col++) {
-            *buf++ = 255 * color.y();
-        }
-        for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
-             pad++) {
-             *buf++ = testRandMod(256);
-        }
-    }
-
-    // Fill in U component
-    for (unsigned int row = 0; row < height; row += attrib->uSubSampY) {
-        for (unsigned int col = 0; col < width; col += attrib->uSubSampX) {
-            *buf++ = 255 * color.u();
-        }
-        for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
-             pad += attrib->uSubSampX) {
-            *buf++ = testRandMod(256);
-        }
-    }
-
-    // Fill in V component
-    for (unsigned int row = 0; row < height; row += attrib->vSubSampY) {
-        for (unsigned int col = 0; col < width; col += attrib->vSubSampX) {
-            *buf++ = 255 * color.v();
-        }
-        for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
-             pad += attrib->vSubSampX) {
-            *buf++ = testRandMod(256);
-        }
-    }
-
-    err = gBuf->unlock();
-    if (err != 0) {
-        testPrintE("fillColor unlock failed: %d", err);
-        exit(62);
-    }
-}
-
-void init(void)
-{
-    int rv;
-
-    EGLBoolean returnValue;
-    EGLConfig myConfig = {0};
-    EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
-    EGLint sConfigAttribs[] = {
-        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-        EGL_NONE };
-    EGLint majorVersion, minorVersion;
-
-    checkEglError("<init>");
-    dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    checkEglError("eglGetDisplay");
-    if (dpy == EGL_NO_DISPLAY) {
-        testPrintE("eglGetDisplay returned EGL_NO_DISPLAY");
-        exit(70);
-    }
-
-    returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
-    checkEglError("eglInitialize", returnValue);
-    testPrintI("EGL version %d.%d", majorVersion, minorVersion);
-    if (returnValue != EGL_TRUE) {
-        testPrintE("eglInitialize failed");
-        exit(71);
-    }
-
-    EGLNativeWindowType window = android_createDisplaySurface();
-    if (window == NULL) {
-        testPrintE("android_createDisplaySurface failed");
-        exit(72);
-    }
-    returnValue = EGLUtils::selectConfigForNativeWindow(dpy,
-        sConfigAttribs, window, &myConfig);
-    if (returnValue) {
-        testPrintE("EGLUtils::selectConfigForNativeWindow() returned %d",
-            returnValue);
-        exit(73);
-    }
-    checkEglError("EGLUtils::selectConfigForNativeWindow");
-
-    testPrintI("Chose this configuration:");
-    printEGLConfiguration(dpy, myConfig);
-
-    surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
-    checkEglError("eglCreateWindowSurface");
-    if (surface == EGL_NO_SURFACE) {
-        testPrintE("gelCreateWindowSurface failed.");
-        exit(74);
-    }
-
-    context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, contextAttribs);
-    checkEglError("eglCreateContext");
-    if (context == EGL_NO_CONTEXT) {
-        testPrintE("eglCreateContext failed");
-        exit(75);
-    }
-    returnValue = eglMakeCurrent(dpy, surface, surface, context);
-    checkEglError("eglMakeCurrent", returnValue);
-    if (returnValue != EGL_TRUE) {
-        testPrintE("eglMakeCurrent failed");
-        exit(76);
-    }
-    eglQuerySurface(dpy, surface, EGL_WIDTH, &width);
-    checkEglError("eglQuerySurface");
-    eglQuerySurface(dpy, surface, EGL_HEIGHT, &height);
-    checkEglError("eglQuerySurface");
-
-    testPrintI("Window dimensions: %d x %d", width, height);
-
-    printGLString("Version", GL_VERSION);
-    printGLString("Vendor", GL_VENDOR);
-    printGLString("Renderer", GL_RENDERER);
-    printGLString("Extensions", GL_EXTENSIONS);
-
-    if ((rv = hw_get_module(HWC_HARDWARE_MODULE_ID, &hwcModule)) != 0) {
-        testPrintE("hw_get_module failed, rv: %i", rv);
-        errno = -rv;
-        perror(NULL);
-        exit(77);
-    }
-    if ((rv = hwc_open(hwcModule, &hwcDevice)) != 0) {
-        testPrintE("hwc_open failed, rv: %i", rv);
-        errno = -rv;
-        perror(NULL);
-        exit(78);
-    }
-
-    testPrintI("");
-}
-
-/*
- * Initialize Frames
- *
- * Creates an array of graphic buffers, within the global variable
- * named frames.  The graphic buffers are contained within a vector of
- * vectors.  All the graphic buffers in a particular row are of the same
- * format and dimension.  Each graphic buffer is uniformly filled with a
- * prandomly selected color.  It is likely that each buffer, even
- * in the same row, will be filled with a unique color.
- */
-void initFrames(unsigned int seed)
-{
-    int rv;
-    const size_t maxRows = 5;
-    const size_t minCols = 2;  // Need at least double buffering
-    const size_t maxCols = 4;  // One more than triple buffering
-
-    if (verbose) { testPrintI("initFrames seed: %u", seed); }
-    srand48(seed);
-    size_t rows = testRandMod(maxRows) + 1;
-
-    frames.clear();
-    frames.resize(rows);
-
-    for (unsigned int row = 0; row < rows; row++) {
-        // All frames within a row have to have the same format and
-        // dimensions.  Width and height need to be >= 1.
-        unsigned int formatIdx = testRandMod(NUMA(graphicFormat));
-        const struct graphicFormat *formatPtr = &graphicFormat[formatIdx];
-        int format = formatPtr->format;
-
-        // Pick width and height, which must be >= 1 and the size
-        // mod the wMod/hMod value must be equal to 0.
-        size_t w = (width * maxSizeRatio) * testRandFract();
-        size_t h = (height * maxSizeRatio) * testRandFract();
-        w = max(1u, w);
-        h = max(1u, h);
-        if ((w % formatPtr->wMod) != 0) {
-            w += formatPtr->wMod - (w % formatPtr->wMod);
-        }
-        if ((h % formatPtr->hMod) != 0) {
-            h += formatPtr->hMod - (h % formatPtr->hMod);
-        }
-        if (verbose) {
-            testPrintI("  frame %u width: %u height: %u format: %u %s",
-                       row, w, h, format, graphicFormat2str(format));
-        }
-
-        size_t cols = testRandMod((maxCols + 1) - minCols) + minCols;
-        frames[row].resize(cols);
-        for (unsigned int col = 0; col < cols; col++) {
-            RGBColor color(testRandFract(), testRandFract(), testRandFract());
-            float transp = testRandFract();
-
-            frames[row][col] = new GraphicBuffer(w, h, format, texUsage);
-            if ((rv = frames[row][col]->initCheck()) != NO_ERROR) {
-                testPrintE("GraphicBuffer initCheck failed, rv: %i", rv);
-                testPrintE("  frame %u width: %u height: %u format: %u %s",
-                           row, w, h, format, graphicFormat2str(format));
-                exit(80);
-            }
-
-            fillColor(frames[row][col].get(), color, transp);
-            if (verbose) {
-                testPrintI("    buf: %p handle: %p color: <%f, %f, %f> "
-                           "transp: %f",
-                           frames[row][col].get(), frames[row][col]->handle,
-                           color.r(), color.g(), color.b(), transp);
-            }
-        }
-    }
-}
-
-void displayList(hwc_layer_list_t *list)
-{
-    testPrintI("  flags: %#x%s", list->flags,
-               (list->flags & HWC_GEOMETRY_CHANGED) ? " GEOMETRY_CHANGED" : "");
-    testPrintI("  numHwLayers: %u", list->numHwLayers);
-
-    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
-        testPrintI("    layer %u compositionType: %#x%s%s", layer,
-                   list->hwLayers[layer].compositionType,
-                   (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
-                       ? " FRAMEBUFFER" : "",
-                   (list->hwLayers[layer].compositionType == HWC_OVERLAY)
-                       ? " OVERLAY" : "");
-
-        testPrintI("      hints: %#x",
-                   list->hwLayers[layer].hints,
-                   (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
-                       ? " TRIPLE_BUFFER" : "",
-                   (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
-                       ? " CLEAR_FB" : "");
-
-        testPrintI("      flags: %#x%s",
-                   list->hwLayers[layer].flags,
-                   (list->hwLayers[layer].flags & HWC_SKIP_LAYER)
-                       ? " SKIP_LAYER" : "");
-
-        testPrintI("      handle: %p",
-                   list->hwLayers[layer].handle);
-
-        // Intentionally skipped display of ROT_180 & ROT_270,
-        // which are formed from combinations of the other flags.
-        testPrintI("      transform: %#x%s%s%s",
-                   list->hwLayers[layer].transform,
-                   (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_H)
-                       ? " FLIP_H" : "",
-                   (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_V)
-                       ? " FLIP_V" : "",
-                   (list->hwLayers[layer].transform & HWC_TRANSFORM_ROT_90)
-                       ? " ROT_90" : "");
-
-        testPrintI("      blending: %#x",
-                   list->hwLayers[layer].blending,
-                   (list->hwLayers[layer].blending == HWC_BLENDING_NONE)
-                       ? " NONE" : "",
-                   (list->hwLayers[layer].blending == HWC_BLENDING_PREMULT)
-                       ? " PREMULT" : "",
-                   (list->hwLayers[layer].blending == HWC_BLENDING_COVERAGE)
-                       ? " COVERAGE" : "");
-
-        testPrintI("      sourceCrop: [%i, %i, %i, %i]",
-                   list->hwLayers[layer].sourceCrop.left,
-                   list->hwLayers[layer].sourceCrop.top,
-                   list->hwLayers[layer].sourceCrop.right,
-                   list->hwLayers[layer].sourceCrop.bottom);
-
-        testPrintI("      displayFrame: [%i, %i, %i, %i]",
-                   list->hwLayers[layer].displayFrame.left,
-                   list->hwLayers[layer].displayFrame.top,
-                   list->hwLayers[layer].displayFrame.right,
-                   list->hwLayers[layer].displayFrame.bottom);
-        testPrintI("      scaleFactor: [%f %f]",
-                   (float) (list->hwLayers[layer].displayFrame.right
-                            - list->hwLayers[layer].displayFrame.left)
-                       / (float) (list->hwLayers[layer].sourceCrop.right
-                            - list->hwLayers[layer].sourceCrop.left),
-                   (float) (list->hwLayers[layer].displayFrame.bottom
-                            - list->hwLayers[layer].displayFrame.top)
-                       / (float) (list->hwLayers[layer].sourceCrop.bottom
-                            - list->hwLayers[layer].sourceCrop.top));
-    }
-}
-
-/*
- * Display List Prepare Modifiable
- *
- * Displays the portions of a list that are meant to be modified by
- * a prepare call.
- */
-void displayListPrepareModifiable(hwc_layer_list_t *list)
-{
-    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
-        testPrintI("    layer %u compositionType: %#x%s%s", layer,
-                   list->hwLayers[layer].compositionType,
-                   (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
-                       ? " FRAMEBUFFER" : "",
-                   (list->hwLayers[layer].compositionType == HWC_OVERLAY)
-                       ? " OVERLAY" : "");
-        testPrintI("      hints: %#x%s%s",
-                   list->hwLayers[layer].hints,
-                   (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
-                       ? " TRIPLE_BUFFER" : "",
-                   (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
-                       ? " CLEAR_FB" : "");
-    }
-}
-
-/*
- * Display List Handles
- *
- * Displays the handles of all the graphic buffers in the list.
- */
-void displayListHandles(hwc_layer_list_t *list)
-{
-    const unsigned int maxLayersPerLine = 6;
-
-    ostringstream str("  layers:");
-    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
-        str << ' ' << list->hwLayers[layer].handle;
-        if (((layer % maxLayersPerLine) == (maxLayersPerLine - 1))
-            && (layer != list->numHwLayers - 1)) {
-            testPrintI("%s", str.str().c_str());
-            str.str("    ");
-        }
-    }
-    testPrintI("%s", str.str().c_str());
-}
-
-const char *graphicFormat2str(unsigned int format)
-{
-    const static char *unknown = "unknown";
-
-    for (unsigned int n1 = 0; n1 < NUMA(graphicFormat); n1++) {
-        if (format == graphicFormat[n1].format) {
-            return graphicFormat[n1].desc;
-        }
-    }
-
-    return unknown;
-}
-
-/*
- * Vector Random Select
- *
- * Prandomly selects and returns num elements from vec.
- */
-template <class T>
-vector<T> vectorRandSelect(const vector<T>& vec, size_t num)
-{
-    vector<T> rv = vec;
-
-    while (rv.size() > num) {
-        rv.erase(rv.begin() + testRandMod(rv.size()));
-    }
-
-    return rv;
-}
-
-/*
- * Vector Or
- *
- * Or's togethen the values of each element of vec and returns the result.
- */
-template <class T>
-T vectorOr(const vector<T>& vec)
-{
-    T rv = 0;
-
-    for (size_t n1 = 0; n1 < vec.size(); n1++) {
-        rv |= vec[n1];
-    }
-
-    return rv;
-}
diff --git a/opengl/tests/include/glTestLib.h b/opengl/tests/include/glTestLib.h
new file mode 100644
index 0000000..06fbf5d
--- /dev/null
+++ b/opengl/tests/include/glTestLib.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Graphics Test Library Header
+ */
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+//#include <ui/FramebufferNativeWindow.h>
+//#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+void glTestPrintGLString(const char *name, GLenum s);
+void glTestCheckEglError(const char* op, EGLBoolean returnVal = EGL_TRUE);
+void glTestCheckGlError(const char* op);
+void glTestPrintEGLConfiguration(EGLDisplay dpy, EGLConfig config);
diff --git a/opengl/tests/lib/Android.mk b/opengl/tests/lib/Android.mk
new file mode 100644
index 0000000..7542ac4
--- /dev/null
+++ b/opengl/tests/lib/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE:= libglTest
+LOCAL_SRC_FILES:= glTestLib.cpp
+LOCAL_C_INCLUDES += system/extras/tests/include \
+    bionic \
+    bionic/libstdc++/include \
+    external/stlport/stlport \
+    frameworks/base/opengl/tests/include \
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+LOCAL_SHARED_LIBRARIES += libcutils libutils libstlport
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/opengl/tests/lib/glTestLib.cpp b/opengl/tests/lib/glTestLib.cpp
new file mode 100644
index 0000000..052cbd7
--- /dev/null
+++ b/opengl/tests/lib/glTestLib.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Graphics Test Library
+ */
+
+#include <glTestLib.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <ui/EGLUtils.h>
+
+#include <utils/Log.h>
+#include <testUtil.h>
+
+using namespace std;
+using namespace android;
+
+void glTestPrintGLString(const char *name, GLenum s)
+{
+    const char *v = (const char *) glGetString(s);
+
+    if (v == NULL) {
+        testPrintI("GL %s unknown", name);
+    } else {
+        testPrintI("GL %s = %s", name, v);
+    }
+}
+
+void glTestCheckEglError(const char* op, EGLBoolean returnVal)
+{
+    if (returnVal != EGL_TRUE) {
+        testPrintE("%s() returned %d", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+            = eglGetError()) {
+        testPrintE("after %s() eglError %s (0x%x)",
+                   op, EGLUtils::strerror(error), error);
+    }
+}
+
+void glTestCheckGlError(const char* op)
+{
+    for (GLint error = glGetError(); error; error
+            = glGetError()) {
+        testPrintE("after %s() glError (0x%x)", op, error);
+    }
+}
+
+void glTestPrintEGLConfiguration(EGLDisplay dpy, EGLConfig config)
+{
+
+#define X(VAL) {VAL, #VAL}
+    struct {EGLint attribute; const char* name;} names[] = {
+    X(EGL_BUFFER_SIZE),
+    X(EGL_ALPHA_SIZE),
+    X(EGL_BLUE_SIZE),
+    X(EGL_GREEN_SIZE),
+    X(EGL_RED_SIZE),
+    X(EGL_DEPTH_SIZE),
+    X(EGL_STENCIL_SIZE),
+    X(EGL_CONFIG_CAVEAT),
+    X(EGL_CONFIG_ID),
+    X(EGL_LEVEL),
+    X(EGL_MAX_PBUFFER_HEIGHT),
+    X(EGL_MAX_PBUFFER_PIXELS),
+    X(EGL_MAX_PBUFFER_WIDTH),
+    X(EGL_NATIVE_RENDERABLE),
+    X(EGL_NATIVE_VISUAL_ID),
+    X(EGL_NATIVE_VISUAL_TYPE),
+    X(EGL_SAMPLES),
+    X(EGL_SAMPLE_BUFFERS),
+    X(EGL_SURFACE_TYPE),
+    X(EGL_TRANSPARENT_TYPE),
+    X(EGL_TRANSPARENT_RED_VALUE),
+    X(EGL_TRANSPARENT_GREEN_VALUE),
+    X(EGL_TRANSPARENT_BLUE_VALUE),
+    X(EGL_BIND_TO_TEXTURE_RGB),
+    X(EGL_BIND_TO_TEXTURE_RGBA),
+    X(EGL_MIN_SWAP_INTERVAL),
+    X(EGL_MAX_SWAP_INTERVAL),
+    X(EGL_LUMINANCE_SIZE),
+    X(EGL_ALPHA_MASK_SIZE),
+    X(EGL_COLOR_BUFFER_TYPE),
+    X(EGL_RENDERABLE_TYPE),
+    X(EGL_CONFORMANT),
+   };
+#undef X
+
+    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+        EGLint value = -1;
+        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute,
+                                              &value);
+        EGLint error = eglGetError();
+        if (returnVal && error == EGL_SUCCESS) {
+            testPrintI(" %s: %d (%#x)", names[j].name, value, value);
+        }
+    }
+    testPrintI("");
+}
diff --git a/packages/DefaultContainerService/res/values-ar/strings.xml b/packages/DefaultContainerService/res/values-ar/strings.xml
index b9c27b7..823e472 100644
--- a/packages/DefaultContainerService/res/values-ar/strings.xml
+++ b/packages/DefaultContainerService/res/values-ar/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"خدمة حاوية الوسائط"</string>
+    <string name="service_name" msgid="4841491635055379553">"مساعد الدخول إلى الحزمة"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-bg/strings.xml b/packages/DefaultContainerService/res/values-bg/strings.xml
index 3546c03..7f8939a 100644
--- a/packages/DefaultContainerService/res/values-bg/strings.xml
+++ b/packages/DefaultContainerService/res/values-bg/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Услуга за контейнер за мултимедия"</string>
+    <string name="service_name" msgid="4841491635055379553">"Помощ в достъпа до пакети"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-ca/strings.xml b/packages/DefaultContainerService/res/values-ca/strings.xml
index 218de71..3af2c55 100644
--- a/packages/DefaultContainerService/res/values-ca/strings.xml
+++ b/packages/DefaultContainerService/res/values-ca/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Servei de contenidor multimèdia"</string>
+    <string name="service_name" msgid="4841491635055379553">"Assistent d\'accés a paquets"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-en-rGB/strings.xml b/packages/DefaultContainerService/res/values-en-rGB/strings.xml
index a84e111..216d715 100644
--- a/packages/DefaultContainerService/res/values-en-rGB/strings.xml
+++ b/packages/DefaultContainerService/res/values-en-rGB/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Media Container Service"</string>
+    <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-fa/strings.xml b/packages/DefaultContainerService/res/values-fa/strings.xml
index ac70971..8c1a5d4 100644
--- a/packages/DefaultContainerService/res/values-fa/strings.xml
+++ b/packages/DefaultContainerService/res/values-fa/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"سرویس محفظه رسانه"</string>
+    <string name="service_name" msgid="4841491635055379553">"راهنمای دسترسی به بسته"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-fi/strings.xml b/packages/DefaultContainerService/res/values-fi/strings.xml
index a012b61..216d715 100644
--- a/packages/DefaultContainerService/res/values-fi/strings.xml
+++ b/packages/DefaultContainerService/res/values-fi/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Media Container -palvelu"</string>
+    <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-hr/strings.xml b/packages/DefaultContainerService/res/values-hr/strings.xml
index 1ed69b4..56b7db1 100644
--- a/packages/DefaultContainerService/res/values-hr/strings.xml
+++ b/packages/DefaultContainerService/res/values-hr/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Usluga spremnika za medije"</string>
+    <string name="service_name" msgid="4841491635055379553">"Pomoćnik pristupa paketu"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-hu/strings.xml b/packages/DefaultContainerService/res/values-hu/strings.xml
index 0446603..78ca9fa 100644
--- a/packages/DefaultContainerService/res/values-hu/strings.xml
+++ b/packages/DefaultContainerService/res/values-hu/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Médiatároló szolgáltatás"</string>
+    <string name="service_name" msgid="4841491635055379553">"Csomaghozzáférés-segéd"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-in/strings.xml b/packages/DefaultContainerService/res/values-in/strings.xml
index 2f830b1..da6bf8b 100644
--- a/packages/DefaultContainerService/res/values-in/strings.xml
+++ b/packages/DefaultContainerService/res/values-in/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Layanan Kontainer Media"</string>
+    <string name="service_name" msgid="4841491635055379553">"Pembantu Akses Paket"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-iw/strings.xml b/packages/DefaultContainerService/res/values-iw/strings.xml
index ede8178..c6756d6 100644
--- a/packages/DefaultContainerService/res/values-iw/strings.xml
+++ b/packages/DefaultContainerService/res/values-iw/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"שירות גורם מכיל של מדיה"</string>
+    <string name="service_name" msgid="4841491635055379553">"מסייע גישה לחבילה"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-lt/strings.xml b/packages/DefaultContainerService/res/values-lt/strings.xml
index 0ba10a4..df5ffef 100644
--- a/packages/DefaultContainerService/res/values-lt/strings.xml
+++ b/packages/DefaultContainerService/res/values-lt/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Medijos konteinerio paslauga"</string>
+    <string name="service_name" msgid="4841491635055379553">"Prieig. prie paketo pagalb. priem."</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-lv/strings.xml b/packages/DefaultContainerService/res/values-lv/strings.xml
index a84e111..63beee5 100644
--- a/packages/DefaultContainerService/res/values-lv/strings.xml
+++ b/packages/DefaultContainerService/res/values-lv/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Media Container Service"</string>
+    <string name="service_name" msgid="4841491635055379553">"Pakotnes piekļuves palīgs"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-ro/strings.xml b/packages/DefaultContainerService/res/values-ro/strings.xml
index a84e111..69de00f 100644
--- a/packages/DefaultContainerService/res/values-ro/strings.xml
+++ b/packages/DefaultContainerService/res/values-ro/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Media Container Service"</string>
+    <string name="service_name" msgid="4841491635055379553">"Ajutor accesare pachet"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-sk/strings.xml b/packages/DefaultContainerService/res/values-sk/strings.xml
index a84e111..216d715 100644
--- a/packages/DefaultContainerService/res/values-sk/strings.xml
+++ b/packages/DefaultContainerService/res/values-sk/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Media Container Service"</string>
+    <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-sl/strings.xml b/packages/DefaultContainerService/res/values-sl/strings.xml
index a84e111..af2b13c 100644
--- a/packages/DefaultContainerService/res/values-sl/strings.xml
+++ b/packages/DefaultContainerService/res/values-sl/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Media Container Service"</string>
+    <string name="service_name" msgid="4841491635055379553">"Pomočnik za dostop do paketa"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-sr/strings.xml b/packages/DefaultContainerService/res/values-sr/strings.xml
index 7400eab..b5d77ac 100644
--- a/packages/DefaultContainerService/res/values-sr/strings.xml
+++ b/packages/DefaultContainerService/res/values-sr/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Услуга контејнера за медије"</string>
+    <string name="service_name" msgid="4841491635055379553">"Помоћник за приступ пакету"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-th/strings.xml b/packages/DefaultContainerService/res/values-th/strings.xml
index fac3585..3a7080c 100644
--- a/packages/DefaultContainerService/res/values-th/strings.xml
+++ b/packages/DefaultContainerService/res/values-th/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"บริการพื้นที่จัดเก็บสื่อ"</string>
+    <string name="service_name" msgid="4841491635055379553">"ตัวช่วยเหลือของการเข้าถึงแพคเกจ"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-tl/strings.xml b/packages/DefaultContainerService/res/values-tl/strings.xml
index e080364..216d715 100644
--- a/packages/DefaultContainerService/res/values-tl/strings.xml
+++ b/packages/DefaultContainerService/res/values-tl/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Serbisyo ng Media Container"</string>
+    <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-uk/strings.xml b/packages/DefaultContainerService/res/values-uk/strings.xml
index 7becba1..216d715 100644
--- a/packages/DefaultContainerService/res/values-uk/strings.xml
+++ b/packages/DefaultContainerService/res/values-uk/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Служба зберіг. медіа"</string>
+    <string name="service_name" msgid="4841491635055379553">"Package Access Helper"</string>
 </resources>
diff --git a/packages/DefaultContainerService/res/values-vi/strings.xml b/packages/DefaultContainerService/res/values-vi/strings.xml
index a22d61d..63f1199 100644
--- a/packages/DefaultContainerService/res/values-vi/strings.xml
+++ b/packages/DefaultContainerService/res/values-vi/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- outdated translation 2260781993795858516 -->     <string name="service_name" msgid="4841491635055379553">"Dịch vụ Bộ chứa Phương tiện"</string>
+    <string name="service_name" msgid="4841491635055379553">"Trình t.giúp truy cập gói"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 8a6e82d..5981139 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -81,26 +81,34 @@
 
     <!-- Default for Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS -->
     <string name="def_accessibility_web_content_key_bindings" translatable="false">
-            <!-- DPAD/Trackball UP maps to traverse previous on current axis and send an event. -->
+            <!-- DPAD/Trackball UP - traverse previous on current axis and send an event. -->
             0x13=0x01000100;
-            <!-- DPAD/Trackball DOWN maps to traverse next on current axis and send an event. -->
+            <!-- DPAD/Trackball DOWN - traverse next on current axis and send an event. -->
             0x14=0x01010100;
-            <!-- DPAD/Trackball LEFT maps to action in non-android default navigation axis. -->
-            0x15=0x04000000;
-            <!-- DPAD/Trackball RIGHT maps to no action in non-android default navigation axis. -->
-            0x16=0x04000000;
-            <!-- Left Alt+DPAD/Trackball UP transitions from an axis to another and sends an event. -->
-            <!-- Axis transitions:  2 -> 7; 1 -> 2; 0 -> 1; 3 -> 0; 4 -> 0; 5 -> 0; 6 -> 0; -->
-            0x120013=0x03020701:0x03010201:0x03000101:0x03030001:0x03040001:0x03050001:0x03060001;
-            <!-- Left Alt+DPAD/Trackball DOWN transitions from an axis to another and sends an event. -->
-            <!-- Axis transitions: 1 -> 0; 2 -> 1; 7 -> 2; 3 -> 7; 4 -> 7; 5 -> 7; 6 -> 7; -->
-            0x120014=0x03010001:0x03020101:0x03070201:0x03030701:0x03040701:0x03050701:0x03060701;
-            <!-- Left Alt+DPAD/Trackball LEFT transitions from an axis to another and sends an event. -->
-            <!-- Axis transitions: 4 -> 3; 5 -> 4; 6 -> 5; 0 -> 6; 1 -> 6; 2 -> 6; 7 -> 6; -->
-            0x120015=0x03040301:0x03050401:0x03060501:0x03000601:0x03010601:0x03020601:0x03070601;
-            <!-- Left Alt+DPAD/Trackball RIGHT transitions from an axis to another and sends an event.  -->
-            <!-- Axis transitions: 5 -> 6; 4 -> 5; 3 -> 4; 2 -> 3; 7 -> 3; 1 -> 3; 0 -> 3; -->
-            0x120016=0x03050601:0x03040501:0x03030401:0x03020301:0x03070301:0x03010301:0x03000301;
+            <!-- DPAD/Trackball LEFT - traverse previous on the character navigation axis and send event. -->
+            0x15=0x02000001;
+            <!-- DPAD/Trackball RIGHT - traverse next on the character navigation axis end send event. -->
+            0x16=0x02010001;
+            <!-- Alt+DPAD/Trackball UP - go to the top of the document. -->
+            0x200000013=0x02000601;
+            <!-- Alt+DPAD/Trackball DOWN - go to the bottom of the document. -->
+            0x200000014=0x02010601;
+            <!-- Alt+DPAD/Trackball LEFT - transition from an axis to another and sends an event.-->
+            <!-- Axis transitions: 2 -> 1; -->
+            0x200000015=0x03020101;
+            <!-- Alt+DPAD/Trackball RIGHT - transition from an axis to another and sends an event. -->
+            <!-- Axis transitions:  1 -> 2; -->
+            0x200000016=0x03010201;
+            <!-- Alt+g - go to the previous heading and send an event. -->
+            0x200000023=0x02000301;
+            <!-- Alt+h - go to the next heading and send an event. -->
+            0x200000024=0x02010301;
+            <!-- Alt+COMMA - transition to sentence navigation axis and send an event. -->
+            <!-- Axis transitions:  7 -> 2; -->
+            0x200000037=0x03070201;
+            <!-- Alt+PERIOD - transition to default web view behavior axis and send an event. -->
+            <!-- Axis transitions:  0 -> 7; 1 - > 7; 2 -> 7; -->
+            0x200000038=0x03000701:0x03010701:0x03020701;
     </string>
 
     <!-- Default for Settings.System.USER_ROTATION -->
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index d11a18e..bc7473e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -61,7 +61,7 @@
     // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
     // is properly propagated through your change.  Not doing so will result in a loss of user
     // settings.
-    private static final int DATABASE_VERSION = 62;
+    private static final int DATABASE_VERSION = 63;
 
     private Context mContext;
 
@@ -441,18 +441,7 @@
         }
 
         if (upgradeVersion == 39) {
-            db.beginTransaction();
-            try {
-                String value =
-                        mContext.getResources().getBoolean(
-                        R.bool.def_screen_brightness_automatic_mode) ? "1" : "0";
-                db.execSQL("INSERT OR IGNORE INTO system(name,value) values('" +
-                        Settings.System.SCREEN_BRIGHTNESS_MODE + "','" + value + "');");
-                db.setTransactionSuccessful();
-            } finally {
-                db.endTransaction();
-            }
-
+            upgradeAutoBrightness(db);
             upgradeVersion = 40;
         }
 
@@ -802,6 +791,12 @@
             upgradeVersion = 62;
         }
 
+        // Change the default for screen auto-brightness mode
+        if (upgradeVersion == 62) {
+            upgradeAutoBrightness(db);
+            upgradeVersion = 63;
+        }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
@@ -924,6 +919,20 @@
         }
     }
 
+    private void upgradeAutoBrightness(SQLiteDatabase db) {
+        db.beginTransaction();
+        try {
+            String value =
+                    mContext.getResources().getBoolean(
+                    R.bool.def_screen_brightness_automatic_mode) ? "1" : "0";
+            db.execSQL("INSERT OR REPLACE INTO system(name,value) values('" +
+                    Settings.System.SCREEN_BRIGHTNESS_MODE + "','" + value + "');");
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+    }
+
     /**
      * Loads the default set of bookmarked shortcuts from an xml file.
      *
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 6e2bfdb..f8809d7 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -262,11 +262,8 @@
 
         // Watch for external modifications to the database file,
         // keeping our cache in sync.
-        // It's kinda lame to call mOpenHelper.getReadableDatabase()
-        // during onCreate(), but since ensureAndroidIdIsSet has
-        // already done it above and initialized/upgraded the
-        // database, might as well just use it...
-        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        db.enableWriteAheadLogging();
         sObserverInstance = new SettingsFileObserver(db.getPath());
         sObserverInstance.startWatching();
         startAsyncCachePopulation();
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index d824f30..d3d1750 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -12,6 +12,7 @@
     <application
         android:persistent="true"
         android:allowClearUserData="false"
+        android:hardwareAccelerated="true"
         android:label="@string/app_label"
         android:icon="@drawable/ic_launcher_settings">
 
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 499244b..056e7e7 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 b16e436..20ea735 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 1b6ed74..a5e9c7c 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 43e35d3..0287d5a 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 498adbb..4dfbcb2 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 b7e42a0..b9d4cb0 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 959fc5c..4c8ec0e 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 f905979..7e30894 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 6e8e73c..72635a5 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 b5799c8..6f56886 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 7a419f1..118a6b4 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 98e874a..ecd880f 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 1626895..7251b14 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 3c2e2b9..01135c8 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 77e6ee4..794d9edd 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 00d86bf..851ca41 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 c2574e1..f16783c 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 70c030b..d217d09 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 55caecf..b577ebe 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 b5326d2..6cf4829 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 25fffd6..4bcd2be 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 b6e4ebc..dadb0cd 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 189a089..51d7cc2 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 ebade92..83a8b26 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 6ef71c7..cfeba3e 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 f6b0a17..b090b95 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 259db7a..e1d53bd 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_lights_out_dot_large.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
new file mode 100644
index 0000000..f865e7a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
new file mode 100644
index 0000000..04588bb
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.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 246c6fe..1d97e05 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 34515c7..c9724fc 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 9216030..39025f0 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 e529f6f..a1f7057 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 e529f6f..7cc9f02 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 02c27ee..25ca124 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 57558ad..122a473 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 57558ad..4b126dc 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 e4425b2..828c0e2 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 e4425b2..f52d8f9 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 84ac927..2725ed2 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 09de6b0..61501c1 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 09de6b0..1171ffc 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 13cae40..83cb820 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 690b5f6c7..98c3b10 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 d0a4fd0..9c3c44c 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 05976bd..08b975a 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 2cc3cd6..ae9dc40 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 1c59b2a..94c41a7 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 32e9165..ac32aa6 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 32e9165..9845c46 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 ea71298..34494e3 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 ea71298..77f4a7b 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 869a497..a635c3c 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 869a497..c3e9240 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 1711c82..68ffdc9 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 1711c82..93a3dc0 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/drawable-nodpi/panel_notification.png b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
index b0d9c18..437deff 100644
--- a/packages/SystemUI/res/drawable-nodpi/panel_notification.png
+++ b/packages/SystemUI/res/drawable-nodpi/panel_notification.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png
index 66a54f0..55d38d8 100644
--- a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png
+++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_bg_protect_tile.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/panel_notification_tiled.xml b/packages/SystemUI/res/drawable/panel_notification_tiled.xml
new file mode 100644
index 0000000..9d41e28
--- /dev/null
+++ b/packages/SystemUI/res/drawable/panel_notification_tiled.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<bitmap
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/panel_notification"
+    android:tileMode="repeat"
+    />
+
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml
index 8a01a12..0533b6f 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml
@@ -15,266 +15,128 @@
  * limitations under the License.
 -->
 
-<!--    android:background="@drawable/status_bar_closed_default_background" -->
+<!-- TabletStatusBarView extends FrameLayout -->
 <com.android.systemui.statusbar.tablet.TabletStatusBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:background="@drawable/status_bar_background"
     >
-    <RelativeLayout
-        android:id="@+id/bar_contents"
+    
+    <FrameLayout
+        android:id="@+id/bar_contents_holder"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="@*android:dimen/status_bar_height"
+        android:layout_gravity="bottom"
         >
-
-        <!-- notification icons & panel access -->
-        <LinearLayout
-            android:id="@+id/notificationArea"
-            android:layout_width="wrap_content"
+        <RelativeLayout
+            android:id="@+id/bar_contents"
+            android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:layout_alignParentRight="true"
-            android:orientation="horizontal"
+            android:animateLayoutChanges="true"
             >
-            <com.android.systemui.statusbar.tablet.InputMethodButton
-                android:id="@+id/imeSwitchButton"
+
+            <!-- notification icons & panel access -->
+            <include layout="@layout/status_bar_notification_area" 
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:layout_marginLeft="8dip"
-                android:src="@drawable/ic_sysbar_ime_default"
-                android:visibility="gone"
+                android:layout_alignParentRight="true"
                 />
-            <com.android.systemui.statusbar.tablet.NotificationIconArea
-                android:id="@+id/notificationIcons"
+
+            <!-- navigation controls -->
+            <LinearLayout
+                android:id="@+id/navigationArea"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
+                android:layout_alignParentLeft="true"
                 android:orientation="horizontal"
                 >
-                <view
-                    class="com.android.systemui.statusbar.tablet.NotificationIconArea$IconLayout"
-                    android:id="@+id/icons"
-                    android:layout_width="wrap_content"
-                    android:layout_height="@*android:dimen/status_bar_icon_size"
-                    android:layout_gravity="top"
-                    android:layout_marginTop="5dp"
-                    android:layout_marginLeft="8dp"
+
+                <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
+                    android:layout_width="80dip"
+                    android:layout_height="match_parent"
+                    android:src="@drawable/ic_sysbar_back"
+                    systemui:keyCode="4"
                     />
-            </com.android.systemui.statusbar.tablet.NotificationIconArea>
-
-            <LinearLayout
-                android:id="@+id/notificationTrigger"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                >
-                <com.android.systemui.statusbar.tablet.HoloClock
-                    android:id="@+id/clock"
-                    android:layout_width="wrap_content"
+                <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
+                    android:layout_width="80dip"
                     android:layout_height="match_parent"
-                    >
-                    <TextView android:id="@+id/time_bg"
-                        android:layout_width="wrap_content"
-                        android:layout_height="match_parent"
-                        android:singleLine="true"
-                        android:textSize="72dip"
-                        android:textColor="#1f1f1f" />
-                    <TextView android:id="@+id/time_fg"
-                        android:layout_width="wrap_content"
-                        android:layout_height="match_parent"
-                        android:singleLine="true"
-                        android:textSize="72dip"
-                        android:textColor="#2e2e2e" />
-                </com.android.systemui.statusbar.tablet.HoloClock>
-
-                <TextView
-                    android:id="@+id/network_text"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:layout_marginTop="12dp"
-                    android:layout_marginRight="6dip"
-                    android:layout_marginLeft="6dip"
-                    android:gravity="center"
-                    android:singleLine="true"
-                    android:visibility="gone"
-                    android:textSize="14dip"
-                    android:textColor="#606060"
+                    android:src="@drawable/ic_sysbar_home"
+                    systemui:keyCode="3"
                     />
-
-                <LinearLayout
-                    android:id="@+id/signal_battery_cluster"
-                    android:layout_width="wrap_content"
+                <ImageView android:id="@+id/recent_apps"
+                    android:layout_width="80dip"
                     android:layout_height="match_parent"
-                    android:orientation="horizontal"
-                    android:gravity="center"
-                    >
-                    <FrameLayout
-                        android:layout_height="wrap_content"
-                        android:layout_width="wrap_content"
-                        android:layout_gravity="top"
-                        android:layout_marginTop="19dp"
-                        android:layout_marginRight="4dp"
-                        >
-                        <ImageView
-                            android:id="@+id/network_signal"
-                            android:layout_height="wrap_content"
-                            android:layout_width="wrap_content"
-                            />
-                        <ImageView
-                            android:id="@+id/network_type"
-                            android:layout_height="wrap_content"
-                            android:layout_width="wrap_content"
-                            />
-                    </FrameLayout>
-                    <ImageView
-                        android:id="@+id/battery"
-                        android:layout_height="wrap_content"
-                        android:layout_width="wrap_content"
-                        android:layout_gravity="top"
-                        android:layout_marginTop="19dp"
-                        android:layout_marginLeft="2dp"
-                        android:layout_marginRight="2dp"
-                        />
-                </LinearLayout>
+                    android:src="@drawable/ic_sysbar_recent"
+                    />
+                <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
+                    android:layout_width="80dip"
+                    android:layout_height="match_parent"
+                    android:src="@drawable/ic_sysbar_menu"
+                    systemui:keyCode="82"
+                    android:visibility="invisible"
+                    />
             </LinearLayout>
-        </LinearLayout>
 
-        <!-- navigation controls -->
-        <LinearLayout
-            android:id="@+id/navigationArea"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_alignParentLeft="true"
-            android:orientation="horizontal"
-            >
-
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
-                android:layout_width="96dip"
+            <!-- fake space bar zone -->
+            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/fake_space_bar"
                 android:layout_height="match_parent"
-                android:paddingLeft="18dip"
-                android:paddingRight="18dip"
-                android:src="@drawable/ic_sysbar_back"
-                systemui:keyCode="4"
-                />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
-                android:layout_width="96dip"
-                android:layout_height="match_parent"
-                android:paddingLeft="18dip"
-                android:paddingRight="18dip"
-                android:src="@drawable/ic_sysbar_home"
-                systemui:keyCode="3"
-                />
-            <ImageButton android:id="@+id/recent_apps"
-                android:layout_width="96dip"
-                android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_recent"
-                android:background="@null"
-                android:paddingLeft="18dip"
-                android:clickable="true"
-                android:paddingRight="18dip"
-                />
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/menu"
-                android:layout_width="96dip"
-                android:layout_height="match_parent"
-                android:paddingLeft="18dip"
-                android:paddingRight="18dip"
-                android:src="@drawable/ic_sysbar_menu"
-                systemui:keyCode="82"
-                android:visibility="invisible"
-                />
-            <com.android.systemui.statusbar.tablet.ShirtPocket
-                android:id="@+id/pocket"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:animateLayoutChanges="true"
-                android:clickable="true"
-                android:descendantFocusability="blocksDescendants"
-                android:gravity="center"
-                >
-                <ImageView 
-                    android:id="@+id/pocket_icon"
-                    android:src="@drawable/ic_sysbar_pocket"
-                    android:paddingLeft="18dip"
-                    android:paddingRight="18dip"
-                    android:layout_width="96dip"
-                    android:layout_height="wrap_content"
-                    android:gravity="center"
-                    android:visibility="gone"
-                    />
-            </com.android.systemui.statusbar.tablet.ShirtPocket>
-        </LinearLayout>
-
-        <!-- lights out mode: "shadow" views -->
-        <RelativeLayout
-            android:id="@+id/shadows"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            >
-            <ImageView
-                android:id="@+id/notification_shadow"
-                android:layout_width="176dip"
-                android:layout_height="match_parent"
-                android:paddingRight="48dip"
-                android:layout_alignParentRight="true"
-                android:layout_alignParentBottom="true"
-                android:src="@drawable/ic_sysbar_shadow"
+                android:layout_width="match_parent"
+                android:paddingLeft="8dip"
+                android:paddingRight="8dip"
+                android:layout_toRightOf="@+id/navigationArea"
+                android:layout_toLeftOf="@+id/notificationArea"
                 android:visibility="gone"
-                android:scaleType="fitXY"
-                />
-
-            <ImageView
-                android:id="@+id/back_shadow"
-                android:layout_width="96dip"
-                android:layout_height="match_parent"
-                android:paddingLeft="18dip"
-                android:paddingRight="18dip"
-                android:layout_alignParentLeft="true"
-                android:layout_alignParentBottom="true"
-                android:src="@drawable/ic_sysbar_shadow"
-                android:visibility="gone"
-                />
-            <ImageView
-                android:id="@+id/home_shadow"
-                android:layout_width="96dip"
-                android:layout_height="match_parent"
-                android:paddingLeft="18dip"
-                android:paddingRight="18dip"
-                android:layout_toRightOf="@id/back_shadow"
-                android:layout_alignParentBottom="true"
-                android:src="@drawable/ic_sysbar_shadow"
-                android:visibility="gone"
-                />
-            <ImageView
-                android:id="@+id/recent_shadow"
-                android:layout_width="96dip"
-                android:layout_height="match_parent"
-                android:paddingLeft="18dip"
-                android:paddingRight="18dip"
-                android:layout_toRightOf="@id/home_shadow"
-                android:layout_alignParentBottom="true"
-                android:src="@drawable/ic_sysbar_shadow"
-                android:visibility="gone"
-                />
-            <ImageView
-                android:id="@+id/menu_shadow"
-                android:layout_width="96dip"
-                android:layout_height="match_parent"
-                android:paddingLeft="18dip"
-                android:paddingRight="18dip"
-                android:layout_toRightOf="@id/recent_shadow"
-                android:layout_alignParentBottom="true"
-                android:src="@drawable/ic_sysbar_shadow"
-                android:visibility="gone"
+                systemui:keyCode="62"
                 />
         </RelativeLayout>
+    </FrameLayout>
 
-        <!-- fake space bar zone -->
-        <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/fake_space_bar"
-            android:layout_height="match_parent"
+    <FrameLayout
+        android:id="@+id/bar_shadow_holder"
+        android:layout_width="match_parent"
+        android:layout_height="@*android:dimen/status_bar_height"
+        android:layout_gravity="bottom"
+        >
+        <!-- lights out shade -->
+        <RelativeLayout
+            android:id="@+id/bar_shadow"
             android:layout_width="match_parent"
-            android:paddingLeft="8dip"
-            android:paddingRight="8dip"
-            android:layout_toRightOf="@+id/navigationArea"
-            android:layout_toLeftOf="@+id/notificationArea"
+            android:layout_height="match_parent"
+            android:background="#FF000000"
             android:visibility="gone"
-            systemui:keyCode="62"
-            />
-    </RelativeLayout>
+            >
+            <ImageView
+                android:id="@+id/dot0"
+                android:layout_width="80dip"
+                android:layout_height="48dip"
+                android:src="@drawable/ic_sysbar_lights_out_dot_small"
+                android:layout_alignParentLeft="true"
+                android:layout_alignParentBottom="true"
+                />
+            <ImageView
+                android:id="@+id/dot1"
+                android:layout_width="80dip"
+                android:layout_height="48dip"
+                android:src="@drawable/ic_sysbar_lights_out_dot_large"
+                android:layout_toRightOf="@+id/dot0"
+                android:layout_alignParentBottom="true"
+                />
+            <ImageView
+                android:id="@+id/dot2"
+                android:layout_width="80dip"
+                android:layout_height="48dip"
+                android:src="@drawable/ic_sysbar_lights_out_dot_small"
+                android:layout_toRightOf="@+id/dot1"
+                android:layout_alignParentBottom="true"
+                />
+            <ImageView
+                android:id="@+id/dot3"
+                android:layout_width="80dip"
+                android:layout_height="48dip"
+                android:src="@drawable/ic_sysbar_lights_out_dot_small"
+                android:layout_alignParentRight="true"
+                android:layout_alignParentBottom="true"
+                />
+        </RelativeLayout>
+    </FrameLayout>
 </com.android.systemui.statusbar.tablet.TabletStatusBarView>
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_item.xml b/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_item.xml
new file mode 100644
index 0000000..3028a42
--- /dev/null
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_item.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:background="@drawable/status_bar_item_background"
+    android:orientation="vertical"
+    android:paddingRight="6dip"
+    android:paddingLeft="6dip"
+    android:paddingTop="5dip"
+    android:paddingBottom="5dip"
+    android:gravity="center_vertical">
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:gravity="center_vertical"
+        android:orientation="horizontal">
+        <LinearLayout
+            android:id="@+id/item_subtype"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            android:background="?android:attr/selectableItemBackground">
+            <RadioButton
+                android:id="@+id/item_radio"
+                android:layout_width="30dip"
+                android:layout_height="wrap_content"
+                android:layout_marginRight="11dip"
+                android:focusable="false"
+                android:clickable="false" />
+            <ImageView
+                android:id="@+id/item_icon"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:scaleType="fitCenter" />
+            <LinearLayout
+                android:orientation="vertical"
+                android:layout_width="0px"
+                android:layout_weight="1"
+                android:layout_height="wrap_content">
+                <TextView
+                    android:id="@+id/item_title"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:layout_marginBottom="2dip" />
+                <TextView
+                    android:id="@+id/item_subtitle"
+                    android:layout_marginTop="-4dip"
+                    android:layout_gravity="center_vertical|left"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="?android:attr/textAppearanceSmall" />
+            </LinearLayout>
+        </LinearLayout>
+        <View
+            android:id="@+id/item_vertical_separator"
+            android:layout_width="2dip"
+            android:layout_height="match_parent"
+            android:layout_marginBottom="5dip"
+            android:background="@android:drawable/divider_horizontal_dark" />
+        <ImageView
+            android:id="@+id/item_settings_icon"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="5dip"
+            android:layout_gravity="center_vertical"
+            android:paddingRight="10dip"
+            android:paddingLeft="10dip"
+            android:src="@drawable/ic_sysbar_quicksettings"
+            android:visibility="visible"
+            android:clickable="true"
+            android:focusable="true"
+            android:background="?android:attr/selectableItemBackground" />
+    </LinearLayout>
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dip"
+        android:background="@android:drawable/divider_horizontal_dark" />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_panel.xml
new file mode 100644
index 0000000..c4bca61
--- /dev/null
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_panel.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<com.android.systemui.statusbar.tablet.InputMethodsPanel
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:paddingBottom="28dip"
+    android:orientation="vertical">
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1" />
+    <FrameLayout
+        android:id="@+id/glow"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:background="@drawable/recents_blue_glow">
+        <LinearLayout
+            android:layout_width="450dip"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="20dip"
+            android:orientation="vertical"
+            android:background="@*android:drawable/dialog_full_holo_dark">
+            <ScrollView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:overScrollMode="ifContentScrolls"
+                android:layout_marginTop="3dip"
+                android:layout_weight="1">
+                <LinearLayout
+                    android:id="@+id/input_method_menu_list"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:orientation="vertical" />
+            </ScrollView>
+            <TextView
+                android:id="@+id/ime_settings_shortcut"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:minHeight="?android:attr/listPreferredItemHeight"
+                android:background="?android:attr/selectableItemBackground"
+                android:orientation="vertical"
+                android:paddingRight="6dip"
+                android:paddingLeft="30dip"
+                android:paddingTop="5dip"
+                android:paddingBottom="5dip"
+                android:gravity="center_vertical"
+                android:singleLine="true"
+                android:text="@string/status_bar_input_method_settings_configure_input_methods"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:ellipsize="marquee" />
+        </LinearLayout>
+    </FrameLayout>
+</com.android.systemui.statusbar.tablet.InputMethodsPanel>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_area.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_area.xml
new file mode 100644
index 0000000..72e2c0b
--- /dev/null
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_area.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!-- notification icons & panel access -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    android:id="@+id/notificationArea"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:layout_alignParentRight="true"
+    android:orientation="horizontal"
+    >
+
+    <LinearLayout
+        android:id="@+id/notificationAndImeArea"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:orientation="horizontal"
+        >
+
+        <com.android.systemui.statusbar.tablet.InputMethodButton
+            android:id="@+id/imeSwitchButton"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="8dip"
+            android:src="@drawable/ic_sysbar_ime_default"
+            android:visibility="gone"
+            />
+        <com.android.systemui.statusbar.tablet.NotificationIconArea
+            android:id="@+id/notificationIcons"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:orientation="horizontal"
+            >
+            <view
+                class="com.android.systemui.statusbar.tablet.NotificationIconArea$IconLayout"
+                android:id="@+id/icons"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_gravity="center_vertical"
+                android:paddingTop="5dp"
+                android:layout_marginLeft="8dp"
+                />
+        </com.android.systemui.statusbar.tablet.NotificationIconArea>
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/notificationTrigger"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        >
+        <com.android.systemui.statusbar.tablet.HoloClock
+            android:id="@+id/clock"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            >
+            <TextView android:id="@+id/time_bg"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:singleLine="true"
+                android:textSize="72dip"
+                android:textColor="#1f1f1f" />
+            <TextView android:id="@+id/time_fg"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:singleLine="true"
+                android:textSize="72dip"
+                android:textColor="#2e2e2e" />
+        </com.android.systemui.statusbar.tablet.HoloClock>
+
+        <TextView
+            android:id="@+id/network_text"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginTop="12dp"
+            android:layout_marginRight="6dip"
+            android:layout_marginLeft="6dip"
+            android:gravity="center"
+            android:singleLine="true"
+            android:visibility="gone"
+            android:textSize="14dip"
+            android:textColor="#606060"
+            />
+
+        <LinearLayout
+            android:id="@+id/signal_battery_cluster"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:orientation="horizontal"
+            android:gravity="center"
+            >
+            <FrameLayout
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_gravity="top"
+                android:layout_marginTop="19dp"
+                android:layout_marginRight="4dp"
+                >
+                <ImageView
+                    android:id="@+id/network_signal"
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    />
+                <ImageView
+                    android:id="@+id/network_type"
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    />
+            </FrameLayout>
+            <ImageView
+                android:id="@+id/battery"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_gravity="top"
+                android:layout_marginTop="19dp"
+                android:layout_marginLeft="2dp"
+                android:layout_marginRight="2dp"
+                />
+        </LinearLayout>
+    </LinearLayout>
+</LinearLayout>
+
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
index 2272e34..7f84b21 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
@@ -20,27 +20,35 @@
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
-    android:orientation="vertical"
     android:gravity="right"
-    android:paddingTop="32dp"
     >
 
-    <LinearLayout
+    <View
+        android:id="@+id/scrim"
+        android:background="@drawable/notify_panel_bg_protect"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentRight="true"
+        />
+
+    <RelativeLayout
         android:id="@+id/content_parent"
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
-        android:animateLayoutChanges="true"
-        android:orientation="vertical"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentRight="true"
         >
-
-        <com.android.systemui.statusbar.tablet.NotificationTitleArea
+        <RelativeLayout
             android:id="@+id/title_area"
             android:layout_height="160dp"
             android:layout_width="384dp"
             android:layout_marginLeft="24dp"
             android:paddingTop="20dp"
             android:orientation="vertical"
-            android:animateLayoutChanges="true"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentRight="true"
+            android:background="@drawable/panel_notification_tiled"
             >
 
             <com.android.systemui.statusbar.tablet.HoloClock
@@ -154,16 +162,18 @@
                 android:src="@drawable/status_bar_veto"
                 android:baseline="21dp"
                 />
-        </com.android.systemui.statusbar.tablet.NotificationTitleArea>
+        </RelativeLayout>
 
         <LinearLayout
             android:id="@+id/content_frame"
             android:layout_height="wrap_content"
             android:layout_width="408dp"
             android:orientation="vertical"
+            android:layout_below="@id/title_area"
+            android:layout_alignParentRight="true"
             >
             <ScrollView
-                android:id="@+id/notificationScroller"
+                android:id="@+id/notification_scroller"
                 android:layout_height="wrap_content"
                 android:layout_width="match_parent"
                 android:layout_weight="1"
@@ -184,11 +194,24 @@
                 </com.android.systemui.statusbar.tablet.NotificationLinearLayout>
             </ScrollView>
             <ImageView
+                android:id="@+id/notification_glow"
                 android:layout_width="match_parent"
                 android:layout_height="@dimen/status_bar_panel_bottom_offset"
                 android:layout_marginLeft="16dp"
                 android:src="@drawable/notify_item_glow_bottom"
                 />
         </LinearLayout>
-    </LinearLayout>
+    </RelativeLayout>
+
+    <View
+        android:id="@+id/glow"
+        android:background="@drawable/notify_glow_back"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignTop="@id/content_parent"
+        android:layout_alignLeft="@id/content_parent"
+        android:layout_marginLeft="100dip"
+        android:layout_marginTop="-100dip"
+        />
+
 </com.android.systemui.statusbar.tablet.NotificationPanel>
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 6b12d29..4991a40 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/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml
index 2989be0..3fdfdbb 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml
@@ -31,7 +31,6 @@
         android:layout_alignParentTop="true"
         android:layout_marginLeft="105dip"
         android:scaleType="center"
-        android:background="@drawable/recents_thumbnail_bg"
     />
 
     <ImageView android:id="@+id/app_icon"
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml
index cc044a1..a1216aa 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml
@@ -20,32 +20,36 @@
 
 <com.android.systemui.statusbar.tablet.RecentAppsPanel
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/recents_root"
     android:layout_height="match_parent"
-    android:layout_width="wrap_content"
-    android:layout_marginBottom="48dip"
-    android:background="@drawable/recents_bg_protect_tile"
-    android:id="@+id/recents_bg_protect"
-    android:orientation="vertical">
+    android:layout_width="wrap_content">
 
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="0dip"
-        android:layout_weight="1"
-    />
-
-    <LinearLayout android:id="@+id/recents_glow"
+    <FrameLayout
+        android:id="@+id/recents_bg_protect"
+        android:background="@drawable/recents_bg_protect_tile"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        android:background="@drawable/recents_blue_glow">
+        android:layout_height="match_parent"
+        android:layout_alignParentBottom="true"
+        android:paddingBottom="48dip"
+        android:clipToPadding="false">
 
-        <LinearLayout android:id="@+id/recents_container"
-            android:layout_width="356dip"
+        <LinearLayout android:id="@+id/recents_glow"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:orientation="vertical"
-            android:layout_marginRight="100dip"
-        />
+            android:orientation="horizontal"
+            android:layout_marginBottom="-28dip"
+            android:layout_gravity="bottom"
+            android:background="@drawable/recents_blue_glow">
 
-    </LinearLayout>
+            <LinearLayout android:id="@+id/recents_container"
+                android:layout_width="356dip"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:layout_marginRight="100dip"
+            />
+
+        </LinearLayout>
+
+    </FrameLayout>
 
 </com.android.systemui.statusbar.tablet.RecentAppsPanel>
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_settings_view.xml b/packages/SystemUI/res/layout-xlarge/status_bar_settings_view.xml
index 5e36da3..8a477e4 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_settings_view.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_settings_view.xml
@@ -120,24 +120,6 @@
     </LinearLayout>
     <View style="@style/StatusBarPanelSettingsPanelSeparator" />
 
-    <!-- Volume -->
-    <LinearLayout style="@style/StatusBarPanelSettingsRow" >
-        <ImageView
-                android:id="@+id/volume_icon"
-                style="@style/StatusBarPanelSettingsIcon"
-                android:src="@drawable/ic_sysbar_sound_on"
-                />
-        <com.android.systemui.statusbar.policy.ToggleSlider
-                android:id="@+id/volume"
-                android:layout_width="0dp"
-                android:layout_height="fill_parent"
-                android:layout_weight="1"
-                android:layout_marginRight="2dp"
-                systemui:text="@string/status_bar_settings_mute_label"
-                />
-    </LinearLayout>
-    <View style="@style/StatusBarPanelSettingsPanelSeparator" />
-
     <!-- Notifications / Do not disturb -->
     <LinearLayout
             android:id="@+id/do_not_disturb"
diff --git a/packages/SystemUI/res/values-ar-land/strings.xml b/packages/SystemUI/res/values-ar-land/strings.xml
new file mode 100644
index 0000000..4a9ffc4
--- /dev/null
+++ b/packages/SystemUI/res/values-ar-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"تم قفل الشاشة الآن في الاتجاه الأفقي"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ar-port/strings.xml b/packages/SystemUI/res/values-ar-port/strings.xml
new file mode 100644
index 0000000..8a11d46
--- /dev/null
+++ b/packages/SystemUI/res/values-ar-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"تم قفل الشاشة الآن في الاتجاه العمودي."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ar-xlarge/strings.xml b/packages/SystemUI/res/values-ar-xlarge/strings.xml
index 44e911a..be4334f 100644
--- a/packages/SystemUI/res/values-ar-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-ar-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"محو الكل"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"لا اتصال بالإنترنت"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi متصل"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 4ee82d3..5f01f4d 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"واجهة مستخدم النظام"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"محو"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"عدم الإزعاج"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"إظهار التنبيهات"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"ليس هناك أي تنبيهات"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"مستمر"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"التنبيهات"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"الرجاء توصيل الشاحن"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"البطارية منخفضة:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"انخفضت طاقة البطارية."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"المتبقي: <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"شحن USB غير معتمد."\n"استخدم الشاحن الموفر فقط."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"استخدام البطارية"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"الإعدادات"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"وضع الطائرة"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"تأمين اتجاه الشاشة"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"كتم"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"تلقائي"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"التنبيهات"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"حديثة"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"ليس هناك أية تطبيقات حديثة."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bg-land/strings.xml b/packages/SystemUI/res/values-bg-land/strings.xml
new file mode 100644
index 0000000..0a66f5a
--- /dev/null
+++ b/packages/SystemUI/res/values-bg-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Екранът е заключен в хоризонтална ориентация."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-bg-port/strings.xml b/packages/SystemUI/res/values-bg-port/strings.xml
new file mode 100644
index 0000000..34a7c1d
--- /dev/null
+++ b/packages/SystemUI/res/values-bg-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Екранът е заключен във вертикална ориентация."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-bg-xlarge/strings.xml b/packages/SystemUI/res/values-bg-xlarge/strings.xml
index db572ec..8dd6d7c 100644
--- a/packages/SystemUI/res/values-bg-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-bg-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Изчистване на всичко"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Няма връзка с интернет"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: има връзка"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 9d7b807..aa98f7d 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"Системен ПИ"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Изчистване"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Не ме безпокойте"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Показване на известията"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Няма известия"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"В момента"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Известия"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Моля, включете зарядно устройство"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Батерията се изтощава:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Батерията се изтощава."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"Остава: <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"Не се поддържа зареждане през USB."\n"Използвайте само доставеното зарядно устройство."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Използване на батерията"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Настройки"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Самолетен режим"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Заключване на ориентацията"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"БЕЗ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АВТ."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Известия"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Скорошни"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Няма скорошни приложения."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ca-land/strings.xml b/packages/SystemUI/res/values-ca-land/strings.xml
new file mode 100644
index 0000000..e592e17
--- /dev/null
+++ b/packages/SystemUI/res/values-ca-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Ara la pantalla està bloquejada en orientació horitzontal."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ca-port/strings.xml b/packages/SystemUI/res/values-ca-port/strings.xml
new file mode 100644
index 0000000..c98c170
--- /dev/null
+++ b/packages/SystemUI/res/values-ca-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Ara la pantalla està bloquejada en orientació vertical."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ca-xlarge/strings.xml b/packages/SystemUI/res/values-ca-xlarge/strings.xml
index 2e3baf5..289a2a3 100644
--- a/packages/SystemUI/res/values-ca-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-ca-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Esborra-ho tot"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"No connexió Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: connectat"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index be0407d..583044d 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"IU del sistema"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Esborra"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"No molesteu"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Mostra notificacions"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Cap notificació"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continu"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificacions"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Connecteu el carregador"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Comença a quedar poca bateria:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"La bateria comença a estar baixa."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> restant"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"Càrrega d\'USB no admesa."\n"Utilitza només el carregador proporcionat."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Ús de la bateria"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Configuració"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode d\'avió"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bloquejar orientació pantalla"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"Silen."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificacions"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recents"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"No hi ha aplicacions recents."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index f7d4864..ea5694d 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"Nabíjení pomocí rozhraní USB není podporováno."\n"Používejte pouze nabíječku, která byla dodána se zařízením."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Využití baterie"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nastavení"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Režim V letadle"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Uzamknout orientaci obrazovky"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ZTLUM."</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Žádné nedávno použité aplikace."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"Obrazovka se automaticky otočí."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"Otáčení obrazovky je uzamčeno."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index dad6736..b95c6cb 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"Opladning via USB understøttes ikke."\n"Brug kun den medfølgende oplader."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Batteriforbrug"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Indstillinger"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flytilstand"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Lås skærmretning"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"LYDLØS"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Der er ingen nye programmer."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"Skærmen roterer automatisk."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"Skærmrotationen er nu låst."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-de-xlarge/strings.xml b/packages/SystemUI/res/values-de-xlarge/strings.xml
index a617d7d..73c563c 100644
--- a/packages/SystemUI/res/values-de-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-de-xlarge/strings.xml
@@ -22,5 +22,5 @@
     <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
     <skip />
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Keine Internetverbindung"</string>
-    <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"WLAN verbunden"</string>
+    <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Mit WLAN verbunden"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index a76fe3d..4043c2e 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"USB-Aufladung wird nicht unterstützt."\n"Verwenden Sie das mitgelieferte Aufladegerät."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Akkuverbrauch"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Einstellungen"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WLAN"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flugmodus"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bildschirmausrichtung sperren"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"STUMM"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Keine neuen Anwendungen"</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"Bildschirm wird automatisch gedreht."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"Bildschirmrotation ist jetzt gesperrt."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 4fd5e30..39a462c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"Δεν υποστηρίζεται η φόρτιση USB."\n"Χρησιμοποιείτε μόνο τον φορτιστή που παρέχεται."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Χρήση μπαταρίας"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ρυθμίσεις"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Λειτουργία πτήσης"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Κλείδωμα προσανατολ. οθόνης"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ΣΙΓΑΣΗ"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Δεν υπάρχουν πρόσφατες εφαρμογές."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"Θα γίνεται αυτόματη περιστροφή της οθόνης."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"Η περιστροφή οθόνης είναι κλειδωμένη."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB-land/strings.xml b/packages/SystemUI/res/values-en-rGB-land/strings.xml
new file mode 100644
index 0000000..ba773b8
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rGB-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Screen is now locked in landscape orientation."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rGB-port/strings.xml b/packages/SystemUI/res/values-en-rGB-port/strings.xml
new file mode 100644
index 0000000..d8ddce1
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rGB-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Screen is now locked in portrait orientation."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml b/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml
index b6a9844..fac0137 100644
--- a/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Clear all"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"No Internet connection"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi connected"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 25bceb8..72373bb 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"System UI"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Clear"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Do not disturb"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Show notifications"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No notifications"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ongoing"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Please connect charger"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"The battery is getting low:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"The battery is getting low."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> remaining"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"USB charging not supported."\n"Use only the supplied charger."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Battery use"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Settings"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Airplane mode"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Lock screen orientation"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notifications"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recent"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"No recent applications."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS-xlarge-land/strings.xml b/packages/SystemUI/res/values-es-rUS-xlarge-land/strings.xml
new file mode 100644
index 0000000..78a4c18
--- /dev/null
+++ b/packages/SystemUI/res/values-es-rUS-xlarge-land/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- XL -->
+    <string name="toast_rotation_locked" msgid="2686639138967158852">"La pantalla está bloqueada en orientación paisaje."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-es-rUS-xlarge-port/strings.xml b/packages/SystemUI/res/values-es-rUS-xlarge-port/strings.xml
new file mode 100644
index 0000000..9daef6a
--- /dev/null
+++ b/packages/SystemUI/res/values-es-rUS-xlarge-port/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- XL -->
+    <string name="toast_rotation_locked" msgid="4297721709987511908">"La pantalla está bloqueada en orientación retrato."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml b/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml
index bf627f4..f29259a 100644
--- a/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS-xlarge/strings.xml
@@ -1,26 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/**
- * Copyright (c) 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at 
- *
- *     http://www.apache.org/licenses/LICENSE-2.0 
- *
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- */
- -->
-
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
-    <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Sin conexión a Int."</string>
-    <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"WiFi conectado"</string>
+    <!-- XL xlarge -->
+    <string name="status_bar_clear_all_button" msgid="4341545325987974494">"Eliminar todos"</string>
+    <!-- XL -->
+    <string name="status_bar_no_notifications_title" msgid="2492933749414725897">"No tienes notificaciones"</string>
+    <!-- XL -->
+    <string name="status_bar_settings_rotation_lock" msgid="9125161825884157545">"Bloquear orient. de pant."</string>
+    <!-- XL -->
+    <string name="recent_tasks_app_label" msgid="5550538721034982973">"Google Apps"</string>
+    <!-- XL xlarge -->
+    <string name="status_bar_settings_signal_meter_disconnected" msgid="4866302415753953027">"Sin conexión a Internet"</string>
+    <!-- XL xlarge -->
+    <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="3832182580451976589">"Wi-Fi conectado"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 20c9484..8013a19 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"No admite la carga USB."\n"Usa sólo el cargador provisto."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Uso de la batería"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Configuración"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo avión"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bloq orient de pant"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"SILENC"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"No hay aplicaciones recientes."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"La pantalla rotará automáticamente."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"La rotación de la pantalla se encuentra actualmente bloqueada."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 9e5ede4..3acfb45 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"No se admite la carga por USB."\n"Utiliza solo el cargador proporcionado."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Uso de la batería"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ajustes"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo avión"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bloquear orientación pantalla"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"SILENC"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"No hay aplicaciones recientes."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"La pantalla girará automáticamente."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"La rotación de la pantalla esta bloqueada."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fa-land/strings.xml b/packages/SystemUI/res/values-fa-land/strings.xml
new file mode 100644
index 0000000..adc2b11
--- /dev/null
+++ b/packages/SystemUI/res/values-fa-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"صفحه اکنون در جهت افقی قفل است."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fa-port/strings.xml b/packages/SystemUI/res/values-fa-port/strings.xml
new file mode 100644
index 0000000..609c944
--- /dev/null
+++ b/packages/SystemUI/res/values-fa-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"صفحه اکنون در جهت عمودی قفل است."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fa-xlarge/strings.xml b/packages/SystemUI/res/values-fa-xlarge/strings.xml
index 5583f8e..47312a5 100644
--- a/packages/SystemUI/res/values-fa-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-fa-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"پاک کردن همه"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"اتصال اینترنت موجود نیست"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi متصل شد"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 936236f..0528d68 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"رابط کاربر سیستم"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"پاک کردن"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"مزاحم نشوید"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"نمایش اعلان ها"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"اعلانی موجود نیست"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"در حال انجام"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اعلان ها"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"لطفاً شارژر را وصل کنید"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"باتری در حال کم شدن است:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"باتری در حال کم شدن است."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> باقیمانده است"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"شارژ USB پشتیبانی نمی شود."\n"فقط از شارژر ارائه شده استفاده کنید."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"استفاده از باتری"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"تنظیمات"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"حالت هواپیما"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"قفل جهت صفحه"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"بیصدا"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"خودکار"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"اعلان ها"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"اخیر"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"برنامه اخیری موجود نیست."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fi-land/strings.xml b/packages/SystemUI/res/values-fi-land/strings.xml
new file mode 100644
index 0000000..e1b8a74
--- /dev/null
+++ b/packages/SystemUI/res/values-fi-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Ruutu on nyt lukittu vaakasuuntaan."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fi-port/strings.xml b/packages/SystemUI/res/values-fi-port/strings.xml
new file mode 100644
index 0000000..1e190ff
--- /dev/null
+++ b/packages/SystemUI/res/values-fi-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Ruutu on nyt lukittu pystysuuntaan."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fi-xlarge/strings.xml b/packages/SystemUI/res/values-fi-xlarge/strings.xml
index b33d37e..8b1d91d 100644
--- a/packages/SystemUI/res/values-fi-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-fi-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Poista kaikki"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Ei internetyhteyttä"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wifi yhdistetty"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 9b3632c..1ce102a 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"Käyttöliitt."</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Tyhjennä"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Varattu"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Näytä ilmoitukset"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ei ilmoituksia"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Käynnissä olevat"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ilmoitukset"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Kytke laturi"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Akun virta on vähissä:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Akun virta on vähissä."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> jäljellä"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"USB-latausta ei tueta."\n"Käytä laitteen mukana tullutta laturia."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Akun käyttö"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Asetukset"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"WiFi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Lentokonetila"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Lukitse ruudun suunta"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ÄÄNET."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Ilmoitukset"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Viimeisimmät"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Ei viimeaikaisia sovelluksia."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index db28b04..12308fb 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"Chargement USB non disponible."\n"Vous devez utiliser le chargeur fourni."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Utilisation de la batterie"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Paramètres"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode Avion"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Verrouiller orientation écran"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUET"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Aucune application récente"</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"L\'écran pivote automatiquement."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"La rotation de l\'écran est verrouillée."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hr-land/strings.xml b/packages/SystemUI/res/values-hr-land/strings.xml
new file mode 100644
index 0000000..ce850a9
--- /dev/null
+++ b/packages/SystemUI/res/values-hr-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Zaslona je sada zaključan u pejzažnoj orijentaciji."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hr-port/strings.xml b/packages/SystemUI/res/values-hr-port/strings.xml
new file mode 100644
index 0000000..31d27ad
--- /dev/null
+++ b/packages/SystemUI/res/values-hr-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Zaslona je sada zaključan u portretnoj orijentaciji."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hr-xlarge/strings.xml b/packages/SystemUI/res/values-hr-xlarge/strings.xml
index 59c8e3a..cac702a 100644
--- a/packages/SystemUI/res/values-hr-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-hr-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Izbriši sve"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Nema int. veze"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: povezano"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index e7f4869..411336a 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"UI sustava"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Očisti"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ne uznemiravaj"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Prikaži obavijesti"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Bez obavijesti"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"U tijeku"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obavijesti"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Priključite punjač"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Baterija će uskoro biti potrošena:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Baterija će uskoro biti potrošena."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> preostalo"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"USB punjenje nije podržano."\n"Upotrijebite samo priloženi punjač."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Iskorištenost baterije"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Postavke"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Način rada u zrakoplovu"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Zaključaj orijentaciju zaslona"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"Bez zv."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Obavijesti"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Nedavni"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Nema nedavnih aplikacija."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-hu-land/strings.xml b/packages/SystemUI/res/values-hu-land/strings.xml
new file mode 100644
index 0000000..2b9ab55
--- /dev/null
+++ b/packages/SystemUI/res/values-hu-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"A képernyő zárolva van fekvő tájolásban."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hu-port/strings.xml b/packages/SystemUI/res/values-hu-port/strings.xml
new file mode 100644
index 0000000..6d7294f
--- /dev/null
+++ b/packages/SystemUI/res/values-hu-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"A képernyő zárolva van álló tájolásban."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hu-xlarge/strings.xml b/packages/SystemUI/res/values-hu-xlarge/strings.xml
index 510ba75..d49266f 100644
--- a/packages/SystemUI/res/values-hu-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-hu-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Az összes törlése"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Nincs internetkapcs."</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi csatlakozva"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index e8a6521..b82aa77 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"Rendszer UI"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Törlés"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ne zavarjanak"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Értesítések megjelenítése"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nincs értesítés"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Folyamatban van"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Értesítések"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Kérjük, csatlakoztassa a töltőt"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Akkufeszültség alacsony:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Az akkufeszültség alacsony."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> maradt"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"Az USB-n keresztüli töltés nincs támogatva."\n"Használja a kapott töltőt."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Akkumulátorhasználat"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Beállítások"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Repülőgép üzemmód"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Telefon tájolásának zárolása"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"NÉMÍT"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Értesítések"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Legutóbbiak"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Nincsenek nemrég használt alkalmazások"</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-in-land/strings.xml b/packages/SystemUI/res/values-in-land/strings.xml
new file mode 100644
index 0000000..ebdbb78
--- /dev/null
+++ b/packages/SystemUI/res/values-in-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Sekarang layar dikunci dalam orientasi lanskap."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-in-port/strings.xml b/packages/SystemUI/res/values-in-port/strings.xml
new file mode 100644
index 0000000..5907e6d
--- /dev/null
+++ b/packages/SystemUI/res/values-in-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Sekarang layar dikunci dalam orientasi potret."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-in-xlarge/strings.xml b/packages/SystemUI/res/values-in-xlarge/strings.xml
index 3be43db..81b3d47 100644
--- a/packages/SystemUI/res/values-in-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-in-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Hapus semua"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Tidak ada sambungan internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi tersambung"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 94f93fe..db170ab 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"Sistem UI"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Bersihkan"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Jangan ganggu"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Tampilkan pemberitahuan"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Tidak ada pemberitahuan"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Berkelanjutan"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pemberitahuan"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Harap hubungkan ke pengisi daya"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Baterai kekurangan daya:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Baterai semakin lemah."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> tersisa"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"Pengisian daya USB tidak didukung."\n"Gunakan hanya pengisi daya yang disediakan."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Penggunaan baterai"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Setelan"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode pesawat"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Kunci orientasi layar"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"BISUKAN"</string>
-    <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"OTOMATIS"</string>
+    <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Pemberitahuan"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Terbaru"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Tidak ada aplikasi terbaru."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 91c6d31..ca99d86 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"Ricarica tramite USB non supportata."\n"Utilizza solo il caricatore in dotazione."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Utilizzo batteria"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Impostazioni"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modalità aereo"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Blocca orientamento schermo"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Nessuna applicazione recente."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"Lo schermo ruoterà automaticamente."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"La rotazione dello schermo è bloccata."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-iw-land/strings.xml b/packages/SystemUI/res/values-iw-land/strings.xml
new file mode 100644
index 0000000..9568fc8
--- /dev/null
+++ b/packages/SystemUI/res/values-iw-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"המסך נעול כעת לרוחב."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-iw-port/strings.xml b/packages/SystemUI/res/values-iw-port/strings.xml
new file mode 100644
index 0000000..f951bf6
--- /dev/null
+++ b/packages/SystemUI/res/values-iw-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"המסך נעול כעת לאורך"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-iw-xlarge/strings.xml b/packages/SystemUI/res/values-iw-xlarge/strings.xml
index 5356165..80043b1 100644
--- a/packages/SystemUI/res/values-iw-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-iw-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"נקה הכל"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"אין חיבור לאינטרנט"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi מחובר"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 9896ab0..f2d5621 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"ממשק משתמש של המערכת"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"נקה"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"נא לא להפריע"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"הצג התראות"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"אין התראות"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"מתבצע"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"התראות"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"חבר מטען"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"הסוללה נחלשת:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"עוצמת הסוללה נחלשת."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"נותרו <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"טעינה באמצעות USB אינה נתמכת."\n"השתמש אך ורק במטען שסופק."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"צריכת סוללה"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"הגדרות"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"מצב טיסה"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"נעל כיוון מסך"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"השתק"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"אוטומטי"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"התראות"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"אחרונות"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"אין יישומים חדשים."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index ad36f2b..25d8873 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"USB充電には対応していません。"\n"付属の充電器をお使いください。"</string>
     <string name="battery_low_why" msgid="7279169609518386372">"電池使用量"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"設定"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"機内モード"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"画面の向きをロック"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ミュート"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"新着のアプリケーションはありません。"</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"画面は自動的に回転します。"</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"画面の回転をロックしました。"</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index f0fec0e..6c5970a 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -32,17 +32,16 @@
     <string name="invalid_charger" msgid="4549105996740522523">"USB 충전이 지원되지 않습니다."\n"제공된 충전기만 사용하세요."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"배터리 사용량"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"설정"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"비행기 모드"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"화면 방향 잠금"</string>
-    <string name="status_bar_settings_mute_label" msgid="554682549917429396">"밝기 무시"</string>
+    <string name="status_bar_settings_mute_label" msgid="554682549917429396">"무시"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"자동"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"알림"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"최근 사용한 앱"</string>
     <string name="recent_tasks_empty" msgid="1905484479067697884">"최근에 사용한 애플리케이션이 없습니다."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"화면은 자동으로 회전합니다."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"현재 화면 회전이 잠겨 있습니다."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lt-land/strings.xml b/packages/SystemUI/res/values-lt-land/strings.xml
new file mode 100644
index 0000000..3d976c5
--- /dev/null
+++ b/packages/SystemUI/res/values-lt-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Dabar ekranas užrakintas horizontalioje pozicijoje."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-lt-port/strings.xml b/packages/SystemUI/res/values-lt-port/strings.xml
new file mode 100644
index 0000000..149dbec
--- /dev/null
+++ b/packages/SystemUI/res/values-lt-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Dabar ekranas užrakintas vertikalioje pozicijoje."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-lt-xlarge/strings.xml b/packages/SystemUI/res/values-lt-xlarge/strings.xml
index 398dbf2..f9b3ac1 100644
--- a/packages/SystemUI/res/values-lt-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-lt-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Išvalyti viską"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Nėra interneto ryšio"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Prisijungta prie „Wi-Fi“"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index f571515..90a5e44 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"Sistemos NS"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Išvalyti"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Netrukdyti"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Rodyti pranešimus"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nėra įspėjimų"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Vykstantys"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Įspėjimai"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Prijunkite kroviklį"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Akumuliatorius senka:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Akumuliatorius senka."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"Liko <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"USB krovimas nepalaikomas."\n"Naudokite tik pateiktą įkroviklį."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Akumuliatoriaus naudojimas"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nustatymai"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Lėktuvo režimas"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Užfiksuoti ekrano orientaciją"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"NUTILD."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Pranešimai"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Naujos"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Nėra naujausių programų."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-lv-land/strings.xml b/packages/SystemUI/res/values-lv-land/strings.xml
new file mode 100644
index 0000000..b8fbe16
--- /dev/null
+++ b/packages/SystemUI/res/values-lv-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Ekrāns tagad ir bloķēts ainavas orientācijā."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-lv-port/strings.xml b/packages/SystemUI/res/values-lv-port/strings.xml
new file mode 100644
index 0000000..ac68922
--- /dev/null
+++ b/packages/SystemUI/res/values-lv-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Ekrāns tagad ir bloķēts portreta orientācijā."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-lv-xlarge/strings.xml b/packages/SystemUI/res/values-lv-xlarge/strings.xml
index e647046..af3423f 100644
--- a/packages/SystemUI/res/values-lv-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-lv-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Notīrīt visu"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Nav interneta sav."</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Izv. sav. ar Wi-Fi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index b0b2567..fb33329 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"Sistēmas UI"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Notīrīt"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Netraucēt"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Rādīt paziņojumus"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nav paziņojumu"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Notiekošs"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Paziņojumi"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Lūdzu, pievienojiet uzlādes ierīci."</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Akumulatora uzlādes līmenis kļūst zems:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Akumulators drīz izlādēsies."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"Atlicis: <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"USB lādēšana netiek atbalstīta."\n"Izmantojiet tikai komplektā iekļauto lādētāju."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Akumulatora lietojums"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Iestatījumi"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Lidmašīnas režīms"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bloķēt ekrāna orientāciju"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"IZ. SK."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Paziņojumi"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Nesens"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Nav nesenu lietojumprogrammu."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 1e2e184..82405a8 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"USB-lading støttes ikke."\n"Bruk kun den medfølgende laderen."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Batteribruk"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Innstillinger"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Trådløse nettverk"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flymodus"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Lås skjermretning"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"DEMPET"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Ingen nylig brukte programmer."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"Skjermen vil rotere automatisk."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"Skjermrotering er låst."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index db5abfc..4efdcbb 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"Opladen via USB niet ondersteund."\n"Gebruik alleen de bijgeleverde oplader."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Accugebruik"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Instellingen"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Vliegmodus"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Schermstand vergrendelen"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"DEMPEN"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Geen recente toepassingen."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"Scherm wordt automatisch geroteerd."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"Schermrotatie is nu vergrendeld."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index ef17a47..07ef5ef 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"Ładowanie przy użyciu złącza USB nie jest obsługiwane."\n"Należy używać tylko dołączonej ładowarki."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Użycie baterii"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ustawienia"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Tryb samolotowy"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Zablokuj orientację ekranu"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"WYGAŚ"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Brak ostatnio używanych aplikacji."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"Ekran zostanie obrócony automatycznie."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"Obracanie ekranu zostało zablokowane."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-port/strings.xml b/packages/SystemUI/res/values-port/strings.xml
index d3ab67b..67364a4 100644
--- a/packages/SystemUI/res/values-port/strings.xml
+++ b/packages/SystemUI/res/values-port/strings.xml
@@ -17,7 +17,4 @@
  */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Rotation lock toast text: shown when rotation lock is turned on in portrait orientation.
-         -->
-    <string name="toast_rotation_locked">Screen is now locked in portrait orientation.</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 0c6220b..aa14cce 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"Carregamento USB não suportado. "\n"Utilize apenas o carregador fornecido."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Utilização da bateria"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Definições"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo de avião"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bloquear orientação do ecrã"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"D. SOM"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Nenhuma aplicação recente."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"O ecrã será rodado automaticamente."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"A rotação do ecrã está agora bloqueada."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index de098b7..17be76a 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"O carregamento via USB não é suportado."\n"Use apenas o carregador fornecido."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Uso da bateria"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Configurações"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Modo para avião"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Bloquear orientação de tela"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUDO"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Nenhum aplicativo recente."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"A tela girará automaticamente."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"A rotação da tela está bloqueada."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 6f49c5c..e3fec88 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -55,8 +55,6 @@
     <skip />
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro-land/strings.xml b/packages/SystemUI/res/values-ro-land/strings.xml
new file mode 100644
index 0000000..6896ec8
--- /dev/null
+++ b/packages/SystemUI/res/values-ro-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Ecranul este acum blocat în orientarea de tip peisaj."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ro-port/strings.xml b/packages/SystemUI/res/values-ro-port/strings.xml
new file mode 100644
index 0000000..5931c5e
--- /dev/null
+++ b/packages/SystemUI/res/values-ro-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Ecranul este acum blocat în orientarea de tip portret."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ro-xlarge/strings.xml b/packages/SystemUI/res/values-ro-xlarge/strings.xml
index 3a6edbd..07badf4 100644
--- a/packages/SystemUI/res/values-ro-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-ro-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Ştergeţi-le pe toate"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Fără conex. internet"</string>
-    <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Res. Wi-Fi conectată"</string>
+    <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi conectat"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index ee8734e..2bb3c14 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"UI sistem"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ştergeţi"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Nu deranjaţi"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Afişaţi notificări"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nicio notificare"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"În desfăşurare"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificări"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Conectaţi încărcătorul"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Bateria se termină:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Bateria este descărcată."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"Rămas: <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"Încărcarea USB nu este acceptată. "\n"Utilizaţi numai încărcătorul furnizat."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Utilizarea bateriei"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Setări"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mod Avion"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Blocaţi orientarea ecranului"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"DEZAC."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificări"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Nu există aplicaţii recente."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d5e2719..89b9cc8 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"Зарядка через порт USB не поддерживается."\n"Используйте только зарядное устройство из комплекта поставки."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Расход заряда батареи"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Настройки"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Режим полета"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Закрепить ориентацию экрана"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ВЫКЛ."</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Новых приложений нет"</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"Экран будет поворачиваться автоматически."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"Поворот экрана заблокирован."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sk-land/strings.xml b/packages/SystemUI/res/values-sk-land/strings.xml
new file mode 100644
index 0000000..c0c5ba8
--- /dev/null
+++ b/packages/SystemUI/res/values-sk-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Obrazovka je teraz uzamknutá v orientácii na šírku."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sk-port/strings.xml b/packages/SystemUI/res/values-sk-port/strings.xml
new file mode 100644
index 0000000..c943ab3
--- /dev/null
+++ b/packages/SystemUI/res/values-sk-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Obrazovka je teraz uzamknutá v orientácii na výšku."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sk-xlarge/strings.xml b/packages/SystemUI/res/values-sk-xlarge/strings.xml
index 2c74cc6..ab01a3a 100644
--- a/packages/SystemUI/res/values-sk-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-sk-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
-    <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"bez. pripoj. k Int."</string>
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Vymazať všetky"</string>
+    <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Nepripoj. k Intern."</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi: pripojené"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 12443b1..9716327 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"UI systému"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Vymazať"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Nerušiť"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Zobraziť upozornenia"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Žiadne upozornenia"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Prebiehajúce"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Upozornenia"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Pripojte nabíjačku"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Batéria je skoro vybitá:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Batéria je skoro vybitá."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"Zostáva: <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"Nabíjanie pomocou rozhrania USB nie je podporované."\n"Používajte iba nabíjačku, ktorá bola dodaná spolu so zariadením."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Využitie batérie"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nastavenia"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Režim V lietadle"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Uzamknúť orientáciu obrazovky"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"STLMIŤ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Upozornenia"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Najnovšie"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Žiadne nedávno použité aplikácie."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sl-land/strings.xml b/packages/SystemUI/res/values-sl-land/strings.xml
new file mode 100644
index 0000000..a17c5f0
--- /dev/null
+++ b/packages/SystemUI/res/values-sl-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Zaslon je zaklenjen v ležeči usmerjenosti."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sl-port/strings.xml b/packages/SystemUI/res/values-sl-port/strings.xml
new file mode 100644
index 0000000..b71a6ea
--- /dev/null
+++ b/packages/SystemUI/res/values-sl-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Zaslon je zaklenjen v pokončni usmerjenosti."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sl-xlarge/strings.xml b/packages/SystemUI/res/values-sl-xlarge/strings.xml
index 59ce54f..ef50a67 100644
--- a/packages/SystemUI/res/values-sl-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-sl-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Počisti vse"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Brez inter. povez."</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi – povezano"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index aa6cb12..b05b93c 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -19,22 +19,17 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"Sistemski uporabniški vmesnik"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Počisti"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Ne moti"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Pokaži obvestila"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ni obvestil"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Trenutno"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obvestila"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Priključite napajalnik"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Baterija je skoraj prazna:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Baterija je skoraj prazna."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> preostalo"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"Polnjenje po povezavi USB ni podprto."\n"Uporabite priloženi polnilnik."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Uporaba baterije"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Nastavitve"</string>
     <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
@@ -45,12 +40,9 @@
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"SAMOD."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Obvestila"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Nedavno"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Ni novih programov."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sr-land/strings.xml b/packages/SystemUI/res/values-sr-land/strings.xml
new file mode 100644
index 0000000..3dd9774
--- /dev/null
+++ b/packages/SystemUI/res/values-sr-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Екран је сада закључан у вертикалном положају."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sr-port/strings.xml b/packages/SystemUI/res/values-sr-port/strings.xml
new file mode 100644
index 0000000..9c305c0
--- /dev/null
+++ b/packages/SystemUI/res/values-sr-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Екран је сада закључан у хоризонталном положају."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sr-xlarge/strings.xml b/packages/SystemUI/res/values-sr-xlarge/strings.xml
index fe14153..f5fcfbc 100644
--- a/packages/SystemUI/res/values-sr-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-sr-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Обриши све"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Нема интернет везе"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi је повезан"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index dfefae2..ff1d3fb 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"UI система"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Обриши"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Не узнемиравај"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Приказуј упозорења"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Нема обавештења"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Текуће"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Обавештења"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Прикључите пуњач"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Ниво напуњености батерије је низак:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Батерија ће се ускоро испразнити."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"преостало је <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"Пуњење преко USB-а није подржано."\n"Користите само приложени пуњач."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Коришћење батерије"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Подешавања"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Режим рада у авиону"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Закључавање положаја екрана"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"УГАСИ"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АУТОM."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Обавештења"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Недавно"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Нема недавних апликација"</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 6198aac..06b6880 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"Det går inte att ladda via USB."\n"Använd endast den laddare som levererades med telefonen."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Batteriförbrukning"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Inställningar"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Flygplansläge"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Lås bildskärmens riktning"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"TYST"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Inga nya program."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"Skärmen roteras automatiskt."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"Skärmrotationen är nu låst."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-th-land/strings.xml b/packages/SystemUI/res/values-th-land/strings.xml
new file mode 100644
index 0000000..5cc5013
--- /dev/null
+++ b/packages/SystemUI/res/values-th-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"ขณะนี้หน้าจอถูกล็อกการวางแนวในแนวนอน"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-th-port/strings.xml b/packages/SystemUI/res/values-th-port/strings.xml
new file mode 100644
index 0000000..abe230b
--- /dev/null
+++ b/packages/SystemUI/res/values-th-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"ขณะนี้หน้าจอถูกล็อกการวางแนวในแนวตั้ง"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-th-xlarge/strings.xml b/packages/SystemUI/res/values-th-xlarge/strings.xml
index 7a66312..fb4cbae 100644
--- a/packages/SystemUI/res/values-th-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-th-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"ล้างทั้งหมด"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"ไม่มีการเชื่อมต่ออินเทอร์เน็ต"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"เชื่อมต่อ Wi-Fi แล้ว"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 8f226fb..2d337a90 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"ส่วนติดต่อผู้ใช้ของระบบ"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"ล้างข้อมูล"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"ห้ามรบกวน"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"แสดงการแจ้งเตือน"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"ไม่มีการแจ้งเตือน"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ดำเนินอยู่"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"การแจ้งเตือน"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"โปรดเสียบอุปกรณ์ชาร์จ"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"แบตเตอรี่เหลือน้อย"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"แบตเตอรี่เหลือน้อย"</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"เหลืออีก <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"ไม่สนับสนุนการชาร์จแบบ USB"\n"ใช้เฉพาะที่ชาร์จที่ให้มาเท่านั้น"</string>
     <string name="battery_low_why" msgid="7279169609518386372">"การใช้แบตเตอรี่"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"การตั้งค่า"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"โหมดใช้งานบนเครื่องบิน"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"ล็อกแนวหน้าจอ"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ปิดเสียง"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"อัตโนมัติ"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"การแจ้งเตือน"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"เมื่อเร็วๆ นี้"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"ไม่มีแอปพลิเคชันล่าสุด"</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tl-land/strings.xml b/packages/SystemUI/res/values-tl-land/strings.xml
new file mode 100644
index 0000000..551e620
--- /dev/null
+++ b/packages/SystemUI/res/values-tl-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Naka-lock na ngayon ang screen at nasa pahigang oryentasyon."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-tl-port/strings.xml b/packages/SystemUI/res/values-tl-port/strings.xml
new file mode 100644
index 0000000..d51f19f
--- /dev/null
+++ b/packages/SystemUI/res/values-tl-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Naka-lock na ngayon ang screen at nasa patayong orientation."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-tl-xlarge/strings.xml b/packages/SystemUI/res/values-tl-xlarge/strings.xml
index 225b545..3560c96 100644
--- a/packages/SystemUI/res/values-tl-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-tl-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"I-clear ang lahat"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Wala net connection"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Konektado ang WiFi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index d0811c5..e94d3cc 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"UI ng System"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"I-clear"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Huwag gambalain"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Magpakita ng notification"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Walang mga notification"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Nagpapatuloy"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Mga Notification"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Pakikonekta ang charger"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Humihina ang baterya:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Humihina na ang baterya."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> natitira"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"Hindi sinusuportahan ang pag-charge sa USB."\n"Gamitin lang ang ibinigay na charger."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Paggamit ng baterya"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Mga Setting"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Airplane mode"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Naka-lock na screen orientation"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Mga Notification"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Kamakailan"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Walang kamakailang mga application."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 69e9f3e..4c3f818 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"USB üzerinden şarj desteklenmiyor."\n"Yalnızca ürünle birlikte verilen şarj cihazını kullanın."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Pil kullanımı"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ayarlar"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Kablosuz"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Uçak modu"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Ekran yönünü kilitle"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"KAPAT"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"Hiçbir yeni uygulama yok."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"Ekran otomatik olarak dönecektir."</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"Ekran dönüşü şimdi kilitlendi."</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-uk-land/strings.xml b/packages/SystemUI/res/values-uk-land/strings.xml
new file mode 100644
index 0000000..7f5b0f8
--- /dev/null
+++ b/packages/SystemUI/res/values-uk-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Екран зараз заблоковано в альбомній орієнтації."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-uk-port/strings.xml b/packages/SystemUI/res/values-uk-port/strings.xml
new file mode 100644
index 0000000..f0ea45f
--- /dev/null
+++ b/packages/SystemUI/res/values-uk-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Екран зараз заблоковано в книжковій орієнтації."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-uk-xlarge/strings.xml b/packages/SystemUI/res/values-uk-xlarge/strings.xml
index 7645f5e..47242a6 100644
--- a/packages/SystemUI/res/values-uk-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-uk-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Очистити все"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Інтернет не під\'єдн."</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi під\'єднано"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 078d81a..85ead1c 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"Інтерф.сист."</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Очист."</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Не турбувати"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Показувати сповіщення"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Немає сповіщень"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Поточні"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Сповіщення"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Підключ. заряд. пристрій"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Батарея виснажується:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Батарея виснажується."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"Залишилося <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"Заряджання USB не підтримується."\n"Використовуйте лише наданий у комплекті зарядний пристрій."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Викор. батареї"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Налаштування"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Режим польоту"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Заблокувати орієнтацію екрана"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ІГНОР."</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АВТОМ."</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Сповіщення"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Останні"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Немає останніх програм."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-vi-land/strings.xml b/packages/SystemUI/res/values-vi-land/strings.xml
new file mode 100644
index 0000000..e0c73ec
--- /dev/null
+++ b/packages/SystemUI/res/values-vi-land/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"Màn hình hiện bị khóa theo hướng ngang."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-vi-port/strings.xml b/packages/SystemUI/res/values-vi-port/strings.xml
new file mode 100644
index 0000000..2446f77
--- /dev/null
+++ b/packages/SystemUI/res/values-vi-port/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="toast_rotation_locked" msgid="1716565836190665743">"Màn hình hiện bị khóa theo hướng dọc."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-vi-xlarge/strings.xml b/packages/SystemUI/res/values-vi-xlarge/strings.xml
index eba1b72..cd390b3 100644
--- a/packages/SystemUI/res/values-vi-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-vi-xlarge/strings.xml
@@ -19,8 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
-    <skip />
+    <string name="status_bar_clear_all_button" msgid="4722520806446512408">"Xóa tất cả"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"Không có kết nối Internet"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Đã kết nối Wi-Fi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index e47e519..71df0c3 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -19,38 +19,29 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for app_label (7164937344850004466) -->
-    <skip />
+    <string name="app_label" msgid="7164937344850004466">"Giao diện người dùng hệ thống"</string>
     <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Xoá"</string>
-    <!-- no translation found for status_bar_do_not_disturb_button (5812628897510997853) -->
-    <skip />
-    <!-- no translation found for status_bar_please_disturb_button (3345398298841572813) -->
-    <skip />
+    <string name="status_bar_do_not_disturb_button" msgid="5812628897510997853">"Không làm phiền"</string>
+    <string name="status_bar_please_disturb_button" msgid="3345398298841572813">"Hiển thị thông báo"</string>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Không có thông báo nào"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Đang diễn ra"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Thông báo"</string>
     <string name="battery_low_title" msgid="7923774589611311406">"Vui lòng kết nối bộ sạc"</string>
-    <!-- outdated translation 7388781709819722764 -->     <string name="battery_low_subtitle" msgid="1752040062087829196">"Pin đang yếu:"</string>
-    <!-- no translation found for battery_low_percent_format (1077244949318261761) -->
-    <skip />
-    <!-- no translation found for invalid_charger (4549105996740522523) -->
-    <skip />
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Pin đang yếu."</string>
+    <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> còn lại"</string>
+    <string name="invalid_charger" msgid="4549105996740522523">"Không hỗ trợ sạc qua USB."\n"Chỉ sử dụng bộ sạc được cung cấp."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Sử dụng pin"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Cài đặt"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Chế độ trên máy bay"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"Khóa hướng màn hình"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"TẮT TIẾNG"</string>
     <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"TỰ ĐỘNG"</string>
     <string name="status_bar_settings_notifications" msgid="397146176280905137">"Thông báo"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Gần đây"</string>
-    <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
-    <skip />
+    <string name="recent_tasks_empty" msgid="1905484479067697884">"Không có ứng dụng nào gần đây."</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <!-- no translation found for toast_rotation_free (2700542202836832631) -->
-    <skip />
-    <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
     <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-xlarge-port/dimens.xml b/packages/SystemUI/res/values-xlarge-port/dimens.xml
new file mode 100644
index 0000000..56effa3
--- /dev/null
+++ b/packages/SystemUI/res/values-xlarge-port/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+*/
+-->
+<resources>
+    <!-- gap on either side of status bar notification icons -->
+    <dimen name="status_bar_icon_padding">2dp</dimen>
+</resources>
+
+
+
diff --git a/packages/SystemUI/res/values-xlarge/config.xml b/packages/SystemUI/res/values-xlarge/config.xml
index e140914..299ab97 100644
--- a/packages/SystemUI/res/values-xlarge/config.xml
+++ b/packages/SystemUI/res/values-xlarge/config.xml
@@ -24,7 +24,7 @@
 
     <!-- Component to be used as the status bar service.  Must implement the IStatusBar
      interface.  This name is in the ComponentName flattened format (package/class)  -->
-    <string name="config_statusBarComponent">com.android.systemui.statusbar.tablet.TabletStatusBar</string>
+    <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.tablet.TabletStatusBar</string>
 
     <!-- Whether or not we show the number in the bar. -->
     <bool name="config_statusBarShowNumber">false</bool>
diff --git a/packages/SystemUI/res/values-xlarge/dimens.xml b/packages/SystemUI/res/values-xlarge/dimens.xml
index 5ae3982..b9f5837 100644
--- a/packages/SystemUI/res/values-xlarge/dimens.xml
+++ b/packages/SystemUI/res/values-xlarge/dimens.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- * Copyright (c) 2006, The Android Open Source Project
+ * Copyright (c) 2010, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); 
  * you may not use this file except in compliance with the License. 
@@ -24,6 +24,8 @@
     <dimen name="notification_ticker_width">360dp</dimen>
     <!-- Status bar panel bottom offset (height of status bar - overlap) -->
     <dimen name="status_bar_panel_bottom_offset">36dp</dimen>
+    <!-- gap on either side of status bar notification icons -->
+    <dimen name="status_bar_icon_padding">8dp</dimen>
 </resources>
 
 
diff --git a/packages/SystemUI/res/values-xlarge/strings.xml b/packages/SystemUI/res/values-xlarge/strings.xml
index 279a135..f7b642d 100644
--- a/packages/SystemUI/res/values-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-xlarge/strings.xml
@@ -18,7 +18,7 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- The text for the button in the notification window-shade that clears
-         all of the currently visible notifications. -->
+         all of the currently visible notifications. [CHAR LIMIT=10]-->
     <string name="status_bar_clear_all_button">Clear all</string>
 
     <!-- System panel ("Quick Settings") -->
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 03cd73d..0cdc38d 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"不支持 USB 充电功能。"\n"只能使用随附的充电器充电。"</string>
     <string name="battery_low_why" msgid="7279169609518386372">"电量使用情况"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"设置"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"飞行模式"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"锁定屏幕浏览模式"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"静音"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"没有最近使用的应用程序。"</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"屏幕会自动旋转。"</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"屏幕旋转现已锁定。"</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml b/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml
index 6e52cdf..6a8ef52 100644
--- a/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW-xlarge/strings.xml
@@ -21,6 +21,6 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- no translation found for status_bar_clear_all_button (4722520806446512408) -->
     <skip />
-    <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"沒有網際網路連線"</string>
+    <string name="status_bar_settings_signal_meter_disconnected" msgid="4684094636492991496">"沒有網路連線"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="1456658018593445677">"Wi-Fi 已連線"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 90d8e41..c85020f 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -32,8 +32,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"不支援 USB 充電。"\n"僅能使用隨附的充電器。"</string>
     <string name="battery_low_why" msgid="7279169609518386372">"電池使用狀況"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"設定"</string>
-    <!-- no translation found for status_bar_settings_wifi_button (1733928151698311923) -->
-    <skip />
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"飛行模式"</string>
     <string name="status_bar_settings_rotation_lock" msgid="8361452930058000609">"鎖定螢幕瀏覽模式"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"關閉"</string>
@@ -43,6 +42,6 @@
     <string name="recent_tasks_empty" msgid="1905484479067697884">"沒有最近用過的應用程式。"</string>
     <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
     <skip />
-    <string name="toast_rotation_free" msgid="2700542202836832631">"螢幕會自動旋轉。"</string>
-    <string name="toast_rotation_locked" msgid="7484691306949652450">"螢幕旋轉功能現已鎖定。"</string>
+    <!-- no translation found for bluetooth_tethered (7094101612161133267) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 9737028..53d06c0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -108,11 +108,8 @@
     <!-- Recent apps label. Shown as title on recent apps panel -->
     <string name="recent_tasks_app_label">Apps</string>
 
-    <!-- Rotation lock toast text: shown when rotation lock is turned off (and the screen will
-         auto-rotate based on the accelerometer).  [CHAR LIMIT=NONE]-->
-    <string name="toast_rotation_free">Screen will rotate automatically.</string>
-    
-    <!-- Rotation lock toast text: shown when rotation lock is turned on and the orientation is
-         undefined.  [CHAR LIMIT=NONE] -->
-    <string name="toast_rotation_locked">Screen rotation is now locked.</string>
+    <!-- Network connection string for Bluetooth Reverse Tethering -->
+    <string name="bluetooth_tethered">Bluetooth tethered</string>
+    <!-- Title of a button to open the settings for input methods [CHAR LIMIT=30] -->
+    <string name="status_bar_input_method_settings_configure_input_methods">Configure input methods</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
index 53fe2ff..2110483c 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUI.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -20,11 +20,15 @@
 import java.io.PrintWriter;
 
 import android.content.Context;
+import android.content.res.Configuration;
 
 public abstract class SystemUI {
     public Context mContext;
 
     public abstract void start();
+    
+    protected void onConfigurationChanged(Configuration newConfig) {
+    }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
     }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 65990ad..870acd3 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.res.Configuration;
 import android.os.Binder;
 import android.os.IBinder;
 import android.util.Slog;
@@ -79,6 +80,13 @@
         }
     }
 
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        for (SystemUI ui: mServices) {
+            ui.onConfigurationChanged(newConfig);
+        }
+    }
+
     /**
      * Nobody binds to us.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 9dfc9c3..a81484c 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -186,7 +186,7 @@
                 b.setCancelable(true);
                 b.setTitle(R.string.battery_low_title);
                 b.setView(v);
-                b.setIcon(android.R.drawable.ic_dialog_alert);
+                b.setIconAttribute(android.R.attr.alertDialogIcon);
                 b.setPositiveButton(android.R.string.ok, null);
 
             final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
@@ -249,7 +249,7 @@
         AlertDialog.Builder b = new AlertDialog.Builder(mContext);
             b.setCancelable(true);
             b.setMessage(R.string.invalid_charger);
-            b.setIcon(android.R.drawable.ic_dialog_alert);
+            b.setIconAttribute(android.R.attr.alertDialogIcon);
             b.setPositiveButton(android.R.string.ok, null);
 
         AlertDialog d = b.create();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 7e8a5c1..004174e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -19,6 +19,7 @@
 import android.app.Notification;
 import android.os.IBinder;
 import android.view.View;
+import android.widget.ImageView;
 
 import com.android.internal.statusbar.StatusBarNotification;
 
@@ -36,6 +37,7 @@
         public View row; // the outer expanded view
         public View content; // takes the click events and sends the PendingIntent
         public View expanded; // the inflated RemoteViews
+        public ImageView largeIcon;
         public Entry() {}
         public Entry(IBinder key, StatusBarNotification n, StatusBarIconView ic) {
             this.key = key;
@@ -88,6 +90,7 @@
         entry.content = content;
         entry.expanded = expanded;
         entry.icon = icon;
+        entry.largeIcon = null; // TODO add support for large icons
         return add(entry);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
index 472a225..8fca759 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
@@ -52,6 +52,7 @@
     // Up-call methods
     protected abstract View makeStatusBarView();
     protected abstract int getStatusBarGravity();
+    public abstract int getStatusBarHeight();
 
     private DoNotDisturb mDoNotDisturb;
 
@@ -104,8 +105,7 @@
         }
 
         // Put up the view
-        final Resources res = mContext.getResources();
-        final int height= res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+        final int height = getStatusBarHeight();
 
         final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 0d6c5f6..132433b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -287,9 +287,13 @@
         return Gravity.TOP | Gravity.FILL_HORIZONTAL;
     }
 
-    private void addIntruderView() {
+    public int getStatusBarHeight() {
         final Resources res = mContext.getResources();
-        final int height= res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+        return res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+    }
+
+    private void addIntruderView() {
+        final int height = getStatusBarHeight();
 
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 5374957..3a7bd90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -78,6 +78,8 @@
 
         mWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
+
+        setClickable(true);
     }
 
     public boolean onTouchEvent(MotionEvent ev) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 1090463..cb5e361 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.policy;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -23,6 +25,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Resources;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.wifi.SupplicantState;
@@ -61,6 +64,7 @@
     boolean mDataConnected;
     IccCard.State mSimState = IccCard.State.READY;
     int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
+    int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
     int mDataState = TelephonyManager.DATA_DISCONNECTED;
     int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
     ServiceState mServiceState;
@@ -73,7 +77,7 @@
     int mDataDirectionIconId;
     int mDataSignalIconId;
     int mDataTypeIconId;
- 
+
     // wifi
     final WifiManager mWifiManager;
     boolean mWifiEnabled, mWifiConnected;
@@ -81,6 +85,11 @@
     String mWifiSsid;
     int mWifiIconId;
 
+    // bluetooth
+    private boolean mBluetoothTethered = false;
+    private int mBluetoothTetherIconId =
+        com.android.internal.R.drawable.stat_sys_tether_bluetooth;
+
     // data connectivity (regardless of state, can we access the internet?)
     // state of inet connection - 0 not connected, 100 connected
     private int mInetCondition = 0;
@@ -100,7 +109,7 @@
     int mLastCombinedSignalIconId = -1;
     int mLastDataTypeIconId = -1;
     String mLastLabel = "";
-    
+
     // yuck -- stop doing this here and put it in the framework
     IBatteryStats mBatteryStats;
 
@@ -231,11 +240,12 @@
         @Override
         public void onDataConnectionStateChanged(int state, int networkType) {
             if (DEBUG) {
-                Slog.d(TAG, "onDataConnectionStateChanged: state=" + state 
+                Slog.d(TAG, "onDataConnectionStateChanged: state=" + state
                         + " type=" + networkType);
             }
             mDataState = state;
-            updateDataNetType(networkType);
+            mDataNetType = networkType;
+            updateDataNetType();
             updateDataIcon();
             refreshViews();
         }
@@ -406,8 +416,12 @@
         }
     }
 
-    private final void updateDataNetType(int net) {
-        switch (net) {
+    private final void updateDataNetType() {
+        switch (mDataNetType) {
+            case TelephonyManager.NETWORK_TYPE_UNKNOWN:
+                mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
+                mDataTypeIconId = 0;
+                break;
             case TelephonyManager.NETWORK_TYPE_EDGE:
                 mDataIconList = TelephonyIcons.DATA_E[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_edge;
@@ -446,7 +460,7 @@
             default:
                 mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
                 mDataTypeIconId = R.drawable.stat_sys_signal_gprs;
-            break;
+                break;
         }
         if ((isCdma() && isCdmaEri()) || mPhone.isNetworkRoaming()) {
             mDataTypeIconId = R.drawable.stat_sys_signal_roam;
@@ -632,7 +646,7 @@
         switch (info.getType()) {
             case ConnectivityManager.TYPE_MOBILE:
                 mInetCondition = inetCondition;
-                updateDataNetType(info.getSubtype());
+                updateDataNetType();
                 updateDataIcon();
                 updateTelephonySignalStrength(); // apply any change in connectionStatus
                 break;
@@ -640,13 +654,22 @@
                 mInetCondition = inetCondition;
                 updateWifiIcons();
                 break;
+            case ConnectivityManager.TYPE_BLUETOOTH:
+                mInetCondition = inetCondition;
+                if (info != null) {
+                    mBluetoothTethered = info.isConnected() ? true: false;
+                } else {
+                    mBluetoothTethered = false;
+                }
+                break;
         }
     }
 
 
     // ===== Update the views =======================================================
 
-    // figure out what to show: first wifi, then 3G, then nothing
+    // figure out what to show- there should be one connected network or nothing
+    // General order of preference is: wifi, 3G than bluetooth. This might vary by product.
     void refreshViews() {
         Context context = mContext;
 
@@ -663,12 +686,16 @@
             }
             combinedSignalIconId = mWifiIconId;
             dataTypeIconId = 0;
+        } else if (mDataConnected) {
+            label = mNetworkName;
+            combinedSignalIconId = mDataSignalIconId;
+            dataTypeIconId = mDataTypeIconId;
+        } else if (mBluetoothTethered) {
+            label = mContext.getString(R.string.bluetooth_tethered);
+            combinedSignalIconId = mBluetoothTetherIconId;
+            dataTypeIconId = 0;
         } else {
-            if (mDataConnected) {
-                label = mNetworkName;
-            } else {
-                label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
-            }
+            label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
             combinedSignalIconId = mDataSignalIconId;
             dataTypeIconId = mDataTypeIconId;
         }
@@ -680,7 +707,8 @@
                     + " mDataDirectionIconId=0x" + Integer.toHexString(mDataDirectionIconId)
                     + " mDataSignalIconId=0x" + Integer.toHexString(mDataSignalIconId)
                     + " mDataTypeIconId=0x" + Integer.toHexString(mDataTypeIconId)
-                    + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId));
+                    + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId)
+                    + "mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId));
         }
 
         // the phone icon on phones
@@ -748,4 +776,102 @@
             }
         }
     }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("  - telephony ------");
+        pw.print("  mHspaDataDistinguishable=");
+        pw.println(mHspaDataDistinguishable);
+        pw.print("  mDataConnected=");
+        pw.println(mDataConnected);
+        pw.print("  mSimState=");
+        pw.println(mSimState);
+        pw.print("  mPhoneState=");
+        pw.println(mPhoneState);
+        pw.print("  mDataState=");
+        pw.println(mDataState);
+        pw.print("  mDataActivity=");
+        pw.println(mDataActivity);
+        pw.print("  mServiceState=");
+        pw.println(mServiceState.toString());
+        pw.print("  mNetworkName=");
+        pw.println(mNetworkName);
+        pw.print("  mNetworkNameDefault=");
+        pw.println(mNetworkNameDefault);
+        pw.print("  mNetworkNameSeparator=");
+        pw.println(mNetworkNameSeparator);
+        pw.print("  mPhoneSignalIconId=0x");
+        pw.print(Integer.toHexString(mPhoneSignalIconId));
+        pw.print("/");
+        pw.println(getResourceName(mPhoneSignalIconId));
+        pw.print("  mDataDirectionIconId=");
+        pw.print(Integer.toHexString(mDataDirectionIconId));
+        pw.print("/");
+        pw.println(getResourceName(mDataDirectionIconId));
+        pw.print("  mDataSignalIconId=");
+        pw.print(Integer.toHexString(mDataSignalIconId));
+        pw.print("/");
+        pw.println(getResourceName(mDataSignalIconId));
+        pw.print("  mDataTypeIconId=");
+        pw.print(Integer.toHexString(mDataTypeIconId));
+        pw.print("/");
+        pw.println(getResourceName(mDataTypeIconId));
+
+        pw.println("  - wifi ------");
+        pw.print("  mWifiEnabled=");
+        pw.println(mWifiEnabled);
+        pw.print("  mWifiConnected=");
+        pw.println(mWifiConnected);
+        pw.print("  mWifiLevel=");
+        pw.println(mWifiLevel);
+        pw.print("  mWifiSsid=");
+        pw.println(mWifiSsid);
+        pw.print("  mWifiIconId=");
+        pw.println(mWifiIconId);
+
+        pw.println("  - Bluetooth ----");
+        pw.print(" mBtReverseTethered=");
+        pw.println(mBluetoothTethered);
+
+        pw.println("  - connectivity ------");
+        pw.print("  mInetCondition=");
+        pw.println(mInetCondition);
+
+        pw.println("  - icons ------");
+        pw.print("  mLastPhoneSignalIconId=0x");
+        pw.print(Integer.toHexString(mLastPhoneSignalIconId));
+        pw.print("/");
+        pw.println(getResourceName(mLastPhoneSignalIconId));
+        pw.print("  mLastDataDirectionIconId=0x");
+        pw.print(Integer.toHexString(mLastDataDirectionIconId));
+        pw.print("/");
+        pw.println(getResourceName(mLastDataDirectionIconId));
+        pw.print("  mLastWifiIconId=0x");
+        pw.print(Integer.toHexString(mLastWifiIconId));
+        pw.print("/");
+        pw.println(getResourceName(mLastWifiIconId));
+        pw.print("  mLastCombinedSignalIconId=0x");
+        pw.print(Integer.toHexString(mLastCombinedSignalIconId));
+        pw.print("/");
+        pw.println(getResourceName(mLastCombinedSignalIconId));
+        pw.print("  mLastDataTypeIconId=0x");
+        pw.print(Integer.toHexString(mLastDataTypeIconId));
+        pw.print("/");
+        pw.println(getResourceName(mLastCombinedSignalIconId));
+        pw.print("  mLastLabel=");
+        pw.print(mLastLabel);
+    }
+
+    private String getResourceName(int resId) {
+        if (resId == 0) {
+            final Resources res = mContext.getResources();
+            try {
+                return res.getResourceName(resId);
+            } catch (android.content.res.Resources.NotFoundException ex) {
+                return "(unknown)";
+            }
+        } else {
+            return "(null)";
+        }
+    }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
new file mode 100644
index 0000000..5616159
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.tablet;
+
+import java.util.ArrayList;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.util.DisplayMetrics;
+import android.util.Slog;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManagerImpl;
+import android.view.WindowManagerPolicy;
+
+public class HeightReceiver extends BroadcastReceiver {
+    private static final String TAG = "StatusBar.HeightReceiver";
+
+    public interface OnBarHeightChangedListener {
+        public void onBarHeightChanged(int height);
+    }
+
+    Context mContext;
+    ArrayList<OnBarHeightChangedListener> mListeners = new ArrayList<OnBarHeightChangedListener>();
+    WindowManager mWindowManager;
+    int mHeight;
+
+    public HeightReceiver(Context context) {
+        mContext = context;
+        mWindowManager = WindowManagerImpl.getDefault();
+    }
+
+    public void addOnBarHeightChangedListener(OnBarHeightChangedListener l) {
+        mListeners.add(l);
+        l.onBarHeightChanged(mHeight);
+    }
+
+    public void removeOnBarHeightChangedListener(OnBarHeightChangedListener l) {
+        mListeners.remove(l);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final boolean plugged
+                = intent.getBooleanExtra(WindowManagerPolicy.EXTRA_HDMI_PLUGGED_STATE, false);
+        setPlugged(plugged);
+    }
+
+    public void registerReceiver() {
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(WindowManagerPolicy.ACTION_HDMI_PLUGGED);
+        final Intent val = mContext.registerReceiver(this, filter);
+        onReceive(mContext, val);
+    }
+
+    private void setPlugged(boolean plugged) {
+        final Resources res = mContext.getResources();
+
+        Slog.d(TAG, "plugged=" + plugged);
+        int height = -1;
+        if (plugged) {
+            final DisplayMetrics metrics = new DisplayMetrics();
+            mWindowManager.getDefaultDisplay().getMetrics(metrics);
+            Slog.d(TAG, "metrics=" + metrics);
+            height = metrics.heightPixels - 720;
+        }
+
+        final int minHeight
+                = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+        if (height < minHeight) {
+            height = minHeight;
+        }
+        Slog.d(TAG, "using height=" + height + " old=" + mHeight);
+        mHeight = height;
+
+        final int N = mListeners.size();
+        for (int i=0; i<N; i++) {
+            mListeners.get(i).onBarHeightChanged(height);
+        }
+    }
+
+    public int getHeight() {
+        return mHeight;
+    }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
index ddce6bf..69bc161 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
@@ -19,11 +19,9 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
-import android.os.Handler;
 import android.os.IBinder;
 import android.provider.Settings;
 import android.util.Log;
-import android.util.Slog;
 import android.util.AttributeSet;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -31,11 +29,8 @@
 import android.view.View;
 import android.widget.ImageView;
 
-import com.android.server.InputMethodManagerService;
 import com.android.systemui.R;
 
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -48,22 +43,24 @@
     // IME shortcut button is disabled.
     private static final int ID_IME_SHORTCUT_BUTTON = 0;
 
+    // These values are defined in Settings application.
+    private static final int ID_IME_BUTTON_VISIBILITY_AUTO = 0;
+    private static final int ID_IME_BUTTON_VISIBILITY_ALWAYS_SHOW = 1;
+    private static final int ID_IME_BUTTON_VISIBILITY_ALWAYS_HIDE = 2;
+
     // other services we wish to talk to
     private final InputMethodManager mImm;
     private final int mId;
-    // Cache of InputMethodsInfo
-    private final HashMap<String, InputMethodInfo> mInputMethodsInfo =
-            new HashMap<String, InputMethodInfo>();
     private ImageView mIcon;
     private IBinder mToken;
-    private boolean mKeyboardShown;
+    private boolean mKeyboardVisible = false;
+    private boolean mScreenLocked = false;
     private InputMethodInfo mShortcutInfo;
     private InputMethodSubtype mShortcutSubtype;
 
     public InputMethodButton(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        mKeyboardShown = false;
         // Resource Id of the input method button. This id is defined in status_bar.xml
         mId = getId();
         // IME hookup
@@ -94,21 +91,7 @@
     protected void onAttachedToWindow() {
         mIcon = (ImageView) findViewById(mId);
 
-        refreshStatusIcon(mKeyboardShown);
-    }
-
-    private InputMethodInfo getCurrentInputMethodInfo() {
-        String curInputMethodId = Settings.Secure.getString(getContext()
-                .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
-        if (!mInputMethodsInfo.containsKey(curInputMethodId)) {
-            mInputMethodsInfo.clear();
-            List<InputMethodInfo> imis = mImm.getInputMethodList();
-            for (int i = 0; i < imis.size(); ++i) {
-                InputMethodInfo imi = imis.get(i);
-                mInputMethodsInfo.put(imi.getId(), imi);
-            }
-        }
-        return mInputMethodsInfo.get(curInputMethodId);
+        refreshStatusIcon();
     }
 
     // TODO: Need to show an appropriate drawable for this shortcut button,
@@ -136,8 +119,7 @@
         final PackageManager pm = getContext().getPackageManager();
         if (imi != null) {
             if (DEBUG) {
-                Log.d(TAG, "Update icons of IME: " + imi.getPackageName() + ","
-                        + subtype.getLocale() + "," + subtype.getMode());
+                Log.d(TAG, "Update icons of IME: " + imi.getPackageName());
             }
             if (subtype != null) {
                 return pm.getDrawable(imi.getPackageName(), subtype.getIconResId(),
@@ -162,43 +144,58 @@
     // * There are no explicitly enabled (by the user) subtypes of the IME, or the IME doesn't have
     // its subtypes at all
     private boolean needsToShowIMEButton() {
+        if (!mKeyboardVisible || mScreenLocked) return false;
         List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
         final int size = imis.size();
-        return size > 1
-                || (size == 1 && mImm.getEnabledInputMethodSubtypeList(imis.get(0)).size() > 1);
+        final int visibility = loadInputMethodSelectorVisibility();
+        switch (visibility) {
+            case ID_IME_BUTTON_VISIBILITY_AUTO:
+                return size > 1 || (size == 1
+                        && mImm.getEnabledInputMethodSubtypeList(imis.get(0), false).size() > 1);
+            case ID_IME_BUTTON_VISIBILITY_ALWAYS_SHOW:
+                return true;
+            case ID_IME_BUTTON_VISIBILITY_ALWAYS_HIDE:
+                return false;
+        }
+        return false;
     }
 
-    private void refreshStatusIcon(boolean keyboardShown) {
-        if (!keyboardShown) {
-            setVisibility(View.INVISIBLE);
+    private void refreshStatusIcon() {
+        if (mIcon == null) {
+            return;
+        }
+        if (!needsToShowIMEButton()) {
+            setVisibility(View.GONE);
             return;
         } else {
             setVisibility(View.VISIBLE);
         }
         Drawable icon = null;
         switch (mId) {
-            case ID_IME_SWITCH_BUTTON:
-                // TODO: Just showing the first shortcut IME subtype for now. Should handle all
-                // shortcuts as appropriate.
-                icon = getSubtypeIcon(getCurrentInputMethodInfo(),
-                        mImm.getCurrentInputMethodSubtype());
-                break;
             case ID_IME_SHORTCUT_BUTTON:
                 icon = getShortcutInputMethodAndSubtypeDrawable();
                 break;
         }
-        if (mIcon != null) {
-            if (icon == null) {
-                mIcon.setImageResource(R.drawable.ic_sysbar_ime_default);
-            } else {
-                mIcon.setImageDrawable(icon);
-            }
+        if (icon == null) {
+            mIcon.setImageResource(R.drawable.ic_sysbar_ime);
+        } else {
+            mIcon.setImageDrawable(icon);
         }
     }
 
-    public void setIMEButtonVisible(IBinder token, boolean visible) {
+    private int loadInputMethodSelectorVisibility() {
+        return Settings.Secure.getInt(getContext().getContentResolver(),
+                Settings.Secure.INPUT_METHOD_SELECTOR_VISIBILITY, ID_IME_BUTTON_VISIBILITY_AUTO);
+    }
+
+    public void setIMEButtonVisible(IBinder token, boolean keyboardVisible) {
         mToken = token;
-        mKeyboardShown = visible ? needsToShowIMEButton() : false;
-        refreshStatusIcon(mKeyboardShown);
+        mKeyboardVisible = keyboardVisible;
+        refreshStatusIcon();
+    }
+
+    public void setScreenLocked(boolean locked) {
+        mScreenLocked = locked;
+        refreshStatusIcon();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
new file mode 100644
index 0000000..d4ba693
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.tablet;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Pair;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RadioButton;
+import android.widget.TextView;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+import com.android.systemui.R;
+
+public class InputMethodsPanel extends LinearLayout implements StatusBarPanel, OnClickListener {
+    private static final boolean DEBUG = TabletStatusBar.DEBUG;
+    private static final String TAG = "InputMethodsPanel";
+
+    private final InputMethodManager mImm;
+    private final HashMap<InputMethodInfo, List<InputMethodSubtype>>
+            mEnabledInputMethodAndSubtypesCache =
+                    new HashMap<InputMethodInfo, List<InputMethodSubtype>>();
+    private final HashMap<View, Pair<InputMethodInfo, InputMethodSubtype>> mRadioViewAndImiMap =
+            new HashMap<View, Pair<InputMethodInfo, InputMethodSubtype>>();
+    private final PackageManager mPackageManager;
+
+    private Context mContext;
+    private IBinder mToken;
+    private LinearLayout mInputMethodMenuList;
+    private String mEnabledInputMethodAndSubtypesCacheStr;
+    private View mConfigureImeShortcut;
+
+    public InputMethodsPanel(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public InputMethodsPanel(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mContext = context;
+        mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+        mPackageManager = context.getPackageManager();
+    }
+
+    @Override
+    public void onFinishInflate() {
+        mInputMethodMenuList = (LinearLayout) findViewById(R.id.input_method_menu_list);
+        mConfigureImeShortcut = ((View) findViewById(R.id.ime_settings_shortcut));
+        mConfigureImeShortcut.setOnClickListener(this);
+        // TODO: If configurations for IME are not changed, do not update
+        // by checking onConfigurationChanged.
+        updateUiElements();
+    }
+
+    @Override
+    public boolean isInContentArea(int x, int y) {
+        return false;
+    }
+
+    @Override
+    protected void onVisibilityChanged(View changedView, int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+        if (visibility == View.VISIBLE && changedView == this) {
+            updateUiElements();
+        }
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (view == mConfigureImeShortcut) {
+            showConfigureInputMethods();
+            onFinishPanel(true);
+            return;
+        }
+    }
+
+    private void onFinishPanel(boolean closeKeyboard) {
+        setVisibility(View.GONE);
+        if (closeKeyboard) {
+            mImm.hideSoftInputFromWindow(getWindowToken(), 0);
+        }
+    }
+
+    private void startActivity(Intent intent) {
+        mContext.startActivity(intent);
+    }
+
+    private void showConfigureInputMethods() {
+        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        startActivity(intent);
+    }
+
+    private View createInputMethodItem(
+            final InputMethodInfo imi, final InputMethodSubtype subtype) {
+        CharSequence subtypeName = getSubtypeName(imi, subtype);
+        CharSequence imiName = getIMIName(imi);
+        Drawable icon = getSubtypeIcon(imi, subtype);
+        View view = View.inflate(mContext, R.layout.status_bar_input_methods_item, null);
+        ImageView subtypeIcon = (ImageView)view.findViewById(R.id.item_icon);
+        TextView itemTitle = (TextView)view.findViewById(R.id.item_title);
+        TextView itemSubtitle = (TextView)view.findViewById(R.id.item_subtitle);
+        ImageView settingsIcon = (ImageView)view.findViewById(R.id.item_settings_icon);
+        View subtypeView = view.findViewById(R.id.item_subtype);
+        if (subtypeName == null) {
+            itemTitle.setText(imiName);
+            itemSubtitle.setVisibility(View.GONE);
+        } else {
+            itemTitle.setText(subtypeName);
+            itemSubtitle.setVisibility(View.VISIBLE);
+            itemSubtitle.setText(imiName);
+        }
+        subtypeIcon.setImageDrawable(icon);
+        final String settingsActivity = imi.getSettingsActivity();
+        if (!TextUtils.isEmpty(settingsActivity)) {
+            settingsIcon.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View arg0) {
+                    Intent intent = new Intent(Intent.ACTION_MAIN);
+                    intent.setClassName(imi.getPackageName(), settingsActivity);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                            | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+                            | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                    startActivity(intent);
+                    onFinishPanel(true);
+                }
+            });
+        } else {
+            // Do not show the settings icon if the IME does not have a settings preference
+            view.findViewById(R.id.item_vertical_separator).setVisibility(View.GONE);
+            settingsIcon.setVisibility(View.GONE);
+        }
+        mRadioViewAndImiMap.put(
+                subtypeView, new Pair<InputMethodInfo, InputMethodSubtype> (imi, subtype));
+        subtypeView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype =
+                        updateRadioButtonsByView(view);
+                onFinishPanel(false);
+                setInputMethodAndSubtype(imiAndSubtype.first, imiAndSubtype.second);
+            }
+        });
+        return view;
+    }
+
+    private void updateUiElements() {
+        // TODO: Reuse subtype views.
+        mInputMethodMenuList.removeAllViews();
+        mRadioViewAndImiMap.clear();
+        HashMap<InputMethodInfo, List<InputMethodSubtype>> enabledIMIs
+                = getEnabledInputMethodAndSubtypeList();
+        // TODO: Sort by alphabet and mode.
+        Set<InputMethodInfo> cachedImiSet = enabledIMIs.keySet();
+        for (InputMethodInfo imi: cachedImiSet) {
+            List<InputMethodSubtype> subtypes = enabledIMIs.get(imi);
+            if (subtypes == null || subtypes.size() == 0) {
+                mInputMethodMenuList.addView(
+                        createInputMethodItem(imi, null));
+                continue;
+            }
+            for (InputMethodSubtype subtype: subtypes) {
+                mInputMethodMenuList.addView(createInputMethodItem(imi, subtype));
+            }
+        }
+        updateRadioButtons();
+    }
+
+    public void setIMEToken(IBinder token) {
+        mToken = token;
+    }
+
+    private void setInputMethodAndSubtype(InputMethodInfo imi, InputMethodSubtype subtype) {
+        if (mToken != null) {
+            mImm.setInputMethodAndSubtype(mToken, imi.getId(), subtype);
+        } else {
+            Log.w(TAG, "IME Token is not set yet.");
+        }
+    }
+
+    // Turn on the selected radio button when the user chooses the item
+    private Pair<InputMethodInfo, InputMethodSubtype> updateRadioButtonsByView(View selectedView) {
+        Pair<InputMethodInfo, InputMethodSubtype> selectedImiAndSubtype = null;
+        if (mRadioViewAndImiMap.containsKey(selectedView)) {
+            for (View radioView: mRadioViewAndImiMap.keySet()) {
+                RadioButton subtypeRadioButton =
+                        (RadioButton) radioView.findViewById(R.id.item_radio);
+                if (subtypeRadioButton == null) {
+                    Log.w(TAG, "RadioButton was not found in the selected subtype view");
+                    return null;
+                }
+                if (radioView == selectedView) {
+                    Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype =
+                        mRadioViewAndImiMap.get(radioView);
+                    selectedImiAndSubtype = imiAndSubtype;
+                    subtypeRadioButton.setChecked(true);
+                } else {
+                    subtypeRadioButton.setChecked(false);
+                }
+            }
+        }
+        return selectedImiAndSubtype;
+    }
+
+    private void updateRadioButtons() {
+        updateRadioButtonsByImiAndSubtype(
+                getCurrentInputMethodInfo(), mImm.getCurrentInputMethodSubtype());
+    }
+
+    // Turn on the selected radio button at startup
+    private void updateRadioButtonsByImiAndSubtype(
+            InputMethodInfo imi, InputMethodSubtype subtype) {
+        if (DEBUG) {
+            Log.d(TAG, "Update radio buttons by " + imi.getId() + ", " + subtype);
+        }
+        for (View radioView: mRadioViewAndImiMap.keySet()) {
+            RadioButton subtypeRadioButton =
+                    (RadioButton) radioView.findViewById(R.id.item_radio);
+            if (subtypeRadioButton == null) {
+                Log.w(TAG, "RadioButton was not found in the selected subtype view");
+                return;
+            }
+            Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype =
+                mRadioViewAndImiMap.get(radioView);
+            if (imiAndSubtype.first.getId().equals(imi.getId())
+                    && (imiAndSubtype.second == null || imiAndSubtype.second.equals(subtype))) {
+                subtypeRadioButton.setChecked(true);
+            } else {
+                subtypeRadioButton.setChecked(false);
+            }
+        }
+    }
+
+    private HashMap<InputMethodInfo, List<InputMethodSubtype>>
+            getEnabledInputMethodAndSubtypeList() {
+        String newEnabledIMIs = Settings.Secure.getString(
+                mContext.getContentResolver(), Settings.Secure.ENABLED_INPUT_METHODS);
+        if (mEnabledInputMethodAndSubtypesCacheStr == null
+                || !mEnabledInputMethodAndSubtypesCacheStr.equals(newEnabledIMIs)) {
+            mEnabledInputMethodAndSubtypesCache.clear();
+            final List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
+            for (InputMethodInfo imi: imis) {
+                mEnabledInputMethodAndSubtypesCache.put(imi,
+                        mImm.getEnabledInputMethodSubtypeList(imi, true));
+            }
+            mEnabledInputMethodAndSubtypesCacheStr = newEnabledIMIs;
+        }
+        return mEnabledInputMethodAndSubtypesCache;
+    }
+
+    private InputMethodInfo getCurrentInputMethodInfo() {
+        String curInputMethodId = Settings.Secure.getString(getContext()
+                .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+        Set<InputMethodInfo> cachedImiSet = mEnabledInputMethodAndSubtypesCache.keySet();
+        // 1. Search IMI in cache
+        for (InputMethodInfo imi: cachedImiSet) {
+            if (imi.getId().equals(curInputMethodId)) {
+                return imi;
+            }
+        }
+        // 2. Get current enabled IMEs and search IMI
+        cachedImiSet = getEnabledInputMethodAndSubtypeList().keySet();
+        for (InputMethodInfo imi: cachedImiSet) {
+            if (imi.getId().equals(curInputMethodId)) {
+                return imi;
+            }
+        }
+        return null;
+    }
+
+    private CharSequence getIMIName(InputMethodInfo imi) {
+        if (imi == null) return null;
+        return mPackageManager.getApplicationLabel(imi.getServiceInfo().applicationInfo);
+    }
+
+    private CharSequence getSubtypeName(InputMethodInfo imi, InputMethodSubtype subtype) {
+        if (imi == null || subtype == null) return null;
+        // TODO: Change the language of subtype name according to subtype's locale.
+        return mPackageManager.getText(
+                imi.getPackageName(), subtype.getNameResId(), imi.getServiceInfo().applicationInfo);
+    }
+
+    private Drawable getSubtypeIcon(InputMethodInfo imi, InputMethodSubtype subtype) {
+        if (imi != null) {
+            if (DEBUG) {
+                Log.d(TAG, "Update icons of IME: " + imi.getPackageName());
+                if (subtype != null) {
+                    Log.d(TAG, "subtype =" + subtype.getLocale() + "," + subtype.getMode());
+                }
+            }
+            if (subtype != null) {
+                return mPackageManager.getDrawable(imi.getPackageName(), subtype.getIconResId(),
+                        imi.getServiceInfo().applicationInfo);
+            } else if (imi.getSubtypes().size() > 0) {
+                return mPackageManager.getDrawable(imi.getPackageName(),
+                        imi.getSubtypes().get(0).getIconResId(),
+                        imi.getServiceInfo().applicationInfo);
+            } else {
+                try {
+                    return mPackageManager.getApplicationInfo(
+                            imi.getPackageName(), 0).loadIcon(mPackageManager);
+                } catch (PackageManager.NameNotFoundException e) {
+                    Log.w(TAG, "IME can't be found: " + imi.getPackageName());
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 82c1d17..a2f6e3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.tablet;
 
 import android.animation.Animator;
+import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
@@ -33,28 +34,30 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.FrameLayout;
 import android.widget.TextView;
 
 import com.android.systemui.R;
 
-public class NotificationPanel extends LinearLayout implements StatusBarPanel,
+public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
         View.OnClickListener {
-    static final String TAG = "NotificationPanel";
+    static final String TAG = "Tablet/NotificationPanel";
+    static final boolean DEBUG = false;
 
     boolean mShowing;
     View mTitleArea;
     View mSettingsButton;
     View mNotificationButton;
     View mNotificationScroller;
+    View mNotificationGlow;
     ViewGroup mContentFrame;
     Rect mContentArea;
     View mSettingsView;
+    View mScrim, mGlow;
     ViewGroup mContentParent;
 
     Choreographer mChoreo = new Choreographer();
-    int mStatusBarHeight;
-    Drawable mBgDrawable;
-    Drawable mGlowDrawable;
 
     public NotificationPanel(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -62,13 +65,6 @@
 
     public NotificationPanel(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-
-        final Resources res = context.getResources();
-
-        mStatusBarHeight = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
-        mBgDrawable = res.getDrawable(R.drawable.notify_panel_bg_protect);
-        mGlowDrawable = res.getDrawable(R.drawable.notify_glow_back);
     }
 
     @Override
@@ -78,14 +74,18 @@
         setWillNotDraw(false);
 
         mContentParent = (ViewGroup)findViewById(R.id.content_parent);
+        mContentParent.bringToFront();
         mTitleArea = findViewById(R.id.title_area);
+        mTitleArea.setOnClickListener(this);
+
+        mScrim = findViewById(R.id.scrim);
+        mGlow = findViewById(R.id.glow);
 
         mSettingsButton = (ImageView)findViewById(R.id.settings_button);
-        mSettingsButton.setOnClickListener(this);
         mNotificationButton = (ImageView)findViewById(R.id.notification_button);
-        mNotificationButton.setOnClickListener(this);
 
-        mNotificationScroller = findViewById(R.id.notificationScroller);
+        mNotificationScroller = findViewById(R.id.notification_scroller);
+        mNotificationGlow = findViewById(R.id.notification_glow);
         mContentFrame = (ViewGroup)findViewById(R.id.content_frame);
     }
 
@@ -130,21 +130,6 @@
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
-        // We know that none of our children are GONE, so don't worry about skipping GONE views.
-        final int N = getChildCount();
-        if (N == 0) {
-            return;
-        }
-        final int allocatedBottom = getChildAt(N-1).getBottom();
-        final int shift = b - allocatedBottom - getPaddingBottom();
-        if (shift <= 0) {
-            return;
-        }
-        for (int i=0; i<N; i++) {
-            final View c = getChildAt(i);
-            c.layout(c.getLeft(), c.getTop() + shift, c.getRight(), c.getBottom() + shift);
-        }
-
         mChoreo.setPanelHeight(mContentParent.getHeight());
     }
 
@@ -152,33 +137,15 @@
     public void onSizeChanged(int w, int h, int oldw, int oldh) {
         super.onSizeChanged(w, h, oldw, oldh);
         mContentArea = null;
-        mBgDrawable.setBounds(0, 0, w, h-mStatusBarHeight);
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        int saveCount;
-        final int w = getWidth();
-        final int h = getHeight();
-
-        super.onDraw(canvas);
-
-        // Background protection
-        mBgDrawable.draw(canvas);
-
-        // The panel glow (behind status bar)
-
-        saveCount = canvas.save();
-        canvas.clipRect(0, 0, w, h-mStatusBarHeight);
-        mGlowDrawable.draw(canvas);
-        canvas.restoreToCount(saveCount);
     }
 
     public void onClick(View v) {
-        if (v == mSettingsButton) {
-            switchToSettingsMode();
-        } else if (v == mNotificationButton) {
-            switchToNotificationMode();
+        if (v == mTitleArea) {
+            if (mSettingsView == null) {
+                switchToSettingsMode();
+            } else {
+                switchToNotificationMode();
+            }
         }
     }
 
@@ -218,97 +185,109 @@
     void addSettingsView() {
         LayoutInflater infl = LayoutInflater.from(getContext());
         mSettingsView = infl.inflate(R.layout.status_bar_settings_view, mContentFrame, false);
-        mContentFrame.addView(mSettingsView);
+        mContentFrame.addView(mSettingsView, mContentFrame.indexOfChild(mNotificationGlow));
     }
 
     private class Choreographer implements Animator.AnimatorListener {
-        int mBgAlpha;
-        ValueAnimator mBgAnim;
+        boolean mVisible;
         int mPanelHeight;
-        int mPanelBottom;
-        ValueAnimator mPositionAnim;
+        AnimatorSet mContentAnim;
 
         // should group this into a multi-property animation
-        final int OPEN_DURATION = 200;
+        final int OPEN_DURATION = 136;
+        final int CLOSE_DURATION = 250;
+
+        // the panel will start to appear this many px from the end
+        final int HYPERSPACE_OFFRAMP = 30;
 
         Choreographer() {
         }
 
-        void createAnimation(boolean visible) {
-            mBgAnim = ObjectAnimator.ofInt(this, "bgAlpha", mBgAlpha, visible ? 255 : 0)
-                    .setDuration(OPEN_DURATION);
-            mBgAnim.addListener(this);
+        void createAnimation(boolean appearing) {
+            Animator bgAnim = ObjectAnimator.ofFloat(mScrim,
+                    "alpha", mScrim.getAlpha(), appearing ? 1 : 0);
 
-            mPositionAnim = ObjectAnimator.ofInt(this, "panelBottom", mPanelBottom,
-                        visible ? mPanelHeight : 0)
-                    .setDuration(OPEN_DURATION);
-        }
+            float start, end;
 
-        void startAnimation(boolean visible) {
-            if (mBgAnim == null) {
-                createAnimation(visible);
-                mBgAnim.start();
-                mPositionAnim.start();
+            // 0: on-screen
+            // height: off-screen
+            float y = mContentParent.getTranslationY();
+            if (appearing) {
+                // we want to go from near-the-top to the top, unless we're half-open in the right
+                // general vicinity
+                start = (y < HYPERSPACE_OFFRAMP)
+                    ? y
+                    : HYPERSPACE_OFFRAMP;
+                end = 0;
             } else {
-                mBgAnim.reverse();
-                mPositionAnim.reverse();
+                start = y;
+                end = y + HYPERSPACE_OFFRAMP;
             }
+            Animator posAnim = ObjectAnimator.ofFloat(mContentParent, "translationY", start, end);
+            posAnim.setInterpolator(appearing
+                    ? new android.view.animation.DecelerateInterpolator(2.0f)
+                    : new android.view.animation.AccelerateInterpolator(2.0f));
+
+            Animator glowAnim = ObjectAnimator.ofFloat(mGlow, "alpha",
+                    mGlow.getAlpha(), appearing ? 1.0f : 0.0f);
+            glowAnim.setInterpolator(appearing
+                    ? new android.view.animation.AccelerateInterpolator(1.0f)
+                    : new android.view.animation.DecelerateInterpolator(1.0f));
+
+            mContentAnim = new AnimatorSet();
+            mContentAnim
+                .play(ObjectAnimator.ofFloat(mContentParent, "alpha", mContentParent.getAlpha(),
+                                                                      appearing ? 1.0f : 0.0f))
+                .with(glowAnim)
+                .with(bgAnim)
+                .with(posAnim)
+                ;
+            mContentAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
+            mContentAnim.addListener(this);
         }
 
-        void jumpTo(boolean visible) {
-            setBgAlpha(visible ? 255 : 0);
-            setPanelBottom(visible ? mPanelHeight : 0);
+        void startAnimation(boolean appearing) {
+            if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");
+
+            createAnimation(appearing);
+
+            mContentParent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            mContentAnim.start();
+
+            mVisible = appearing;
         }
 
-        public void setBgAlpha(int alpha) {
-            mBgAlpha = alpha;
-            mBgDrawable.setAlpha((int)(alpha));
-            invalidate();
-        }
-
-        // 0 is closed, the height of the panel is open
-        public void setPanelBottom(int y) {
-            mPanelBottom = y;
-            int translationY = mPanelHeight - y;
-            mContentParent.setTranslationY(translationY);
-
-            final int glowXOffset = 100;
-            final int glowYOffset = 100;
-            int glowX = mContentParent.getLeft() - glowXOffset;
-            int glowY = mContentParent.getTop() - glowYOffset + translationY;
-            mGlowDrawable.setBounds(glowX, glowY, glowX + mGlowDrawable.getIntrinsicWidth(),
-                    glowY + mGlowDrawable.getIntrinsicHeight());
-
-            float alpha;
-            if (mPanelBottom > glowYOffset) {
-                alpha = 1;
-            } else {
-                alpha = ((float)mPanelBottom) / glowYOffset;
-            }
-            mContentParent.setAlpha(alpha);
-            mGlowDrawable.setAlpha((int)(255 * alpha));
-
-            if (false) {
-                Slog.d(TAG, "mPanelBottom=" + mPanelBottom + "translationY=" + translationY
-                        + " alpha=" + alpha + " glowY=" + glowY);
-            }
+        void jumpTo(boolean appearing) {
+//            setBgAlpha(appearing ? 255 : 0);
+            mContentParent.setTranslationY(appearing ? 0 : mPanelHeight);
         }
 
         public void setPanelHeight(int h) {
+            if (DEBUG) Slog.d(TAG, "panelHeight=" + h);
             mPanelHeight = h;
-            setPanelBottom(mPanelBottom);
+            if (mPanelHeight == 0) {
+                // fully closed, no animation necessary
+            } else if (mVisible) {
+                if (DEBUG) {
+                    Slog.d(TAG, "panelHeight not zero but trying to open; scheduling an anim to open fully");
+                }
+                startAnimation(true);
+            }
         }
 
         public void onAnimationCancel(Animator animation) {
-            //Slog.d(TAG, "onAnimationCancel mBgAlpha=" + mBgAlpha);
+            if (DEBUG) Slog.d(TAG, "onAnimationCancel");
+            // force this to zero so we close the window
+            mVisible = false;
         }
 
         public void onAnimationEnd(Animator animation) {
-            //Slog.d(TAG, "onAnimationEnd mBgAlpha=" + mBgAlpha);
-            if (mBgAlpha == 0) {
+            if (DEBUG) Slog.d(TAG, "onAnimationEnd");
+            if (! mVisible) {
                 setVisibility(View.GONE);
             }
-            mBgAnim = null;
+            mContentParent.setLayerType(View.LAYER_TYPE_NONE, null);
+            mContentAnim = null;
         }
 
         public void onAnimationRepeat(Animator animation) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationTitleArea.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationTitleArea.java
deleted file mode 100644
index d4413db..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationTitleArea.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.tablet;
-
-import android.content.Context;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap;
-import android.graphics.Paint;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.util.Slog;
-import android.widget.ImageView;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import com.android.systemui.R;
-
-public class NotificationTitleArea extends RelativeLayout {
-    static final String TAG = "NotificationTitleArea";
-
-    View mSettingsButton;
-    View mNotificationButton;
-    View mNotificationScroller;
-    FrameLayout mSettingsFrame;
-    View mSettingsPanel;
-
-    // for drawing the background
-    Bitmap mTexture;
-    Paint mPaint;
-    int mTextureWidth;
-    int mTextureHeight;
-    
-
-    public NotificationTitleArea(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public NotificationTitleArea(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        // for drawing the background
-        mTexture = BitmapFactory.decodeResource(getResources(), R.drawable.panel_notification);
-        mTextureWidth = mTexture.getWidth();
-        mTextureHeight = mTexture.getHeight();
-
-        mPaint = new Paint();
-        mPaint.setDither(false);
-    }
-
-    public void onFinishInflate() {
-        super.onFinishInflate();
-        setWillNotDraw(false);
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        final Bitmap texture = mTexture;
-        final Paint paint = mPaint;
-
-        final int width = getWidth();
-        final int height = getHeight();
-
-        final int textureWidth = mTextureWidth;
-        final int textureHeight = mTextureHeight;
-
-        int x = 0;
-        int y;
-
-        while (x < width) {
-            y = 0;
-            while (y < height) {
-                canvas.drawBitmap(texture, x, y, paint);
-                y += textureHeight;
-            }
-            x += textureWidth;
-        }
-    }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
index e0f37ca..bab8ed3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
@@ -23,8 +23,6 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.app.ActivityManager;
-import android.app.IThumbnailReceiver;
-import android.app.ActivityManager.RunningTaskInfo;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -33,43 +31,45 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.Shader.TileMode;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
-import android.os.RemoteException;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.Slog;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
 import android.widget.TextView;
 
 import com.android.systemui.R;
 
-public class RecentAppsPanel extends LinearLayout implements StatusBarPanel, OnClickListener {
-    private static final int COLLAPSE_DURATION = 360;
+public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, OnClickListener {
+    private static final int GLOW_PADDING = 15;
     private static final String TAG = "RecentAppsPanel";
     private static final boolean DEBUG = TabletStatusBar.DEBUG;
-    private static final int DISPLAY_TASKS_PORTRAIT = 8;
+    private static final int DISPLAY_TASKS_PORTRAIT = 7; // Limited by max binder transaction size
     private static final int DISPLAY_TASKS_LANDSCAPE = 5; // number of recent tasks to display
-    private static final int MAX_TASKS = DISPLAY_TASKS_PORTRAIT + 2; // allow extra for non-apps
-    private static final int STAGGER_ANIMATION_DELAY = 30;
-    private static final long ALPHA_ANIMATION_DURATION = 120;
+    private static final int MAX_TASKS = DISPLAY_TASKS_PORTRAIT + 1; // allow extra for non-apps
     private TabletStatusBar mBar;
-    private LinearLayout mRecentsContainer;
-    private View mRecentsGlowView;
     private ArrayList<ActivityDescription> mActivityDescriptions;
     private int mIconDpi;
-    private AnimatorSet mAnimationSet;
-    private View mBackgroundProtector;
+    private View mRecentsScrim;
+    private View mRecentsGlowView;
+    private LinearLayout mRecentsContainer;
+    private Bitmap mGlowBitmap;
+    private boolean mShowing;
+    private Choreographer mChoreo;
 
     static class ActivityDescription {
         int id;
@@ -105,6 +105,145 @@
         return x >= l && x < r && y >= t && y < b;
     }
 
+    public void show(boolean show, boolean animate) {
+        if (animate) {
+            if (mShowing != show) {
+                mShowing = show;
+                if (show) {
+                    setVisibility(View.VISIBLE);
+                }
+                mChoreo.startAnimation(show);
+            }
+        } else {
+            mShowing = show;
+            setVisibility(show ? View.VISIBLE : View.GONE);
+            mChoreo.jumpTo(show);
+        }
+    }
+
+    /**
+     * We need to be aligned at the bottom.  LinearLayout can't do this, so instead,
+     * let LinearLayout do all the hard work, and then shift everything down to the bottom.
+     */
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        mChoreo.setPanelHeight(mRecentsContainer.getHeight());
+    }
+
+    /**
+     * Whether the panel is showing, or, if it's animating, whether it will be
+     * when the animation is done.
+     */
+    public boolean isShowing() {
+        return mShowing;
+    }
+
+    private static class Choreographer implements Animator.AnimatorListener {
+        // should group this into a multi-property animation
+        private static final int OPEN_DURATION = 136;
+        private static final int CLOSE_DURATION = 250;
+
+        boolean mVisible;
+        int mPanelHeight;
+        View mRootView;
+        View mScrimView;
+        View mContentView;
+        AnimatorSet mContentAnim;
+
+        // the panel will start to appear this many px from the end
+        final int HYPERSPACE_OFFRAMP = 200;
+
+        public Choreographer(View root, View scrim, View content) {
+            mRootView = root;
+            mScrimView = scrim;
+            mContentView = content;
+        }
+
+        void createAnimation(boolean appearing) {
+            float start, end;
+
+            if (DEBUG) Log.e(TAG, "createAnimation()", new Exception());
+
+            // 0: on-screen
+            // height: off-screen
+            float y = mContentView.getTranslationY();
+            if (appearing) {
+                // we want to go from near-the-top to the top, unless we're half-open in the right
+                // general vicinity
+                start = (y < HYPERSPACE_OFFRAMP) ? y : HYPERSPACE_OFFRAMP;
+                end = 0;
+            } else {
+                start = y;
+                end = y + HYPERSPACE_OFFRAMP;
+            }
+
+            Animator posAnim = ObjectAnimator.ofFloat(mContentView, "translationY",
+                    start, end);
+            posAnim.setInterpolator(appearing
+                    ? new android.view.animation.DecelerateInterpolator(2.5f)
+                    : new android.view.animation.AccelerateInterpolator(2.5f));
+
+            Animator glowAnim = ObjectAnimator.ofFloat(mContentView, "alpha",
+                    mContentView.getAlpha(), appearing ? 1.0f : 0.0f);
+            glowAnim.setInterpolator(appearing
+                    ? new android.view.animation.AccelerateInterpolator(1.0f)
+                    : new android.view.animation.DecelerateInterpolator(1.0f));
+
+            Animator bgAnim = ObjectAnimator.ofInt(mScrimView.getBackground(),
+                    "alpha", appearing ? 0 : 255, appearing ? 255 : 0);
+
+            mContentAnim = new AnimatorSet();
+            mContentAnim
+                    .play(bgAnim)
+                    .with(glowAnim)
+                    .with(posAnim);
+            mContentAnim.setDuration(appearing ? OPEN_DURATION : CLOSE_DURATION);
+            mContentAnim.addListener(this);
+        }
+
+        void startAnimation(boolean appearing) {
+            if (DEBUG) Slog.d(TAG, "startAnimation(appearing=" + appearing + ")");
+
+            createAnimation(appearing);
+
+            mContentView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            mContentAnim.start();
+
+            mVisible = appearing;
+        }
+
+        void jumpTo(boolean appearing) {
+            mContentView.setTranslationY(appearing ? 0 : mPanelHeight);
+        }
+
+        public void setPanelHeight(int h) {
+            if (DEBUG) Slog.d(TAG, "panelHeight=" + h);
+            mPanelHeight = h;
+        }
+
+        public void onAnimationCancel(Animator animation) {
+            if (DEBUG) Slog.d(TAG, "onAnimationCancel");
+            // force this to zero so we close the window
+            mVisible = false;
+        }
+
+        public void onAnimationEnd(Animator animation) {
+            if (DEBUG) Slog.d(TAG, "onAnimationEnd");
+            if (!mVisible) {
+                mRootView.setVisibility(View.GONE);
+            }
+            mContentView.setLayerType(View.LAYER_TYPE_NONE, null);
+            mContentAnim = null;
+        }
+
+        public void onAnimationRepeat(Animator animation) {
+        }
+
+        public void onAnimationStart(Animator animation) {
+        }
+    }
+
     public void setBar(TabletStatusBar bar) {
         mBar = bar;
     }
@@ -121,6 +260,7 @@
                 & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE;
 
         mIconDpi = xlarge ? DisplayMetrics.DENSITY_HIGH : res.getDisplayMetrics().densityDpi;
+        mGlowBitmap = BitmapFactory.decodeResource(res, R.drawable.recents_thumbnail_bg);
     }
 
     @Override
@@ -128,12 +268,12 @@
         super.onFinishInflate();
         mRecentsContainer = (LinearLayout) findViewById(R.id.recents_container);
         mRecentsGlowView = findViewById(R.id.recents_glow);
-        mBackgroundProtector = (View) findViewById(R.id.recents_bg_protect);
+        mRecentsScrim = (View) findViewById(R.id.recents_bg_protect);
+        mChoreo = new Choreographer(this, mRecentsScrim, mRecentsGlowView);
 
         // In order to save space, we make the background texture repeat in the Y direction
-        View view = findViewById(R.id.recents_bg_protect);
-        if (view != null && view.getBackground() instanceof BitmapDrawable) {
-            ((BitmapDrawable) view.getBackground()).setTileModeY(TileMode.REPEAT);
+        if (mRecentsScrim != null && mRecentsScrim.getBackground() instanceof BitmapDrawable) {
+            ((BitmapDrawable) mRecentsScrim.getBackground()).setTileModeY(TileMode.REPEAT);
         }
     }
 
@@ -225,8 +365,8 @@
                 if (title != null && title.length() > 0 && icon != null) {
                     if (DEBUG) Log.v(TAG, "creating activity desc for id=" + id + ", label=" + title);
                     ActivityDescription item = new ActivityDescription(
-                            crop(recentInfo.thumbnail), icon, title, recentInfo.description,
-                            intent, id, index, info.packageName);
+                            recentInfo.thumbnail, icon, title,
+                            recentInfo.description, intent, id, index, info.packageName);
                     activityDescriptions.add(item);
                     ++index;
                 } else {
@@ -252,37 +392,45 @@
 
     private void refreshApplicationList() {
         mActivityDescriptions = getRecentTasks();
-        updateUiElements(getResources().getConfiguration(), true);
+        if (mActivityDescriptions.size() > 0) {
+            updateUiElements(getResources().getConfiguration(), true);
+        } else {
+            // Immediately hide this panel
+            mShowing = false;
+            setVisibility(View.GONE);
+            // mBar.animateCollapse();
+        }
     }
 
-    private Bitmap crop(Bitmap bitmap) {
-        if (bitmap == null || bitmap.getWidth() >= bitmap.getHeight()) {
-            return bitmap;
+    private Bitmap compositeBitmap(Bitmap background, Bitmap thumbnail) {
+        Bitmap outBitmap = background.copy(background.getConfig(), true);
+        if (thumbnail != null) {
+            Canvas canvas = new Canvas(outBitmap);
+            Paint paint = new Paint();
+            paint.setAntiAlias(true);
+            paint.setFilterBitmap(true);
+            paint.setAlpha(255);
+            final int srcWidth = thumbnail.getWidth();
+            final int height = thumbnail.getHeight();
+            final int srcHeight = srcWidth > height ? height
+                    : (height - height * srcWidth / height);
+            canvas.drawBitmap(thumbnail,
+                    new Rect(0, 0, srcWidth-1, srcHeight-1),
+                    new RectF(GLOW_PADDING,
+                            GLOW_PADDING - 4.0f,
+                            outBitmap.getWidth() - GLOW_PADDING + 2.0f,
+                            outBitmap.getHeight() - GLOW_PADDING + 3.0f), paint);
         }
-        final int width = bitmap.getWidth();
-        final int height = bitmap.getHeight();
-        Bitmap outBitmap = Bitmap.createBitmap(height, width, bitmap.getConfig());
-        Canvas canvas = new Canvas(outBitmap);
-        Paint paint = new Paint();
-        paint.setAntiAlias(true);
-        paint.setFilterBitmap(true);
-        canvas.drawBitmap(bitmap,
-                new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight() - height * width / height),
-                new Rect(0, 0, outBitmap.getWidth(), outBitmap.getHeight()),
-                paint);
         return outBitmap;
     }
 
     private void updateUiElements(Configuration config, boolean animate) {
         mRecentsContainer.removeAllViews();
 
-        final float initialAlpha = 0.0f;
         final int first = 0;
         final boolean isPortrait = config.orientation == Configuration.ORIENTATION_PORTRAIT;
         final int taskCount = isPortrait ? DISPLAY_TASKS_PORTRAIT : DISPLAY_TASKS_LANDSCAPE;
         final int last = Math.min(mActivityDescriptions.size(), taskCount) - 1;
-        ArrayList<Animator> anims = new ArrayList<Animator>(last+1);
-        DecelerateInterpolator interp = new DecelerateInterpolator();
         for (int i = last; i >= first; i--) {
             ActivityDescription activityDescription = mActivityDescriptions.get(i);
             View view = View.inflate(mContext, R.layout.status_bar_recent_item, null);
@@ -291,49 +439,18 @@
             TextView appLabel = (TextView) view.findViewById(R.id.app_label);
             TextView appDesc = (TextView) view.findViewById(R.id.app_description);
             final Bitmap thumb = activityDescription.thumbnail;
-            appThumbnail.setImageBitmap(crop(thumb));
+            appThumbnail.setImageBitmap(compositeBitmap(mGlowBitmap, thumb));
             appIcon.setImageDrawable(activityDescription.icon);
             appLabel.setText(activityDescription.label);
             appDesc.setText(activityDescription.description);
             view.setOnClickListener(this);
             view.setTag(activityDescription);
             mRecentsContainer.addView(view);
-
-            if (animate) {
-                view.setAlpha(initialAlpha);
-                ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", initialAlpha, 1.0f);
-                anim.setDuration(ALPHA_ANIMATION_DURATION);
-                anim.setStartDelay((last-i) * STAGGER_ANIMATION_DELAY);
-                anim.setInterpolator(interp);
-                anims.add(anim);
-            }
         }
 
         int views = mRecentsContainer.getChildCount();
         mRecentsContainer.setVisibility(views > 0 ? View.VISIBLE : View.GONE);
         mRecentsGlowView.setVisibility(views > 0 ? View.VISIBLE : View.GONE);
-
-        if (animate && views > 0) {
-            ObjectAnimator anim = ObjectAnimator.ofFloat(mRecentsGlowView, "alpha",
-                    initialAlpha, 1.0f);
-            anim.setDuration((last-first) * STAGGER_ANIMATION_DELAY);
-            anim.setInterpolator(interp);
-            anims.add(anim);
-        }
-
-        if (animate) {
-            ObjectAnimator anim = ObjectAnimator.ofFloat(mBackgroundProtector, "alpha",
-                    initialAlpha, 1.0f);
-            anim.setDuration(last * STAGGER_ANIMATION_DELAY);
-            anim.setInterpolator(interp);
-            anims.add(anim);
-        }
-
-        if (anims.size() > 0) {
-            mAnimationSet = new AnimatorSet();
-            mAnimationSet.playTogether(anims);
-            mAnimationSet.start();
-        }
     }
 
     public void onClick(View v) {
@@ -350,6 +467,7 @@
             if (DEBUG) Log.v(TAG, "Starting activity " + intent);
             getContext().startActivity(intent);
         }
+        setVisibility(View.GONE);
         mBar.animateCollapse();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
index 01436f8..07af466 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
@@ -41,7 +41,6 @@
 
     AirplaneModeController mAirplane;
     AutoRotateController mRotate;
-    VolumeController mVolume;
     BrightnessController mBrightness;
     DoNotDisturbController mDoNotDisturb;
 
@@ -64,8 +63,6 @@
         findViewById(R.id.network).setOnClickListener(this);
         mRotate = new AutoRotateController(context,
                 (CompoundButton)findViewById(R.id.rotate_checkbox));
-        mVolume = new VolumeController(context,
-                (ToggleSlider)findViewById(R.id.volume));
         mBrightness = new BrightnessController(context,
                 (ToggleSlider)findViewById(R.id.brightness));
         mDoNotDisturb = new DoNotDisturbController(context,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
index 698f5af..2ebd067 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -39,21 +39,19 @@
 
 import com.android.systemui.R;
 
-public class ShirtPocket extends FrameLayout {
+public class ShirtPocket extends ImageView {
     private static final boolean DEBUG = false;
     private static final String  TAG = "StatusBar/ShirtPocket";
 
     private ClipData mClipping = null;
 
     private View mWindow = null;
-    private ImageView mIcon;
     private ImageView mPreviewIcon;
     private TextView mDescription;
     private TextView mAltText;
 
     public ShirtPocket(Context context, AttributeSet attrs) {
         super(context, attrs);
-        setupWindow();
     }
 
     // TODO: "pin area" panel, dragging things out
@@ -63,8 +61,7 @@
         // Drag API notes: we must be visible to receive drag events
         setVisibility(View.VISIBLE);
 
-        mIcon = (ImageView) findViewById(R.id.pocket_icon);
-        refreshStatusIcon();
+        refresh();
 
         setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
@@ -76,19 +73,16 @@
         });
     }
 
-    private void refreshStatusIcon() {
+    private void refresh() {
         setClickable(mClipping != null);
-        mIcon.setImageResource(mClipping == null
-                ? R.drawable.ic_sysbar_pocket_hidden
-                : R.drawable.ic_sysbar_pocket_holding);
-        mIcon.setVisibility(mClipping == null ? View.GONE : View.VISIBLE);
+        // XXX: TODO
     }
     
     private void showWindow() {
         getHandler().post(new Runnable() {
             public void run() {
                 mWindow.setVisibility(View.VISIBLE);
-                refreshStatusIcon();
+                refresh();
             }
         });
     }
@@ -97,7 +91,7 @@
         getHandler().post(new Runnable() {
             public void run() {
                 mWindow.setVisibility(View.GONE);
-                refreshStatusIcon();
+                refresh();
             }
         });
     }
@@ -106,7 +100,7 @@
         getHandler().postDelayed(new Runnable() {
             public void run() {
                 mWindow.setVisibility(View.GONE);
-                refreshStatusIcon();
+                refresh();
             }
         },
         250);
@@ -153,23 +147,23 @@
                 final ClipData clip = mClipping;
                 if (clip != null) {
                     final Bitmap icon = clip.getIcon();
-                    DragThumbnailBuilder thumb;
+                    DragShadowBuilder shadow;
                     if (icon != null) {
-                        thumb = new DragThumbnailBuilder(v) {
-                            public void onProvideThumbnailMetrics(Point thumbnailSize, Point thumbnailTouchPoint) {
-                                thumbnailSize.set(icon.getWidth(), icon.getHeight());
-                                thumbnailTouchPoint.set(thumbnailSize.x / 2, thumbnailSize.y / 2);
+                        shadow = new DragShadowBuilder(v) {
+                            public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
+                                shadowSize.set(icon.getWidth(), icon.getHeight());
+                                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
                             }
-                            public void onDrawThumbnail(Canvas canvas) {
+                            public void onDrawShadow(Canvas canvas) {
                                 canvas.drawBitmap(icon, 0, 0, new Paint());
                             }
                         };
                     } else {
                         // uhhh, what now?
-                        thumb = new DragThumbnailBuilder(mWindow.findViewById(R.id.preview));
+                        shadow = new DragShadowBuilder(mWindow.findViewById(R.id.preview));
                     }
 
-                    v.startDrag(clip, thumb, false, null);
+                    v.startDrag(clip, shadow, null, 0);
 
                     // TODO: only discard the clipping if it was accepted
                     stash(null);
@@ -183,65 +177,27 @@
         }
     };
 
-    private void setupWindow() {
-        mWindow = View.inflate(getContext(), R.layout.status_bar_pocket_panel, null);
-
-        mPreviewIcon = (ImageView) mWindow.findViewById(R.id.icon);
-        mDescription = (TextView) mWindow.findViewById(R.id.description);
-        mAltText = (TextView) mWindow.findViewById(R.id.alt);
-
-        mWindow.setVisibility(View.GONE);
-        mWindow.setOnTouchListener(mWindowTouchListener);
-        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                400,
-                250,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
-                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
-                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
-                PixelFormat.TRANSLUCENT);
-        lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
-//        int pos[] = new int[2];
-//        getLocationOnScreen(pos);
-//        lp.x = pos[1];
-//        lp.y = 0;
-        lp.setTitle("ShirtPocket");
-        lp.windowAnimations = R.style.Animation_ShirtPocketPanel;
-
-        WindowManagerImpl.getDefault().addView(mWindow, lp);
-
-    }
-
     public boolean onDragEvent(DragEvent event) {
         if (DEBUG) Slog.d(TAG, "onDragEvent: " + event);
-        if (mIcon != null) {
-            switch (event.getAction()) {
-                // We want to appear whenever a potential drag takes off from anywhere in the UI.
-                case DragEvent.ACTION_DRAG_STARTED:
-                    mIcon.setImageResource(mClipping == null
-                            ? R.drawable.ic_sysbar_pocket
-                            : R.drawable.ic_sysbar_pocket_holding);
-                    mIcon.setVisibility(View.VISIBLE);
-                    break;
-                case DragEvent.ACTION_DRAG_ENTERED:
-                    if (DEBUG) Slog.d(TAG, "entered!");
-                    mIcon.setImageResource(R.drawable.ic_sysbar_pocket_drag);
-                    break;
-                case DragEvent.ACTION_DRAG_EXITED:
-                    if (DEBUG) Slog.d(TAG, "exited!");
-                    mIcon.setImageResource(mClipping == null
-                            ? R.drawable.ic_sysbar_pocket
-                            : R.drawable.ic_sysbar_pocket_holding);
-                    break;
-                case DragEvent.ACTION_DROP:
-                    if (DEBUG) Slog.d(TAG, "dropped!");
-                    stash(event.getClipData());
-                    refreshStatusIcon();
-                    break;
-                case DragEvent.ACTION_DRAG_ENDED:
-                    refreshStatusIcon();
-                    break;
-            }
+        switch (event.getAction()) {
+            // We want to appear whenever a potential drag takes off from anywhere in the UI.
+            case DragEvent.ACTION_DRAG_STARTED:
+                // XXX: TODO
+                break;
+            case DragEvent.ACTION_DRAG_ENTERED:
+                if (DEBUG) Slog.d(TAG, "entered!");
+                // XXX: TODO
+                break;
+            case DragEvent.ACTION_DRAG_EXITED:
+                if (DEBUG) Slog.d(TAG, "exited!");
+                setVisibility(mClipping == null ? View.GONE : View.VISIBLE);
+                break;
+            case DragEvent.ACTION_DROP:
+                if (DEBUG) Slog.d(TAG, "dropped!");
+                stash(event.getClipData());
+                break;
+            case DragEvent.ACTION_DRAG_ENDED:
+                break;
         }
         return true; // we want everything, thank you
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 7a7976a..d8e3053 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -31,6 +31,7 @@
 import android.app.StatusBarManager;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
@@ -73,29 +74,36 @@
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.recent.RecentApplicationsActivity;
 
-public class TabletStatusBar extends StatusBar {
+public class TabletStatusBar extends StatusBar implements
+        HeightReceiver.OnBarHeightChangedListener {
     public static final boolean DEBUG = false;
     public static final String TAG = "TabletStatusBar";
 
+    public static final int MAX_NOTIFICATION_ICONS = 5;
+    // IME switcher icon is big and occupy width of two icons
+    public static final int MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE = MAX_NOTIFICATION_ICONS - 2;
+
     public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
     public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
     public static final int MSG_OPEN_NOTIFICATION_PEEK = 1002;
     public static final int MSG_CLOSE_NOTIFICATION_PEEK = 1003;
     public static final int MSG_OPEN_RECENTS_PANEL = 1020;
     public static final int MSG_CLOSE_RECENTS_PANEL = 1021;
-    public static final int MSG_HIDE_SHADOWS = 1030;
-    public static final int MSG_SHOW_SHADOWS = 1031;
-    public static final int MSG_RESTORE_SHADOWS = 1032;
+    public static final int MSG_SHOW_CHROME = 1030;
+    public static final int MSG_HIDE_CHROME = 1031;
+    public static final int MSG_OPEN_INPUT_METHODS_PANEL = 1040;
+    public static final int MSG_CLOSE_INPUT_METHODS_PANEL = 1041;
 
     // Fitts' Law assistance for LatinIME; TODO: replace with a more general approach
     private static final boolean FAKE_SPACE_BAR = true;
 
-    private static final int MAX_IMAGE_LEVEL = 10000;
-    private static final boolean USE_2D_RECENTS = true;
-
     public static final int LIGHTS_ON_DELAY = 5000;
 
-    int mIconSize;
+    // The height of the bar, as definied by the build.  It may be taller if we're plugged
+    // into hdmi.
+    int mNaturalBarHeight = -1;
+    int mIconSize = -1;
+    int mIconHPadding = -1;
 
     H mHandler = new H();
 
@@ -115,6 +123,7 @@
     View mMenuButton;
     View mRecentButton;
 
+    ViewGroup mNotificationAndImeArea;
     InputMethodButton mInputMethodSwitchButton;
 
     NotificationPanel mNotificationPanel;
@@ -129,14 +138,14 @@
 
     ViewGroup mPile;
 
+    HeightReceiver mHeightReceiver;
     BatteryController mBatteryController;
     NetworkController mNetworkController;
 
     View mBarContents;
 
-    // lights out support
-    View mBackShadow, mHomeShadow, mRecentShadow, mMenuShadow, mNotificationShadow;
-    ShadowController mShadowController;
+    // hide system chrome ("lights out") support
+    View mShadow;
 
     NotificationIconArea.IconLayout mIconLayout;
 
@@ -150,14 +159,13 @@
 
     boolean mNotificationsOn = true;
     private RecentAppsPanel mRecentsPanel;
+    private InputMethodsPanel mInputMethodsPanel;
+
+    public Context getContext() { return mContext; }
 
     protected void addPanelWindows() {
         final Context context = mContext;
 
-        final Resources res = context.getResources();
-        final int barHeight= res.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
-
         // Notification Panel
         mNotificationPanel = (NotificationPanel)View.inflate(context,
                 R.layout.status_bar_notification_panel, null);
@@ -181,7 +189,7 @@
         mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
 
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
+                720, // ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
@@ -194,6 +202,7 @@
         lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
                 | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
         lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
+//        lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
 
         WindowManagerImpl.getDefault().addView(mNotificationPanel, lp);
 
@@ -205,16 +214,16 @@
         mNotificationPeekWindow.setOnTouchListener(
                 new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PEEK, mNotificationPeekWindow));
         mNotificationPeekScrubRight = new LayoutTransition();
-        mNotificationPeekScrubRight.setAnimator(LayoutTransition.APPEARING, 
+        mNotificationPeekScrubRight.setAnimator(LayoutTransition.APPEARING,
                 ObjectAnimator.ofInt(null, "left", -512, 0));
-        mNotificationPeekScrubRight.setAnimator(LayoutTransition.DISAPPEARING, 
+        mNotificationPeekScrubRight.setAnimator(LayoutTransition.DISAPPEARING,
                 ObjectAnimator.ofInt(null, "left", -512, 0));
         mNotificationPeekScrubRight.setDuration(500);
 
         mNotificationPeekScrubLeft = new LayoutTransition();
-        mNotificationPeekScrubLeft.setAnimator(LayoutTransition.APPEARING, 
+        mNotificationPeekScrubLeft.setAnimator(LayoutTransition.APPEARING,
                 ObjectAnimator.ofInt(null, "left", 512, 0));
-        mNotificationPeekScrubLeft.setAnimator(LayoutTransition.DISAPPEARING, 
+        mNotificationPeekScrubLeft.setAnimator(LayoutTransition.DISAPPEARING,
                 ObjectAnimator.ofInt(null, "left", 512, 0));
         mNotificationPeekScrubLeft.setDuration(500);
 
@@ -234,30 +243,50 @@
         WindowManagerImpl.getDefault().addView(mNotificationPeekWindow, lp);
 
         // Recents Panel
-        if (USE_2D_RECENTS) {
-            mRecentsPanel = (RecentAppsPanel) View.inflate(context,
-                    R.layout.status_bar_recent_panel, null);
-            mRecentsPanel.setVisibility(View.GONE);
-            mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL,
-                    mRecentsPanel));
-            mStatusBarView.setIgnoreChildren(2, mRecentButton, mRecentsPanel);
+        mRecentsPanel = (RecentAppsPanel) View.inflate(context,
+                R.layout.status_bar_recent_panel, null);
+        mRecentsPanel.setVisibility(View.GONE);
+        mRecentsPanel.setOnTouchListener(new TouchOutsideListener(MSG_CLOSE_RECENTS_PANEL,
+                mRecentsPanel));
+        mStatusBarView.setIgnoreChildren(2, mRecentButton, mRecentsPanel);
 
-            lp = new WindowManager.LayoutParams(
-                    ViewGroup.LayoutParams.WRAP_CONTENT,
-                    ViewGroup.LayoutParams.WRAP_CONTENT,
-                    WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
-                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                        | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
-                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
-                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
-                    PixelFormat.TRANSLUCENT);
-            lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
-            lp.setTitle("RecentsPanel");
-            lp.windowAnimations = R.style.Animation_RecentPanel;
+        lp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+                    | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+                PixelFormat.TRANSLUCENT);
+        lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
+        lp.setTitle("RecentsPanel");
+        lp.windowAnimations = R.style.Animation_RecentPanel;
 
-            WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
-            mRecentsPanel.setBar(this);
-        }
+        WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
+        mRecentsPanel.setBar(this);
+
+        // Input methods Panel
+        mInputMethodsPanel = (InputMethodsPanel) View.inflate(context,
+                R.layout.status_bar_input_methods_panel, null);
+        mInputMethodsPanel.setVisibility(View.GONE);
+        mInputMethodsPanel.setOnTouchListener(new TouchOutsideListener(
+                MSG_CLOSE_INPUT_METHODS_PANEL, mInputMethodsPanel));
+        mStatusBarView.setIgnoreChildren(3, mInputMethodSwitchButton, mInputMethodsPanel);
+        lp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+                    | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+                PixelFormat.TRANSLUCENT);
+        lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
+        lp.setTitle("InputMethodsPanel");
+        lp.windowAnimations = R.style.Animation_RecentPanel;
+
+        WindowManagerImpl.getDefault().addView(mInputMethodsPanel, lp);
     }
 
     @Override
@@ -265,14 +294,41 @@
         super.start(); // will add the main bar view
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        loadDimens();
+    }
+
+    protected void loadDimens() {
+        final Resources res = mContext.getResources();
+
+        mNaturalBarHeight = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.status_bar_height);
+
+        int newIconSize = res.getDimensionPixelSize(
+            com.android.internal.R.dimen.status_bar_icon_size);
+        int newIconHPadding = res.getDimensionPixelSize(
+            R.dimen.status_bar_icon_padding);
+
+        if (newIconHPadding != mIconHPadding || newIconSize != mIconSize) {
+//            Slog.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding);
+            mIconHPadding = newIconHPadding;
+            mIconSize = newIconSize;
+            reloadAllNotificationIcons(); // reload the tray
+        }
+    }
+
     protected View makeStatusBarView() {
         final Context context = mContext;
-        final Resources res = context.getResources();
-        
+
         mWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
 
-        mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
+        // This guy will listen for HDMI plugged broadcasts so we can resize the
+        // status bar as appropriate.
+        mHeightReceiver = new HeightReceiver(mContext);
+        mHeightReceiver.registerReceiver();
+        loadDimens();
 
         final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
                 context, R.layout.status_bar, null);
@@ -300,7 +356,7 @@
         mNotificationPeekTapDuration = vc.getTapTimeout();
         mNotificationFlingVelocity = 300; // px/s
 
-        mTicker = new TabletTicker(context);
+        mTicker = new TabletTicker(this);
 
         // The icons
         mBatteryController = new BatteryController(mContext);
@@ -317,32 +373,63 @@
         mHomeButton = mNavigationArea.findViewById(R.id.home);
         mMenuButton = mNavigationArea.findViewById(R.id.menu);
         mRecentButton = mNavigationArea.findViewById(R.id.recent_apps);
-        Slog.d(TAG, "rec=" + mRecentButton + ", listener=" + mOnClickListener);
         mRecentButton.setOnClickListener(mOnClickListener);
 
         // The bar contents buttons
+        mNotificationAndImeArea = (ViewGroup)sb.findViewById(R.id.notificationAndImeArea);
         mInputMethodSwitchButton = (InputMethodButton) sb.findViewById(R.id.imeSwitchButton);
+        // Overwrite the lister
+        mInputMethodSwitchButton.setOnClickListener(mOnClickListener);
 
         // for redirecting errant bar taps to the IME
         mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
 
         // "shadows" of the status bar features, for lights-out mode
-        mBackShadow = sb.findViewById(R.id.back_shadow);
-        mHomeShadow = sb.findViewById(R.id.home_shadow);
-        mRecentShadow = sb.findViewById(R.id.recent_shadow);
-        mMenuShadow = sb.findViewById(R.id.menu_shadow);
-        mNotificationShadow = sb.findViewById(R.id.notification_shadow);
+        mShadow = sb.findViewById(R.id.bar_shadow);
+        mShadow.setOnTouchListener(
+            new View.OnTouchListener() {
+                public boolean onTouch(View v, MotionEvent ev) {
+                    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+                        mShadow.setVisibility(View.GONE);
+                        mBarContents.setVisibility(View.VISIBLE);
+                    }
+                    return false;
+                }
+            });
 
-        mShadowController = new ShadowController(false);
-        mShadowController.add(mBackButton, mBackShadow);
-        mShadowController.add(mHomeButton, mHomeShadow);
-        mShadowController.add(mRecentButton, mRecentShadow);
-        mShadowController.add(mMenuButton, mMenuShadow);
-        mShadowController.add(mNotificationArea, mNotificationShadow);
+        // tuning parameters
+        final int LIGHTS_GOING_OUT_SYSBAR_DURATION = 600;
+        final int LIGHTS_GOING_OUT_SHADOW_DURATION = 1000;
+        final int LIGHTS_GOING_OUT_SHADOW_DELAY    = 500;
+
+        final int LIGHTS_COMING_UP_SYSBAR_DURATION = 200;
+//        final int LIGHTS_COMING_UP_SYSBAR_DELAY    = 50;
+        final int LIGHTS_COMING_UP_SHADOW_DURATION = 0;
+
+        LayoutTransition xition = new LayoutTransition();
+        xition.setAnimator(LayoutTransition.APPEARING,
+               ObjectAnimator.ofFloat(null, "alpha", 0.5f, 1f));
+        xition.setDuration(LayoutTransition.APPEARING, LIGHTS_COMING_UP_SYSBAR_DURATION);
+        xition.setStartDelay(LayoutTransition.APPEARING, 0);
+        xition.setAnimator(LayoutTransition.DISAPPEARING,
+               ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
+        xition.setDuration(LayoutTransition.DISAPPEARING, LIGHTS_GOING_OUT_SYSBAR_DURATION);
+        xition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
+        ((ViewGroup)sb.findViewById(R.id.bar_contents_holder)).setLayoutTransition(xition);
+
+        xition = new LayoutTransition();
+        xition.setAnimator(LayoutTransition.APPEARING,
+               ObjectAnimator.ofFloat(null, "alpha", 0f, 1f));
+        xition.setDuration(LayoutTransition.APPEARING, LIGHTS_GOING_OUT_SHADOW_DURATION);
+        xition.setStartDelay(LayoutTransition.APPEARING, LIGHTS_GOING_OUT_SHADOW_DELAY);
+        xition.setAnimator(LayoutTransition.DISAPPEARING,
+               ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
+        xition.setDuration(LayoutTransition.DISAPPEARING, LIGHTS_COMING_UP_SHADOW_DURATION);
+        xition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
+        ((ViewGroup)sb.findViewById(R.id.bar_shadow_holder)).setLayoutTransition(xition);
 
         // set the initial view visibility
         setAreThereNotifications();
-        refreshNotificationTrigger();
 
         // Add the windows
         addPanelWindows();
@@ -353,13 +440,33 @@
         ScrollView scroller = (ScrollView)mPile.getParent();
         scroller.setFillViewport(true);
 
+        mHeightReceiver.addOnBarHeightChangedListener(this);
+
         return sb;
     }
 
+    public int getStatusBarHeight() {
+        return mHeightReceiver.getHeight();
+    }
+
     protected int getStatusBarGravity() {
         return Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
     }
 
+    public void onBarHeightChanged(int height) {
+        final WindowManager.LayoutParams lp
+                = (WindowManager.LayoutParams)mStatusBarView.getLayoutParams();
+        if (lp == null) {
+            // haven't been added yet
+            return;
+        }
+        if (lp.height != height) {
+            lp.height = height;
+            final WindowManager wm = WindowManagerImpl.getDefault();
+            wm.updateViewLayout(mStatusBarView, lp);
+        }
+    }
+
     private class H extends Handler {
         public void handleMessage(Message m) {
             switch (m.what) {
@@ -376,18 +483,18 @@
 
                         final int peekIndex = m.arg1;
                         if (peekIndex < N) {
-                            Slog.d(TAG, "loading peek: " + peekIndex);
+                            //Slog.d(TAG, "loading peek: " + peekIndex);
                             NotificationData.Entry entry = mNotns.get(N-1-peekIndex);
                             NotificationData.Entry copy = new NotificationData.Entry(
-                                    entry.key, 
-                                    entry.notification, 
+                                    entry.key,
+                                    entry.notification,
                                     entry.icon);
                             inflateViews(copy, mNotificationPeekRow);
 
                             entry.icon.setBackgroundColor(0x20FFFFFF);
 
 //                          mNotificationPeekRow.setLayoutTransition(
-//                              peekIndex < mNotificationPeekIndex 
+//                              peekIndex < mNotificationPeekIndex
 //                                  ? mNotificationPeekScrubLeft
 //                                  : mNotificationPeekScrubRight);
 
@@ -420,8 +527,7 @@
                     if (!mNotificationPanel.isShowing()) {
                         mNotificationPeekWindow.setVisibility(View.GONE);
                         mNotificationPanel.show(true, true);
-                        // synchronize with current shadow state
-                        mShadowController.hideElement(mNotificationArea);
+                        mNotificationArea.setVisibility(View.GONE);
                         mTicker.halt();
                     }
                     break;
@@ -429,52 +535,45 @@
                     if (DEBUG) Slog.d(TAG, "closing notifications panel");
                     if (mNotificationPanel.isShowing()) {
                         mNotificationPanel.show(false, true);
-                        // synchronize with current shadow state
-                        mShadowController.showElement(mNotificationArea);
+                        mNotificationArea.setVisibility(View.VISIBLE);
                     }
                     break;
                 case MSG_OPEN_RECENTS_PANEL:
                     if (DEBUG) Slog.d(TAG, "opening recents panel");
-                    if (mRecentsPanel != null) mRecentsPanel.setVisibility(View.VISIBLE);
+                    if (mRecentsPanel != null) {
+                        mRecentsPanel.setVisibility(View.VISIBLE);
+                        mRecentsPanel.show(true, true);
+                    }
                     break;
                 case MSG_CLOSE_RECENTS_PANEL:
                     if (DEBUG) Slog.d(TAG, "closing recents panel");
-                    if (mRecentsPanel != null) mRecentsPanel.setVisibility(View.GONE);
+                    if (mRecentsPanel != null && mRecentsPanel.isShowing()) {
+                        mRecentsPanel.show(false, true);
+                    }
                     break;
-                case MSG_HIDE_SHADOWS:
+                case MSG_OPEN_INPUT_METHODS_PANEL:
+                    if (DEBUG) Slog.d(TAG, "opening input methods panel");
+                    if (mInputMethodsPanel != null) mInputMethodsPanel.setVisibility(View.VISIBLE);
+                    break;
+                case MSG_CLOSE_INPUT_METHODS_PANEL:
+                    if (DEBUG) Slog.d(TAG, "closing input methods panel");
+                    if (mInputMethodsPanel != null) mInputMethodsPanel.setVisibility(View.GONE);
+                    break;
+                case MSG_SHOW_CHROME:
                     if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)");
-                    mShadowController.hideAllShadows();
+                    mBarContents.setVisibility(View.VISIBLE);
+                    mShadow.setVisibility(View.GONE);
                     break;
-                case MSG_SHOW_SHADOWS:
+                case MSG_HIDE_CHROME:
                     if (DEBUG) Slog.d(TAG, "showing shadows (lights out)");
                     animateCollapse();
-                    mShadowController.showAllShadows();
-                    break;
-                case MSG_RESTORE_SHADOWS:
-                    if (DEBUG) Slog.d(TAG, "quickly re-showing shadows if appropriate");
-                    mShadowController.refresh();
+                    mBarContents.setVisibility(View.GONE);
+                    mShadow.setVisibility(View.VISIBLE);
                     break;
             }
         }
     }
 
-    public void refreshNotificationTrigger() {
-        /*
-        if (mNotificationTrigger == null) return;
-
-        int resId;
-        boolean panel = (mNotificationPanel != null && mNotificationPanel.isShowing();
-        if (!mNotificationsOn) {
-            resId = R.drawable.ic_sysbar_noti_dnd;
-        } else if (mNotns.size() > 0) {
-            resId = panel ? R.drawable.ic_sysbar_noti_avail_open : R.drawable.ic_sysbar_noti_avail;
-        } else {
-            resId = panel ? R.drawable.ic_sysbar_noti_none_open : R.drawable.ic_sysbar_noti_none;
-        }
-        //mNotificationTrigger.setImageResource(resId);
-        */
-    }
-
     public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
         if (DEBUG) Slog.d(TAG, "addIcon(" + slot + ") -> " + icon);
     }
@@ -504,7 +603,7 @@
             } catch (PendingIntent.CanceledException e) {
             }
         } else {
-            tick(key, notification);
+            tick(key, notification, true);
         }
 
         setAreThereNotifications();
@@ -536,18 +635,17 @@
 
         // Can we just reapply the RemoteViews in place?  If when didn't change, the order
         // didn't change.
-        boolean orderUnchanged = (notification.notification.when == oldNotification.notification.when
-                && notification.isOngoing() == oldNotification.isOngoing()
-                && oldEntry.expanded != null
-                && contentView != null
-                && oldContentView != null
+        boolean contentsUnchanged = oldEntry.expanded != null
+                && contentView != null && oldContentView != null
                 && contentView.getPackage() != null
                 && oldContentView.getPackage() != null
                 && oldContentView.getPackage().equals(contentView.getPackage())
-                && oldContentView.getLayoutId() == contentView.getLayoutId());
+                && oldContentView.getLayoutId() == contentView.getLayoutId();
         ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent();
-        boolean isLastAnyway = rowParent.indexOfChild(oldEntry.row) == rowParent.getChildCount() - 1;
-        if (orderUnchanged || isLastAnyway) {
+        boolean orderUnchanged = notification.notification.when==oldNotification.notification.when
+                && notification.isOngoing() == oldNotification.isOngoing();
+        boolean isLastAnyway = rowParent.indexOfChild(oldEntry.row) == rowParent.getChildCount()-1;
+        if (contentsUnchanged && (orderUnchanged || isLastAnyway)) {
             if (DEBUG) Slog.d(TAG, "reusing notification for key: " + key);
             oldEntry.notification = notification;
             try {
@@ -569,6 +667,21 @@
                     handleNotificationError(key, notification, "Couldn't update icon: " + ic);
                     return;
                 }
+                // Update the large icon
+                if (notification.notification.largeIcon != null) {
+                    oldEntry.largeIcon.setImageBitmap(notification.notification.largeIcon);
+                } else {
+                    oldEntry.largeIcon.getLayoutParams().width = 0;
+                    oldEntry.largeIcon.setVisibility(View.INVISIBLE);
+                }
+
+                if (key == mNotificationPeekKey) {
+                    // must update the peek window
+                    Message peekMsg = mHandler.obtainMessage(MSG_OPEN_NOTIFICATION_PEEK);
+                    peekMsg.arg1 = mNotificationPeekIndex;
+                    mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PEEK);
+                    mHandler.sendMessage(peekMsg);
+                }
             }
             catch (RuntimeException e) {
                 // It failed to add cleanly.  Log, and remove the view from the panel.
@@ -587,7 +700,7 @@
         if (false && immersive) {
             // TODO: immersive mode
         } else {
-            tick(key, notification);
+            tick(key, notification, false);
         }
 
         setAreThereNotifications();
@@ -622,6 +735,11 @@
             Slog.d(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes"));
             showClock(show);
         }
+        if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
+            boolean show = (state & StatusBarManager.DISABLE_SYSTEM_INFO) == 0;
+            Slog.d(TAG, "DISABLE_SYSTEM_INFO: " + (show ? "no" : "yes"));
+            mNotificationTrigger.setVisibility(show ? View.VISIBLE : View.GONE);
+        }
         if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
             if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
                 Slog.d(TAG, "DISABLE_EXPAND: yes");
@@ -632,12 +750,12 @@
             if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
                 Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
                 // synchronize with current shadow state
-                mShadowController.hideElement(mNotificationIconArea);
+                mNotificationIconArea.setVisibility(View.GONE);
                 mTicker.halt();
             } else {
                 Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
                 // synchronize with current shadow state
-                mShadowController.showElement(mNotificationIconArea);
+                mNotificationIconArea.setVisibility(View.VISIBLE);
             }
         } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
             if ((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
@@ -648,9 +766,11 @@
             if ((state & StatusBarManager.DISABLE_NAVIGATION) != 0) {
                 Slog.d(TAG, "DISABLE_NAVIGATION: yes");
                 mNavigationArea.setVisibility(View.GONE);
+                mInputMethodSwitchButton.setScreenLocked(true);
             } else {
                 Slog.d(TAG, "DISABLE_NAVIGATION: no");
                 mNavigationArea.setVisibility(View.VISIBLE);
+                mInputMethodSwitchButton.setScreenLocked(false);
             }
         }
     }
@@ -659,11 +779,16 @@
         return n.tickerView != null || !TextUtils.isEmpty(n.tickerText);
     }
 
-    private void tick(IBinder key, StatusBarNotification n) {
+    private void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
         // Don't show the ticker when the windowshade is open.
         if (mNotificationPanel.isShowing()) {
             return;
         }
+        // If they asked for FLAG_ONLY_ALERT_ONCE, then only show this notification
+        // if it's a new notification.
+        if (!firstTime && (n.notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
+            return;
+        }
         // Show the ticker if one is requested. Also don't do this
         // until status bar window is attached to the window manager,
         // because...  well, what's the point otherwise?  And trying to
@@ -672,10 +797,16 @@
             if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS
                             | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) {
                 mTicker.add(key, n);
+                mNotificationAndImeArea.setVisibility(View.GONE);
             }
         }
     }
 
+    // called by TabletTicker when it's done with all queued ticks
+    public void doneTicking() {
+        mNotificationAndImeArea.setVisibility(View.VISIBLE);
+    }
+
     public void animateExpand() {
         mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
         mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
@@ -686,6 +817,8 @@
         mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
         mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
         mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
+        mHandler.removeMessages(MSG_CLOSE_INPUT_METHODS_PANEL);
+        mHandler.sendEmptyMessage(MSG_CLOSE_INPUT_METHODS_PANEL);
     }
 
     // called by StatusBar
@@ -693,13 +826,12 @@
     public void setLightsOn(boolean on) {
         // Policy note: if the frontmost activity needs the menu key, we assume it is a legacy app
         // that can't handle lights-out mode.
-        if (mMenuButton.getVisibility() == View.VISIBLE
-                || mMenuShadow.getVisibility() == View.VISIBLE) {
+        if (mMenuButton.getVisibility() == View.VISIBLE) {
             on = true;
         }
-        mHandler.removeMessages(MSG_SHOW_SHADOWS);
-        mHandler.removeMessages(MSG_HIDE_SHADOWS);
-        mHandler.sendEmptyMessage(on ? MSG_HIDE_SHADOWS : MSG_SHOW_SHADOWS);
+        mHandler.removeMessages(MSG_HIDE_CHROME);
+        mHandler.removeMessages(MSG_SHOW_CHROME);
+        mHandler.sendEmptyMessage(on ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
     }
 
     public void setMenuKeyVisible(boolean visible) {
@@ -716,7 +848,12 @@
         if (DEBUG) {
             Slog.d(TAG, (visible?"showing":"hiding") + " the IME button");
         }
+        int oldVisibility = mInputMethodSwitchButton.getVisibility();
         mInputMethodSwitchButton.setIMEButtonVisible(token, visible);
+        if (oldVisibility != mInputMethodSwitchButton.getVisibility()) {
+            updateNotificationIcons();
+        }
+        mInputMethodsPanel.setIMEToken(token);
         mBackButton.setImageResource(
                 visible ? R.drawable.ic_sysbar_back_ime : R.drawable.ic_sysbar_back);
         if (FAKE_SPACE_BAR) {
@@ -733,22 +870,9 @@
             return false;
         }
     }
-    
+
     private void setAreThereNotifications() {
         final boolean hasClearable = mNotns.hasClearableItems();
-
-        //Slog.d(TAG, "setAreThereNotifications hasClerable=" + hasClearable);
-
-        /*
-        mOngoingTitle.setVisibility(ongoing ? View.VISIBLE : View.GONE);
-        mLatestTitle.setVisibility(latest ? View.VISIBLE : View.GONE);
-
-        if (ongoing || latest) {
-            mNoNotificationsTitle.setVisibility(View.GONE);
-        } else {
-            mNoNotificationsTitle.setVisibility(View.VISIBLE);
-        }
-        */
     }
 
     /**
@@ -777,6 +901,8 @@
                 onClickNotificationTrigger();
             } else if (v == mRecentButton) {
                 onClickRecentButton();
+            } else if (v == mInputMethodSwitchButton) {
+                onClickInputMethodSwitchButton();
             }
         }
     };
@@ -787,7 +913,6 @@
             if (!mNotificationsOn) {
                 mNotificationsOn = true;
                 mIconLayout.setVisibility(View.VISIBLE); // TODO: animation
-                refreshNotificationTrigger();
             } else {
                 int msg = !mNotificationPanel.isShowing()
                     ? MSG_OPEN_NOTIFICATION_PANEL
@@ -817,6 +942,18 @@
         }
     }
 
+    public void onClickInputMethodSwitchButton() {
+        if (DEBUG) Slog.d(TAG, "clicked input methods panel; disabled=" + mDisabled);
+        int msg = (mInputMethodsPanel.getVisibility() == View.GONE) ?
+                MSG_OPEN_INPUT_METHODS_PANEL : MSG_CLOSE_INPUT_METHODS_PANEL;
+        mHandler.removeMessages(msg);
+        mHandler.sendEmptyMessage(msg);
+    }
+
+    public NotificationClicker makeClicker(PendingIntent intent, String pkg, String tag, int id) {
+        return new NotificationClicker(intent, pkg, tag, id);
+    }
+
     private class NotificationClicker implements View.OnClickListener {
         private PendingIntent mIntent;
         private String mPkg;
@@ -885,7 +1022,7 @@
         // Remove the icon.
 //        ViewGroup iconParent = (ViewGroup)entry.icon.getParent();
 //        if (iconParent != null) iconParent.removeView(entry.icon);
-        refreshIcons();
+        updateNotificationIcons();
 
         return entry.notification;
     }
@@ -981,18 +1118,25 @@
 
         // Add the icon.
         mNotns.add(entry);
-        refreshIcons();
+        updateNotificationIcons();
 
         return iconView;
     }
 
-    private void refreshIcons() {
+    private void reloadAllNotificationIcons() {
+        if (mIconLayout == null) return;
+        mIconLayout.removeAllViews();
+        updateNotificationIcons();
+    }
+
+    private void updateNotificationIcons() {
         // XXX: need to implement a new limited linear layout class
         // to avoid removing & readding everything
 
-        final int ICON_LIMIT = 4;
+        if (mIconLayout == null) return;
+
         final LinearLayout.LayoutParams params
-            = new LinearLayout.LayoutParams(mIconSize, mIconSize);
+            = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight);
 
         int N = mNotns.size();
 
@@ -1002,7 +1146,12 @@
 
         ArrayList<View> toShow = new ArrayList<View>();
 
-        for (int i=0; i<ICON_LIMIT; i++) {
+        // When IME button is visible, the number of notification icons should be decremented
+        // to fit the upper limit.
+        final int maxNotificationIconsCount =
+                (mInputMethodSwitchButton.getVisibility() != View.GONE) ?
+                        MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE : MAX_NOTIFICATION_ICONS;
+        for (int i=0; i< maxNotificationIconsCount; i++) {
             if (i>=N) break;
             toShow.add(mNotns.get(N-i-1).icon);
         }
@@ -1021,13 +1170,13 @@
 
         for (int i=0; i<toShow.size(); i++) {
             View v = toShow.get(i);
+            v.setPadding(mIconHPadding, 0, mIconHPadding, 0);
             if (v.getParent() == null) {
-                mIconLayout.addView(toShow.get(i), i, params);
+                mIconLayout.addView(v, i, params);
             }
         }
 
         loadNotificationPanel();
-        refreshNotificationTrigger();
     }
 
     private void loadNotificationPanel() {
@@ -1094,7 +1243,11 @@
                     }
                 });
         } else {
-            vetoButton.setVisibility(View.INVISIBLE);
+            if ((sbn.notification.flags & Notification.FLAG_ONGOING_EVENT) == 0) {
+                vetoButton.setVisibility(View.INVISIBLE);
+            } else {
+                vetoButton.setVisibility(View.GONE);
+            }
         }
 
         // the large icon
@@ -1139,10 +1292,12 @@
         entry.row = row;
         entry.content = content;
         entry.expanded = expanded;
+        entry.largeIcon = largeIcon;
 
         return true;
     }
 
+/*
     public class ShadowController {
         boolean mShowShadows;
         Map<View, View> mShadowsForElements = new IdentityHashMap<View, View>(7);
@@ -1176,11 +1331,11 @@
             mElementTransition.setDuration(LayoutTransition.DISAPPEARING, 400);
 
             mShadowTransition = new LayoutTransition();
-            mShadowTransition.setAnimator(LayoutTransition.APPEARING, 
+            mShadowTransition.setAnimator(LayoutTransition.APPEARING,
                     ObjectAnimator.ofFloat(null, "alpha", 0f, 1f));
             mShadowTransition.setDuration(LayoutTransition.APPEARING, 200);
             mShadowTransition.setStartDelay(LayoutTransition.APPEARING, 100);
-            mShadowTransition.setAnimator(LayoutTransition.DISAPPEARING, 
+            mShadowTransition.setAnimator(LayoutTransition.DISAPPEARING,
                     ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
             mShadowTransition.setDuration(LayoutTransition.DISAPPEARING, 100);
 
@@ -1221,7 +1376,7 @@
                             case MotionEvent.ACTION_UP:
                                 mHandler.removeMessages(MSG_RESTORE_SHADOWS);
                                 if (mShowShadows) {
-                                    mHandler.sendEmptyMessageDelayed(MSG_RESTORE_SHADOWS, 
+                                    mHandler.sendEmptyMessageDelayed(MSG_RESTORE_SHADOWS,
                                             v == mNotificationShadow ? 5000 : 500);
                                 }
                                 last = true;
@@ -1289,6 +1444,7 @@
             button.setVisibility(mShowShadows ? View.INVISIBLE : View.VISIBLE);
         }
     }
+    */
 
     public class TouchOutsideListener implements View.OnTouchListener {
         private int mMsg;
@@ -1315,6 +1471,8 @@
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.print("mDisabled=0x");
         pw.println(Integer.toHexString(mDisabled));
+        pw.println("mNetworkController:");
+        mNetworkController.dump(fd, pw, args);
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
index 823b793..4ee985d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
@@ -27,9 +27,9 @@
 public class TabletStatusBarView extends FrameLayout {
     private Handler mHandler;
 
-    private View[] mIgnoreChildren = new View[3];
-    private View[] mPanels = new View[3];
-    private int[] mPos = new int[2];
+    private final View[] mIgnoreChildren = new View[4];
+    private final View[] mPanels = new View[4];
+    private final int[] mPos = new int[2];
 
     public TabletStatusBarView(Context context) {
         super(context);
@@ -39,6 +39,7 @@
         super(context, attrs);
     }
 
+    @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
             if (TabletStatusBar.DEBUG) {
@@ -48,18 +49,23 @@
             mHandler.sendEmptyMessage(TabletStatusBar.MSG_CLOSE_NOTIFICATION_PANEL);
             mHandler.removeMessages(TabletStatusBar.MSG_CLOSE_RECENTS_PANEL);
             mHandler.sendEmptyMessage(TabletStatusBar.MSG_CLOSE_RECENTS_PANEL);
+            mHandler.removeMessages(TabletStatusBar.MSG_CLOSE_INPUT_METHODS_PANEL);
+            mHandler.sendEmptyMessage(TabletStatusBar.MSG_CLOSE_INPUT_METHODS_PANEL);
 
             for (int i=0; i < mPanels.length; i++) {
                 if (mPanels[i] != null && mPanels[i].getVisibility() == View.VISIBLE) {
                     if (eventInside(mIgnoreChildren[i], ev)) {
                         if (TabletStatusBar.DEBUG) {
-                            Slog.d(TabletStatusBar.TAG, "TabletStatusBarView eating event for view: " + mIgnoreChildren[i]);
+                            Slog.d(TabletStatusBar.TAG,
+                                    "TabletStatusBarView eating event for view: "
+                                    + mIgnoreChildren[i]);
                         }
                         return true;
                     }
                 }
             }
         }
+        Slog.d(TabletStatusBar.TAG, "TabletStatusBarView not intercepting event");
         return super.onInterceptTouchEvent(ev);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index b3aed03..7705dfc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -18,7 +18,9 @@
 
 import java.util.Arrays;
 
+import android.animation.LayoutTransition;
 import android.app.Notification;
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -45,9 +47,14 @@
 import com.android.systemui.R;
 import com.android.systemui.statusbar.StatusBarIconView;
 
-public class TabletTicker extends Handler {
+public class TabletTicker
+        extends Handler
+        implements LayoutTransition.TransitionListener {
+
     private static final String TAG = "StatusBar.TabletTicker";
 
+    private static final boolean CLICKABLE_TICKER = false;
+
     // 3 is enough to let us see most cases, but not get so far behind that it's too annoying.
     private static final int QUEUE_LENGTH = 3;
 
@@ -66,8 +73,14 @@
     private StatusBarNotification[] mQueue = new StatusBarNotification[QUEUE_LENGTH];
     private int mQueuePos;
 
-    public TabletTicker(Context context) {
-        mContext = context;
+    private TabletStatusBar mBar;
+
+    private LayoutTransition mLayoutTransition;
+    private boolean mWindowShouldClose;
+
+    public TabletTicker(TabletStatusBar bar) {
+        mBar = bar;
+        mContext = bar.getContext();
     }
 
     public void add(IBinder key, StatusBarNotification notification) {
@@ -170,11 +183,7 @@
         }
 
         // if there's nothing left, close the window
-        // TODO: Do this when the animation is done instead
-        if (mCurrentView == null && mWindow != null) {
-            WindowManagerImpl.getDefault().removeView(mWindow);
-            mWindow = null;
-        }
+        mWindowShouldClose = (mCurrentView == null && mWindow != null);
     }
 
     private void dequeue() {
@@ -200,19 +209,41 @@
         final FrameLayout view = new FrameLayout(mContext);
         final int width = res.getDimensionPixelSize(R.dimen.notification_ticker_width);
         final int height = res.getDimensionPixelSize(R.dimen.notification_large_icon_height);
-        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, height,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
-                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+        int windowFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
-                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+        if (CLICKABLE_TICKER) {
+            windowFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+        } else {
+            windowFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+        }
+        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, height,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, windowFlags,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
+//        lp.windowAnimations = com.android.internal.R.style.Animation_Toast;
+
+        mLayoutTransition = new LayoutTransition();
+        mLayoutTransition.addTransitionListener(this);
+        view.setLayoutTransition(mLayoutTransition);
         lp.setTitle("NotificationTicker");
         view.setLayoutParams(lp);
         return view;
     }
 
+    public void startTransition(LayoutTransition transition, ViewGroup container,
+            View view, int transitionType) {}
+
+    public void endTransition(LayoutTransition transition, ViewGroup container,
+            View view, int transitionType) {
+        if (mWindowShouldClose) {
+            WindowManagerImpl.getDefault().removeView(mWindow);
+            mWindow = null;
+            mWindowShouldClose = false;
+            mBar.doneTicking();
+        }
+    }
+
     private View makeTickerView(StatusBarNotification notification) {
         final Notification n = notification.notification;
 
@@ -266,6 +297,17 @@
             largeIcon.setImageBitmap(n.largeIcon);
             largeIcon.setVisibility(View.VISIBLE);
         }
+
+        if (CLICKABLE_TICKER) {
+            PendingIntent contentIntent = notification.notification.contentIntent;
+            if (contentIntent != null) {
+                group.setOnClickListener(mBar.makeClicker(contentIntent,
+                            notification.pkg, notification.tag, notification.id));
+            } else {
+                group.setOnClickListener(null);
+            }
+        }
+
         return group;
     }
 }
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp
index 8dc88db..27d1fc0 100644
--- a/packages/TtsService/jni/android_tts_SynthProxy.cpp
+++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp
@@ -17,7 +17,7 @@
 #include <stdio.h>
 #include <unistd.h>
 
-#define LOG_TAG "SynthProxy"
+#define LOG_TAG "SynthProxyJNI"
 
 #include <utils/Log.h>
 #include <nativehelper/jni.h>
@@ -33,8 +33,8 @@
 #define DEFAULT_TTS_FORMAT      AudioSystem::PCM_16_BIT
 #define DEFAULT_TTS_NB_CHANNELS 1
 #define DEFAULT_TTS_BUFFERSIZE  2048
-// TODO use the TTS stream type when available
 #define DEFAULT_TTS_STREAM_TYPE AudioSystem::MUSIC
+#define DEFAULT_VOLUME          1.0f
 
 // EQ + BOOST parameters
 #define FILTER_LOWSHELF_ATTENUATION -18.0f // in dB
@@ -154,7 +154,7 @@
 class SynthProxyJniStorage {
     public :
         jobject                   tts_ref;
-        android_tts_engine_t*       mEngine;
+        android_tts_engine_t*     mEngine;
         void*                     mEngineLibHandle;
         AudioTrack*               mAudioOut;
         int8_t                    mPlayState;
@@ -165,6 +165,7 @@
         int                       mNbChannels;
         int8_t *                  mBuffer;
         size_t                    mBufferSize;
+        float                     mVolume[2];
 
         SynthProxyJniStorage() {
             tts_ref = NULL;
@@ -179,6 +180,8 @@
             mBufferSize = DEFAULT_TTS_BUFFERSIZE;
             mBuffer = new int8_t[mBufferSize];
             memset(mBuffer, 0, mBufferSize);
+            mVolume[AudioTrack::LEFT] = DEFAULT_VOLUME;
+            mVolume[AudioTrack::RIGHT] = DEFAULT_VOLUME;
         }
 
         ~SynthProxyJniStorage() {
@@ -189,7 +192,7 @@
                 mEngine = NULL;
             }
             if (mEngineLibHandle) {
-                //LOGE("~SynthProxyJniStorage(): before close library");
+                //LOGV("~SynthProxyJniStorage(): before close library");
                 int res = dlclose(mEngineLibHandle);
                 LOGE_IF( res != 0, "~SynthProxyJniStorage(): dlclose returned %d", res);
             }
@@ -241,7 +244,7 @@
               mAudioOut = NULL;
             } else {
               //LOGI("AudioTrack OK");
-              mAudioOut->setVolume(1.0f, 1.0f);
+              mAudioOut->setVolume(mVolume[AudioTrack::LEFT], mVolume[AudioTrack::RIGHT]);
               LOGV("AudioTrack ready");
             }
             mPlayLock.unlock();
@@ -277,7 +280,7 @@
 __ttsSynthDoneCB(void ** pUserdata, uint32_t rate,
                android_tts_audio_format_t format, int channel,
                int8_t **pWav, size_t *pBufferSize,
-               android_tts_synth_status_t status) 
+               android_tts_synth_status_t status)
 {
     //LOGV("ttsSynthDoneCallback: %d bytes", bufferSize);
     AudioSystem::audio_format  encoding;
@@ -618,7 +621,7 @@
     Mutex::Autolock l(engineMutex);
 
     SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-    LOGI("setting speech rate to %d", speechRate);
+    //LOGI("setting speech rate to %d", speechRate);
     android_tts_engine_t *engine = pSynthData->mEngine;
 
     if (engine) {
@@ -647,7 +650,7 @@
     sprintf(buffer, "%d", pitch);
 
     SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
-    LOGI("setting pitch to %d", pitch);
+    //LOGI("setting pitch to %d", pitch);
     android_tts_engine_t *engine = pSynthData->mEngine;
 
     if (engine) {
@@ -783,7 +786,7 @@
 
 static int
 android_tts_SynthProxy_speak(JNIEnv *env, jobject thiz, jint jniData,
-        jstring textJavaString, jint javaStreamType)
+        jstring textJavaString, jint javaStreamType, jfloat volume, jfloat pan)
 {
     int result = ANDROID_TTS_FAILURE;
 
@@ -798,9 +801,34 @@
 
     SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
 
-    pSynthData->mPlayLock.lock();
-    pSynthData->mPlayState = SYNTHPLAYSTATE_IS_PLAYING;
-    pSynthData->mPlayLock.unlock();
+    {//scope for lock on mPlayLock
+        Mutex::Autolock _l(pSynthData->mPlayLock);
+
+        pSynthData->mPlayState = SYNTHPLAYSTATE_IS_PLAYING;
+
+        // clip volume and pan
+        float vol = (volume > 1.0f) ? 1.0f : (volume < 0.0f) ? 0.0f : volume;
+        float panning = (pan > 1.0f) ? 1.0f : (pan < -1.0f) ? -1.0f : pan;
+        // compute playback volume based on volume and pan, using balance rule, in order to avoid
+        // lowering volume when panning in center
+        pSynthData->mVolume[AudioTrack::LEFT] = vol;
+        pSynthData->mVolume[AudioTrack::RIGHT] = vol;
+        if (panning > 0.0f) {
+            pSynthData->mVolume[AudioTrack::LEFT] *= (1.0f - panning);
+        } else if (panning < 0.0f) {
+            pSynthData->mVolume[AudioTrack::RIGHT] *= (1.0f + panning);
+        }
+
+        // apply the volume if there is an output
+        if (NULL != pSynthData->mAudioOut) {
+            pSynthData->mAudioOut->setVolume(pSynthData->mVolume[AudioTrack::LEFT],
+                    pSynthData->mVolume[AudioTrack::RIGHT]);
+        }
+
+        //LOGV("android_tts_SynthProxy_speak() vol=%.3f pan=%.3f, mVolume=[%.1f %.1f]",
+        //        volume, pan,
+        //        pSynthData->mVolume[AudioTrack::LEFT], pSynthData->mVolume[AudioTrack::RIGHT]);
+    }
 
     afterSynthData_t* pForAfter = new (afterSynthData_t);
     pForAfter->jniStorage = jniData;
@@ -935,7 +963,7 @@
         (void*)android_tts_SynthProxy_stopSync
     },
     {   "native_speak",
-        "(ILjava/lang/String;I)I",
+        "(ILjava/lang/String;IFF)I",
         (void*)android_tts_SynthProxy_speak
     },
     {   "native_synthesizeToFile",
diff --git a/packages/TtsService/src/android/tts/SynthProxy.java b/packages/TtsService/src/android/tts/SynthProxy.java
index 525a504..f5f5fcf 100755
--- a/packages/TtsService/src/android/tts/SynthProxy.java
+++ b/packages/TtsService/src/android/tts/SynthProxy.java
@@ -78,12 +78,13 @@
     /**
      * Synthesize speech and speak it directly using AudioTrack.
      */
-    public int speak(String text, int streamType) {
+    public int speak(String text, int streamType, float volume, float pan) {
+        Log.i(TAG, "speak() on stream "+ streamType);
         if ((streamType > -1) && (streamType < AudioSystem.getNumStreamTypes())) {
-            return native_speak(mJniData, text, streamType);
+            return native_speak(mJniData, text, streamType, volume, pan);
         } else {
             Log.e("SynthProxy", "Trying to speak with invalid stream type " + streamType);
-            return native_speak(mJniData, text, AudioManager.STREAM_MUSIC);
+            return native_speak(mJniData, text, AudioManager.STREAM_MUSIC, volume, pan);
         }
     }
 
@@ -93,6 +94,7 @@
      * "/sdcard/???.wav" is recommended.
      */
     public int synthesizeToFile(String text, String filename) {
+        Log.i(TAG, "synthesizeToFile() to file "+ filename);
         return native_synthesizeToFile(mJniData, text, filename);
     }
 
@@ -192,7 +194,8 @@
 
     private native final int native_stopSync(int jniData);
 
-    private native final int native_speak(int jniData, String text, int streamType);
+    private native final int native_speak(int jniData, String text, int streamType, float volume,
+            float pan);
 
     private native final int native_synthesizeToFile(int jniData, String text, String filename);
 
diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java
index 08bbfb2..c562327 100755
--- a/packages/TtsService/src/android/tts/TtsService.java
+++ b/packages/TtsService/src/android/tts/TtsService.java
@@ -121,7 +121,6 @@
     private static final int SPEECHQUEUELOCK_TIMEOUT = 5000;
     private static final int MAX_SPEECH_ITEM_CHAR_LENGTH = 4000;
     private static final int MAX_FILENAME_LENGTH = 250;
-    // TODO use the TTS stream type when available
     private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_MUSIC;
     // TODO use TextToSpeech.DEFAULT_SYNTH once it is unhidden
     private static final String DEFAULT_SYNTH = "com.svox.pico";
@@ -791,6 +790,8 @@
                     String speechRate = "";
                     String engine = "";
                     String pitch = "";
+                    float volume = TextToSpeech.Engine.DEFAULT_VOLUME;
+                    float pan = TextToSpeech.Engine.DEFAULT_PAN;
                     if (speechItem.mParams != null){
                         for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){
                             String param = speechItem.mParams.get(i);
@@ -816,6 +817,18 @@
                                     engine = speechItem.mParams.get(i + 1);
                                 } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_PITCH)) {
                                     pitch = speechItem.mParams.get(i + 1);
+                                } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_VOLUME)) {
+                                    try {
+                                        volume = Float.parseFloat(speechItem.mParams.get(i + 1));
+                                    } catch (NumberFormatException e) {
+                                        volume = TextToSpeech.Engine.DEFAULT_VOLUME;
+                                    }
+                                } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_PAN)) {
+                                    try {
+                                        pan = Float.parseFloat(speechItem.mParams.get(i + 1));
+                                    } catch (NumberFormatException e) {
+                                        pan = TextToSpeech.Engine.DEFAULT_PAN;
+                                    }
                                 }
                             }
                         }
@@ -844,7 +857,7 @@
                             setPitch("", getDefaultPitch());
                         }
                         try {
-                            sNativeSynth.speak(speechItem.mText, streamType);
+                            sNativeSynth.speak(speechItem.mText, streamType, volume, pan);
                         } catch (NullPointerException e) {
                             // synth will become null during onDestroy()
                             Log.v(SERVICE_TAG, " null synth, can't speak");
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
index 63b87b1..a618423 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
@@ -328,6 +328,7 @@
             public void run() {
                 Log.i(TAG, "VPN connectivity monitor running");
                 try {
+                    mNotification.update(mStartTime); // to pop up notification
                     for (int i = 10; ; i--) {
                         long now = System.currentTimeMillis();
 
@@ -417,13 +418,27 @@
 
     // Helper class for showing, updating notification.
     private class NotificationHelper {
+        private NotificationManager mNotificationManager = (NotificationManager)
+                mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+        private Notification mNotification =
+                new Notification(R.drawable.vpn_connected, null, 0L);
+        private PendingIntent mPendingIntent = PendingIntent.getActivity(
+                mContext, 0,
+                new VpnManager(mContext).createSettingsActivityIntent(), 0);
+        private String mConnectedTitle;
+
         void update(long now) {
-            String title = getNotificationTitle(true);
-            Notification n = new Notification(R.drawable.vpn_connected, title,
-                    mStartTime);
-            n.setLatestEventInfo(mContext, title,
+            Notification n = mNotification;
+            if (now == mStartTime) {
+                // to pop up the notification for the first time
+                n.when = mStartTime;
+                n.tickerText = mConnectedTitle = getNotificationTitle(true);
+            } else {
+                n.tickerText = null;
+            }
+            n.setLatestEventInfo(mContext, mConnectedTitle,
                     getConnectedNotificationMessage(now),
-                    prepareNotificationIntent());
+                    mPendingIntent);
             n.flags |= Notification.FLAG_NO_CLEAR;
             n.flags |= Notification.FLAG_ONGOING_EVENT;
             enableNotification(n);
@@ -435,25 +450,18 @@
                     title, System.currentTimeMillis());
             n.setLatestEventInfo(mContext, title,
                     getDisconnectedNotificationMessage(),
-                    prepareNotificationIntent());
+                    mPendingIntent);
             n.flags |= Notification.FLAG_AUTO_CANCEL;
             disableNotification();
             enableNotification(n);
         }
 
         void disableNotification() {
-            ((NotificationManager) mContext.getSystemService(
-                    Context.NOTIFICATION_SERVICE)).cancel(NOTIFICATION_ID);
+            mNotificationManager.cancel(NOTIFICATION_ID);
         }
 
         private void enableNotification(Notification n) {
-            ((NotificationManager) mContext.getSystemService(
-                    Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, n);
-        }
-
-        private PendingIntent prepareNotificationIntent() {
-            return PendingIntent.getActivity(mContext, 0,
-                    new VpnManager(mContext).createSettingsActivityIntent(), 0);
+            mNotificationManager.notify(NOTIFICATION_ID, n);
         }
 
         private String getNotificationTitle(boolean connected) {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
index 82753b2..6b52454 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -18,6 +18,11 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
 import android.telephony.TelephonyManager;
 import android.view.KeyEvent;
@@ -37,12 +42,34 @@
  */
 public abstract class KeyguardViewBase extends FrameLayout {
 
+    private static final int BACKGROUND_COLOR = 0x70000000;
     private KeyguardViewCallback mCallback;
     private AudioManager mAudioManager;
     private TelephonyManager mTelephonyManager = null;
 
     public KeyguardViewBase(Context context) {
         super(context);
+
+        // This is a faster way to draw the background on devices without hardware acceleration
+        setBackgroundDrawable(new Drawable() {
+            @Override
+            public void draw(Canvas canvas) {
+                canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC);
+            }
+
+            @Override
+            public void setAlpha(int alpha) {
+            }
+
+            @Override
+            public void setColorFilter(ColorFilter cf) {
+            }
+
+            @Override
+            public int getOpacity() {
+                return PixelFormat.TRANSLUCENT;
+            }
+        });
     }
 
     // used to inject callback
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 50d10bf..79fbe0e 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -23,6 +23,7 @@
 import com.android.internal.widget.WaveView;
 import com.android.internal.widget.WaveView.OnTriggerListener;
 
+import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -80,11 +81,6 @@
     // last known battery level
     private int mBatteryLevel = 100;
 
-    private String mNextAlarm = null;
-    private Drawable mAlarmIcon = null;
-    private String mCharging = null;
-    private Drawable mChargingIcon = null;
-
     private boolean mSilentMode;
     private AudioManager mAudioManager;
     private String mDateFormatString;
@@ -255,9 +251,9 @@
     private boolean shouldEnableMenuKey() {
         final Resources res = getResources();
         final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
-        final boolean isMonkey = SystemProperties.getBoolean("ro.monkey", false);
+        final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
         final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
-        return !configDisabled || isMonkey || fileOverride;
+        return !configDisabled || isTestHarness || fileOverride;
     }
 
     /**
@@ -356,9 +352,6 @@
         mStatus = getCurrentStatus(updateMonitor.getSimState());
         updateLayout(mStatus);
 
-        refreshBatteryStringAndIcon();
-        refreshAlarmDisplay();
-
         mTimeFormat = DateFormat.getTimeFormat(getContext());
         mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);
         refreshTimeAndDateDisplay();
@@ -417,14 +410,6 @@
     private Runnable mPendingR1;
     private Runnable mPendingR2;
 
-    private void refreshAlarmDisplay() {
-        mNextAlarm = mLockPatternUtils.getNextAlarm();
-        if (mNextAlarm != null) {
-            mAlarmIcon = getContext().getResources().getDrawable(R.drawable.ic_lock_idle_alarm);
-        }
-        updateStatusLines();
-    }
-
     /** {@inheritDoc} */
     public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
             int batteryLevel) {
@@ -433,32 +418,9 @@
         mPluggedIn = pluggedIn;
         mBatteryLevel = batteryLevel;
 
-        refreshBatteryStringAndIcon();
         updateStatusLines();
     }
 
-    private void refreshBatteryStringAndIcon() {
-        if (!mShowingBatteryInfo) {
-            mCharging = null;
-            return;
-        }
-
-        if (mChargingIcon == null) {
-            mChargingIcon =
-                    getContext().getResources().getDrawable(R.drawable.ic_lock_idle_charging);
-        }
-
-        if (mPluggedIn) {
-            if (mBatteryLevel >= 100) {
-                mCharging = getContext().getString(R.string.lockscreen_charged);
-            } else {
-                mCharging = getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel);
-            }
-        } else {
-            mCharging = getContext().getString(R.string.lockscreen_low_battery);
-        }
-    }
-
     /** {@inheritDoc} */
     public void onTimeChanged() {
         refreshTimeAndDateDisplay();
@@ -469,7 +431,7 @@
     }
 
     private void updateStatusLines() {
-        mStatusView.updateStatusLines(mStatus.showStatusLines(), mCharging, mChargingIcon, mAlarmIcon);
+        mStatusView.updateStatusLines(mStatus.showStatusLines());
     }
 
     /** {@inheritDoc} */
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
index 35fa3e5..5d1455e 100644
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -396,7 +396,7 @@
                 mLockPatternView
                         .setDisplayMode(LockPatternView.DisplayMode.Correct);
                 mStatusView.setInstructions("");
-                mStatusView.updateStatusLines();
+                mStatusView.updateStatusLines(true);
                 mCallback.keyguardDone(true);
                 mCallback.reportSuccessfulUnlockAttempt();
             } else {
@@ -416,7 +416,7 @@
                     // TODO mUnlockIcon.setVisibility(View.VISIBLE);
                     mStatusView.setInstructions(
                             getContext().getString(R.string.lockscreen_pattern_wrong));
-                    mStatusView.updateStatusLines();
+                    mStatusView.updateStatusLines(true);
                     mLockPatternView.postDelayed(
                             mCancelPatternRunnable,
                             PATTERN_CLEAR_TIMEOUT_MS);
@@ -437,7 +437,7 @@
                 mStatusView.setInstructions(getContext().getString(
                         R.string.lockscreen_too_many_failed_attempts_countdown,
                         secondsRemaining));
-                mStatusView.updateStatusLines();
+                mStatusView.updateStatusLines(true);
             }
 
             @Override
@@ -445,7 +445,7 @@
                 mLockPatternView.setEnabled(true);
                 mStatusView.setInstructions(getContext().getString(
                         R.string.lockscreen_pattern_instructions));
-                mStatusView.updateStatusLines();
+                mStatusView.updateStatusLines(true);
                 // TODO mUnlockIcon.setVisibility(View.VISIBLE);
                 mFailedPatternAttemptsSinceLastTimeout = 0;
                 if (mEnableFallback) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 5faece7..d6b7366 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -15,21 +15,25 @@
 
 package com.android.internal.policy.impl;
 
+import static android.view.View.MeasureSpec.AT_MOST;
+import static android.view.View.MeasureSpec.EXACTLY;
+import static android.view.View.MeasureSpec.getMode;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY;
 import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
 
 import com.android.internal.view.BaseSurfaceHolder;
 import com.android.internal.view.RootViewSurfaceTaker;
 import com.android.internal.view.StandaloneActionMode;
+import com.android.internal.view.menu.ActionMenuView;
 import com.android.internal.view.menu.ContextMenuBuilder;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuDialogHelper;
+import com.android.internal.view.menu.MenuItemImpl;
 import com.android.internal.view.menu.MenuPopupHelper;
 import com.android.internal.view.menu.MenuView;
 import com.android.internal.view.menu.SubMenuBuilder;
@@ -51,13 +55,13 @@
 import android.os.Parcelable;
 import android.util.AndroidRuntimeException;
 import android.util.Config;
+import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.TypedValue;
 import android.view.ActionMode;
 import android.view.Gravity;
-import android.view.HardwareRenderer;
 import android.view.InputQueue;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
@@ -72,6 +76,7 @@
 import android.view.ViewStub;
 import android.view.Window;
 import android.view.WindowManager;
+import android.view.View.MeasureSpec;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.animation.Animation;
@@ -98,7 +103,10 @@
      * Simple callback used by the context menu and its submenus. The options
      * menu submenus do not use this (their behavior is more complex).
      */
-    DialogMenuCallback mContextMenuCallback = new DialogMenuCallback(FEATURE_CONTEXT_MENU);
+    final DialogMenuCallback mContextMenuCallback = new DialogMenuCallback(FEATURE_CONTEXT_MENU);
+
+    final TypedValue mMinWidthMajor = new TypedValue();
+    final TypedValue mMinWidthMinor = new TypedValue();
 
     // This is the top-level view of the window, containing the window decor.
     private DecorView mDecor;
@@ -430,6 +438,21 @@
             return;
         }
 
+        // Don't open an options panel for honeycomb apps on xlarge devices.
+        // (The app should be using an action bar for menu items.)
+        if (st.featureId == FEATURE_OPTIONS_PANEL) {
+            Context context = getContext();
+            Configuration config = context.getResources().getConfiguration();
+            boolean isXLarge = (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) ==
+                    Configuration.SCREENLAYOUT_SIZE_XLARGE;
+            boolean isHoneycombApp = context.getApplicationInfo().targetSdkVersion >=
+                    android.os.Build.VERSION_CODES.HONEYCOMB;
+
+            if (isXLarge && isHoneycombApp) {
+                return;
+            }
+        }
+
         Callback cb = getCallback();
         if ((cb != null) && (!cb.onMenuOpened(st.featureId, st.menu))) {
             // Callback doesn't want the menu to open, reset any state
@@ -868,12 +891,16 @@
             // The window manager will give us a valid window token
             new MenuDialogHelper(subMenu).show(null);
         } else if (hasFeature(FEATURE_ACTION_BAR)) {
-            mActionButtonPopup = new ActionButtonSubmenu(getContext(), subMenu);
-            mActionButtonPopup.show();
-            Callback cb = getCallback();
-            if (cb != null) {
-                cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
-            }
+            mDecor.post(new Runnable() {
+                public void run() {
+                    mActionButtonPopup = new ActionButtonSubmenu(getContext(), subMenu);
+                    mActionButtonPopup.show();
+                    Callback cb = getCallback();
+                    if (cb != null) {
+                        cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
+                    }
+                }
+            });
         }
 
         return true;
@@ -1237,6 +1264,11 @@
     }
 
     @Override
+    public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
+        return mDecor.superDispatchKeyShortcutEvent(event);
+    }
+
+    @Override
     public boolean superDispatchTouchEvent(MotionEvent event) {
         return mDecor.superDispatchTouchEvent(event);
     }
@@ -1592,24 +1624,7 @@
                 // First handle chording of panel key: if a panel key is held
                 // but not released, try to execute a shortcut in it.
                 if ((mPanelChordingKey > 0) && (mPanelChordingKey != keyCode)) {
-                    // Perform the shortcut (mPreparedPanel can be null since
-                    // global shortcuts (such as search) don't rely on a
-                    // prepared panel or menu).
-                    boolean handled = performPanelShortcut(mPreparedPanel, keyCode, event,
-                            Menu.FLAG_PERFORM_NO_CLOSE);
-
-                    if (!handled) {
-                        /*
-                         * If not handled, then pass it to the view hierarchy
-                         * and anyone else that may be interested.
-                         */
-                        handled = dispatchKeyShortcutEvent(event);
-
-                        if (handled && mPreparedPanel != null) {
-                            mPreparedPanel.isHandled = true;
-                        }
-                    }
-
+                    boolean handled = dispatchKeyShortcutEvent(event);
                     if (handled) {
                         return true;
                     }
@@ -1643,6 +1658,26 @@
         }
 
         @Override
+        public boolean dispatchKeyShortcutEvent(KeyEvent ev) {
+            // Perform the shortcut (mPreparedPanel can be null since
+            // global shortcuts (such as search) don't rely on a
+            // prepared panel or menu).
+            boolean handled = performPanelShortcut(mPreparedPanel, ev.getKeyCode(), ev,
+                    Menu.FLAG_PERFORM_NO_CLOSE);
+            if (handled) {
+                if (mPreparedPanel != null) {
+                    mPreparedPanel.isHandled = true;
+                }
+                return true;
+            }
+
+            // Shortcut not handled by the panel.  Dispatch to the view hierarchy.
+            final Callback cb = getCallback();
+            return cb != null && mFeatureId < 0 ? cb.dispatchKeyShortcutEvent(ev) : super
+                    .dispatchKeyShortcutEvent(ev);
+        }
+
+        @Override
         public boolean dispatchTouchEvent(MotionEvent ev) {
             final Callback cb = getCallback();
             return cb != null && mFeatureId < 0 ? cb.dispatchTouchEvent(ev) : super
@@ -1660,6 +1695,10 @@
             return super.dispatchKeyEvent(event);
         }
 
+        public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
+            return super.dispatchKeyShortcutEvent(event);
+        }
+
         public boolean superDispatchTouchEvent(MotionEvent event) {
             return super.dispatchTouchEvent(event);
         }
@@ -1831,6 +1870,45 @@
         }
 
         @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
+            final boolean isPortrait = metrics.widthPixels < metrics.heightPixels;
+
+            final int widthMode = getMode(widthMeasureSpec);
+
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+            int width = getMeasuredWidth();
+            boolean measure = false;
+
+            widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, EXACTLY);
+
+            final TypedValue tv = isPortrait ? mMinWidthMinor : mMinWidthMajor;
+
+            if (widthMode == AT_MOST && tv.type != TypedValue.TYPE_NULL) {
+                final int min;
+                if (tv.type == TypedValue.TYPE_DIMENSION) {
+                    min = (int)tv.getDimension(metrics);
+                } else if (tv.type == TypedValue.TYPE_FRACTION) {
+                    min = (int)tv.getFraction(metrics.widthPixels, metrics.widthPixels);
+                } else {
+                    min = 0;
+                }
+
+                if (width < min) {
+                    widthMeasureSpec = MeasureSpec.makeMeasureSpec(min, EXACTLY);
+                    measure = true;
+                }
+            }
+
+            // TODO: Support height?
+
+            if (measure) {
+                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            }
+        }
+
+        @Override
         public void draw(Canvas canvas) {
             super.draw(canvas);
 
@@ -2239,6 +2317,9 @@
             setFlags(FLAG_SPLIT_TOUCH, FLAG_SPLIT_TOUCH&(~getForcedWindowFlags()));
         }
 
+        a.getValue(com.android.internal.R.styleable.Window_windowMinWidthMajor, mMinWidthMajor);
+        a.getValue(com.android.internal.R.styleable.Window_windowMinWidthMinor, mMinWidthMinor);
+
         if (getContext().getApplicationInfo().targetSdkVersion
                 < android.os.Build.VERSION_CODES.HONEYCOMB) {
             addFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);
@@ -2294,7 +2375,10 @@
         // System.out.println("Features: 0x" + Integer.toHexString(features));
         if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
             if (mIsFloating) {
-                layoutResource = com.android.internal.R.layout.dialog_title_icons;
+                TypedValue res = new TypedValue();
+                getContext().getTheme().resolveAttribute(
+                        com.android.internal.R.attr.dialogTitleIconsDecorLayout, res, true);
+                layoutResource = res.resourceId;
             } else {
                 layoutResource = com.android.internal.R.layout.screen_title_icons;
             }
@@ -2311,7 +2395,10 @@
             // Special case for a window with a custom title.
             // If the window is floating, we need a dialog layout
             if (mIsFloating) {
-                layoutResource = com.android.internal.R.layout.dialog_custom_title;
+                TypedValue res = new TypedValue();
+                getContext().getTheme().resolveAttribute(
+                        com.android.internal.R.attr.dialogCustomTitleDecorLayout, res, true);
+                layoutResource = res.resourceId;
             } else {
                 layoutResource = com.android.internal.R.layout.screen_custom_title;
             }
@@ -2321,7 +2408,10 @@
             // If no other features and not embedded, only need a title.
             // If the window is floating, we need a dialog layout
             if (mIsFloating) {
-                layoutResource = com.android.internal.R.layout.dialog_title;
+                TypedValue res = new TypedValue();
+                getContext().getTheme().resolveAttribute(
+                        com.android.internal.R.attr.dialogTitleDecorLayout, res, true);
+                layoutResource = res.resourceId;
             } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
                 if ((features & (1 << FEATURE_ACTION_BAR_OVERLAY)) != 0) {
                     layoutResource = com.android.internal.R.layout.screen_action_bar_overlay;
@@ -2980,6 +3070,20 @@
         public ActionButtonSubmenu(Context context, SubMenuBuilder subMenu) {
             super(context, subMenu);
             mSubMenu = subMenu;
+
+            MenuBuilder parentMenu = subMenu.getRootMenu();
+            MenuItemImpl item = (MenuItemImpl) subMenu.getItem();
+            if (!item.isActionButton()) {
+                // Give a reasonable anchor to nested submenus.
+                ActionMenuView amv = (ActionMenuView) parentMenu.getMenuView(
+                        MenuBuilder.TYPE_ACTION_BUTTON, null);
+
+                View anchor = amv.getOverflowButton();
+                if (anchor == null) {
+                    anchor = amv;
+                }
+                setAnchorView(anchor);
+            }
         }
 
         @Override
@@ -2991,10 +3095,11 @@
 
         @Override
         public void run() {
-            show();
-            Callback cb = getCallback();
-            if (cb != null) {
-                cb.onMenuOpened(FEATURE_ACTION_BAR, mSubMenu);
+            if (tryShow()) {
+                Callback cb = getCallback();
+                if (cb != null) {
+                    cb.onMenuOpened(FEATURE_ACTION_BAR, mSubMenu);
+                }
             }
         }
     }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index c6984a4..2a39322 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -34,15 +34,16 @@
 import android.database.ContentObserver;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.LocalPowerManager;
-import android.os.Looper;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.UEventObserver;
 import android.os.Vibrator;
 import android.provider.Settings;
 
@@ -112,6 +113,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
 import android.view.WindowManagerImpl;
 import android.view.WindowManagerPolicy;
 import android.view.animation.Animation;
@@ -119,6 +121,11 @@
 import android.media.IAudioService;
 import android.media.AudioManager;
 
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 /**
@@ -176,6 +183,8 @@
     // things in here CAN NOT take focus, but are shown on top of everything else.
     static final int SYSTEM_OVERLAY_LAYER = 18;
     static final int SECURE_SYSTEM_OVERLAY_LAYER = 19;
+    // the (mouse) pointer layer
+    static final int POINTER_LAYER = 20;
 
     static final int APPLICATION_MEDIA_SUBLAYER = -2;
     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -230,9 +239,15 @@
     volatile boolean mPowerKeyHandled;
     RecentApplicationsDialog mRecentAppsDialog;
     Handler mHandler;
-    
+
+    private static final int LID_ABSENT = -1;
+    private static final int LID_CLOSED = 0;
+    private static final int LID_OPEN = 1;
+
+    int mLidOpen = LID_ABSENT;
+
     boolean mSystemReady;
-    boolean mLidOpen;
+    boolean mHdmiPlugged;
     int mUiMode = Configuration.UI_MODE_TYPE_NORMAL;
     int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
     int mLidOpenRotation;
@@ -348,6 +363,13 @@
 
     final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction();
 
+    private UEventObserver mHDMIObserver = new UEventObserver() {
+        @Override
+        public void onUEvent(UEventObserver.UEvent event) {
+            setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
+        }
+    };
+
     class SettingsObserver extends ContentObserver {
         SettingsObserver(Handler handler) {
             super(handler);
@@ -695,6 +717,13 @@
         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_safeModeEnabledVibePattern);
 
+        // watch for HDMI plug messages if the hdmi switch exists
+        if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
+            mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
+        }
+        mHdmiPlugged = !readHdmiState();
+        setHdmiPlugged(!mHdmiPlugged);
+
         // Note: the Configuration is not stable here, so we cannot load mStatusBarCanHide from
         // config_statusBarCanHide because the latter depends on the screen size
     }
@@ -872,21 +901,31 @@
     void readLidState() {
         try {
             int sw = mWindowManager.getSwitchState(SW_LID);
-            if (sw >= 0) {
-                mLidOpen = sw == 0;
+            if (sw > 0) {
+                mLidOpen = LID_OPEN;
+            } else if (sw == 0) {
+                mLidOpen = LID_CLOSED;
+            } else {
+                mLidOpen = LID_ABSENT;
             }
         } catch (RemoteException e) {
             // Ignore
         }
     }
     
-    private int determineHiddenState(boolean lidOpen,
-            int mode, int hiddenValue, int visibleValue) {
+    private int determineHiddenState(int mode, int hiddenValue, int visibleValue) {
+        if (KEYBOARD_ALWAYS_HIDDEN) {
+            return hiddenValue;
+        }
+        if (mLidOpen == LID_ABSENT) {
+            return visibleValue;
+        }
+
         switch (mode) {
             case 1:
-                return lidOpen ? visibleValue : hiddenValue;
+                return mLidOpen == LID_OPEN ? visibleValue : hiddenValue;
             case 2:
-                return lidOpen ? hiddenValue : visibleValue;
+                return mLidOpen == LID_OPEN ? hiddenValue : visibleValue;
         }
         return visibleValue;
     }
@@ -894,12 +933,11 @@
     /** {@inheritDoc} */
     public void adjustConfigurationLw(Configuration config) {
         readLidState();
-        final boolean lidOpen = !KEYBOARD_ALWAYS_HIDDEN && mLidOpen;
-        mPowerManager.setKeyboardVisibility(lidOpen);
-        config.hardKeyboardHidden = determineHiddenState(lidOpen,
+        mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN);
+        config.hardKeyboardHidden = determineHiddenState(
                 mLidKeyboardAccessibility, Configuration.HARDKEYBOARDHIDDEN_YES,
                 Configuration.HARDKEYBOARDHIDDEN_NO);
-        config.navigationHidden = determineHiddenState(lidOpen,
+        config.navigationHidden = determineHiddenState(
                 mLidNavigationAccessibility, Configuration.NAVIGATIONHIDDEN_YES,
                 Configuration.NAVIGATIONHIDDEN_NO);
         config.keyboardHidden = (config.hardKeyboardHidden
@@ -950,6 +988,8 @@
             return WALLPAPER_LAYER;
         case TYPE_DRAG:
             return DRAG_LAYER;
+        case TYPE_POINTER:
+            return POINTER_LAYER;
         }
         Log.e(TAG, "Unknown window type: " + type);
         return APPLICATION_LAYER;
@@ -998,23 +1038,16 @@
         
         try {
             Context context = mContext;
-            boolean setTheme = false;
             //Log.i(TAG, "addStartingWindow " + packageName + ": nonLocalizedLabel="
             //        + nonLocalizedLabel + " theme=" + Integer.toHexString(theme));
-            if (theme != 0 || labelRes != 0) {
+            if (theme != context.getThemeResId() || labelRes != 0) {
                 try {
                     context = context.createPackageContext(packageName, 0);
-                    if (theme != 0) {
-                        context.setTheme(theme);
-                        setTheme = true;
-                    }
+                    context.setTheme(theme);
                 } catch (PackageManager.NameNotFoundException e) {
                     // Ignore
                 }
             }
-            if (!setTheme) {
-                context.setTheme(com.android.internal.R.style.Theme);
-            }
             
             Window win = PolicyManager.makeNewWindow(context);
             if (win.getWindowStyle().getBoolean(
@@ -1954,16 +1987,16 @@
     /** {@inheritDoc} */
     public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
         // lid changed state
-        mLidOpen = lidOpen;
-        boolean awakeNow = mKeyguardMediator.doLidChangeTq(mLidOpen);
+        mLidOpen = lidOpen ? LID_OPEN : LID_CLOSED;
+        boolean awakeNow = mKeyguardMediator.doLidChangeTq(lidOpen);
         updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
         if (awakeNow) {
-            // If the lid opening and we don't have to keep the
+            // If the lid is opening and we don't have to keep the
             // keyguard up, then we can turn on the screen
             // immediately.
             mKeyguardMediator.pokeWakelock();
         } else if (keyguardIsShowingTq()) {
-            if (mLidOpen) {
+            if (lidOpen) {
                 // If we are opening the lid and not hiding the
                 // keyguard, then we need to have it turn on the
                 // screen once it is shown.
@@ -1972,7 +2005,7 @@
             }
         } else {
             // Light up the keyboard if we are sliding up.
-            if (mLidOpen) {
+            if (lidOpen) {
                 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
                         LocalPowerManager.BUTTON_EVENT);
             } else {
@@ -1982,6 +2015,45 @@
         }
     }
 
+    void setHdmiPlugged(boolean plugged) {
+        if (mHdmiPlugged != plugged) {
+            mHdmiPlugged = plugged;
+            updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
+            Intent intent = new Intent(ACTION_HDMI_PLUGGED);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+            intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
+            mContext.sendStickyBroadcast(intent);
+        }
+    }
+
+    boolean readHdmiState() {
+        final String filename = "/sys/class/switch/hdmi/state";
+        FileReader reader = null;
+        try {
+            reader = new FileReader(filename);
+            char[] buf = new char[15];
+            int n = reader.read(buf);
+            if (n > 1) {
+                return 0 != Integer.parseInt(new String(buf, 0, n-1));
+            } else {
+                return false;
+            }
+        } catch (IOException ex) {
+            Slog.d(TAG, "couldn't read hdmi state from " + filename + ": " + ex);
+            return false;
+        } catch (NumberFormatException ex) {
+            Slog.d(TAG, "couldn't read hdmi state from " + filename + ": " + ex);
+            return false;
+        } finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (IOException ex) {
+                }
+            }
+        }
+    }
+
     /**
      * @return Whether music is being played right now.
      */
@@ -2360,15 +2432,27 @@
             Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                     .getDefaultDisplay();
             if (d.getWidth() > d.getHeight()) {
-                mPortraitRotation = Surface.ROTATION_90;
                 mLandscapeRotation = Surface.ROTATION_0;
-                mUpsideDownRotation = Surface.ROTATION_270;
                 mSeascapeRotation = Surface.ROTATION_180;
+                if (mContext.getResources().getBoolean(
+                        com.android.internal.R.bool.config_reverseDefaultRotation)) {
+                    mPortraitRotation = Surface.ROTATION_90;
+                    mUpsideDownRotation = Surface.ROTATION_270;
+                } else {
+                    mPortraitRotation = Surface.ROTATION_270;
+                    mUpsideDownRotation = Surface.ROTATION_90;
+                }
             } else {
                 mPortraitRotation = Surface.ROTATION_0;
-                mLandscapeRotation = Surface.ROTATION_90;
                 mUpsideDownRotation = Surface.ROTATION_180;
-                mSeascapeRotation = Surface.ROTATION_270;
+                if (mContext.getResources().getBoolean(
+                        com.android.internal.R.bool.config_reverseDefaultRotation)) {
+                    mLandscapeRotation = Surface.ROTATION_270;
+                    mSeascapeRotation = Surface.ROTATION_90;
+                } else {
+                    mLandscapeRotation = Surface.ROTATION_90;
+                    mSeascapeRotation = Surface.ROTATION_270;
+                }
             }
         }
 
@@ -2401,7 +2485,9 @@
             // case for nosensor meaning ignore sensor and consider only lid
             // or orientation sensor disabled
             //or case.unspecified
-            if (mLidOpen) {
+            if (mHdmiPlugged) {
+                return Surface.ROTATION_0;
+            } else if (mLidOpen == LID_OPEN) {
                 return mLidOpenRotation;
             } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
                 return mCarDockRotation;
@@ -2478,7 +2564,9 @@
             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);
@@ -2567,9 +2655,11 @@
     }
 
     void updateRotation(int animFlags) {
-        mPowerManager.setKeyboardVisibility(mLidOpen);
+        mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN);
         int rotation = Surface.ROTATION_0;
-        if (mLidOpen) {
+        if (mHdmiPlugged) {
+            rotation = Surface.ROTATION_0;
+        } else if (mLidOpen == LID_OPEN) {
             rotation = mLidOpenRotation;
         } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
             rotation = mCarDockRotation;
@@ -2736,4 +2826,70 @@
         // disable key repeat when screen is off
         return mScreenOn;
     }
+
+    public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
+                pw.print(" mSystemRead="); pw.println(mSystemReady);
+        pw.print(prefix); pw.print("mLidOpen="); pw.print(mLidOpen);
+                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
+                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
+        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
+                pw.print(" mDockMode="); pw.print(mDockMode);
+                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
+                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
+        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
+                pw.print(" mUserRotation="); pw.print(mUserRotation);
+                pw.print("mAllowAllRotations="); pw.println(mAllowAllRotations);
+        pw.print(prefix); pw.print("mAccelerometerDefault="); pw.print(mAccelerometerDefault);
+                pw.print(" mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
+        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
+                pw.print(mCarDockEnablesAccelerometer);
+                pw.print(" mDeskDockEnablesAccelerometer=");
+                pw.println(mDeskDockEnablesAccelerometer);
+        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
+                pw.print(mLidKeyboardAccessibility);
+                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
+                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
+        pw.print(prefix); pw.print("mScreenOn="); pw.print(mScreenOn);
+                pw.print(" mOrientationSensorEnabled="); pw.print(mOrientationSensorEnabled);
+                pw.print(" mHasSoftInput="); pw.println(mHasSoftInput);
+        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
+                pw.print(","); pw.print(mUnrestrictedScreenTop);
+                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
+                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
+        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
+                pw.print(","); pw.print(mRestrictedScreenTop);
+                pw.print(") "); pw.print(mRestrictedScreenWidth);
+                pw.print("x"); pw.println(mRestrictedScreenHeight);
+        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
+                pw.print(","); pw.print(mCurTop);
+                pw.print(")-("); pw.print(mCurRight);
+                pw.print(","); pw.print(mCurBottom); pw.println(")");
+        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
+                pw.print(","); pw.print(mContentTop);
+                pw.print(")-("); pw.print(mContentRight);
+                pw.print(","); pw.print(mContentBottom); pw.println(")");
+        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
+                pw.print(","); pw.print(mDockTop);
+                pw.print(")-("); pw.print(mDockRight);
+                pw.print(","); pw.print(mDockBottom); pw.println(")");
+        pw.print(prefix); pw.print("mDockLayer="); pw.println(mDockLayer);
+        pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
+                pw.println(mTopFullscreenOpaqueWindowState);
+        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
+                pw.print(" mForceStatusBar="); pw.print(mForceStatusBar);
+                pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
+        pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
+                pw.print(" mHomePressed="); pw.println(mHomePressed);
+        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
+                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
+                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
+        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
+                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
+                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
+        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
+                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
+        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
+                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/StatusView.java b/policy/src/com/android/internal/policy/impl/StatusView.java
index 2b78851..1caf0b7 100644
--- a/policy/src/com/android/internal/policy/impl/StatusView.java
+++ b/policy/src/com/android/internal/policy/impl/StatusView.java
@@ -19,6 +19,11 @@
 import android.widget.TextView;
 
 class StatusView {
+    private static final int LOCK_ICON = R.drawable.ic_lock_idle_lock;
+    private static final int ALARM_ICON = R.drawable.ic_lock_idle_alarm;
+    private static final int CHARGING_ICON = R.drawable.ic_lock_idle_charging;
+    private static final int BATTERY_LOW_ICON = R.drawable.ic_lock_idle_low_battery;
+
     private String mDateFormatString;
 
     private TextView mCarrier;
@@ -33,20 +38,18 @@
     // last known battery level
     private int mBatteryLevel = 100;
 
-    private String mNextAlarm = null;
-
     private String mInstructions = null;
     private TextView mStatus1;
-    private TextView mStatus2;
     private TextView mPropertyOf;
 
-    private boolean mHasStatus2;
     private boolean mHasCarrier;
     private boolean mHasDate;
-    private boolean mHasProperty;
 
     private View mView;
 
+    private TextView mAlarmStatus;
+    private LockPatternUtils mLockPatternUtils;
+
     private View findViewById(int id) {
         return mView.findViewById(id);
     }
@@ -69,7 +72,7 @@
         mShowingBatteryInfo = showBatteryInfo;
         mPluggedIn = pluggedIn;
         mBatteryLevel = batteryLevel;
-        updateStatusLines();
+        updateStatusLines(true);
     }
 
     void onTimeChanged() {
@@ -91,14 +94,14 @@
         mDate = (TextView) findViewById(R.id.date);
         mHasDate = (mDate != null);
         mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);
+        mLockPatternUtils = lockPatternUtils;
 
         refreshTimeAndDateDisplay();
 
         mStatus1 = (TextView) findViewById(R.id.status1);
-        mStatus2 = (TextView) findViewById(R.id.status2);
-        mHasStatus2 = (mStatus2 != null);
+        mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
+        mAlarmStatus.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
         mPropertyOf = (TextView) findViewById(R.id.propertyOf);
-        mHasProperty = (mPropertyOf != null);
 
         resetStatusInfo(updateMonitor, lockPatternUtils);
 
@@ -107,7 +110,6 @@
             mCarrier.setSelected(true);
             mCarrier.setTextColor(0xffffffff);
         }
-
     }
 
     void resetStatusInfo(KeyguardUpdateMonitor updateMonitor, LockPatternUtils lockPatternUtils) {
@@ -115,19 +117,18 @@
         mShowingBatteryInfo = updateMonitor.shouldShowBatteryInfo();
         mPluggedIn = updateMonitor.isDevicePluggedIn();
         mBatteryLevel = updateMonitor.getBatteryLevel();
-        mNextAlarm = lockPatternUtils.getNextAlarm();
-        updateStatusLines();
+        updateStatusLines(true);
     }
 
     void setInstructionText(int stringId) {
         mStatus1.setText(stringId);
-        mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_lock, 0, 0, 0);
+        mStatus1.setCompoundDrawablesWithIntrinsicBounds(LOCK_ICON, 0, 0, 0);
         mStatus1.setVisibility(View.VISIBLE);
     }
 
     void setInstructionText(String string) {
         mStatus1.setText(string);
-        mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_lock, 0, 0, 0);
+        mStatus1.setCompoundDrawablesWithIntrinsicBounds(LOCK_ICON, 0, 0, 0);
         mStatus1.setVisibility(View.VISIBLE);
     }
 
@@ -138,9 +139,22 @@
         mCarrier.setText(string);
     }
 
-    /** Originated from PatternUnlockScreen **/
-    void updateStatusLines() {
-        if (mHasProperty) {
+    /**
+     * Update the status lines based on these rules:
+     * AlarmStatus: Alarm state always gets it's own line.
+     * Status1 is shared between help, battery status and generic unlock instructions,
+     * prioritized in that order.
+     * @param showStatusLines status lines are shown if true
+     */
+    void updateStatusLines(boolean showStatusLines) {
+        if (!showStatusLines) {
+            mStatus1.setVisibility(showStatusLines ? View.VISIBLE : View.GONE);
+            mAlarmStatus.setVisibility(showStatusLines ? View.VISIBLE : View.GONE);
+            return;
+        }
+
+        // Update owner info
+        if (mPropertyOf != null) {
             ContentResolver res = getContext().getContentResolver();
             String info = Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO);
             boolean enabled = Settings.Secure.getInt(res,
@@ -151,104 +165,44 @@
                     View.VISIBLE : View.INVISIBLE);
         }
 
-        if (!mHasStatus2) return;
+        // Update Alarm status
+        String nextAlarm = mLockPatternUtils.getNextAlarm();
+        if (!TextUtils.isEmpty(nextAlarm)) {
+            mAlarmStatus.setText(nextAlarm);
+            mAlarmStatus.setVisibility(View.VISIBLE);
+        } else {
+            mAlarmStatus.setVisibility(View.GONE);
+        }
 
+        // Update Status1
         if (mInstructions != null) {
-            // instructions only
+            // Instructions only
+            final int resId = TextUtils.isEmpty(mInstructions) ? 0 : LOCK_ICON;
             mStatus1.setText(mInstructions);
-            if (TextUtils.isEmpty(mInstructions)) {
-                mStatus1.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
-            } else {
-                mStatus1.setCompoundDrawablesWithIntrinsicBounds(
-                        R.drawable.ic_lock_idle_lock, 0, 0, 0);
-            }
-
+            mStatus1.setCompoundDrawablesWithIntrinsicBounds(resId, 0, 0, 0);
             mStatus1.setVisibility(View.VISIBLE);
-            mStatus2.setVisibility(View.INVISIBLE);
-        } else if (mShowingBatteryInfo && mNextAlarm == null) {
-            // battery only
+        } else if (mShowingBatteryInfo) {
+            // Battery status
             if (mPluggedIn) {
-              if (mBatteryLevel >= 100) {
-                mStatus1.setText(getContext().getString(R.string.lockscreen_charged));
-              } else {
-                  mStatus1.setText(getContext().getString(R.string.lockscreen_plugged_in,
-                          mBatteryLevel));
-              }
+                // Charging or charged
+                if (mBatteryLevel >= 100) {
+                    mStatus1.setText(getContext().getString(R.string.lockscreen_charged));
+                } else {
+                    mStatus1.setText(getContext().getString(R.string.lockscreen_plugged_in,
+                            mBatteryLevel));
+                }
+                mStatus1.setCompoundDrawablesWithIntrinsicBounds(CHARGING_ICON, 0, 0, 0);
             } else {
+                // Battery is low
                 mStatus1.setText(getContext().getString(R.string.lockscreen_low_battery));
+                mStatus1.setCompoundDrawablesWithIntrinsicBounds(BATTERY_LOW_ICON, 0, 0, 0);
             }
-            mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_charging, 0,
-                    0, 0);
-
             mStatus1.setVisibility(View.VISIBLE);
-            mStatus2.setVisibility(View.INVISIBLE);
-
-        } else if (mNextAlarm != null && !mShowingBatteryInfo) {
-            // alarm only
-            mStatus1.setText(mNextAlarm);
-            mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_alarm, 0,
-                    0, 0);
-
-            mStatus1.setVisibility(View.VISIBLE);
-            mStatus2.setVisibility(View.INVISIBLE);
-        } else if (mNextAlarm != null && mShowingBatteryInfo) {
-            // both battery and next alarm
-            mStatus1.setText(mNextAlarm);
-            mStatus2.setText(getContext().getString(
-                    R.string.lockscreen_battery_short,
-                    Math.min(100, mBatteryLevel)));
-            mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_alarm, 0,
-                    0, 0);
-            if (mPluggedIn) {
-                mStatus2.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_charging,
-                        0, 0, 0);
-            } else {
-                mStatus2.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
-            }
-
-            mStatus1.setVisibility(View.VISIBLE);
-            mStatus2.setVisibility(View.VISIBLE);
         } else {
             // nothing specific to show; show general instructions
             mStatus1.setText(R.string.lockscreen_pattern_instructions);
-            mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_lock, 0,
-                    0, 0);
-
+            mStatus1.setCompoundDrawablesWithIntrinsicBounds(LOCK_ICON, 0,0, 0);
             mStatus1.setVisibility(View.VISIBLE);
-            mStatus2.setVisibility(View.INVISIBLE);
-        }
-    }
-
-    /** Originated from LockScreen **/
-    // TODO Merge with function above
-    void updateStatusLines(boolean showStatusLines, String charging, Drawable chargingIcon,
-            Drawable alarmIcon) {
-        if (!showStatusLines || (charging == null && mNextAlarm == null)) {
-            mStatus1.setVisibility(View.INVISIBLE);
-            mStatus2.setVisibility(View.INVISIBLE);
-        } else if (charging != null && mNextAlarm == null) {
-            // charging only
-            mStatus1.setVisibility(View.VISIBLE);
-            mStatus2.setVisibility(View.INVISIBLE);
-
-            mStatus1.setText(charging);
-            mStatus1.setCompoundDrawablesWithIntrinsicBounds(chargingIcon, null, null, null);
-        } else if (mNextAlarm != null && charging == null) {
-            // next alarm only
-            mStatus1.setVisibility(View.VISIBLE);
-            mStatus2.setVisibility(View.INVISIBLE);
-
-            mStatus1.setText(mNextAlarm);
-            mStatus1.setCompoundDrawablesWithIntrinsicBounds(alarmIcon, null, null, null);
-        } else if (charging != null && mNextAlarm != null) {
-            // both charging and next alarm
-            mStatus1.setVisibility(View.VISIBLE);
-            mStatus2.setVisibility(View.VISIBLE);
-
-            mStatus1.setText(charging);
-            mStatus1.setCompoundDrawablesWithIntrinsicBounds(chargingIcon, null, null, null);
-            mStatus2.setText(mNextAlarm);
-            mStatus2.setCompoundDrawablesWithIntrinsicBounds(alarmIcon, null, null, null);
         }
     }
 
diff --git a/services/audioflinger/A2dpAudioInterface.cpp b/services/audioflinger/A2dpAudioInterface.cpp
index aee01ab..d926cb1 100644
--- a/services/audioflinger/A2dpAudioInterface.cpp
+++ b/services/audioflinger/A2dpAudioInterface.cpp
@@ -260,6 +260,7 @@
     if (pRate) *pRate = lRate;
 
     mDevice = device;
+    mBufferDurationUs = ((bufferSize() * 1000 )/ frameSize() / sampleRate()) * 1000;
     return NO_ERROR;
 }
 
@@ -288,6 +289,7 @@
         if (mStandby) {
             acquire_wake_lock (PARTIAL_WAKE_LOCK, sA2dpWakeLock);
             mStandby = false;
+            mLastWriteTime = systemTime();
         }
 
         status = init();
@@ -308,6 +310,15 @@
             buffer = (char *)buffer + status;
         }
 
+        // if A2DP sink runs abnormally fast, sleep a little so that audioflinger mixer thread
+        // does no spin and starve other threads.
+        // NOTE: It is likely that the A2DP headset is being disconnected
+        nsecs_t now = systemTime();
+        if ((uint32_t)ns2us(now - mLastWriteTime) < (mBufferDurationUs >> 2)) {
+            LOGV("A2DP sink runs too fast");
+            usleep(mBufferDurationUs - (uint32_t)ns2us(now - mLastWriteTime));
+        }
+        mLastWriteTime = now;
         return bytes;
 
     }
@@ -316,7 +327,7 @@
     standby();
 
     // Simulate audio output timing in case of error
-    usleep(((bytes * 1000 )/ frameSize() / sampleRate()) * 1000);
+    usleep(mBufferDurationUs);
 
     return status;
 }
diff --git a/services/audioflinger/A2dpAudioInterface.h b/services/audioflinger/A2dpAudioInterface.h
index cef1926..dbe2c6a 100644
--- a/services/audioflinger/A2dpAudioInterface.h
+++ b/services/audioflinger/A2dpAudioInterface.h
@@ -117,6 +117,8 @@
                 uint32_t    mDevice;
                 bool        mClosing;
                 bool        mSuspended;
+                nsecs_t     mLastWriteTime;
+                uint32_t    mBufferDurationUs;
     };
 
     friend class A2dpAudioStreamOut;
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index 5b9273d..eeca7ab 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -1587,6 +1587,10 @@
             if (device) break;
             device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
             if (device) break;
+            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
+            if (device) break;
+            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
+            if (device) break;
             device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
             if (device) break;
 #ifdef WITH_A2DP
@@ -1605,10 +1609,12 @@
             break;
 
         case AudioSystem::FORCE_SPEAKER:
-            if (!isInCall() || strategy != STRATEGY_DTMF) {
-                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
-                if (device) break;
-            }
+            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
+            if (device) break;
+            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
+            if (device) break;
+            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
+            if (device) break;
 #ifdef WITH_A2DP
             // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
             // A2DP speaker when forcing to speaker output
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 87975af..b52fc69 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -49,7 +49,8 @@
     libcutils \
     libmedia \
     libcamera_client \
-    libsurfaceflinger_client
+    libsurfaceflinger_client \
+    libgui
 
 LOCAL_MODULE:= libcameraservice
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 15f6a44..3d8ca7a 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -27,6 +27,7 @@
 #include <binder/MemoryHeapBase.h>
 #include <cutils/atomic.h>
 #include <cutils/properties.h>
+#include <gui/SurfaceTextureClient.h>
 #include <hardware/hardware.h>
 #include <media/AudioSystem.h>
 #include <media/mediaplayer.h>
@@ -306,6 +307,8 @@
     mCameraFacing = cameraFacing;
     mClientPid = clientPid;
     mMsgEnabled = 0;
+    mSurface = 0;
+    mPreviewWindow = 0;
     mHardware->setCallbacks(notifyCallback,
                             dataCallback,
                             dataCallbackTimestamp,
@@ -470,19 +473,16 @@
 
     // return if no change in surface.
     // asBinder() is safe on NULL (returns NULL)
-    if (getISurface(surface)->asBinder() == mSurface->asBinder()) {
+    if (getISurface(surface)->asBinder() == mSurface) {
         return result;
     }
 
     if (mSurface != 0) {
         LOG1("clearing old preview surface %p", mSurface.get());
     }
-    if (surface != 0) {
-        mSurface = getISurface(surface);
-    } else {
-        mSurface = 0;
-    }
+    mSurface = getISurface(surface)->asBinder();
     mPreviewWindow = surface;
+
     // If preview has been already started, register preview
     // buffers now.
     if (mHardware->previewEnabled()) {
@@ -496,6 +496,45 @@
     return result;
 }
 
+// set the SurfaceTexture that the preview will use
+status_t CameraService::Client::setPreviewTexture(
+        const sp<ISurfaceTexture>& surfaceTexture) {
+    LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(),
+            getCallingPid());
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    // return if no change in surface.
+    // asBinder() is safe on NULL (returns NULL)
+    if (surfaceTexture->asBinder() == mSurface) {
+        return result;
+    }
+
+    if (mSurface != 0) {
+        LOG1("clearing old preview surface %p", mSurface.get());
+    }
+    mSurface = surfaceTexture->asBinder();
+    if (surfaceTexture != 0) {
+        mPreviewWindow = new SurfaceTextureClient(surfaceTexture);
+    } else {
+        mPreviewWindow = 0;
+    }
+
+    // If preview has been already started, set overlay or register preview
+    // buffers now.
+    if (mHardware->previewEnabled()) {
+        // XXX: What if the new preview window is 0?
+        if (mPreviewWindow != 0) {
+            native_window_set_buffers_transform(mPreviewWindow.get(),
+                                                mOrientation);
+            result = mHardware->setPreviewWindow(mPreviewWindow);
+        }
+    }
+
+    return result;
+}
+
 // set the preview callback flag to affect how the received frames from
 // preview are handled.
 void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
@@ -960,23 +999,6 @@
     }
     disableMsgType(CAMERA_MSG_SHUTTER);
 
-    // It takes some time before yuvPicture callback to be called.
-    // Register the buffer for raw image here to reduce latency.
-    if (mSurface != 0) {
-        int w, h;
-        CameraParameters params(mHardware->getParameters());
-        if (size == NULL) {
-            params.getPictureSize(&w, &h);
-        } else {
-            w = size->width;
-            h = size->height;
-            w &= ~1;
-            h &= ~1;
-            LOG1("Snapshot image width=%d, height=%d", w, h);
-        }
-        IPCThreadState::self()->flushCommands();
-    }
-
     mLock.unlock();
 }
 
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d78d7e5..ccb9cf7 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -94,6 +94,7 @@
         virtual status_t        lock();
         virtual status_t        unlock();
         virtual status_t        setPreviewDisplay(const sp<Surface>& surface);
+        virtual status_t        setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture);
         virtual void            setPreviewCallbackFlag(int flag);
         virtual status_t        startPreview();
         virtual void            stopPreview();
@@ -180,7 +181,8 @@
 
         // Ensures atomicity among the public methods
         mutable Mutex                   mLock;
-        sp<ISurface>                    mSurface;
+        // This is a binder of Surface or SurfaceTexture.
+        sp<IBinder>                     mSurface;
         sp<ANativeWindow>               mPreviewWindow;
 
         // If the user want us to return a copy of the preview frame (instead
diff --git a/services/input/Android.mk b/services/input/Android.mk
new file mode 100644
index 0000000..d7b61fc
--- /dev/null
+++ b/services/input/Android.mk
@@ -0,0 +1,57 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+    EventHub.cpp \
+    InputDispatcher.cpp \
+    InputManager.cpp \
+    InputReader.cpp \
+    InputWindow.cpp \
+    PointerController.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libutils \
+    libhardware \
+    libhardware_legacy \
+    libsurfaceflinger_client \
+    libskia \
+    libui
+
+LOCAL_C_INCLUDES := \
+    external/skia/include/core
+
+LOCAL_MODULE:= libinput
+
+LOCAL_MODULE_TAGS := optional
+
+ifeq ($(TARGET_SIMULATOR),true)
+    LOCAL_LDLIBS += -lpthread
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+
+
+# Include subdirectory makefiles
+# ============================================================
+
+# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
+# team really wants is to build the stuff defined by this makefile.
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
new file mode 100644
index 0000000..487e73f
--- /dev/null
+++ b/services/input/EventHub.cpp
@@ -0,0 +1,1095 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// Handle events, like key input and vsync.
+//
+// The goal is to provide an optimized solution for Linux, not an
+// implementation that works well across all platforms.  We expect
+// events to arrive on file descriptors, so that we can use a select()
+// select() call to sleep.
+//
+// We can't select() on anything but network sockets in Windows, so we
+// provide an alternative implementation of waitEvent for that platform.
+//
+#define LOG_TAG "EventHub"
+
+//#define LOG_NDEBUG 0
+
+#include "EventHub.h"
+
+#include <hardware_legacy/power.h>
+
+#include <cutils/properties.h>
+#include <utils/Log.h>
+#include <utils/Timers.h>
+#include <utils/threads.h>
+#include <utils/Errors.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <memory.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <ui/KeyLayoutMap.h>
+#include <ui/KeyCharacterMap.h>
+#include <ui/VirtualKeyMap.h>
+
+#include <string.h>
+#include <stdint.h>
+#include <dirent.h>
+#ifdef HAVE_INOTIFY
+# include <sys/inotify.h>
+#endif
+#ifdef HAVE_ANDROID_OS
+# include <sys/limits.h>        /* not part of Linux */
+#endif
+#include <sys/poll.h>
+#include <sys/ioctl.h>
+
+/* this macro is used to tell if "bit" is set in "array"
+ * it selects a byte from the array, and does a boolean AND
+ * operation with a byte that only has the relevant bit set.
+ * eg. to check for the 12th bit, we do (array[1] & 1<<4)
+ */
+#define test_bit(bit, array)    (array[bit/8] & (1<<(bit%8)))
+
+/* this macro computes the number of bytes needed to represent a bit array of the specified size */
+#define sizeof_bit_array(bits)  ((bits + 7) / 8)
+
+// Fd at index 0 is always reserved for inotify
+#define FIRST_ACTUAL_DEVICE_INDEX 1
+
+#define INDENT "  "
+#define INDENT2 "    "
+#define INDENT3 "      "
+
+namespace android {
+
+static const char *WAKE_LOCK_ID = "KeyEvents";
+static const char *DEVICE_PATH = "/dev/input";
+
+/* return the larger integer */
+static inline int max(int v1, int v2)
+{
+    return (v1 > v2) ? v1 : v2;
+}
+
+static inline const char* toString(bool value) {
+    return value ? "true" : "false";
+}
+
+// --- EventHub::Device ---
+
+EventHub::Device::Device(int fd, int32_t id, const String8& path,
+        const InputDeviceIdentifier& identifier) :
+        next(NULL),
+        fd(fd), id(id), path(path), identifier(identifier),
+        classes(0), keyBitmask(NULL), configuration(NULL), virtualKeyMap(NULL) {
+}
+
+EventHub::Device::~Device() {
+    close();
+    delete[] keyBitmask;
+    delete configuration;
+    delete virtualKeyMap;
+}
+
+void EventHub::Device::close() {
+    if (fd >= 0) {
+        ::close(fd);
+        fd = -1;
+    }
+}
+
+
+// --- EventHub ---
+
+EventHub::EventHub(void) :
+        mError(NO_INIT), mBuiltInKeyboardId(-1), mNextDeviceId(1),
+        mOpeningDevices(0), mClosingDevices(0),
+        mOpened(false), mNeedToSendFinishedDeviceScan(false),
+        mInputBufferIndex(0), mInputBufferCount(0), mInputFdIndex(0) {
+    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
+#ifdef EV_SW
+    memset(mSwitches, 0, sizeof(mSwitches));
+#endif
+}
+
+EventHub::~EventHub(void) {
+    release_wake_lock(WAKE_LOCK_ID);
+    // we should free stuff here...
+}
+
+status_t EventHub::errorCheck() const {
+    return mError;
+}
+
+String8 EventHub::getDeviceName(int32_t deviceId) const {
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device == NULL) return String8();
+    return device->identifier.name;
+}
+
+uint32_t EventHub::getDeviceClasses(int32_t deviceId) const {
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device == NULL) return 0;
+    return device->classes;
+}
+
+void EventHub::getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device && device->configuration) {
+        *outConfiguration = *device->configuration;
+    } else {
+        outConfiguration->clear();
+    }
+}
+
+status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
+        RawAbsoluteAxisInfo* outAxisInfo) const {
+    outAxisInfo->clear();
+
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device == NULL) return -1;
+
+    struct input_absinfo info;
+
+    if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
+        LOGW("Error reading absolute controller %d for device %s fd %d\n",
+             axis, device->identifier.name.string(), device->fd);
+        return -errno;
+    }
+
+    if (info.minimum != info.maximum) {
+        outAxisInfo->valid = true;
+        outAxisInfo->minValue = info.minimum;
+        outAxisInfo->maxValue = info.maximum;
+        outAxisInfo->flat = info.flat;
+        outAxisInfo->fuzz = info.fuzz;
+    }
+    return OK;
+}
+
+int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
+    if (scanCode >= 0 && scanCode <= KEY_MAX) {
+        AutoMutex _l(mLock);
+
+        Device* device = getDeviceLocked(deviceId);
+        if (device != NULL) {
+            return getScanCodeStateLocked(device, scanCode);
+        }
+    }
+    return AKEY_STATE_UNKNOWN;
+}
+
+int32_t EventHub::getScanCodeStateLocked(Device* device, int32_t scanCode) const {
+    uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
+    memset(key_bitmask, 0, sizeof(key_bitmask));
+    if (ioctl(device->fd,
+               EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
+        return test_bit(scanCode, key_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
+    }
+    return AKEY_STATE_UNKNOWN;
+}
+
+int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
+    AutoMutex _l(mLock);
+
+    Device* device = getDeviceLocked(deviceId);
+    if (device != NULL) {
+        return getKeyCodeStateLocked(device, keyCode);
+    }
+    return AKEY_STATE_UNKNOWN;
+}
+
+int32_t EventHub::getKeyCodeStateLocked(Device* device, int32_t keyCode) const {
+    if (!device->keyMap.haveKeyLayout()) {
+        return AKEY_STATE_UNKNOWN;
+    }
+
+    Vector<int32_t> scanCodes;
+    device->keyMap.keyLayoutMap->findScanCodes(keyCode, &scanCodes);
+
+    uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
+    memset(key_bitmask, 0, sizeof(key_bitmask));
+    if (ioctl(device->fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
+        #if 0
+        for (size_t i=0; i<=KEY_MAX; i++) {
+            LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask));
+        }
+        #endif
+        const size_t N = scanCodes.size();
+        for (size_t i=0; i<N && i<=KEY_MAX; i++) {
+            int32_t sc = scanCodes.itemAt(i);
+            //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask));
+            if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) {
+                return AKEY_STATE_DOWN;
+            }
+        }
+        return AKEY_STATE_UP;
+    }
+    return AKEY_STATE_UNKNOWN;
+}
+
+int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
+#ifdef EV_SW
+    if (sw >= 0 && sw <= SW_MAX) {
+        AutoMutex _l(mLock);
+
+        Device* device = getDeviceLocked(deviceId);
+        if (device != NULL) {
+            return getSwitchStateLocked(device, sw);
+        }
+    }
+#endif
+    return AKEY_STATE_UNKNOWN;
+}
+
+int32_t EventHub::getSwitchStateLocked(Device* device, int32_t sw) const {
+    uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
+    memset(sw_bitmask, 0, sizeof(sw_bitmask));
+    if (ioctl(device->fd,
+               EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
+        return test_bit(sw, sw_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
+    }
+    return AKEY_STATE_UNKNOWN;
+}
+
+bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
+        const int32_t* keyCodes, uint8_t* outFlags) const {
+    AutoMutex _l(mLock);
+
+    Device* device = getDeviceLocked(deviceId);
+    if (device != NULL) {
+        return markSupportedKeyCodesLocked(device, numCodes, keyCodes, outFlags);
+    }
+    return false;
+}
+
+bool EventHub::markSupportedKeyCodesLocked(Device* device, size_t numCodes,
+        const int32_t* keyCodes, uint8_t* outFlags) const {
+    if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
+        return false;
+    }
+
+    Vector<int32_t> scanCodes;
+    for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
+        scanCodes.clear();
+
+        status_t err = device->keyMap.keyLayoutMap->findScanCodes(keyCodes[codeIndex], &scanCodes);
+        if (! err) {
+            // check the possible scan codes identified by the layout map against the
+            // map of codes actually emitted by the driver
+            for (size_t sc = 0; sc < scanCodes.size(); sc++) {
+                if (test_bit(scanCodes[sc], device->keyBitmask)) {
+                    outFlags[codeIndex] = 1;
+                    break;
+                }
+            }
+        }
+    }
+    return true;
+}
+
+status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
+        int32_t* outKeycode, uint32_t* outFlags) const
+{
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    
+    if (device && device->keyMap.haveKeyLayout()) {
+        status_t err = device->keyMap.keyLayoutMap->map(scancode, outKeycode, outFlags);
+        if (err == NO_ERROR) {
+            return NO_ERROR;
+        }
+    }
+    
+    if (mBuiltInKeyboardId != -1) {
+        device = getDeviceLocked(mBuiltInKeyboardId);
+        
+        if (device && device->keyMap.haveKeyLayout()) {
+            status_t err = device->keyMap.keyLayoutMap->map(scancode, outKeycode, outFlags);
+            if (err == NO_ERROR) {
+                return NO_ERROR;
+            }
+        }
+    }
+    
+    *outKeycode = 0;
+    *outFlags = 0;
+    return NAME_NOT_FOUND;
+}
+
+void EventHub::addExcludedDevice(const char* deviceName)
+{
+    AutoMutex _l(mLock);
+
+    String8 name(deviceName);
+    mExcludedDevices.push_back(name);
+}
+
+bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device) {
+        uint8_t bitmask[sizeof_bit_array(LED_MAX + 1)];
+        memset(bitmask, 0, sizeof(bitmask));
+        if (ioctl(device->fd, EVIOCGBIT(EV_LED, sizeof(bitmask)), bitmask) >= 0) {
+            if (test_bit(led, bitmask)) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device) {
+        struct input_event ev;
+        ev.time.tv_sec = 0;
+        ev.time.tv_usec = 0;
+        ev.type = EV_LED;
+        ev.code = led;
+        ev.value = on ? 1 : 0;
+
+        ssize_t nWrite;
+        do {
+            nWrite = write(device->fd, &ev, sizeof(struct input_event));
+        } while (nWrite == -1 && errno == EINTR);
+    }
+}
+
+void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
+        Vector<VirtualKeyDefinition>& outVirtualKeys) const {
+    outVirtualKeys.clear();
+
+    AutoMutex _l(mLock);
+    Device* device = getDeviceLocked(deviceId);
+    if (device && device->virtualKeyMap) {
+        outVirtualKeys.appendVector(device->virtualKeyMap->getVirtualKeys());
+    }
+}
+
+EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
+    if (deviceId == 0) {
+        deviceId = mBuiltInKeyboardId;
+    }
+
+    size_t numDevices = mDevices.size();
+    for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < numDevices; i++) {
+        Device* device = mDevices[i];
+        if (device->id == deviceId) {
+            return device;
+        }
+    }
+    return NULL;
+}
+
+bool EventHub::getEvent(RawEvent* outEvent) {
+    outEvent->deviceId = 0;
+    outEvent->type = 0;
+    outEvent->scanCode = 0;
+    outEvent->keyCode = 0;
+    outEvent->flags = 0;
+    outEvent->value = 0;
+    outEvent->when = 0;
+
+    // Note that we only allow one caller to getEvent(), so don't need
+    // to do locking here...  only when adding/removing devices.
+
+    if (!mOpened) {
+        mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
+        mOpened = true;
+        mNeedToSendFinishedDeviceScan = true;
+    }
+
+    for (;;) {
+        // Report any devices that had last been added/removed.
+        if (mClosingDevices != NULL) {
+            Device* device = mClosingDevices;
+            LOGV("Reporting device closed: id=%d, name=%s\n",
+                 device->id, device->path.string());
+            mClosingDevices = device->next;
+            if (device->id == mBuiltInKeyboardId) {
+                outEvent->deviceId = 0;
+            } else {
+                outEvent->deviceId = device->id;
+            }
+            outEvent->type = DEVICE_REMOVED;
+            outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
+            delete device;
+            mNeedToSendFinishedDeviceScan = true;
+            return true;
+        }
+
+        if (mOpeningDevices != NULL) {
+            Device* device = mOpeningDevices;
+            LOGV("Reporting device opened: id=%d, name=%s\n",
+                 device->id, device->path.string());
+            mOpeningDevices = device->next;
+            if (device->id == mBuiltInKeyboardId) {
+                outEvent->deviceId = 0;
+            } else {
+                outEvent->deviceId = device->id;
+            }
+            outEvent->type = DEVICE_ADDED;
+            outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
+            mNeedToSendFinishedDeviceScan = true;
+            return true;
+        }
+
+        if (mNeedToSendFinishedDeviceScan) {
+            mNeedToSendFinishedDeviceScan = false;
+            outEvent->type = FINISHED_DEVICE_SCAN;
+            outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
+            return true;
+        }
+
+        // Grab the next input event.
+        for (;;) {
+            // Consume buffered input events, if any.
+            if (mInputBufferIndex < mInputBufferCount) {
+                const struct input_event& iev = mInputBufferData[mInputBufferIndex++];
+                const Device* device = mDevices[mInputFdIndex];
+
+                LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d", device->path.string(),
+                     (int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value);
+                if (device->id == mBuiltInKeyboardId) {
+                    outEvent->deviceId = 0;
+                } else {
+                    outEvent->deviceId = device->id;
+                }
+                outEvent->type = iev.type;
+                outEvent->scanCode = iev.code;
+                outEvent->flags = 0;
+                if (iev.type == EV_KEY) {
+                    outEvent->keyCode = AKEYCODE_UNKNOWN;
+                    if (device->keyMap.haveKeyLayout()) {
+                        status_t err = device->keyMap.keyLayoutMap->map(iev.code,
+                                &outEvent->keyCode, &outEvent->flags);
+                        LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n",
+                                iev.code, outEvent->keyCode, outEvent->flags, err);
+                    }
+                } else {
+                    outEvent->keyCode = iev.code;
+                }
+                outEvent->value = iev.value;
+
+                // Use an event timestamp in the same timebase as
+                // java.lang.System.nanoTime() and android.os.SystemClock.uptimeMillis()
+                // as expected by the rest of the system.
+                outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
+                return true;
+            }
+
+            // Finish reading all events from devices identified in previous poll().
+            // This code assumes that mInputDeviceIndex is initially 0 and that the
+            // revents member of pollfd is initialized to 0 when the device is first added.
+            // Since mFds[0] is used for inotify, we process regular events starting at index 1.
+            mInputFdIndex += 1;
+            if (mInputFdIndex >= mFds.size()) {
+                break;
+            }
+
+            const struct pollfd& pfd = mFds[mInputFdIndex];
+            if (pfd.revents & POLLIN) {
+                int32_t readSize = read(pfd.fd, mInputBufferData,
+                        sizeof(struct input_event) * INPUT_BUFFER_SIZE);
+                if (readSize < 0) {
+                    if (errno != EAGAIN && errno != EINTR) {
+                        LOGW("could not get event (errno=%d)", errno);
+                    }
+                } else if ((readSize % sizeof(struct input_event)) != 0) {
+                    LOGE("could not get event (wrong size: %d)", readSize);
+                } else {
+                    mInputBufferCount = size_t(readSize) / sizeof(struct input_event);
+                    mInputBufferIndex = 0;
+                }
+            }
+        }
+
+#if HAVE_INOTIFY
+        // readNotify() will modify mFDs and mFDCount, so this must be done after
+        // processing all other events.
+        if(mFds[0].revents & POLLIN) {
+            readNotify(mFds[0].fd);
+            mFds.editItemAt(0).revents = 0;
+            continue; // report added or removed devices immediately
+        }
+#endif
+
+        mInputFdIndex = 0;
+
+        // Poll for events.  Mind the wake lock dance!
+        // We hold a wake lock at all times except during poll().  This works due to some
+        // subtle choreography.  When a device driver has pending (unread) events, it acquires
+        // a kernel wake lock.  However, once the last pending event has been read, the device
+        // driver will release the kernel wake lock.  To prevent the system from going to sleep
+        // when this happens, the EventHub holds onto its own user wake lock while the client
+        // is processing events.  Thus the system can only sleep if there are no events
+        // pending or currently being processed.
+        release_wake_lock(WAKE_LOCK_ID);
+
+        int pollResult = poll(mFds.editArray(), mFds.size(), -1);
+
+        acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
+
+        if (pollResult <= 0) {
+            if (errno != EINTR) {
+                LOGW("poll failed (errno=%d)\n", errno);
+                usleep(100000);
+            }
+        }
+    }
+}
+
+/*
+ * Open the platform-specific input device.
+ */
+bool EventHub::openPlatformInput(void) {
+    /*
+     * Open platform-specific input device(s).
+     */
+    int res, fd;
+
+#ifdef HAVE_INOTIFY
+    fd = inotify_init();
+    res = inotify_add_watch(fd, DEVICE_PATH, IN_DELETE | IN_CREATE);
+    if(res < 0) {
+        LOGE("could not add watch for %s, %s\n", DEVICE_PATH, strerror(errno));
+    }
+#else
+    /*
+     * The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd.
+     * We allocate space for it and set it to something invalid.
+     */
+    fd = -1;
+#endif
+
+    // Reserve fd index 0 for inotify.
+    struct pollfd pollfd;
+    pollfd.fd = fd;
+    pollfd.events = POLLIN;
+    pollfd.revents = 0;
+    mFds.push(pollfd);
+    mDevices.push(NULL);
+
+    res = scanDir(DEVICE_PATH);
+    if(res < 0) {
+        LOGE("scan dir failed for %s\n", DEVICE_PATH);
+    }
+
+    return true;
+}
+
+// ----------------------------------------------------------------------------
+
+static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) {
+    const uint8_t* end = array + endIndex;
+    array += startIndex;
+    while (array != end) {
+        if (*(array++) != 0) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static const int32_t GAMEPAD_KEYCODES[] = {
+        AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C,
+        AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z,
+        AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1,
+        AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2,
+        AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR,
+        AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE
+};
+
+int EventHub::openDevice(const char *devicePath) {
+    char buffer[80];
+
+    LOGV("Opening device: %s", devicePath);
+
+    AutoMutex _l(mLock);
+
+    int fd = open(devicePath, O_RDWR);
+    if(fd < 0) {
+        LOGE("could not open %s, %s\n", devicePath, strerror(errno));
+        return -1;
+    }
+
+    InputDeviceIdentifier identifier;
+
+    // Get device name.
+    if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
+        //fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
+    } else {
+        buffer[sizeof(buffer) - 1] = '\0';
+        identifier.name.setTo(buffer);
+    }
+
+    // Check to see if the device is on our excluded list
+    List<String8>::iterator iter = mExcludedDevices.begin();
+    List<String8>::iterator end = mExcludedDevices.end();
+    for ( ; iter != end; iter++) {
+        const char* test = *iter;
+        if (identifier.name == test) {
+            LOGI("ignoring event id %s driver %s\n", devicePath, test);
+            close(fd);
+            return -1;
+        }
+    }
+
+    // Get device driver version.
+    int driverVersion;
+    if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
+        LOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
+        close(fd);
+        return -1;
+    }
+
+    // Get device identifier.
+    struct input_id inputId;
+    if(ioctl(fd, EVIOCGID, &inputId)) {
+        LOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
+        close(fd);
+        return -1;
+    }
+    identifier.bus = inputId.bustype;
+    identifier.product = inputId.product;
+    identifier.vendor = inputId.vendor;
+    identifier.version = inputId.version;
+
+    // Get device physical location.
+    if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
+        //fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
+    } else {
+        buffer[sizeof(buffer) - 1] = '\0';
+        identifier.location.setTo(buffer);
+    }
+
+    // Get device unique id.
+    if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
+        //fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
+    } else {
+        buffer[sizeof(buffer) - 1] = '\0';
+        identifier.uniqueId.setTo(buffer);
+    }
+
+    // Make file descriptor non-blocking for use with poll().
+    if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
+        LOGE("Error %d making device file descriptor non-blocking.", errno);
+        close(fd);
+        return -1;
+    }
+
+    // Allocate device.  (The device object takes ownership of the fd at this point.)
+    int32_t deviceId = mNextDeviceId++;
+    Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
+
+#if 0
+    LOGI("add device %d: %s\n", deviceId, devicePath);
+    LOGI("  bus:       %04x\n"
+         "  vendor     %04x\n"
+         "  product    %04x\n"
+         "  version    %04x\n",
+        identifier.bus, identifier.vendor, identifier.product, identifier.version);
+    LOGI("  name:      \"%s\"\n", identifier.name.string());
+    LOGI("  location:  \"%s\"\n", identifier.location.string());
+    LOGI("  unique id: \"%s\"\n", identifier.uniqueId.string());
+    LOGI("  driver:    v%d.%d.%d\n",
+        driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
+#endif
+
+    // Load the configuration file for the device.
+    loadConfiguration(device);
+
+    // Figure out the kinds of events the device reports.
+    
+    uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
+    memset(key_bitmask, 0, sizeof(key_bitmask));
+
+    LOGV("Getting keys...");
+    if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
+        //LOGI("MAP\n");
+        //for (int i = 0; i < sizeof(key_bitmask); i++) {
+        //    LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
+        //}
+
+        // See if this is a keyboard.  Ignore everything in the button range except for
+        // gamepads which are also considered keyboards.
+        if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
+                || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),
+                        sizeof_bit_array(BTN_DIGI))
+                || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
+                        sizeof_bit_array(KEY_MAX + 1))) {
+            device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
+
+            device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
+            if (device->keyBitmask != NULL) {
+                memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
+            } else {
+                delete device;
+                LOGE("out of memory allocating key bitmask");
+                return -1;
+            }
+        }
+    }
+    
+    // See if this is a cursor device such as a trackball or mouse.
+    if (test_bit(BTN_MOUSE, key_bitmask)) {
+        uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)];
+        memset(rel_bitmask, 0, sizeof(rel_bitmask));
+        LOGV("Getting relative controllers...");
+        if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) {
+            if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
+                device->classes |= INPUT_DEVICE_CLASS_CURSOR;
+            }
+        }
+    }
+
+    // See if this is a touch pad.
+    uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];
+    memset(abs_bitmask, 0, sizeof(abs_bitmask));
+    LOGV("Getting absolute controllers...");
+    if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {
+        // Is this a new modern multi-touch driver?
+        if (test_bit(ABS_MT_POSITION_X, abs_bitmask)
+                && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
+            device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT;
+
+        // Is this an old style single-touch driver?
+        } else if (test_bit(BTN_TOUCH, key_bitmask)
+                && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
+            device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN;
+        }
+    }
+
+#ifdef EV_SW
+    // figure out the switches this device reports
+    uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
+    memset(sw_bitmask, 0, sizeof(sw_bitmask));
+    bool hasSwitches = false;
+    if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
+        for (int i=0; i<EV_SW; i++) {
+            //LOGI("Device %d sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
+            if (test_bit(i, sw_bitmask)) {
+                hasSwitches = true;
+                if (mSwitches[i] == 0) {
+                    mSwitches[i] = device->id;
+                }
+            }
+        }
+    }
+    if (hasSwitches) {
+        device->classes |= INPUT_DEVICE_CLASS_SWITCH;
+    }
+#endif
+
+    if ((device->classes & INPUT_DEVICE_CLASS_TOUCHSCREEN)) {
+        // Load the virtual keys for the touch screen, if any.
+        // We do this now so that we can make sure to load the keymap if necessary.
+        status_t status = loadVirtualKeyMap(device);
+        if (!status) {
+            device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
+        }
+    }
+
+    if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
+        // Load the keymap for the device.
+        status_t status = loadKeyMap(device);
+
+        // Set system properties for the keyboard.
+        setKeyboardProperties(device, false);
+
+        // Register the keyboard as a built-in keyboard if it is eligible.
+        if (!status
+                && mBuiltInKeyboardId == -1
+                && isEligibleBuiltInKeyboard(device->identifier,
+                        device->configuration, &device->keyMap)) {
+            mBuiltInKeyboardId = device->id;
+            setKeyboardProperties(device, true);
+        }
+
+        // 'Q' key support = cheap test of whether this is an alpha-capable kbd
+        if (hasKeycodeLocked(device, AKEYCODE_Q)) {
+            device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
+        }
+
+        // See if this device has a DPAD.
+        if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
+                hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
+                hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
+                hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
+                hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
+            device->classes |= INPUT_DEVICE_CLASS_DPAD;
+        }
+
+        // See if this device has a gamepad.
+        for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
+            if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
+                device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
+                break;
+            }
+        }
+    }
+
+    // If the device isn't recognized as something we handle, don't monitor it.
+    if (device->classes == 0) {
+        LOGV("Dropping device: id=%d, path='%s', name='%s'",
+                deviceId, devicePath, device->identifier.name.string());
+        delete device;
+        return -1;
+    }
+
+    LOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
+            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s",
+         deviceId, fd, devicePath, device->identifier.name.string(),
+         device->classes,
+         device->configurationFile.string(),
+         device->keyMap.keyLayoutFile.string(),
+         device->keyMap.keyCharacterMapFile.string(),
+         toString(mBuiltInKeyboardId == deviceId));
+
+    struct pollfd pollfd;
+    pollfd.fd = fd;
+    pollfd.events = POLLIN;
+    pollfd.revents = 0;
+    mFds.push(pollfd);
+    mDevices.push(device);
+
+    device->next = mOpeningDevices;
+    mOpeningDevices = device;
+    return 0;
+}
+
+void EventHub::loadConfiguration(Device* device) {
+    device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
+            device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
+    if (device->configurationFile.isEmpty()) {
+        LOGD("No input device configuration file found for device '%s'.",
+                device->identifier.name.string());
+    } else {
+        status_t status = PropertyMap::load(device->configurationFile,
+                &device->configuration);
+        if (status) {
+            LOGE("Error loading input device configuration file for device '%s'.  "
+                    "Using default configuration.",
+                    device->identifier.name.string());
+        }
+    }
+}
+
+status_t EventHub::loadVirtualKeyMap(Device* device) {
+    // The virtual key map is supplied by the kernel as a system board property file.
+    String8 path;
+    path.append("/sys/board_properties/virtualkeys.");
+    path.append(device->identifier.name);
+    if (access(path.string(), R_OK)) {
+        return NAME_NOT_FOUND;
+    }
+    return VirtualKeyMap::load(path, &device->virtualKeyMap);
+}
+
+status_t EventHub::loadKeyMap(Device* device) {
+    return device->keyMap.load(device->identifier, device->configuration);
+}
+
+void EventHub::setKeyboardProperties(Device* device, bool builtInKeyboard) {
+    int32_t id = builtInKeyboard ? 0 : device->id;
+    android::setKeyboardProperties(id, device->identifier,
+            device->keyMap.keyLayoutFile, device->keyMap.keyCharacterMapFile);
+}
+
+void EventHub::clearKeyboardProperties(Device* device, bool builtInKeyboard) {
+    int32_t id = builtInKeyboard ? 0 : device->id;
+    android::clearKeyboardProperties(id);
+}
+
+bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
+    if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
+        return false;
+    }
+    
+    Vector<int32_t> scanCodes;
+    device->keyMap.keyLayoutMap->findScanCodes(keycode, &scanCodes);
+    const size_t N = scanCodes.size();
+    for (size_t i=0; i<N && i<=KEY_MAX; i++) {
+        int32_t sc = scanCodes.itemAt(i);
+        if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
+            return true;
+        }
+    }
+    
+    return false;
+}
+
+int EventHub::closeDevice(const char *devicePath) {
+    AutoMutex _l(mLock);
+
+    for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < mDevices.size(); i++) {
+        Device* device = mDevices[i];
+        if (device->path == devicePath) {
+            LOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x\n",
+                 device->path.string(), device->identifier.name.string(), device->id,
+                 device->fd, device->classes);
+
+#ifdef EV_SW
+            for (int j=0; j<EV_SW; j++) {
+                if (mSwitches[j] == device->id) {
+                    mSwitches[j] = 0;
+                }
+            }
+#endif
+
+            if (device->id == mBuiltInKeyboardId) {
+                LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
+                        device->path.string(), mBuiltInKeyboardId);
+                mBuiltInKeyboardId = -1;
+                clearKeyboardProperties(device, true);
+            }
+            clearKeyboardProperties(device, false);
+
+            mFds.removeAt(i);
+            mDevices.removeAt(i);
+            device->close();
+
+            device->next = mClosingDevices;
+            mClosingDevices = device;
+            return 0;
+        }
+    }
+    LOGE("remove device: %s not found\n", devicePath);
+    return -1;
+}
+
+int EventHub::readNotify(int nfd) {
+#ifdef HAVE_INOTIFY
+    int res;
+    char devname[PATH_MAX];
+    char *filename;
+    char event_buf[512];
+    int event_size;
+    int event_pos = 0;
+    struct inotify_event *event;
+
+    LOGV("EventHub::readNotify nfd: %d\n", nfd);
+    res = read(nfd, event_buf, sizeof(event_buf));
+    if(res < (int)sizeof(*event)) {
+        if(errno == EINTR)
+            return 0;
+        LOGW("could not get event, %s\n", strerror(errno));
+        return 1;
+    }
+    //printf("got %d bytes of event information\n", res);
+
+    strcpy(devname, DEVICE_PATH);
+    filename = devname + strlen(devname);
+    *filename++ = '/';
+
+    while(res >= (int)sizeof(*event)) {
+        event = (struct inotify_event *)(event_buf + event_pos);
+        //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
+        if(event->len) {
+            strcpy(filename, event->name);
+            if(event->mask & IN_CREATE) {
+                openDevice(devname);
+            }
+            else {
+                closeDevice(devname);
+            }
+        }
+        event_size = sizeof(*event) + event->len;
+        res -= event_size;
+        event_pos += event_size;
+    }
+#endif
+    return 0;
+}
+
+int EventHub::scanDir(const char *dirname)
+{
+    char devname[PATH_MAX];
+    char *filename;
+    DIR *dir;
+    struct dirent *de;
+    dir = opendir(dirname);
+    if(dir == NULL)
+        return -1;
+    strcpy(devname, dirname);
+    filename = devname + strlen(devname);
+    *filename++ = '/';
+    while((de = readdir(dir))) {
+        if(de->d_name[0] == '.' &&
+           (de->d_name[1] == '\0' ||
+            (de->d_name[1] == '.' && de->d_name[2] == '\0')))
+            continue;
+        strcpy(filename, de->d_name);
+        openDevice(devname);
+    }
+    closedir(dir);
+    return 0;
+}
+
+void EventHub::dump(String8& dump) {
+    dump.append("Event Hub State:\n");
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        dump.appendFormat(INDENT "BuiltInKeyboardId: %d\n", mBuiltInKeyboardId);
+
+        dump.append(INDENT "Devices:\n");
+
+        for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < mDevices.size(); i++) {
+            const Device* device = mDevices[i];
+            if (device) {
+                if (mBuiltInKeyboardId == device->id) {
+                    dump.appendFormat(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
+                            device->id, device->identifier.name.string());
+                } else {
+                    dump.appendFormat(INDENT2 "%d: %s\n", device->id,
+                            device->identifier.name.string());
+                }
+                dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
+                dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
+                dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
+                dump.appendFormat(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string());
+                dump.appendFormat(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
+                        "product=0x%04x, version=0x%04x\n",
+                        device->identifier.bus, device->identifier.vendor,
+                        device->identifier.product, device->identifier.version);
+                dump.appendFormat(INDENT3 "KeyLayoutFile: %s\n",
+                        device->keyMap.keyLayoutFile.string());
+                dump.appendFormat(INDENT3 "KeyCharacterMapFile: %s\n",
+                        device->keyMap.keyCharacterMapFile.string());
+                dump.appendFormat(INDENT3 "ConfigurationFile: %s\n",
+                        device->configurationFile.string());
+            }
+        }
+    } // release lock
+}
+
+}; // namespace android
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
new file mode 100644
index 0000000..74b7ec5
--- /dev/null
+++ b/services/input/EventHub.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+#ifndef _RUNTIME_EVENT_HUB_H
+#define _RUNTIME_EVENT_HUB_H
+
+#include <ui/Input.h>
+#include <ui/Keyboard.h>
+#include <ui/KeyLayoutMap.h>
+#include <ui/KeyCharacterMap.h>
+#include <ui/VirtualKeyMap.h>
+#include <utils/String8.h>
+#include <utils/threads.h>
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Errors.h>
+#include <utils/PropertyMap.h>
+#include <utils/Vector.h>
+
+#include <linux/input.h>
+
+/* These constants are not defined in linux/input.h but they are part of the multitouch
+ * input protocol. */
+
+#define ABS_MT_TOUCH_MAJOR 0x30  /* Major axis of touching ellipse */
+#define ABS_MT_TOUCH_MINOR 0x31  /* Minor axis (omit if circular) */
+#define ABS_MT_WIDTH_MAJOR 0x32  /* Major axis of approaching ellipse */
+#define ABS_MT_WIDTH_MINOR 0x33  /* Minor axis (omit if circular) */
+#define ABS_MT_ORIENTATION 0x34  /* Ellipse orientation */
+#define ABS_MT_POSITION_X 0x35   /* Center X ellipse position */
+#define ABS_MT_POSITION_Y 0x36   /* Center Y ellipse position */
+#define ABS_MT_TOOL_TYPE 0x37    /* Type of touching device (finger, pen, ...) */
+#define ABS_MT_BLOB_ID 0x38      /* Group a set of packets as a blob */
+#define ABS_MT_TRACKING_ID 0x39  /* Unique ID of initiated contact */
+#define ABS_MT_PRESSURE 0x3a     /* Pressure on contact area */
+
+#define MT_TOOL_FINGER 0 /* Identifies a finger */
+#define MT_TOOL_PEN 1    /* Identifies a pen */
+
+#define SYN_MT_REPORT 2
+
+/* Convenience constants. */
+
+#define BTN_FIRST 0x100  // first button scancode
+#define BTN_LAST 0x15f   // last button scancode
+
+struct pollfd;
+
+namespace android {
+
+/*
+ * A raw event as retrieved from the EventHub.
+ */
+struct RawEvent {
+    nsecs_t when;
+    int32_t deviceId;
+    int32_t type;
+    int32_t scanCode;
+    int32_t keyCode;
+    int32_t value;
+    uint32_t flags;
+};
+
+/* Describes an absolute axis. */
+struct RawAbsoluteAxisInfo {
+    bool valid; // true if the information is valid, false otherwise
+
+    int32_t minValue;  // minimum value
+    int32_t maxValue;  // maximum value
+    int32_t flat;      // center flat position, eg. flat == 8 means center is between -8 and 8
+    int32_t fuzz;      // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
+
+    inline int32_t getRange() { return maxValue - minValue; }
+
+    inline void clear() {
+        valid = false;
+        minValue = 0;
+        maxValue = 0;
+        flat = 0;
+        fuzz = 0;
+    }
+};
+
+/*
+ * Input device classes.
+ */
+enum {
+    /* The input device is a keyboard. */
+    INPUT_DEVICE_CLASS_KEYBOARD      = 0x00000001,
+
+    /* The input device is an alpha-numeric keyboard (not just a dial pad). */
+    INPUT_DEVICE_CLASS_ALPHAKEY      = 0x00000002,
+
+    /* The input device is a touchscreen (either single-touch or multi-touch). */
+    INPUT_DEVICE_CLASS_TOUCHSCREEN   = 0x00000004,
+
+    /* The input device is a cursor device such as a trackball or mouse. */
+    INPUT_DEVICE_CLASS_CURSOR        = 0x00000008,
+
+    /* The input device is a multi-touch touchscreen. */
+    INPUT_DEVICE_CLASS_TOUCHSCREEN_MT= 0x00000010,
+
+    /* The input device is a directional pad (implies keyboard, has DPAD keys). */
+    INPUT_DEVICE_CLASS_DPAD          = 0x00000020,
+
+    /* The input device is a gamepad (implies keyboard, has BUTTON keys). */
+    INPUT_DEVICE_CLASS_GAMEPAD       = 0x00000040,
+
+    /* The input device has switches. */
+    INPUT_DEVICE_CLASS_SWITCH        = 0x00000080,
+};
+
+/*
+ * Grand Central Station for events.
+ *
+ * The event hub aggregates input events received across all known input
+ * devices on the system, including devices that may be emulated by the simulator
+ * environment.  In addition, the event hub generates fake input events to indicate
+ * when devices are added or removed.
+ *
+ * The event hub provides a stream of input events (via the getEvent function).
+ * It also supports querying the current actual state of input devices such as identifying
+ * which keys are currently down.  Finally, the event hub keeps track of the capabilities of
+ * individual input devices, such as their class and the set of key codes that they support.
+ */
+class EventHubInterface : public virtual RefBase {
+protected:
+    EventHubInterface() { }
+    virtual ~EventHubInterface() { }
+
+public:
+    // Synthetic raw event type codes produced when devices are added or removed.
+    enum {
+        // Sent when a device is added.
+        DEVICE_ADDED = 0x10000000,
+        // Sent when a device is removed.
+        DEVICE_REMOVED = 0x20000000,
+        // Sent when all added/removed devices from the most recent scan have been reported.
+        // This event is always sent at least once.
+        FINISHED_DEVICE_SCAN = 0x30000000,
+    };
+
+    virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
+
+    virtual String8 getDeviceName(int32_t deviceId) const = 0;
+
+    virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const = 0;
+
+    virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
+            RawAbsoluteAxisInfo* outAxisInfo) const = 0;
+
+    virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
+            int32_t* outKeycode, uint32_t* outFlags) const = 0;
+
+    // exclude a particular device from opening
+    // this can be used to ignore input devices for sensors
+    virtual void addExcludedDevice(const char* deviceName) = 0;
+
+    /*
+     * Wait for the next event to become available and return it.
+     * After returning, the EventHub holds onto a wake lock until the next call to getEvent.
+     * This ensures that the device will not go to sleep while the event is being processed.
+     * If the device needs to remain awake longer than that, then the caller is responsible
+     * for taking care of it (say, by poking the power manager user activity timer).
+     */
+    virtual bool getEvent(RawEvent* outEvent) = 0;
+
+    /*
+     * Query current input state.
+     */
+    virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0;
+    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
+    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
+
+    /*
+     * Examine key input devices for specific framework keycode support
+     */
+    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
+            uint8_t* outFlags) const = 0;
+
+    virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
+    virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
+
+    virtual void getVirtualKeyDefinitions(int32_t deviceId,
+            Vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
+
+    virtual void dump(String8& dump) = 0;
+};
+
+class EventHub : public EventHubInterface
+{
+public:
+    EventHub();
+
+    status_t errorCheck() const;
+
+    virtual uint32_t getDeviceClasses(int32_t deviceId) const;
+
+    virtual String8 getDeviceName(int32_t deviceId) const;
+
+    virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const;
+
+    virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
+            RawAbsoluteAxisInfo* outAxisInfo) const;
+
+    virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
+            int32_t* outKeycode, uint32_t* outFlags) const;
+
+    virtual void addExcludedDevice(const char* deviceName);
+
+    virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
+    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const;
+    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const;
+
+    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags) const;
+
+    virtual bool getEvent(RawEvent* outEvent);
+
+    virtual bool hasLed(int32_t deviceId, int32_t led) const;
+    virtual void setLedState(int32_t deviceId, int32_t led, bool on);
+
+    virtual void getVirtualKeyDefinitions(int32_t deviceId,
+            Vector<VirtualKeyDefinition>& outVirtualKeys) const;
+
+    virtual void dump(String8& dump);
+
+protected:
+    virtual ~EventHub();
+    
+private:
+    bool openPlatformInput(void);
+
+    int openDevice(const char *devicePath);
+    int closeDevice(const char *devicePath);
+    int scanDir(const char *dirname);
+    int readNotify(int nfd);
+
+    status_t mError;
+
+    struct Device {
+        Device* next;
+
+        int fd;
+        const int32_t id;
+        const String8 path;
+        const InputDeviceIdentifier identifier;
+
+        uint32_t classes;
+        uint8_t* keyBitmask;
+        String8 configurationFile;
+        PropertyMap* configuration;
+        VirtualKeyMap* virtualKeyMap;
+        KeyMap keyMap;
+
+        Device(int fd, int32_t id, const String8& path, const InputDeviceIdentifier& identifier);
+        ~Device();
+
+        void close();
+    };
+
+    Device* getDeviceLocked(int32_t deviceId) const;
+    bool hasKeycodeLocked(Device* device, int keycode) const;
+
+    int32_t getScanCodeStateLocked(Device* device, int32_t scanCode) const;
+    int32_t getKeyCodeStateLocked(Device* device, int32_t keyCode) const;
+    int32_t getSwitchStateLocked(Device* device, int32_t sw) const;
+    bool markSupportedKeyCodesLocked(Device* device, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags) const;
+
+    void loadConfiguration(Device* device);
+    status_t loadVirtualKeyMap(Device* device);
+    status_t loadKeyMap(Device* device);
+    void setKeyboardProperties(Device* device, bool builtInKeyboard);
+    void clearKeyboardProperties(Device* device, bool builtInKeyboard);
+
+    // Protect all internal state.
+    mutable Mutex mLock;
+
+    // The actual id of the built-in keyboard, or -1 if none.
+    // EventHub remaps the built-in keyboard to id 0 externally as required by the API.
+    int32_t mBuiltInKeyboardId;
+
+    int32_t mNextDeviceId;
+
+    // Parallel arrays of fds and devices.
+    // First index is reserved for inotify.
+    Vector<struct pollfd> mFds;
+    Vector<Device*> mDevices;
+
+    Device *mOpeningDevices;
+    Device *mClosingDevices;
+
+    bool mOpened;
+    bool mNeedToSendFinishedDeviceScan;
+    List<String8> mExcludedDevices;
+
+    // device ids that report particular switches.
+#ifdef EV_SW
+    int32_t mSwitches[SW_MAX + 1];
+#endif
+
+    static const int INPUT_BUFFER_SIZE = 64;
+    struct input_event mInputBufferData[INPUT_BUFFER_SIZE];
+    size_t mInputBufferIndex;
+    size_t mInputBufferCount;
+    size_t mInputFdIndex;
+};
+
+}; // namespace android
+
+#endif // _RUNTIME_EVENT_HUB_H
diff --git a/services/input/InputApplication.h b/services/input/InputApplication.h
new file mode 100644
index 0000000..cc80062
--- /dev/null
+++ b/services/input/InputApplication.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UI_INPUT_APPLICATION_H
+#define _UI_INPUT_APPLICATION_H
+
+#include <ui/Input.h>
+
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/String8.h>
+
+namespace android {
+
+/*
+ * A handle to an application that can receive input.
+ * Used by the native input dispatcher to indirectly refer to the window manager objects
+ * that describe an application.
+ */
+class InputApplicationHandle : public RefBase {
+protected:
+    InputApplicationHandle() { }
+    virtual ~InputApplicationHandle() { }
+};
+
+
+/*
+ * An input application describes properties of an application that can receive input.
+ */
+struct InputApplication {
+    sp<InputApplicationHandle> inputApplicationHandle;
+    String8 name;
+    nsecs_t dispatchingTimeout;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_APPLICATION_H
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
new file mode 100644
index 0000000..b5a4bd2
--- /dev/null
+++ b/services/input/InputDispatcher.cpp
@@ -0,0 +1,3825 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputDispatcher"
+
+//#define LOG_NDEBUG 0
+
+// Log detailed debug messages about each inbound event notification to the dispatcher.
+#define DEBUG_INBOUND_EVENT_DETAILS 0
+
+// Log detailed debug messages about each outbound event processed by the dispatcher.
+#define DEBUG_OUTBOUND_EVENT_DETAILS 0
+
+// Log debug messages about batching.
+#define DEBUG_BATCHING 0
+
+// Log debug messages about the dispatch cycle.
+#define DEBUG_DISPATCH_CYCLE 0
+
+// Log debug messages about registrations.
+#define DEBUG_REGISTRATION 0
+
+// Log debug messages about performance statistics.
+#define DEBUG_PERFORMANCE_STATISTICS 0
+
+// Log debug messages about input event injection.
+#define DEBUG_INJECTION 0
+
+// Log debug messages about input event throttling.
+#define DEBUG_THROTTLING 0
+
+// Log debug messages about input focus tracking.
+#define DEBUG_FOCUS 0
+
+// Log debug messages about the app switch latency optimization.
+#define DEBUG_APP_SWITCH 0
+
+#include "InputDispatcher.h"
+
+#include <cutils/log.h>
+#include <ui/PowerManager.h>
+
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+
+#define INDENT "  "
+#define INDENT2 "    "
+
+namespace android {
+
+// Default input dispatching timeout if there is no focused application or paused window
+// from which to determine an appropriate dispatching timeout.
+const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
+
+// Amount of time to allow for all pending events to be processed when an app switch
+// key is on the way.  This is used to preempt input dispatch and drop input events
+// when an application takes too long to respond and the user has pressed an app switch key.
+const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
+
+// Amount of time to allow for an event to be dispatched (measured since its eventTime)
+// before considering it stale and dropping it.
+const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
+
+
+static inline nsecs_t now() {
+    return systemTime(SYSTEM_TIME_MONOTONIC);
+}
+
+static inline const char* toString(bool value) {
+    return value ? "true" : "false";
+}
+
+static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
+    return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
+            >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+}
+
+static bool isValidKeyAction(int32_t action) {
+    switch (action) {
+    case AKEY_EVENT_ACTION_DOWN:
+    case AKEY_EVENT_ACTION_UP:
+        return true;
+    default:
+        return false;
+    }
+}
+
+static bool validateKeyEvent(int32_t action) {
+    if (! isValidKeyAction(action)) {
+        LOGE("Key event has invalid action code 0x%x", action);
+        return false;
+    }
+    return true;
+}
+
+static bool isValidMotionAction(int32_t action, size_t pointerCount) {
+    switch (action & AMOTION_EVENT_ACTION_MASK) {
+    case AMOTION_EVENT_ACTION_DOWN:
+    case AMOTION_EVENT_ACTION_UP:
+    case AMOTION_EVENT_ACTION_CANCEL:
+    case AMOTION_EVENT_ACTION_MOVE:
+    case AMOTION_EVENT_ACTION_OUTSIDE:
+        return true;
+    case AMOTION_EVENT_ACTION_POINTER_DOWN:
+    case AMOTION_EVENT_ACTION_POINTER_UP: {
+        int32_t index = getMotionEventActionPointerIndex(action);
+        return index >= 0 && size_t(index) < pointerCount;
+    }
+    default:
+        return false;
+    }
+}
+
+static bool validateMotionEvent(int32_t action, size_t pointerCount,
+        const int32_t* pointerIds) {
+    if (! isValidMotionAction(action, pointerCount)) {
+        LOGE("Motion event has invalid action code 0x%x", action);
+        return false;
+    }
+    if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
+        LOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.",
+                pointerCount, MAX_POINTERS);
+        return false;
+    }
+    BitSet32 pointerIdBits;
+    for (size_t i = 0; i < pointerCount; i++) {
+        int32_t id = pointerIds[i];
+        if (id < 0 || id > MAX_POINTER_ID) {
+            LOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
+                    id, MAX_POINTER_ID);
+            return false;
+        }
+        if (pointerIdBits.hasBit(id)) {
+            LOGE("Motion event has duplicate pointer id %d", id);
+            return false;
+        }
+        pointerIdBits.markBit(id);
+    }
+    return true;
+}
+
+
+// --- InputDispatcher ---
+
+InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
+    mPolicy(policy),
+    mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
+    mNextUnblockedEvent(NULL),
+    mDispatchEnabled(true), mDispatchFrozen(false),
+    mFocusedWindow(NULL),
+    mFocusedApplication(NULL),
+    mCurrentInputTargetsValid(false),
+    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
+    mLooper = new Looper(false);
+
+    mInboundQueue.headSentinel.refCount = -1;
+    mInboundQueue.headSentinel.type = EventEntry::TYPE_SENTINEL;
+    mInboundQueue.headSentinel.eventTime = LONG_LONG_MIN;
+
+    mInboundQueue.tailSentinel.refCount = -1;
+    mInboundQueue.tailSentinel.type = EventEntry::TYPE_SENTINEL;
+    mInboundQueue.tailSentinel.eventTime = LONG_LONG_MAX;
+
+    mKeyRepeatState.lastKeyEntry = NULL;
+
+    int32_t maxEventsPerSecond = policy->getMaxEventsPerSecond();
+    mThrottleState.minTimeBetweenEvents = 1000000000LL / maxEventsPerSecond;
+    mThrottleState.lastDeviceId = -1;
+
+#if DEBUG_THROTTLING
+    mThrottleState.originalSampleCount = 0;
+    LOGD("Throttling - Max events per second = %d", maxEventsPerSecond);
+#endif
+}
+
+InputDispatcher::~InputDispatcher() {
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        resetKeyRepeatLocked();
+        releasePendingEventLocked();
+        drainInboundQueueLocked();
+    }
+
+    while (mConnectionsByReceiveFd.size() != 0) {
+        unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
+    }
+}
+
+void InputDispatcher::dispatchOnce() {
+    nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
+    nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
+
+    nsecs_t nextWakeupTime = LONG_LONG_MAX;
+    { // acquire lock
+        AutoMutex _l(mLock);
+        dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime);
+
+        if (runCommandsLockedInterruptible()) {
+            nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
+        }
+    } // release lock
+
+    // Wait for callback or timeout or wake.  (make sure we round up, not down)
+    nsecs_t currentTime = now();
+    int32_t timeoutMillis;
+    if (nextWakeupTime > currentTime) {
+        uint64_t timeout = uint64_t(nextWakeupTime - currentTime);
+        timeout = (timeout + 999999LL) / 1000000LL;
+        timeoutMillis = timeout > INT_MAX ? -1 : int32_t(timeout);
+    } else {
+        timeoutMillis = 0;
+    }
+
+    mLooper->pollOnce(timeoutMillis);
+}
+
+void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
+        nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime) {
+    nsecs_t currentTime = now();
+
+    // Reset the key repeat timer whenever we disallow key events, even if the next event
+    // is not a key.  This is to ensure that we abort a key repeat if the device is just coming
+    // out of sleep.
+    if (keyRepeatTimeout < 0) {
+        resetKeyRepeatLocked();
+    }
+
+    // If dispatching is frozen, do not process timeouts or try to deliver any new events.
+    if (mDispatchFrozen) {
+#if DEBUG_FOCUS
+        LOGD("Dispatch frozen.  Waiting some more.");
+#endif
+        return;
+    }
+
+    // Optimize latency of app switches.
+    // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
+    // been pressed.  When it expires, we preempt dispatch and drop all other pending events.
+    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
+    if (mAppSwitchDueTime < *nextWakeupTime) {
+        *nextWakeupTime = mAppSwitchDueTime;
+    }
+
+    // Ready to start a new event.
+    // If we don't already have a pending event, go grab one.
+    if (! mPendingEvent) {
+        if (mInboundQueue.isEmpty()) {
+            if (isAppSwitchDue) {
+                // The inbound queue is empty so the app switch key we were waiting
+                // for will never arrive.  Stop waiting for it.
+                resetPendingAppSwitchLocked(false);
+                isAppSwitchDue = false;
+            }
+
+            // Synthesize a key repeat if appropriate.
+            if (mKeyRepeatState.lastKeyEntry) {
+                if (currentTime >= mKeyRepeatState.nextRepeatTime) {
+                    mPendingEvent = synthesizeKeyRepeatLocked(currentTime, keyRepeatDelay);
+                } else {
+                    if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
+                        *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
+                    }
+                }
+            }
+            if (! mPendingEvent) {
+                return;
+            }
+        } else {
+            // Inbound queue has at least one entry.
+            EventEntry* entry = mInboundQueue.headSentinel.next;
+
+            // Throttle the entry if it is a move event and there are no
+            // other events behind it in the queue.  Due to movement batching, additional
+            // samples may be appended to this event by the time the throttling timeout
+            // expires.
+            // TODO Make this smarter and consider throttling per device independently.
+            if (entry->type == EventEntry::TYPE_MOTION
+                    && !isAppSwitchDue
+                    && mDispatchEnabled
+                    && (entry->policyFlags & POLICY_FLAG_PASS_TO_USER)
+                    && !entry->isInjected()) {
+                MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+                int32_t deviceId = motionEntry->deviceId;
+                uint32_t source = motionEntry->source;
+                if (! isAppSwitchDue
+                        && motionEntry->next == & mInboundQueue.tailSentinel // exactly one event
+                        && motionEntry->action == AMOTION_EVENT_ACTION_MOVE
+                        && deviceId == mThrottleState.lastDeviceId
+                        && source == mThrottleState.lastSource) {
+                    nsecs_t nextTime = mThrottleState.lastEventTime
+                            + mThrottleState.minTimeBetweenEvents;
+                    if (currentTime < nextTime) {
+                        // Throttle it!
+#if DEBUG_THROTTLING
+                        LOGD("Throttling - Delaying motion event for "
+                                "device %d, source 0x%08x by up to %0.3fms.",
+                                deviceId, source, (nextTime - currentTime) * 0.000001);
+#endif
+                        if (nextTime < *nextWakeupTime) {
+                            *nextWakeupTime = nextTime;
+                        }
+                        if (mThrottleState.originalSampleCount == 0) {
+                            mThrottleState.originalSampleCount =
+                                    motionEntry->countSamples();
+                        }
+                        return;
+                    }
+                }
+
+#if DEBUG_THROTTLING
+                if (mThrottleState.originalSampleCount != 0) {
+                    uint32_t count = motionEntry->countSamples();
+                    LOGD("Throttling - Motion event sample count grew by %d from %d to %d.",
+                            count - mThrottleState.originalSampleCount,
+                            mThrottleState.originalSampleCount, count);
+                    mThrottleState.originalSampleCount = 0;
+                }
+#endif
+
+                mThrottleState.lastEventTime = entry->eventTime < currentTime
+                        ? entry->eventTime : currentTime;
+                mThrottleState.lastDeviceId = deviceId;
+                mThrottleState.lastSource = source;
+            }
+
+            mInboundQueue.dequeue(entry);
+            mPendingEvent = entry;
+        }
+
+        // Poke user activity for this event.
+        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
+            pokeUserActivityLocked(mPendingEvent);
+        }
+    }
+
+    // Now we have an event to dispatch.
+    // All events are eventually dequeued and processed this way, even if we intend to drop them.
+    assert(mPendingEvent != NULL);
+    bool done = false;
+    DropReason dropReason = DROP_REASON_NOT_DROPPED;
+    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
+        dropReason = DROP_REASON_POLICY;
+    } else if (!mDispatchEnabled) {
+        dropReason = DROP_REASON_DISABLED;
+    }
+
+    if (mNextUnblockedEvent == mPendingEvent) {
+        mNextUnblockedEvent = NULL;
+    }
+
+    switch (mPendingEvent->type) {
+    case EventEntry::TYPE_CONFIGURATION_CHANGED: {
+        ConfigurationChangedEntry* typedEntry =
+                static_cast<ConfigurationChangedEntry*>(mPendingEvent);
+        done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
+        dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
+        break;
+    }
+
+    case EventEntry::TYPE_KEY: {
+        KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
+        if (isAppSwitchDue) {
+            if (isAppSwitchKeyEventLocked(typedEntry)) {
+                resetPendingAppSwitchLocked(true);
+                isAppSwitchDue = false;
+            } else if (dropReason == DROP_REASON_NOT_DROPPED) {
+                dropReason = DROP_REASON_APP_SWITCH;
+            }
+        }
+        if (dropReason == DROP_REASON_NOT_DROPPED
+                && isStaleEventLocked(currentTime, typedEntry)) {
+            dropReason = DROP_REASON_STALE;
+        }
+        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
+            dropReason = DROP_REASON_BLOCKED;
+        }
+        done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
+                &dropReason, nextWakeupTime);
+        break;
+    }
+
+    case EventEntry::TYPE_MOTION: {
+        MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
+        if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
+            dropReason = DROP_REASON_APP_SWITCH;
+        }
+        if (dropReason == DROP_REASON_NOT_DROPPED
+                && isStaleEventLocked(currentTime, typedEntry)) {
+            dropReason = DROP_REASON_STALE;
+        }
+        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
+            dropReason = DROP_REASON_BLOCKED;
+        }
+        done = dispatchMotionLocked(currentTime, typedEntry,
+                &dropReason, nextWakeupTime);
+        break;
+    }
+
+    default:
+        assert(false);
+        break;
+    }
+
+    if (done) {
+        if (dropReason != DROP_REASON_NOT_DROPPED) {
+            dropInboundEventLocked(mPendingEvent, dropReason);
+        }
+
+        releasePendingEventLocked();
+        *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
+    }
+}
+
+bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
+    bool needWake = mInboundQueue.isEmpty();
+    mInboundQueue.enqueueAtTail(entry);
+
+    switch (entry->type) {
+    case EventEntry::TYPE_KEY: {
+        // Optimize app switch latency.
+        // If the application takes too long to catch up then we drop all events preceding
+        // the app switch key.
+        KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
+        if (isAppSwitchKeyEventLocked(keyEntry)) {
+            if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
+                mAppSwitchSawKeyDown = true;
+            } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
+                if (mAppSwitchSawKeyDown) {
+#if DEBUG_APP_SWITCH
+                    LOGD("App switch is pending!");
+#endif
+                    mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
+                    mAppSwitchSawKeyDown = false;
+                    needWake = true;
+                }
+            }
+        }
+        break;
+    }
+
+    case EventEntry::TYPE_MOTION: {
+        // Optimize case where the current application is unresponsive and the user
+        // decides to touch a window in a different application.
+        // If the application takes too long to catch up then we drop all events preceding
+        // the touch into the other window.
+        MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+        if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
+                && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
+                && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
+                && mInputTargetWaitApplication != NULL) {
+            int32_t x = int32_t(motionEntry->firstSample.pointerCoords[0].x);
+            int32_t y = int32_t(motionEntry->firstSample.pointerCoords[0].y);
+            const InputWindow* touchedWindow = findTouchedWindowAtLocked(x, y);
+            if (touchedWindow
+                    && touchedWindow->inputWindowHandle != NULL
+                    && touchedWindow->inputWindowHandle->getInputApplicationHandle()
+                            != mInputTargetWaitApplication) {
+                // User touched a different application than the one we are waiting on.
+                // Flag the event, and start pruning the input queue.
+                mNextUnblockedEvent = motionEntry;
+                needWake = true;
+            }
+        }
+        break;
+    }
+    }
+
+    return needWake;
+}
+
+const InputWindow* InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
+    // Traverse windows from front to back to find touched window.
+    size_t numWindows = mWindows.size();
+    for (size_t i = 0; i < numWindows; i++) {
+        const InputWindow* window = & mWindows.editItemAt(i);
+        int32_t flags = window->layoutParamsFlags;
+
+        if (window->visible) {
+            if (!(flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
+                bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
+                        | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
+                if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
+                    // Found window.
+                    return window;
+                }
+            }
+        }
+
+        if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
+            // Error window is on top but not visible, so touch is dropped.
+            return NULL;
+        }
+    }
+    return NULL;
+}
+
+void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
+    const char* reason;
+    switch (dropReason) {
+    case DROP_REASON_POLICY:
+#if DEBUG_INBOUND_EVENT_DETAILS
+        LOGD("Dropped event because policy consumed it.");
+#endif
+        reason = "inbound event was dropped because the policy consumed it";
+        break;
+    case DROP_REASON_DISABLED:
+        LOGI("Dropped event because input dispatch is disabled.");
+        reason = "inbound event was dropped because input dispatch is disabled";
+        break;
+    case DROP_REASON_APP_SWITCH:
+        LOGI("Dropped event because of pending overdue app switch.");
+        reason = "inbound event was dropped because of pending overdue app switch";
+        break;
+    case DROP_REASON_BLOCKED:
+        LOGI("Dropped event because the current application is not responding and the user "
+                "has started interating with a different application.");
+        reason = "inbound event was dropped because the current application is not responding "
+                "and the user has started interating with a different application";
+        break;
+    case DROP_REASON_STALE:
+        LOGI("Dropped event because it is stale.");
+        reason = "inbound event was dropped because it is stale";
+        break;
+    default:
+        assert(false);
+        return;
+    }
+
+    switch (entry->type) {
+    case EventEntry::TYPE_KEY:
+        synthesizeCancelationEventsForAllConnectionsLocked(
+                InputState::CANCEL_NON_POINTER_EVENTS, reason);
+        break;
+    case EventEntry::TYPE_MOTION: {
+        MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
+            synthesizeCancelationEventsForAllConnectionsLocked(
+                    InputState::CANCEL_POINTER_EVENTS, reason);
+        } else {
+            synthesizeCancelationEventsForAllConnectionsLocked(
+                    InputState::CANCEL_NON_POINTER_EVENTS, reason);
+        }
+        break;
+    }
+    }
+}
+
+bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
+    return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
+}
+
+bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
+    return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
+            && isAppSwitchKeyCode(keyEntry->keyCode)
+            && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
+            && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
+}
+
+bool InputDispatcher::isAppSwitchPendingLocked() {
+    return mAppSwitchDueTime != LONG_LONG_MAX;
+}
+
+void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
+    mAppSwitchDueTime = LONG_LONG_MAX;
+
+#if DEBUG_APP_SWITCH
+    if (handled) {
+        LOGD("App switch has arrived.");
+    } else {
+        LOGD("App switch was abandoned.");
+    }
+#endif
+}
+
+bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry) {
+    return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
+}
+
+bool InputDispatcher::runCommandsLockedInterruptible() {
+    if (mCommandQueue.isEmpty()) {
+        return false;
+    }
+
+    do {
+        CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
+
+        Command command = commandEntry->command;
+        (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
+
+        commandEntry->connection.clear();
+        mAllocator.releaseCommandEntry(commandEntry);
+    } while (! mCommandQueue.isEmpty());
+    return true;
+}
+
+InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
+    CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
+    mCommandQueue.enqueueAtTail(commandEntry);
+    return commandEntry;
+}
+
+void InputDispatcher::drainInboundQueueLocked() {
+    while (! mInboundQueue.isEmpty()) {
+        EventEntry* entry = mInboundQueue.dequeueAtHead();
+        releaseInboundEventLocked(entry);
+    }
+}
+
+void InputDispatcher::releasePendingEventLocked() {
+    if (mPendingEvent) {
+        releaseInboundEventLocked(mPendingEvent);
+        mPendingEvent = NULL;
+    }
+}
+
+void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
+    InjectionState* injectionState = entry->injectionState;
+    if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
+#if DEBUG_DISPATCH_CYCLE
+        LOGD("Injected inbound event was dropped.");
+#endif
+        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
+    }
+    mAllocator.releaseEventEntry(entry);
+}
+
+void InputDispatcher::resetKeyRepeatLocked() {
+    if (mKeyRepeatState.lastKeyEntry) {
+        mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
+        mKeyRepeatState.lastKeyEntry = NULL;
+    }
+}
+
+InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
+        nsecs_t currentTime, nsecs_t keyRepeatDelay) {
+    KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
+
+    // Reuse the repeated key entry if it is otherwise unreferenced.
+    uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
+            | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
+    if (entry->refCount == 1) {
+        mAllocator.recycleKeyEntry(entry);
+        entry->eventTime = currentTime;
+        entry->policyFlags = policyFlags;
+        entry->repeatCount += 1;
+    } else {
+        KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
+                entry->deviceId, entry->source, policyFlags,
+                entry->action, entry->flags, entry->keyCode, entry->scanCode,
+                entry->metaState, entry->repeatCount + 1, entry->downTime);
+
+        mKeyRepeatState.lastKeyEntry = newEntry;
+        mAllocator.releaseKeyEntry(entry);
+
+        entry = newEntry;
+    }
+    entry->syntheticRepeat = true;
+
+    // Increment reference count since we keep a reference to the event in
+    // mKeyRepeatState.lastKeyEntry in addition to the one we return.
+    entry->refCount += 1;
+
+    if (entry->repeatCount == 1) {
+        entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
+    }
+
+    mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
+    return entry;
+}
+
+bool InputDispatcher::dispatchConfigurationChangedLocked(
+        nsecs_t currentTime, ConfigurationChangedEntry* entry) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+    LOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
+#endif
+
+    // Reset key repeating in case a keyboard device was added or removed or something.
+    resetKeyRepeatLocked();
+
+    // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doNotifyConfigurationChangedInterruptible);
+    commandEntry->eventTime = entry->eventTime;
+    return true;
+}
+
+bool InputDispatcher::dispatchKeyLocked(
+        nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
+        DropReason* dropReason, nsecs_t* nextWakeupTime) {
+    // Preprocessing.
+    if (! entry->dispatchInProgress) {
+        if (entry->repeatCount == 0
+                && entry->action == AKEY_EVENT_ACTION_DOWN
+                && (entry->policyFlags & POLICY_FLAG_TRUSTED)
+                && !entry->isInjected()) {
+            if (mKeyRepeatState.lastKeyEntry
+                    && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
+                // We have seen two identical key downs in a row which indicates that the device
+                // driver is automatically generating key repeats itself.  We take note of the
+                // repeat here, but we disable our own next key repeat timer since it is clear that
+                // we will not need to synthesize key repeats ourselves.
+                entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
+                resetKeyRepeatLocked();
+                mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
+            } else {
+                // Not a repeat.  Save key down state in case we do see a repeat later.
+                resetKeyRepeatLocked();
+                mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
+            }
+            mKeyRepeatState.lastKeyEntry = entry;
+            entry->refCount += 1;
+        } else if (! entry->syntheticRepeat) {
+            resetKeyRepeatLocked();
+        }
+
+        entry->dispatchInProgress = true;
+        resetTargetsLocked();
+
+        logOutboundKeyDetailsLocked("dispatchKey - ", entry);
+    }
+
+    // Give the policy a chance to intercept the key.
+    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
+        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
+            CommandEntry* commandEntry = postCommandLocked(
+                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
+            if (mFocusedWindow) {
+                commandEntry->inputWindowHandle = mFocusedWindow->inputWindowHandle;
+            }
+            commandEntry->keyEntry = entry;
+            entry->refCount += 1;
+            return false; // wait for the command to run
+        } else {
+            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
+        }
+    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
+        if (*dropReason == DROP_REASON_NOT_DROPPED) {
+            *dropReason = DROP_REASON_POLICY;
+        }
+    }
+
+    // Clean up if dropping the event.
+    if (*dropReason != DROP_REASON_NOT_DROPPED) {
+        resetTargetsLocked();
+        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
+                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
+        return true;
+    }
+
+    // Identify targets.
+    if (! mCurrentInputTargetsValid) {
+        int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
+                entry, nextWakeupTime);
+        if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
+            return false;
+        }
+
+        setInjectionResultLocked(entry, injectionResult);
+        if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
+            return true;
+        }
+
+        addMonitoringTargetsLocked();
+        commitTargetsLocked();
+    }
+
+    // Dispatch the key.
+    dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
+    return true;
+}
+
+void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+    LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
+            "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
+            "repeatCount=%d, downTime=%lld",
+            prefix,
+            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
+            entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
+            entry->repeatCount, entry->downTime);
+#endif
+}
+
+bool InputDispatcher::dispatchMotionLocked(
+        nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
+    // Preprocessing.
+    if (! entry->dispatchInProgress) {
+        entry->dispatchInProgress = true;
+        resetTargetsLocked();
+
+        logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
+    }
+
+    // Clean up if dropping the event.
+    if (*dropReason != DROP_REASON_NOT_DROPPED) {
+        resetTargetsLocked();
+        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
+                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
+        return true;
+    }
+
+    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
+
+    // Identify targets.
+    if (! mCurrentInputTargetsValid) {
+        int32_t injectionResult;
+        if (isPointerEvent) {
+            // Pointer event.  (eg. touchscreen)
+            injectionResult = findTouchedWindowTargetsLocked(currentTime,
+                    entry, nextWakeupTime);
+        } else {
+            // Non touch event.  (eg. trackball)
+            injectionResult = findFocusedWindowTargetsLocked(currentTime,
+                    entry, nextWakeupTime);
+        }
+        if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
+            return false;
+        }
+
+        setInjectionResultLocked(entry, injectionResult);
+        if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
+            return true;
+        }
+
+        addMonitoringTargetsLocked();
+        commitTargetsLocked();
+    }
+
+    // Dispatch the motion.
+    dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
+    return true;
+}
+
+
+void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+    LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
+            "action=0x%x, flags=0x%x, "
+            "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
+            prefix,
+            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
+            entry->action, entry->flags,
+            entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
+            entry->downTime);
+
+    // Print the most recent sample that we have available, this may change due to batching.
+    size_t sampleCount = 1;
+    const MotionSample* sample = & entry->firstSample;
+    for (; sample->next != NULL; sample = sample->next) {
+        sampleCount += 1;
+    }
+    for (uint32_t i = 0; i < entry->pointerCount; i++) {
+        LOGD("  Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
+                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
+                "orientation=%f",
+                i, entry->pointerIds[i],
+                sample->pointerCoords[i].x, sample->pointerCoords[i].y,
+                sample->pointerCoords[i].pressure, sample->pointerCoords[i].size,
+                sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor,
+                sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor,
+                sample->pointerCoords[i].orientation);
+    }
+
+    // Keep in mind that due to batching, it is possible for the number of samples actually
+    // dispatched to change before the application finally consumed them.
+    if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
+        LOGD("  ... Total movement samples currently batched %d ...", sampleCount);
+    }
+#endif
+}
+
+void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
+        EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
+#if DEBUG_DISPATCH_CYCLE
+    LOGD("dispatchEventToCurrentInputTargets - "
+            "resumeWithAppendedMotionSample=%s",
+            toString(resumeWithAppendedMotionSample));
+#endif
+
+    assert(eventEntry->dispatchInProgress); // should already have been set to true
+
+    pokeUserActivityLocked(eventEntry);
+
+    for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
+        const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
+
+        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
+        if (connectionIndex >= 0) {
+            sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
+            prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
+                    resumeWithAppendedMotionSample);
+        } else {
+#if DEBUG_FOCUS
+            LOGD("Dropping event delivery to target with channel '%s' because it "
+                    "is no longer registered with the input dispatcher.",
+                    inputTarget.inputChannel->getName().string());
+#endif
+        }
+    }
+}
+
+void InputDispatcher::resetTargetsLocked() {
+    mCurrentInputTargetsValid = false;
+    mCurrentInputTargets.clear();
+    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
+    mInputTargetWaitApplication.clear();
+}
+
+void InputDispatcher::commitTargetsLocked() {
+    mCurrentInputTargetsValid = true;
+}
+
+int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
+        const EventEntry* entry, const InputApplication* application, const InputWindow* window,
+        nsecs_t* nextWakeupTime) {
+    if (application == NULL && window == NULL) {
+        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
+#if DEBUG_FOCUS
+            LOGD("Waiting for system to become ready for input.");
+#endif
+            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
+            mInputTargetWaitStartTime = currentTime;
+            mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
+            mInputTargetWaitTimeoutExpired = false;
+            mInputTargetWaitApplication.clear();
+        }
+    } else {
+        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
+#if DEBUG_FOCUS
+            LOGD("Waiting for application to become ready for input: %s",
+                    getApplicationWindowLabelLocked(application, window).string());
+#endif
+            nsecs_t timeout = window ? window->dispatchingTimeout :
+                application ? application->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
+
+            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
+            mInputTargetWaitStartTime = currentTime;
+            mInputTargetWaitTimeoutTime = currentTime + timeout;
+            mInputTargetWaitTimeoutExpired = false;
+            mInputTargetWaitApplication.clear();
+
+            if (window && window->inputWindowHandle != NULL) {
+                mInputTargetWaitApplication =
+                        window->inputWindowHandle->getInputApplicationHandle();
+            }
+            if (mInputTargetWaitApplication == NULL && application) {
+                mInputTargetWaitApplication = application->inputApplicationHandle;
+            }
+        }
+    }
+
+    if (mInputTargetWaitTimeoutExpired) {
+        return INPUT_EVENT_INJECTION_TIMED_OUT;
+    }
+
+    if (currentTime >= mInputTargetWaitTimeoutTime) {
+        onANRLocked(currentTime, application, window, entry->eventTime, mInputTargetWaitStartTime);
+
+        // Force poll loop to wake up immediately on next iteration once we get the
+        // ANR response back from the policy.
+        *nextWakeupTime = LONG_LONG_MIN;
+        return INPUT_EVENT_INJECTION_PENDING;
+    } else {
+        // Force poll loop to wake up when timeout is due.
+        if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
+            *nextWakeupTime = mInputTargetWaitTimeoutTime;
+        }
+        return INPUT_EVENT_INJECTION_PENDING;
+    }
+}
+
+void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
+        const sp<InputChannel>& inputChannel) {
+    if (newTimeout > 0) {
+        // Extend the timeout.
+        mInputTargetWaitTimeoutTime = now() + newTimeout;
+    } else {
+        // Give up.
+        mInputTargetWaitTimeoutExpired = true;
+
+        // Release the touch targets.
+        mTouchState.reset();
+
+        // Input state will not be realistic.  Mark it out of sync.
+        if (inputChannel.get()) {
+            ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
+            if (connectionIndex >= 0) {
+                sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
+                if (connection->status == Connection::STATUS_NORMAL) {
+                    synthesizeCancelationEventsForConnectionLocked(
+                            connection, InputState::CANCEL_ALL_EVENTS,
+                            "application not responding");
+                }
+            }
+        }
+    }
+}
+
+nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
+        nsecs_t currentTime) {
+    if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
+        return currentTime - mInputTargetWaitStartTime;
+    }
+    return 0;
+}
+
+void InputDispatcher::resetANRTimeoutsLocked() {
+#if DEBUG_FOCUS
+        LOGD("Resetting ANR timeouts.");
+#endif
+
+    // Reset input target wait timeout.
+    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
+}
+
+int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
+        const EventEntry* entry, nsecs_t* nextWakeupTime) {
+    mCurrentInputTargets.clear();
+
+    int32_t injectionResult;
+
+    // If there is no currently focused window and no focused application
+    // then drop the event.
+    if (! mFocusedWindow) {
+        if (mFocusedApplication) {
+#if DEBUG_FOCUS
+            LOGD("Waiting because there is no focused window but there is a "
+                    "focused application that may eventually add a window: %s.",
+                    getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
+#endif
+            injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+                    mFocusedApplication, NULL, nextWakeupTime);
+            goto Unresponsive;
+        }
+
+        LOGI("Dropping event because there is no focused window or focused application.");
+        injectionResult = INPUT_EVENT_INJECTION_FAILED;
+        goto Failed;
+    }
+
+    // Check permissions.
+    if (! checkInjectionPermission(mFocusedWindow, entry->injectionState)) {
+        injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
+        goto Failed;
+    }
+
+    // If the currently focused window is paused then keep waiting.
+    if (mFocusedWindow->paused) {
+#if DEBUG_FOCUS
+        LOGD("Waiting because focused window is paused.");
+#endif
+        injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+                mFocusedApplication, mFocusedWindow, nextWakeupTime);
+        goto Unresponsive;
+    }
+
+    // If the currently focused window is still working on previous events then keep waiting.
+    if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) {
+#if DEBUG_FOCUS
+        LOGD("Waiting because focused window still processing previous input.");
+#endif
+        injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+                mFocusedApplication, mFocusedWindow, nextWakeupTime);
+        goto Unresponsive;
+    }
+
+    // Success!  Output targets.
+    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
+    addWindowTargetLocked(mFocusedWindow, InputTarget::FLAG_FOREGROUND, BitSet32(0));
+
+    // Done.
+Failed:
+Unresponsive:
+    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
+    updateDispatchStatisticsLocked(currentTime, entry,
+            injectionResult, timeSpentWaitingForApplication);
+#if DEBUG_FOCUS
+    LOGD("findFocusedWindow finished: injectionResult=%d, "
+            "timeSpendWaitingForApplication=%0.1fms",
+            injectionResult, timeSpentWaitingForApplication / 1000000.0);
+#endif
+    return injectionResult;
+}
+
+int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
+        const MotionEntry* entry, nsecs_t* nextWakeupTime) {
+    enum InjectionPermission {
+        INJECTION_PERMISSION_UNKNOWN,
+        INJECTION_PERMISSION_GRANTED,
+        INJECTION_PERMISSION_DENIED
+    };
+
+    mCurrentInputTargets.clear();
+
+    nsecs_t startTime = now();
+
+    // For security reasons, we defer updating the touch state until we are sure that
+    // event injection will be allowed.
+    //
+    // FIXME In the original code, screenWasOff could never be set to true.
+    //       The reason is that the POLICY_FLAG_WOKE_HERE
+    //       and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
+    //       EV_KEY, EV_REL and EV_ABS events.  As it happens, the touch event was
+    //       actually enqueued using the policyFlags that appeared in the final EV_SYN
+    //       events upon which no preprocessing took place.  So policyFlags was always 0.
+    //       In the new native input dispatcher we're a bit more careful about event
+    //       preprocessing so the touches we receive can actually have non-zero policyFlags.
+    //       Unfortunately we obtain undesirable behavior.
+    //
+    //       Here's what happens:
+    //
+    //       When the device dims in anticipation of going to sleep, touches
+    //       in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
+    //       the device to brighten and reset the user activity timer.
+    //       Touches on other windows (such as the launcher window)
+    //       are dropped.  Then after a moment, the device goes to sleep.  Oops.
+    //
+    //       Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
+    //       instead of POLICY_FLAG_WOKE_HERE...
+    //
+    bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
+
+    int32_t action = entry->action;
+    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
+
+    // Update the touch state as needed based on the properties of the touch event.
+    int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
+    InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
+    bool isSplit, wrongDevice;
+    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
+        mTempTouchState.reset();
+        mTempTouchState.down = true;
+        mTempTouchState.deviceId = entry->deviceId;
+        isSplit = false;
+        wrongDevice = false;
+    } else {
+        mTempTouchState.copyFrom(mTouchState);
+        isSplit = mTempTouchState.split;
+        wrongDevice = mTempTouchState.down && mTempTouchState.deviceId != entry->deviceId;
+        if (wrongDevice) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+            LOGD("Dropping event because a pointer for a different device is already down.");
+#endif
+            injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            goto Failed;
+        }
+    }
+
+    if (maskedAction == AMOTION_EVENT_ACTION_DOWN
+            || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
+        /* Case 1: New splittable pointer going down. */
+
+        int32_t pointerIndex = getMotionEventActionPointerIndex(action);
+        int32_t x = int32_t(entry->firstSample.pointerCoords[pointerIndex].x);
+        int32_t y = int32_t(entry->firstSample.pointerCoords[pointerIndex].y);
+        const InputWindow* newTouchedWindow = NULL;
+        const InputWindow* topErrorWindow = NULL;
+
+        // Traverse windows from front to back to find touched window and outside targets.
+        size_t numWindows = mWindows.size();
+        for (size_t i = 0; i < numWindows; i++) {
+            const InputWindow* window = & mWindows.editItemAt(i);
+            int32_t flags = window->layoutParamsFlags;
+
+            if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
+                if (! topErrorWindow) {
+                    topErrorWindow = window;
+                }
+            }
+
+            if (window->visible) {
+                if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
+                    bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
+                            | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
+                    if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
+                        if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
+                            newTouchedWindow = window;
+                        }
+                        break; // found touched window, exit window loop
+                    }
+                }
+
+                if (maskedAction == AMOTION_EVENT_ACTION_DOWN
+                        && (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)) {
+                    int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
+                    if (isWindowObscuredAtPointLocked(window, x, y)) {
+                        outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+                    }
+
+                    mTempTouchState.addOrUpdateWindow(window, outsideTargetFlags, BitSet32(0));
+                }
+            }
+        }
+
+        // If there is an error window but it is not taking focus (typically because
+        // it is invisible) then wait for it.  Any other focused window may in
+        // fact be in ANR state.
+        if (topErrorWindow && newTouchedWindow != topErrorWindow) {
+#if DEBUG_FOCUS
+            LOGD("Waiting because system error window is pending.");
+#endif
+            injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+                    NULL, NULL, nextWakeupTime);
+            injectionPermission = INJECTION_PERMISSION_UNKNOWN;
+            goto Unresponsive;
+        }
+
+        // Figure out whether splitting will be allowed for this window.
+        if (newTouchedWindow && newTouchedWindow->supportsSplitTouch()) {
+            // New window supports splitting.
+            isSplit = true;
+        } else if (isSplit) {
+            // New window does not support splitting but we have already split events.
+            // Assign the pointer to the first foreground window we find.
+            // (May be NULL which is why we put this code block before the next check.)
+            newTouchedWindow = mTempTouchState.getFirstForegroundWindow();
+        }
+
+        // If we did not find a touched window then fail.
+        if (! newTouchedWindow) {
+            if (mFocusedApplication) {
+#if DEBUG_FOCUS
+                LOGD("Waiting because there is no touched window but there is a "
+                        "focused application that may eventually add a new window: %s.",
+                        getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
+#endif
+                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+                        mFocusedApplication, NULL, nextWakeupTime);
+                goto Unresponsive;
+            }
+
+            LOGI("Dropping event because there is no touched window or focused application.");
+            injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            goto Failed;
+        }
+
+        // Set target flags.
+        int32_t targetFlags = InputTarget::FLAG_FOREGROUND;
+        if (isSplit) {
+            targetFlags |= InputTarget::FLAG_SPLIT;
+        }
+        if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
+            targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+        }
+
+        // Update the temporary touch state.
+        BitSet32 pointerIds;
+        if (isSplit) {
+            uint32_t pointerId = entry->pointerIds[pointerIndex];
+            pointerIds.markBit(pointerId);
+        }
+        mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
+    } else {
+        /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
+
+        // If the pointer is not currently down, then ignore the event.
+        if (! mTempTouchState.down) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+            LOGD("Dropping event because the pointer is not down or we previously "
+                    "dropped the pointer down event.");
+#endif
+            injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            goto Failed;
+        }
+    }
+
+    // Check permission to inject into all touched foreground windows and ensure there
+    // is at least one touched foreground window.
+    {
+        bool haveForegroundWindow = false;
+        for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
+            const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
+            if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
+                haveForegroundWindow = true;
+                if (! checkInjectionPermission(touchedWindow.window, entry->injectionState)) {
+                    injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
+                    injectionPermission = INJECTION_PERMISSION_DENIED;
+                    goto Failed;
+                }
+            }
+        }
+        if (! haveForegroundWindow) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+            LOGD("Dropping event because there is no touched foreground window to receive it.");
+#endif
+            injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            goto Failed;
+        }
+
+        // Permission granted to injection into all touched foreground windows.
+        injectionPermission = INJECTION_PERMISSION_GRANTED;
+    }
+
+    // Ensure all touched foreground windows are ready for new input.
+    for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
+        const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
+        if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
+            // If the touched window is paused then keep waiting.
+            if (touchedWindow.window->paused) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+                LOGD("Waiting because touched window is paused.");
+#endif
+                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+                        NULL, touchedWindow.window, nextWakeupTime);
+                goto Unresponsive;
+            }
+
+            // If the touched window is still working on previous events then keep waiting.
+            if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.window)) {
+#if DEBUG_FOCUS
+                LOGD("Waiting because touched window still processing previous input.");
+#endif
+                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
+                        NULL, touchedWindow.window, nextWakeupTime);
+                goto Unresponsive;
+            }
+        }
+    }
+
+    // If this is the first pointer going down and the touched window has a wallpaper
+    // then also add the touched wallpaper windows so they are locked in for the duration
+    // of the touch gesture.
+    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
+        const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow();
+        if (foregroundWindow->hasWallpaper) {
+            for (size_t i = 0; i < mWindows.size(); i++) {
+                const InputWindow* window = & mWindows[i];
+                if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) {
+                    mTempTouchState.addOrUpdateWindow(window,
+                            InputTarget::FLAG_WINDOW_IS_OBSCURED, BitSet32(0));
+                }
+            }
+        }
+    }
+
+    // Success!  Output targets.
+    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
+
+    for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
+        const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
+        addWindowTargetLocked(touchedWindow.window, touchedWindow.targetFlags,
+                touchedWindow.pointerIds);
+    }
+
+    // Drop the outside touch window since we will not care about them in the next iteration.
+    mTempTouchState.removeOutsideTouchWindows();
+
+Failed:
+    // Check injection permission once and for all.
+    if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
+        if (checkInjectionPermission(NULL, entry->injectionState)) {
+            injectionPermission = INJECTION_PERMISSION_GRANTED;
+        } else {
+            injectionPermission = INJECTION_PERMISSION_DENIED;
+        }
+    }
+
+    // Update final pieces of touch state if the injector had permission.
+    if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
+        if (!wrongDevice) {
+            if (maskedAction == AMOTION_EVENT_ACTION_UP
+                    || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
+                // All pointers up or canceled.
+                mTempTouchState.reset();
+            } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
+                // First pointer went down.
+                if (mTouchState.down) {
+#if DEBUG_FOCUS
+                    LOGD("Pointer down received while already down.");
+#endif
+                }
+            } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
+                // One pointer went up.
+                if (isSplit) {
+                    int32_t pointerIndex = getMotionEventActionPointerIndex(action);
+                    uint32_t pointerId = entry->pointerIds[pointerIndex];
+
+                    for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
+                        TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
+                        if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
+                            touchedWindow.pointerIds.clearBit(pointerId);
+                            if (touchedWindow.pointerIds.isEmpty()) {
+                                mTempTouchState.windows.removeAt(i);
+                                continue;
+                            }
+                        }
+                        i += 1;
+                    }
+                }
+            }
+
+            // Save changes to touch state.
+            mTouchState.copyFrom(mTempTouchState);
+        }
+    } else {
+#if DEBUG_FOCUS
+        LOGD("Not updating touch focus because injection was denied.");
+#endif
+    }
+
+Unresponsive:
+    // Reset temporary touch state to ensure we release unnecessary references to input channels.
+    mTempTouchState.reset();
+
+    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
+    updateDispatchStatisticsLocked(currentTime, entry,
+            injectionResult, timeSpentWaitingForApplication);
+#if DEBUG_FOCUS
+    LOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
+            "timeSpentWaitingForApplication=%0.1fms",
+            injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
+#endif
+    return injectionResult;
+}
+
+void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
+        BitSet32 pointerIds) {
+    mCurrentInputTargets.push();
+
+    InputTarget& target = mCurrentInputTargets.editTop();
+    target.inputChannel = window->inputChannel;
+    target.flags = targetFlags;
+    target.xOffset = - window->frameLeft;
+    target.yOffset = - window->frameTop;
+    target.pointerIds = pointerIds;
+}
+
+void InputDispatcher::addMonitoringTargetsLocked() {
+    for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
+        mCurrentInputTargets.push();
+
+        InputTarget& target = mCurrentInputTargets.editTop();
+        target.inputChannel = mMonitoringChannels[i];
+        target.flags = 0;
+        target.xOffset = 0;
+        target.yOffset = 0;
+    }
+}
+
+bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
+        const InjectionState* injectionState) {
+    if (injectionState
+            && (window == NULL || window->ownerUid != injectionState->injectorUid)
+            && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
+        if (window) {
+            LOGW("Permission denied: injecting event from pid %d uid %d to window "
+                    "with input channel %s owned by uid %d",
+                    injectionState->injectorPid, injectionState->injectorUid,
+                    window->inputChannel->getName().string(),
+                    window->ownerUid);
+        } else {
+            LOGW("Permission denied: injecting event from pid %d uid %d",
+                    injectionState->injectorPid, injectionState->injectorUid);
+        }
+        return false;
+    }
+    return true;
+}
+
+bool InputDispatcher::isWindowObscuredAtPointLocked(
+        const InputWindow* window, int32_t x, int32_t y) const {
+    size_t numWindows = mWindows.size();
+    for (size_t i = 0; i < numWindows; i++) {
+        const InputWindow* other = & mWindows.itemAt(i);
+        if (other == window) {
+            break;
+        }
+        if (other->visible && ! other->isTrustedOverlay() && other->frameContainsPoint(x, y)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* window) {
+    ssize_t connectionIndex = getConnectionIndexLocked(window->inputChannel);
+    if (connectionIndex >= 0) {
+        sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
+        return connection->outboundQueue.isEmpty();
+    } else {
+        return true;
+    }
+}
+
+String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* application,
+        const InputWindow* window) {
+    if (application) {
+        if (window) {
+            String8 label(application->name);
+            label.append(" - ");
+            label.append(window->name);
+            return label;
+        } else {
+            return application->name;
+        }
+    } else if (window) {
+        return window->name;
+    } else {
+        return String8("<unknown application or window>");
+    }
+}
+
+void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
+    int32_t eventType = POWER_MANAGER_BUTTON_EVENT;
+    switch (eventEntry->type) {
+    case EventEntry::TYPE_MOTION: {
+        const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
+        if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
+            return;
+        }
+
+        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
+            eventType = POWER_MANAGER_TOUCH_EVENT;
+        }
+        break;
+    }
+    case EventEntry::TYPE_KEY: {
+        const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
+        if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
+            return;
+        }
+        break;
+    }
+    }
+
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doPokeUserActivityLockedInterruptible);
+    commandEntry->eventTime = eventEntry->eventTime;
+    commandEntry->userActivityEventType = eventType;
+}
+
+void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
+        bool resumeWithAppendedMotionSample) {
+#if DEBUG_DISPATCH_CYCLE
+    LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, "
+            "xOffset=%f, yOffset=%f, "
+            "pointerIds=0x%x, "
+            "resumeWithAppendedMotionSample=%s",
+            connection->getInputChannelName(), inputTarget->flags,
+            inputTarget->xOffset, inputTarget->yOffset,
+            inputTarget->pointerIds.value,
+            toString(resumeWithAppendedMotionSample));
+#endif
+
+    // Make sure we are never called for streaming when splitting across multiple windows.
+    bool isSplit = inputTarget->flags & InputTarget::FLAG_SPLIT;
+    assert(! (resumeWithAppendedMotionSample && isSplit));
+
+    // Skip this event if the connection status is not normal.
+    // We don't want to enqueue additional outbound events if the connection is broken.
+    if (connection->status != Connection::STATUS_NORMAL) {
+#if DEBUG_DISPATCH_CYCLE
+        LOGD("channel '%s' ~ Dropping event because the channel status is %s",
+                connection->getInputChannelName(), connection->getStatusLabel());
+#endif
+        return;
+    }
+
+    // Split a motion event if needed.
+    if (isSplit) {
+        assert(eventEntry->type == EventEntry::TYPE_MOTION);
+
+        MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
+        if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
+            MotionEntry* splitMotionEntry = splitMotionEvent(
+                    originalMotionEntry, inputTarget->pointerIds);
+#if DEBUG_FOCUS
+            LOGD("channel '%s' ~ Split motion event.",
+                    connection->getInputChannelName());
+            logOutboundMotionDetailsLocked("  ", splitMotionEntry);
+#endif
+            eventEntry = splitMotionEntry;
+        }
+    }
+
+    // Resume the dispatch cycle with a freshly appended motion sample.
+    // First we check that the last dispatch entry in the outbound queue is for the same
+    // motion event to which we appended the motion sample.  If we find such a dispatch
+    // entry, and if it is currently in progress then we try to stream the new sample.
+    bool wasEmpty = connection->outboundQueue.isEmpty();
+
+    if (! wasEmpty && resumeWithAppendedMotionSample) {
+        DispatchEntry* motionEventDispatchEntry =
+                connection->findQueuedDispatchEntryForEvent(eventEntry);
+        if (motionEventDispatchEntry) {
+            // If the dispatch entry is not in progress, then we must be busy dispatching an
+            // earlier event.  Not a problem, the motion event is on the outbound queue and will
+            // be dispatched later.
+            if (! motionEventDispatchEntry->inProgress) {
+#if DEBUG_BATCHING
+                LOGD("channel '%s' ~ Not streaming because the motion event has "
+                        "not yet been dispatched.  "
+                        "(Waiting for earlier events to be consumed.)",
+                        connection->getInputChannelName());
+#endif
+                return;
+            }
+
+            // If the dispatch entry is in progress but it already has a tail of pending
+            // motion samples, then it must mean that the shared memory buffer filled up.
+            // Not a problem, when this dispatch cycle is finished, we will eventually start
+            // a new dispatch cycle to process the tail and that tail includes the newly
+            // appended motion sample.
+            if (motionEventDispatchEntry->tailMotionSample) {
+#if DEBUG_BATCHING
+                LOGD("channel '%s' ~ Not streaming because no new samples can "
+                        "be appended to the motion event in this dispatch cycle.  "
+                        "(Waiting for next dispatch cycle to start.)",
+                        connection->getInputChannelName());
+#endif
+                return;
+            }
+
+            // The dispatch entry is in progress and is still potentially open for streaming.
+            // Try to stream the new motion sample.  This might fail if the consumer has already
+            // consumed the motion event (or if the channel is broken).
+            MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
+            MotionSample* appendedMotionSample = motionEntry->lastSample;
+            status_t status = connection->inputPublisher.appendMotionSample(
+                    appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
+            if (status == OK) {
+#if DEBUG_BATCHING
+                LOGD("channel '%s' ~ Successfully streamed new motion sample.",
+                        connection->getInputChannelName());
+#endif
+                return;
+            }
+
+#if DEBUG_BATCHING
+            if (status == NO_MEMORY) {
+                LOGD("channel '%s' ~ Could not append motion sample to currently "
+                        "dispatched move event because the shared memory buffer is full.  "
+                        "(Waiting for next dispatch cycle to start.)",
+                        connection->getInputChannelName());
+            } else if (status == status_t(FAILED_TRANSACTION)) {
+                LOGD("channel '%s' ~ Could not append motion sample to currently "
+                        "dispatched move event because the event has already been consumed.  "
+                        "(Waiting for next dispatch cycle to start.)",
+                        connection->getInputChannelName());
+            } else {
+                LOGD("channel '%s' ~ Could not append motion sample to currently "
+                        "dispatched move event due to an error, status=%d.  "
+                        "(Waiting for next dispatch cycle to start.)",
+                        connection->getInputChannelName(), status);
+            }
+#endif
+            // Failed to stream.  Start a new tail of pending motion samples to dispatch
+            // in the next cycle.
+            motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
+            return;
+        }
+    }
+
+    // This is a new event.
+    // Enqueue a new dispatch entry onto the outbound queue for this connection.
+    DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref
+            inputTarget->flags, inputTarget->xOffset, inputTarget->yOffset);
+    if (dispatchEntry->hasForegroundTarget()) {
+        incrementPendingForegroundDispatchesLocked(eventEntry);
+    }
+
+    // Handle the case where we could not stream a new motion sample because the consumer has
+    // already consumed the motion event (otherwise the corresponding dispatch entry would
+    // still be in the outbound queue for this connection).  We set the head motion sample
+    // to the list starting with the newly appended motion sample.
+    if (resumeWithAppendedMotionSample) {
+#if DEBUG_BATCHING
+        LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
+                "that cannot be streamed because the motion event has already been consumed.",
+                connection->getInputChannelName());
+#endif
+        MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
+        dispatchEntry->headMotionSample = appendedMotionSample;
+    }
+
+    // Enqueue the dispatch entry.
+    connection->outboundQueue.enqueueAtTail(dispatchEntry);
+
+    // If the outbound queue was previously empty, start the dispatch cycle going.
+    if (wasEmpty) {
+        activateConnectionLocked(connection.get());
+        startDispatchCycleLocked(currentTime, connection);
+    }
+}
+
+void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection) {
+#if DEBUG_DISPATCH_CYCLE
+    LOGD("channel '%s' ~ startDispatchCycle",
+            connection->getInputChannelName());
+#endif
+
+    assert(connection->status == Connection::STATUS_NORMAL);
+    assert(! connection->outboundQueue.isEmpty());
+
+    DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
+    assert(! dispatchEntry->inProgress);
+
+    // Mark the dispatch entry as in progress.
+    dispatchEntry->inProgress = true;
+
+    // Update the connection's input state.
+    EventEntry* eventEntry = dispatchEntry->eventEntry;
+    InputState::Consistency consistency = connection->inputState.trackEvent(eventEntry);
+
+#if FILTER_INPUT_EVENTS
+    // Filter out inconsistent sequences of input events.
+    // The input system may drop or inject events in a way that could violate implicit
+    // invariants on input state and potentially cause an application to crash
+    // or think that a key or pointer is stuck down.  Technically we make no guarantees
+    // of consistency but it would be nice to improve on this where possible.
+    // XXX: This code is a proof of concept only.  Not ready for prime time.
+    if (consistency == InputState::TOLERABLE) {
+#if DEBUG_DISPATCH_CYCLE
+        LOGD("channel '%s' ~ Sending an event that is inconsistent with the connection's "
+                "current input state but that is likely to be tolerated by the application.",
+                connection->getInputChannelName());
+#endif
+    } else if (consistency == InputState::BROKEN) {
+        LOGI("channel '%s' ~ Dropping an event that is inconsistent with the connection's "
+                "current input state and that is likely to cause the application to crash.",
+                connection->getInputChannelName());
+        startNextDispatchCycleLocked(currentTime, connection);
+        return;
+    }
+#endif
+
+    // Publish the event.
+    status_t status;
+    switch (eventEntry->type) {
+    case EventEntry::TYPE_KEY: {
+        KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
+
+        // Apply target flags.
+        int32_t action = keyEntry->action;
+        int32_t flags = keyEntry->flags;
+
+        // Publish the key event.
+        status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
+                action, flags, keyEntry->keyCode, keyEntry->scanCode,
+                keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
+                keyEntry->eventTime);
+
+        if (status) {
+            LOGE("channel '%s' ~ Could not publish key event, "
+                    "status=%d", connection->getInputChannelName(), status);
+            abortBrokenDispatchCycleLocked(currentTime, connection);
+            return;
+        }
+        break;
+    }
+
+    case EventEntry::TYPE_MOTION: {
+        MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
+
+        // Apply target flags.
+        int32_t action = motionEntry->action;
+        int32_t flags = motionEntry->flags;
+        if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
+            action = AMOTION_EVENT_ACTION_OUTSIDE;
+        }
+        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
+            flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+        }
+
+        // If headMotionSample is non-NULL, then it points to the first new sample that we
+        // were unable to dispatch during the previous cycle so we resume dispatching from
+        // that point in the list of motion samples.
+        // Otherwise, we just start from the first sample of the motion event.
+        MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
+        if (! firstMotionSample) {
+            firstMotionSample = & motionEntry->firstSample;
+        }
+
+        // Set the X and Y offset depending on the input source.
+        float xOffset, yOffset;
+        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
+            xOffset = dispatchEntry->xOffset;
+            yOffset = dispatchEntry->yOffset;
+        } else {
+            xOffset = 0.0f;
+            yOffset = 0.0f;
+        }
+
+        // Publish the motion event and the first motion sample.
+        status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
+                motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
+                xOffset, yOffset,
+                motionEntry->xPrecision, motionEntry->yPrecision,
+                motionEntry->downTime, firstMotionSample->eventTime,
+                motionEntry->pointerCount, motionEntry->pointerIds,
+                firstMotionSample->pointerCoords);
+
+        if (status) {
+            LOGE("channel '%s' ~ Could not publish motion event, "
+                    "status=%d", connection->getInputChannelName(), status);
+            abortBrokenDispatchCycleLocked(currentTime, connection);
+            return;
+        }
+
+        // Append additional motion samples.
+        MotionSample* nextMotionSample = firstMotionSample->next;
+        for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
+            status = connection->inputPublisher.appendMotionSample(
+                    nextMotionSample->eventTime, nextMotionSample->pointerCoords);
+            if (status == NO_MEMORY) {
+#if DEBUG_DISPATCH_CYCLE
+                    LOGD("channel '%s' ~ Shared memory buffer full.  Some motion samples will "
+                            "be sent in the next dispatch cycle.",
+                            connection->getInputChannelName());
+#endif
+                break;
+            }
+            if (status != OK) {
+                LOGE("channel '%s' ~ Could not append motion sample "
+                        "for a reason other than out of memory, status=%d",
+                        connection->getInputChannelName(), status);
+                abortBrokenDispatchCycleLocked(currentTime, connection);
+                return;
+            }
+        }
+
+        // Remember the next motion sample that we could not dispatch, in case we ran out
+        // of space in the shared memory buffer.
+        dispatchEntry->tailMotionSample = nextMotionSample;
+        break;
+    }
+
+    default: {
+        assert(false);
+    }
+    }
+
+    // Send the dispatch signal.
+    status = connection->inputPublisher.sendDispatchSignal();
+    if (status) {
+        LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
+                connection->getInputChannelName(), status);
+        abortBrokenDispatchCycleLocked(currentTime, connection);
+        return;
+    }
+
+    // Record information about the newly started dispatch cycle.
+    connection->lastEventTime = eventEntry->eventTime;
+    connection->lastDispatchTime = currentTime;
+
+    // Notify other system components.
+    onDispatchCycleStartedLocked(currentTime, connection);
+}
+
+void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection, bool handled) {
+#if DEBUG_DISPATCH_CYCLE
+    LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
+            "%01.1fms since dispatch, handled=%s",
+            connection->getInputChannelName(),
+            connection->getEventLatencyMillis(currentTime),
+            connection->getDispatchLatencyMillis(currentTime),
+            toString(handled));
+#endif
+
+    if (connection->status == Connection::STATUS_BROKEN
+            || connection->status == Connection::STATUS_ZOMBIE) {
+        return;
+    }
+
+    // Reset the publisher since the event has been consumed.
+    // We do this now so that the publisher can release some of its internal resources
+    // while waiting for the next dispatch cycle to begin.
+    status_t status = connection->inputPublisher.reset();
+    if (status) {
+        LOGE("channel '%s' ~ Could not reset publisher, status=%d",
+                connection->getInputChannelName(), status);
+        abortBrokenDispatchCycleLocked(currentTime, connection);
+        return;
+    }
+
+    // Notify other system components and prepare to start the next dispatch cycle.
+    onDispatchCycleFinishedLocked(currentTime, connection, handled);
+}
+
+void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection) {
+    // Start the next dispatch cycle for this connection.
+    while (! connection->outboundQueue.isEmpty()) {
+        DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
+        if (dispatchEntry->inProgress) {
+             // Finish or resume current event in progress.
+            if (dispatchEntry->tailMotionSample) {
+                // We have a tail of undispatched motion samples.
+                // Reuse the same DispatchEntry and start a new cycle.
+                dispatchEntry->inProgress = false;
+                dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
+                dispatchEntry->tailMotionSample = NULL;
+                startDispatchCycleLocked(currentTime, connection);
+                return;
+            }
+            // Finished.
+            connection->outboundQueue.dequeueAtHead();
+            if (dispatchEntry->hasForegroundTarget()) {
+                decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
+            }
+            mAllocator.releaseDispatchEntry(dispatchEntry);
+        } else {
+            // If the head is not in progress, then we must have already dequeued the in
+            // progress event, which means we actually aborted it.
+            // So just start the next event for this connection.
+            startDispatchCycleLocked(currentTime, connection);
+            return;
+        }
+    }
+
+    // Outbound queue is empty, deactivate the connection.
+    deactivateConnectionLocked(connection.get());
+}
+
+void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
+        const sp<Connection>& connection) {
+#if DEBUG_DISPATCH_CYCLE
+    LOGD("channel '%s' ~ abortBrokenDispatchCycle",
+            connection->getInputChannelName());
+#endif
+
+    // Clear the outbound queue.
+    drainOutboundQueueLocked(connection.get());
+
+    // The connection appears to be unrecoverably broken.
+    // Ignore already broken or zombie connections.
+    if (connection->status == Connection::STATUS_NORMAL) {
+        connection->status = Connection::STATUS_BROKEN;
+
+        // Notify other system components.
+        onDispatchCycleBrokenLocked(currentTime, connection);
+    }
+}
+
+void InputDispatcher::drainOutboundQueueLocked(Connection* connection) {
+    while (! connection->outboundQueue.isEmpty()) {
+        DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
+        if (dispatchEntry->hasForegroundTarget()) {
+            decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
+        }
+        mAllocator.releaseDispatchEntry(dispatchEntry);
+    }
+
+    deactivateConnectionLocked(connection);
+}
+
+int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
+    InputDispatcher* d = static_cast<InputDispatcher*>(data);
+
+    { // acquire lock
+        AutoMutex _l(d->mLock);
+
+        ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
+        if (connectionIndex < 0) {
+            LOGE("Received spurious receive callback for unknown input channel.  "
+                    "fd=%d, events=0x%x", receiveFd, events);
+            return 0; // remove the callback
+        }
+
+        nsecs_t currentTime = now();
+
+        sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
+        if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
+            LOGE("channel '%s' ~ Consumer closed input channel or an error occurred.  "
+                    "events=0x%x", connection->getInputChannelName(), events);
+            d->abortBrokenDispatchCycleLocked(currentTime, connection);
+            d->runCommandsLockedInterruptible();
+            return 0; // remove the callback
+        }
+
+        if (! (events & ALOOPER_EVENT_INPUT)) {
+            LOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
+                    "events=0x%x", connection->getInputChannelName(), events);
+            return 1;
+        }
+
+        bool handled = false;
+        status_t status = connection->inputPublisher.receiveFinishedSignal(&handled);
+        if (status) {
+            LOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
+                    connection->getInputChannelName(), status);
+            d->abortBrokenDispatchCycleLocked(currentTime, connection);
+            d->runCommandsLockedInterruptible();
+            return 0; // remove the callback
+        }
+
+        d->finishDispatchCycleLocked(currentTime, connection, handled);
+        d->runCommandsLockedInterruptible();
+        return 1;
+    } // release lock
+}
+
+void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
+        InputState::CancelationOptions options, const char* reason) {
+    for (size_t i = 0; i < mConnectionsByReceiveFd.size(); i++) {
+        synthesizeCancelationEventsForConnectionLocked(
+                mConnectionsByReceiveFd.valueAt(i), options, reason);
+    }
+}
+
+void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
+        const sp<InputChannel>& channel, InputState::CancelationOptions options,
+        const char* reason) {
+    ssize_t index = getConnectionIndexLocked(channel);
+    if (index >= 0) {
+        synthesizeCancelationEventsForConnectionLocked(
+                mConnectionsByReceiveFd.valueAt(index), options, reason);
+    }
+}
+
+void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
+        const sp<Connection>& connection, InputState::CancelationOptions options,
+        const char* reason) {
+    nsecs_t currentTime = now();
+
+    mTempCancelationEvents.clear();
+    connection->inputState.synthesizeCancelationEvents(currentTime, & mAllocator,
+            mTempCancelationEvents, options);
+
+    if (! mTempCancelationEvents.isEmpty()
+            && connection->status != Connection::STATUS_BROKEN) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        LOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
+                "with reality: %s, options=%d.",
+                connection->getInputChannelName(), mTempCancelationEvents.size(), reason, options);
+#endif
+        for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
+            EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
+            switch (cancelationEventEntry->type) {
+            case EventEntry::TYPE_KEY:
+                logOutboundKeyDetailsLocked("cancel - ",
+                        static_cast<KeyEntry*>(cancelationEventEntry));
+                break;
+            case EventEntry::TYPE_MOTION:
+                logOutboundMotionDetailsLocked("cancel - ",
+                        static_cast<MotionEntry*>(cancelationEventEntry));
+                break;
+            }
+
+            int32_t xOffset, yOffset;
+            const InputWindow* window = getWindowLocked(connection->inputChannel);
+            if (window) {
+                xOffset = -window->frameLeft;
+                yOffset = -window->frameTop;
+            } else {
+                xOffset = 0;
+                yOffset = 0;
+            }
+
+            DispatchEntry* cancelationDispatchEntry =
+                    mAllocator.obtainDispatchEntry(cancelationEventEntry, // increments ref
+                    0, xOffset, yOffset);
+            connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
+
+            mAllocator.releaseEventEntry(cancelationEventEntry);
+        }
+
+        if (!connection->outboundQueue.headSentinel.next->inProgress) {
+            startDispatchCycleLocked(currentTime, connection);
+        }
+    }
+}
+
+InputDispatcher::MotionEntry*
+InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
+    assert(pointerIds.value != 0);
+
+    uint32_t splitPointerIndexMap[MAX_POINTERS];
+    int32_t splitPointerIds[MAX_POINTERS];
+    PointerCoords splitPointerCoords[MAX_POINTERS];
+
+    uint32_t originalPointerCount = originalMotionEntry->pointerCount;
+    uint32_t splitPointerCount = 0;
+
+    for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
+            originalPointerIndex++) {
+        int32_t pointerId = uint32_t(originalMotionEntry->pointerIds[originalPointerIndex]);
+        if (pointerIds.hasBit(pointerId)) {
+            splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
+            splitPointerIds[splitPointerCount] = pointerId;
+            splitPointerCoords[splitPointerCount] =
+                    originalMotionEntry->firstSample.pointerCoords[originalPointerIndex];
+            splitPointerCount += 1;
+        }
+    }
+    assert(splitPointerCount == pointerIds.count());
+
+    int32_t action = originalMotionEntry->action;
+    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
+    if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
+            || maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
+        int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
+        int32_t pointerId = originalMotionEntry->pointerIds[originalPointerIndex];
+        if (pointerIds.hasBit(pointerId)) {
+            if (pointerIds.count() == 1) {
+                // The first/last pointer went down/up.
+                action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
+                        ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
+            } else {
+                // A secondary pointer went down/up.
+                uint32_t splitPointerIndex = 0;
+                while (pointerId != splitPointerIds[splitPointerIndex]) {
+                    splitPointerIndex += 1;
+                }
+                action = maskedAction | (splitPointerIndex
+                        << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+            }
+        } else {
+            // An unrelated pointer changed.
+            action = AMOTION_EVENT_ACTION_MOVE;
+        }
+    }
+
+    MotionEntry* splitMotionEntry = mAllocator.obtainMotionEntry(
+            originalMotionEntry->eventTime,
+            originalMotionEntry->deviceId,
+            originalMotionEntry->source,
+            originalMotionEntry->policyFlags,
+            action,
+            originalMotionEntry->flags,
+            originalMotionEntry->metaState,
+            originalMotionEntry->edgeFlags,
+            originalMotionEntry->xPrecision,
+            originalMotionEntry->yPrecision,
+            originalMotionEntry->downTime,
+            splitPointerCount, splitPointerIds, splitPointerCoords);
+
+    for (MotionSample* originalMotionSample = originalMotionEntry->firstSample.next;
+            originalMotionSample != NULL; originalMotionSample = originalMotionSample->next) {
+        for (uint32_t splitPointerIndex = 0; splitPointerIndex < splitPointerCount;
+                splitPointerIndex++) {
+            uint32_t originalPointerIndex = splitPointerIndexMap[splitPointerIndex];
+            splitPointerCoords[splitPointerIndex] =
+                    originalMotionSample->pointerCoords[originalPointerIndex];
+        }
+
+        mAllocator.appendMotionSample(splitMotionEntry, originalMotionSample->eventTime,
+                splitPointerCoords);
+    }
+
+    return splitMotionEntry;
+}
+
+void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
+#endif
+
+    bool needWake;
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
+        needWake = enqueueInboundEventLocked(newEntry);
+    } // release lock
+
+    if (needWake) {
+        mLooper->wake();
+    }
+}
+
+void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
+        uint32_t policyFlags, int32_t action, int32_t flags,
+        int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    LOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
+            "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
+            eventTime, deviceId, source, policyFlags, action, flags,
+            keyCode, scanCode, metaState, downTime);
+#endif
+    if (! validateKeyEvent(action)) {
+        return;
+    }
+
+    if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
+        policyFlags |= POLICY_FLAG_VIRTUAL;
+        flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
+    }
+
+    policyFlags |= POLICY_FLAG_TRUSTED;
+
+    KeyEvent event;
+    event.initialize(deviceId, source, action, flags, keyCode, scanCode,
+            metaState, 0, downTime, eventTime);
+
+    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
+
+    if (policyFlags & POLICY_FLAG_WOKE_HERE) {
+        flags |= AKEY_EVENT_FLAG_WOKE_HERE;
+    }
+
+    bool needWake;
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        int32_t repeatCount = 0;
+        KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
+                deviceId, source, policyFlags, action, flags, keyCode, scanCode,
+                metaState, repeatCount, downTime);
+
+        needWake = enqueueInboundEventLocked(newEntry);
+    } // release lock
+
+    if (needWake) {
+        mLooper->wake();
+    }
+}
+
+void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
+        uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
+        uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+        float xPrecision, float yPrecision, nsecs_t downTime) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    LOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
+            "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
+            "xPrecision=%f, yPrecision=%f, downTime=%lld",
+            eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
+            xPrecision, yPrecision, downTime);
+    for (uint32_t i = 0; i < pointerCount; i++) {
+        LOGD("  Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
+                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
+                "orientation=%f",
+                i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
+                pointerCoords[i].pressure, pointerCoords[i].size,
+                pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
+                pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
+                pointerCoords[i].orientation);
+    }
+#endif
+    if (! validateMotionEvent(action, pointerCount, pointerIds)) {
+        return;
+    }
+
+    policyFlags |= POLICY_FLAG_TRUSTED;
+    mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
+
+    bool needWake;
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        // Attempt batching and streaming of move events.
+        if (action == AMOTION_EVENT_ACTION_MOVE) {
+            // BATCHING CASE
+            //
+            // Try to append a move sample to the tail of the inbound queue for this device.
+            // Give up if we encounter a non-move motion event for this device since that
+            // means we cannot append any new samples until a new motion event has started.
+            for (EventEntry* entry = mInboundQueue.tailSentinel.prev;
+                    entry != & mInboundQueue.headSentinel; entry = entry->prev) {
+                if (entry->type != EventEntry::TYPE_MOTION) {
+                    // Keep looking for motion events.
+                    continue;
+                }
+
+                MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
+                if (motionEntry->deviceId != deviceId) {
+                    // Keep looking for this device.
+                    continue;
+                }
+
+                if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
+                        || motionEntry->pointerCount != pointerCount
+                        || motionEntry->isInjected()) {
+                    // Last motion event in the queue for this device is not compatible for
+                    // appending new samples.  Stop here.
+                    goto NoBatchingOrStreaming;
+                }
+
+                // The last motion event is a move and is compatible for appending.
+                // Do the batching magic.
+                mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
+#if DEBUG_BATCHING
+                LOGD("Appended motion sample onto batch for most recent "
+                        "motion event for this device in the inbound queue.");
+#endif
+                return; // done!
+            }
+
+            // STREAMING CASE
+            //
+            // There is no pending motion event (of any kind) for this device in the inbound queue.
+            // Search the outbound queue for the current foreground targets to find a dispatched
+            // motion event that is still in progress.  If found, then, appen the new sample to
+            // that event and push it out to all current targets.  The logic in
+            // prepareDispatchCycleLocked takes care of the case where some targets may
+            // already have consumed the motion event by starting a new dispatch cycle if needed.
+            if (mCurrentInputTargetsValid) {
+                for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
+                    const InputTarget& inputTarget = mCurrentInputTargets[i];
+                    if ((inputTarget.flags & InputTarget::FLAG_FOREGROUND) == 0) {
+                        // Skip non-foreground targets.  We only want to stream if there is at
+                        // least one foreground target whose dispatch is still in progress.
+                        continue;
+                    }
+
+                    ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
+                    if (connectionIndex < 0) {
+                        // Connection must no longer be valid.
+                        continue;
+                    }
+
+                    sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
+                    if (connection->outboundQueue.isEmpty()) {
+                        // This foreground target has an empty outbound queue.
+                        continue;
+                    }
+
+                    DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
+                    if (! dispatchEntry->inProgress
+                            || dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION
+                            || dispatchEntry->isSplit()) {
+                        // No motion event is being dispatched, or it is being split across
+                        // windows in which case we cannot stream.
+                        continue;
+                    }
+
+                    MotionEntry* motionEntry = static_cast<MotionEntry*>(
+                            dispatchEntry->eventEntry);
+                    if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
+                            || motionEntry->deviceId != deviceId
+                            || motionEntry->pointerCount != pointerCount
+                            || motionEntry->isInjected()) {
+                        // The motion event is not compatible with this move.
+                        continue;
+                    }
+
+                    // Hurray!  This foreground target is currently dispatching a move event
+                    // that we can stream onto.  Append the motion sample and resume dispatch.
+                    mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
+#if DEBUG_BATCHING
+                    LOGD("Appended motion sample onto batch for most recently dispatched "
+                            "motion event for this device in the outbound queues.  "
+                            "Attempting to stream the motion sample.");
+#endif
+                    nsecs_t currentTime = now();
+                    dispatchEventToCurrentInputTargetsLocked(currentTime, motionEntry,
+                            true /*resumeWithAppendedMotionSample*/);
+
+                    runCommandsLockedInterruptible();
+                    return; // done!
+                }
+            }
+
+NoBatchingOrStreaming:;
+        }
+
+        // Just enqueue a new motion event.
+        MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
+                deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
+                xPrecision, yPrecision, downTime,
+                pointerCount, pointerIds, pointerCoords);
+
+        needWake = enqueueInboundEventLocked(newEntry);
+    } // release lock
+
+    if (needWake) {
+        mLooper->wake();
+    }
+}
+
+void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
+        uint32_t policyFlags) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    LOGD("notifySwitch - switchCode=%d, switchValue=%d, policyFlags=0x%x",
+            switchCode, switchValue, policyFlags);
+#endif
+
+    policyFlags |= POLICY_FLAG_TRUSTED;
+    mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
+}
+
+int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
+        int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+    LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
+            "syncMode=%d, timeoutMillis=%d",
+            event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
+#endif
+
+    nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
+
+    uint32_t policyFlags = POLICY_FLAG_INJECTED;
+    if (hasInjectionPermission(injectorPid, injectorUid)) {
+        policyFlags |= POLICY_FLAG_TRUSTED;
+    }
+
+    EventEntry* injectedEntry;
+    switch (event->getType()) {
+    case AINPUT_EVENT_TYPE_KEY: {
+        const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
+        int32_t action = keyEvent->getAction();
+        if (! validateKeyEvent(action)) {
+            return INPUT_EVENT_INJECTION_FAILED;
+        }
+
+        int32_t flags = keyEvent->getFlags();
+        if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
+            policyFlags |= POLICY_FLAG_VIRTUAL;
+        }
+
+        mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
+
+        if (policyFlags & POLICY_FLAG_WOKE_HERE) {
+            flags |= AKEY_EVENT_FLAG_WOKE_HERE;
+        }
+
+        mLock.lock();
+        injectedEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
+                keyEvent->getDeviceId(), keyEvent->getSource(),
+                policyFlags, action, flags,
+                keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
+                keyEvent->getRepeatCount(), keyEvent->getDownTime());
+        break;
+    }
+
+    case AINPUT_EVENT_TYPE_MOTION: {
+        const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
+        int32_t action = motionEvent->getAction();
+        size_t pointerCount = motionEvent->getPointerCount();
+        const int32_t* pointerIds = motionEvent->getPointerIds();
+        if (! validateMotionEvent(action, pointerCount, pointerIds)) {
+            return INPUT_EVENT_INJECTION_FAILED;
+        }
+
+        nsecs_t eventTime = motionEvent->getEventTime();
+        mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
+
+        mLock.lock();
+        const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
+        const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
+        MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
+                motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
+                action, motionEvent->getFlags(),
+                motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
+                motionEvent->getXPrecision(), motionEvent->getYPrecision(),
+                motionEvent->getDownTime(), uint32_t(pointerCount),
+                pointerIds, samplePointerCoords);
+        for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
+            sampleEventTimes += 1;
+            samplePointerCoords += pointerCount;
+            mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
+        }
+        injectedEntry = motionEntry;
+        break;
+    }
+
+    default:
+        LOGW("Cannot inject event of type %d", event->getType());
+        return INPUT_EVENT_INJECTION_FAILED;
+    }
+
+    InjectionState* injectionState = mAllocator.obtainInjectionState(injectorPid, injectorUid);
+    if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
+        injectionState->injectionIsAsync = true;
+    }
+
+    injectionState->refCount += 1;
+    injectedEntry->injectionState = injectionState;
+
+    bool needWake = enqueueInboundEventLocked(injectedEntry);
+    mLock.unlock();
+
+    if (needWake) {
+        mLooper->wake();
+    }
+
+    int32_t injectionResult;
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
+            injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
+        } else {
+            for (;;) {
+                injectionResult = injectionState->injectionResult;
+                if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
+                    break;
+                }
+
+                nsecs_t remainingTimeout = endTime - now();
+                if (remainingTimeout <= 0) {
+#if DEBUG_INJECTION
+                    LOGD("injectInputEvent - Timed out waiting for injection result "
+                            "to become available.");
+#endif
+                    injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
+                    break;
+                }
+
+                mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
+            }
+
+            if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
+                    && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
+                while (injectionState->pendingForegroundDispatches != 0) {
+#if DEBUG_INJECTION
+                    LOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
+                            injectionState->pendingForegroundDispatches);
+#endif
+                    nsecs_t remainingTimeout = endTime - now();
+                    if (remainingTimeout <= 0) {
+#if DEBUG_INJECTION
+                    LOGD("injectInputEvent - Timed out waiting for pending foreground "
+                            "dispatches to finish.");
+#endif
+                        injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
+                        break;
+                    }
+
+                    mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
+                }
+            }
+        }
+
+        mAllocator.releaseInjectionState(injectionState);
+    } // release lock
+
+#if DEBUG_INJECTION
+    LOGD("injectInputEvent - Finished with result %d.  "
+            "injectorPid=%d, injectorUid=%d",
+            injectionResult, injectorPid, injectorUid);
+#endif
+
+    return injectionResult;
+}
+
+bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
+    return injectorUid == 0
+            || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
+}
+
+void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
+    InjectionState* injectionState = entry->injectionState;
+    if (injectionState) {
+#if DEBUG_INJECTION
+        LOGD("Setting input event injection result to %d.  "
+                "injectorPid=%d, injectorUid=%d",
+                 injectionResult, injectionState->injectorPid, injectionState->injectorUid);
+#endif
+
+        if (injectionState->injectionIsAsync) {
+            // Log the outcome since the injector did not wait for the injection result.
+            switch (injectionResult) {
+            case INPUT_EVENT_INJECTION_SUCCEEDED:
+                LOGV("Asynchronous input event injection succeeded.");
+                break;
+            case INPUT_EVENT_INJECTION_FAILED:
+                LOGW("Asynchronous input event injection failed.");
+                break;
+            case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
+                LOGW("Asynchronous input event injection permission denied.");
+                break;
+            case INPUT_EVENT_INJECTION_TIMED_OUT:
+                LOGW("Asynchronous input event injection timed out.");
+                break;
+            }
+        }
+
+        injectionState->injectionResult = injectionResult;
+        mInjectionResultAvailableCondition.broadcast();
+    }
+}
+
+void InputDispatcher::incrementPendingForegroundDispatchesLocked(EventEntry* entry) {
+    InjectionState* injectionState = entry->injectionState;
+    if (injectionState) {
+        injectionState->pendingForegroundDispatches += 1;
+    }
+}
+
+void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* entry) {
+    InjectionState* injectionState = entry->injectionState;
+    if (injectionState) {
+        injectionState->pendingForegroundDispatches -= 1;
+
+        if (injectionState->pendingForegroundDispatches == 0) {
+            mInjectionSyncFinishedCondition.broadcast();
+        }
+    }
+}
+
+const InputWindow* InputDispatcher::getWindowLocked(const sp<InputChannel>& inputChannel) {
+    for (size_t i = 0; i < mWindows.size(); i++) {
+        const InputWindow* window = & mWindows[i];
+        if (window->inputChannel == inputChannel) {
+            return window;
+        }
+    }
+    return NULL;
+}
+
+void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
+#if DEBUG_FOCUS
+    LOGD("setInputWindows");
+#endif
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        // Clear old window pointers.
+        sp<InputChannel> oldFocusedWindowChannel;
+        if (mFocusedWindow) {
+            oldFocusedWindowChannel = mFocusedWindow->inputChannel;
+            mFocusedWindow = NULL;
+        }
+
+        mWindows.clear();
+
+        // Loop over new windows and rebuild the necessary window pointers for
+        // tracking focus and touch.
+        mWindows.appendVector(inputWindows);
+
+        size_t numWindows = mWindows.size();
+        for (size_t i = 0; i < numWindows; i++) {
+            const InputWindow* window = & mWindows.itemAt(i);
+            if (window->hasFocus) {
+                mFocusedWindow = window;
+                break;
+            }
+        }
+
+        if (oldFocusedWindowChannel != NULL) {
+            if (!mFocusedWindow || oldFocusedWindowChannel != mFocusedWindow->inputChannel) {
+#if DEBUG_FOCUS
+                LOGD("Focus left window: %s",
+                        oldFocusedWindowChannel->getName().string());
+#endif
+                synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel,
+                        InputState::CANCEL_NON_POINTER_EVENTS, "focus left window");
+                oldFocusedWindowChannel.clear();
+            }
+        }
+        if (mFocusedWindow && oldFocusedWindowChannel == NULL) {
+#if DEBUG_FOCUS
+            LOGD("Focus entered window: %s",
+                    mFocusedWindow->inputChannel->getName().string());
+#endif
+        }
+
+        for (size_t i = 0; i < mTouchState.windows.size(); ) {
+            TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
+            const InputWindow* window = getWindowLocked(touchedWindow.channel);
+            if (window) {
+                touchedWindow.window = window;
+                i += 1;
+            } else {
+#if DEBUG_FOCUS
+                LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string());
+#endif
+                synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel,
+                        InputState::CANCEL_POINTER_EVENTS, "touched window was removed");
+                mTouchState.windows.removeAt(i);
+            }
+        }
+
+#if DEBUG_FOCUS
+        //logDispatchStateLocked();
+#endif
+    } // release lock
+
+    // Wake up poll loop since it may need to make new input dispatching choices.
+    mLooper->wake();
+}
+
+void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) {
+#if DEBUG_FOCUS
+    LOGD("setFocusedApplication");
+#endif
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        releaseFocusedApplicationLocked();
+
+        if (inputApplication) {
+            mFocusedApplicationStorage = *inputApplication;
+            mFocusedApplication = & mFocusedApplicationStorage;
+        }
+
+#if DEBUG_FOCUS
+        //logDispatchStateLocked();
+#endif
+    } // release lock
+
+    // Wake up poll loop since it may need to make new input dispatching choices.
+    mLooper->wake();
+}
+
+void InputDispatcher::releaseFocusedApplicationLocked() {
+    if (mFocusedApplication) {
+        mFocusedApplication = NULL;
+        mFocusedApplicationStorage.inputApplicationHandle.clear();
+    }
+}
+
+void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
+#if DEBUG_FOCUS
+    LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
+#endif
+
+    bool changed;
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
+            if (mDispatchFrozen && !frozen) {
+                resetANRTimeoutsLocked();
+            }
+
+            if (mDispatchEnabled && !enabled) {
+                resetAndDropEverythingLocked("dispatcher is being disabled");
+            }
+
+            mDispatchEnabled = enabled;
+            mDispatchFrozen = frozen;
+            changed = true;
+        } else {
+            changed = false;
+        }
+
+#if DEBUG_FOCUS
+        //logDispatchStateLocked();
+#endif
+    } // release lock
+
+    if (changed) {
+        // Wake up poll loop since it may need to make new input dispatching choices.
+        mLooper->wake();
+    }
+}
+
+bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
+        const sp<InputChannel>& toChannel) {
+#if DEBUG_FOCUS
+    LOGD("transferTouchFocus: fromChannel=%s, toChannel=%s",
+            fromChannel->getName().string(), toChannel->getName().string());
+#endif
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        const InputWindow* fromWindow = getWindowLocked(fromChannel);
+        const InputWindow* toWindow = getWindowLocked(toChannel);
+        if (! fromWindow || ! toWindow) {
+#if DEBUG_FOCUS
+            LOGD("Cannot transfer focus because from or to window not found.");
+#endif
+            return false;
+        }
+        if (fromWindow == toWindow) {
+#if DEBUG_FOCUS
+            LOGD("Trivial transfer to same window.");
+#endif
+            return true;
+        }
+
+        bool found = false;
+        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
+            const TouchedWindow& touchedWindow = mTouchState.windows[i];
+            if (touchedWindow.window == fromWindow) {
+                int32_t oldTargetFlags = touchedWindow.targetFlags;
+                BitSet32 pointerIds = touchedWindow.pointerIds;
+
+                mTouchState.windows.removeAt(i);
+
+                int32_t newTargetFlags = oldTargetFlags
+                        & (InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_SPLIT);
+                mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds);
+
+                found = true;
+                break;
+            }
+        }
+
+        if (! found) {
+#if DEBUG_FOCUS
+            LOGD("Focus transfer failed because from window did not have focus.");
+#endif
+            return false;
+        }
+
+        ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
+        ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel);
+        if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) {
+            sp<Connection> fromConnection = mConnectionsByReceiveFd.valueAt(fromConnectionIndex);
+            sp<Connection> toConnection = mConnectionsByReceiveFd.valueAt(toConnectionIndex);
+
+            fromConnection->inputState.copyPointerStateTo(toConnection->inputState);
+            synthesizeCancelationEventsForConnectionLocked(fromConnection,
+                    InputState::CANCEL_POINTER_EVENTS,
+                    "transferring touch focus from this window to another window");
+        }
+
+#if DEBUG_FOCUS
+        logDispatchStateLocked();
+#endif
+    } // release lock
+
+    // Wake up poll loop since it may need to make new input dispatching choices.
+    mLooper->wake();
+    return true;
+}
+
+void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
+#if DEBUG_FOCUS
+    LOGD("Resetting and dropping all events (%s).", reason);
+#endif
+
+    synthesizeCancelationEventsForAllConnectionsLocked(InputState::CANCEL_ALL_EVENTS, reason);
+
+    resetKeyRepeatLocked();
+    releasePendingEventLocked();
+    drainInboundQueueLocked();
+    resetTargetsLocked();
+
+    mTouchState.reset();
+}
+
+void InputDispatcher::logDispatchStateLocked() {
+    String8 dump;
+    dumpDispatchStateLocked(dump);
+
+    char* text = dump.lockBuffer(dump.size());
+    char* start = text;
+    while (*start != '\0') {
+        char* end = strchr(start, '\n');
+        if (*end == '\n') {
+            *(end++) = '\0';
+        }
+        LOGD("%s", start);
+        start = end;
+    }
+}
+
+void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
+    dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
+    dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
+
+    if (mFocusedApplication) {
+        dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
+                mFocusedApplication->name.string(),
+                mFocusedApplication->dispatchingTimeout / 1000000.0);
+    } else {
+        dump.append(INDENT "FocusedApplication: <null>\n");
+    }
+    dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
+            mFocusedWindow != NULL ? mFocusedWindow->name.string() : "<null>");
+
+    dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
+    dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
+    dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId);
+    if (!mTouchState.windows.isEmpty()) {
+        dump.append(INDENT "TouchedWindows:\n");
+        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
+            const TouchedWindow& touchedWindow = mTouchState.windows[i];
+            dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
+                    i, touchedWindow.window->name.string(), touchedWindow.pointerIds.value,
+                    touchedWindow.targetFlags);
+        }
+    } else {
+        dump.append(INDENT "TouchedWindows: <none>\n");
+    }
+
+    if (!mWindows.isEmpty()) {
+        dump.append(INDENT "Windows:\n");
+        for (size_t i = 0; i < mWindows.size(); i++) {
+            const InputWindow& window = mWindows[i];
+            dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
+                    "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
+                    "frame=[%d,%d][%d,%d], "
+                    "visibleFrame=[%d,%d][%d,%d], "
+                    "touchableArea=[%d,%d][%d,%d], "
+                    "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
+                    i, window.name.string(),
+                    toString(window.paused),
+                    toString(window.hasFocus),
+                    toString(window.hasWallpaper),
+                    toString(window.visible),
+                    toString(window.canReceiveKeys),
+                    window.layoutParamsFlags, window.layoutParamsType,
+                    window.layer,
+                    window.frameLeft, window.frameTop,
+                    window.frameRight, window.frameBottom,
+                    window.visibleFrameLeft, window.visibleFrameTop,
+                    window.visibleFrameRight, window.visibleFrameBottom,
+                    window.touchableAreaLeft, window.touchableAreaTop,
+                    window.touchableAreaRight, window.touchableAreaBottom,
+                    window.ownerPid, window.ownerUid,
+                    window.dispatchingTimeout / 1000000.0);
+        }
+    } else {
+        dump.append(INDENT "Windows: <none>\n");
+    }
+
+    if (!mMonitoringChannels.isEmpty()) {
+        dump.append(INDENT "MonitoringChannels:\n");
+        for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
+            const sp<InputChannel>& channel = mMonitoringChannels[i];
+            dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string());
+        }
+    } else {
+        dump.append(INDENT "MonitoringChannels: <none>\n");
+    }
+
+    dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
+
+    if (!mActiveConnections.isEmpty()) {
+        dump.append(INDENT "ActiveConnections:\n");
+        for (size_t i = 0; i < mActiveConnections.size(); i++) {
+            const Connection* connection = mActiveConnections[i];
+            dump.appendFormat(INDENT2 "%d: '%s', status=%s, outboundQueueLength=%u, "
+                    "inputState.isNeutral=%s\n",
+                    i, connection->getInputChannelName(), connection->getStatusLabel(),
+                    connection->outboundQueue.count(),
+                    toString(connection->inputState.isNeutral()));
+        }
+    } else {
+        dump.append(INDENT "ActiveConnections: <none>\n");
+    }
+
+    if (isAppSwitchPendingLocked()) {
+        dump.appendFormat(INDENT "AppSwitch: pending, due in %01.1fms\n",
+                (mAppSwitchDueTime - now()) / 1000000.0);
+    } else {
+        dump.append(INDENT "AppSwitch: not pending\n");
+    }
+}
+
+status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
+        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
+#if DEBUG_REGISTRATION
+    LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
+            toString(monitor));
+#endif
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        if (getConnectionIndexLocked(inputChannel) >= 0) {
+            LOGW("Attempted to register already registered input channel '%s'",
+                    inputChannel->getName().string());
+            return BAD_VALUE;
+        }
+
+        sp<Connection> connection = new Connection(inputChannel, inputWindowHandle);
+        status_t status = connection->initialize();
+        if (status) {
+            LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
+                    inputChannel->getName().string(), status);
+            return status;
+        }
+
+        int32_t receiveFd = inputChannel->getReceivePipeFd();
+        mConnectionsByReceiveFd.add(receiveFd, connection);
+
+        if (monitor) {
+            mMonitoringChannels.push(inputChannel);
+        }
+
+        mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
+
+        runCommandsLockedInterruptible();
+    } // release lock
+    return OK;
+}
+
+status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
+#if DEBUG_REGISTRATION
+    LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
+#endif
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
+        if (connectionIndex < 0) {
+            LOGW("Attempted to unregister already unregistered input channel '%s'",
+                    inputChannel->getName().string());
+            return BAD_VALUE;
+        }
+
+        sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
+        mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
+
+        connection->status = Connection::STATUS_ZOMBIE;
+
+        for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
+            if (mMonitoringChannels[i] == inputChannel) {
+                mMonitoringChannels.removeAt(i);
+                break;
+            }
+        }
+
+        mLooper->removeFd(inputChannel->getReceivePipeFd());
+
+        nsecs_t currentTime = now();
+        abortBrokenDispatchCycleLocked(currentTime, connection);
+
+        runCommandsLockedInterruptible();
+    } // release lock
+
+    // Wake the poll loop because removing the connection may have changed the current
+    // synchronization state.
+    mLooper->wake();
+    return OK;
+}
+
+ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
+    ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
+    if (connectionIndex >= 0) {
+        sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
+        if (connection->inputChannel.get() == inputChannel.get()) {
+            return connectionIndex;
+        }
+    }
+
+    return -1;
+}
+
+void InputDispatcher::activateConnectionLocked(Connection* connection) {
+    for (size_t i = 0; i < mActiveConnections.size(); i++) {
+        if (mActiveConnections.itemAt(i) == connection) {
+            return;
+        }
+    }
+    mActiveConnections.add(connection);
+}
+
+void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
+    for (size_t i = 0; i < mActiveConnections.size(); i++) {
+        if (mActiveConnections.itemAt(i) == connection) {
+            mActiveConnections.removeAt(i);
+            return;
+        }
+    }
+}
+
+void InputDispatcher::onDispatchCycleStartedLocked(
+        nsecs_t currentTime, const sp<Connection>& connection) {
+}
+
+void InputDispatcher::onDispatchCycleFinishedLocked(
+        nsecs_t currentTime, const sp<Connection>& connection, bool handled) {
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
+    commandEntry->connection = connection;
+    commandEntry->handled = handled;
+}
+
+void InputDispatcher::onDispatchCycleBrokenLocked(
+        nsecs_t currentTime, const sp<Connection>& connection) {
+    LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
+            connection->getInputChannelName());
+
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
+    commandEntry->connection = connection;
+}
+
+void InputDispatcher::onANRLocked(
+        nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
+        nsecs_t eventTime, nsecs_t waitStartTime) {
+    LOGI("Application is not responding: %s.  "
+            "%01.1fms since event, %01.1fms since wait started",
+            getApplicationWindowLabelLocked(application, window).string(),
+            (currentTime - eventTime) / 1000000.0,
+            (currentTime - waitStartTime) / 1000000.0);
+
+    CommandEntry* commandEntry = postCommandLocked(
+            & InputDispatcher::doNotifyANRLockedInterruptible);
+    if (application) {
+        commandEntry->inputApplicationHandle = application->inputApplicationHandle;
+    }
+    if (window) {
+        commandEntry->inputWindowHandle = window->inputWindowHandle;
+        commandEntry->inputChannel = window->inputChannel;
+    }
+}
+
+void InputDispatcher::doNotifyConfigurationChangedInterruptible(
+        CommandEntry* commandEntry) {
+    mLock.unlock();
+
+    mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
+
+    mLock.lock();
+}
+
+void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
+        CommandEntry* commandEntry) {
+    sp<Connection> connection = commandEntry->connection;
+
+    if (connection->status != Connection::STATUS_ZOMBIE) {
+        mLock.unlock();
+
+        mPolicy->notifyInputChannelBroken(connection->inputWindowHandle);
+
+        mLock.lock();
+    }
+}
+
+void InputDispatcher::doNotifyANRLockedInterruptible(
+        CommandEntry* commandEntry) {
+    mLock.unlock();
+
+    nsecs_t newTimeout = mPolicy->notifyANR(
+            commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle);
+
+    mLock.lock();
+
+    resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
+}
+
+void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
+        CommandEntry* commandEntry) {
+    KeyEntry* entry = commandEntry->keyEntry;
+
+    KeyEvent event;
+    initializeKeyEvent(&event, entry);
+
+    mLock.unlock();
+
+    bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
+            &event, entry->policyFlags);
+
+    mLock.lock();
+
+    entry->interceptKeyResult = consumed
+            ? KeyEntry::INTERCEPT_KEY_RESULT_SKIP
+            : KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
+    mAllocator.releaseKeyEntry(entry);
+}
+
+void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
+        CommandEntry* commandEntry) {
+    sp<Connection> connection = commandEntry->connection;
+    bool handled = commandEntry->handled;
+
+    if (!connection->outboundQueue.isEmpty()) {
+        DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
+        if (dispatchEntry->inProgress
+                && dispatchEntry->hasForegroundTarget()
+                && dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
+            KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
+            if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
+                if (handled) {
+                    // If the application handled a non-fallback key, then immediately
+                    // cancel all fallback keys previously dispatched to the application.
+                    // This behavior will prevent chording with fallback keys (so they cannot
+                    // be used as modifiers) but it will ensure that fallback keys do not
+                    // get stuck.  This takes care of the case where the application does not handle
+                    // the original DOWN so we generate a fallback DOWN but it does handle
+                    // the original UP in which case we would not generate the fallback UP.
+                    synthesizeCancelationEventsForConnectionLocked(connection,
+                            InputState::CANCEL_FALLBACK_EVENTS,
+                            "application handled a non-fallback event, canceling all fallback events");
+                } else {
+                    // If the application did not handle a non-fallback key, then ask
+                    // the policy what to do with it.  We might generate a fallback key
+                    // event here.
+                    KeyEvent event;
+                    initializeKeyEvent(&event, keyEntry);
+
+                    mLock.unlock();
+
+                    bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
+                            &event, keyEntry->policyFlags, &event);
+
+                    mLock.lock();
+
+                    if (connection->status != Connection::STATUS_NORMAL) {
+                        return;
+                    }
+
+                    assert(connection->outboundQueue.headSentinel.next == dispatchEntry);
+
+                    if (fallback) {
+                        // Restart the dispatch cycle using the fallback key.
+                        keyEntry->eventTime = event.getEventTime();
+                        keyEntry->deviceId = event.getDeviceId();
+                        keyEntry->source = event.getSource();
+                        keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
+                        keyEntry->keyCode = event.getKeyCode();
+                        keyEntry->scanCode = event.getScanCode();
+                        keyEntry->metaState = event.getMetaState();
+                        keyEntry->repeatCount = event.getRepeatCount();
+                        keyEntry->downTime = event.getDownTime();
+                        keyEntry->syntheticRepeat = false;
+
+                        dispatchEntry->inProgress = false;
+                        startDispatchCycleLocked(now(), connection);
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    startNextDispatchCycleLocked(now(), connection);
+}
+
+void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
+    mLock.unlock();
+
+    mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);
+
+    mLock.lock();
+}
+
+void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) {
+    event->initialize(entry->deviceId, entry->source, entry->action, entry->flags,
+            entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
+            entry->downTime, entry->eventTime);
+}
+
+void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
+        int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
+    // TODO Write some statistics about how long we spend waiting.
+}
+
+void InputDispatcher::dump(String8& dump) {
+    dump.append("Input Dispatcher State:\n");
+    dumpDispatchStateLocked(dump);
+}
+
+
+// --- InputDispatcher::Queue ---
+
+template <typename T>
+uint32_t InputDispatcher::Queue<T>::count() const {
+    uint32_t result = 0;
+    for (const T* entry = headSentinel.next; entry != & tailSentinel; entry = entry->next) {
+        result += 1;
+    }
+    return result;
+}
+
+
+// --- InputDispatcher::Allocator ---
+
+InputDispatcher::Allocator::Allocator() {
+}
+
+InputDispatcher::InjectionState*
+InputDispatcher::Allocator::obtainInjectionState(int32_t injectorPid, int32_t injectorUid) {
+    InjectionState* injectionState = mInjectionStatePool.alloc();
+    injectionState->refCount = 1;
+    injectionState->injectorPid = injectorPid;
+    injectionState->injectorUid = injectorUid;
+    injectionState->injectionIsAsync = false;
+    injectionState->injectionResult = INPUT_EVENT_INJECTION_PENDING;
+    injectionState->pendingForegroundDispatches = 0;
+    return injectionState;
+}
+
+void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
+        nsecs_t eventTime, uint32_t policyFlags) {
+    entry->type = type;
+    entry->refCount = 1;
+    entry->dispatchInProgress = false;
+    entry->eventTime = eventTime;
+    entry->policyFlags = policyFlags;
+    entry->injectionState = NULL;
+}
+
+void InputDispatcher::Allocator::releaseEventEntryInjectionState(EventEntry* entry) {
+    if (entry->injectionState) {
+        releaseInjectionState(entry->injectionState);
+        entry->injectionState = NULL;
+    }
+}
+
+InputDispatcher::ConfigurationChangedEntry*
+InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
+    ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
+    initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime, 0);
+    return entry;
+}
+
+InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
+        int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
+        int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
+        int32_t repeatCount, nsecs_t downTime) {
+    KeyEntry* entry = mKeyEntryPool.alloc();
+    initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime, policyFlags);
+
+    entry->deviceId = deviceId;
+    entry->source = source;
+    entry->action = action;
+    entry->flags = flags;
+    entry->keyCode = keyCode;
+    entry->scanCode = scanCode;
+    entry->metaState = metaState;
+    entry->repeatCount = repeatCount;
+    entry->downTime = downTime;
+    entry->syntheticRepeat = false;
+    entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
+    return entry;
+}
+
+InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
+        int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
+        int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
+        nsecs_t downTime, uint32_t pointerCount,
+        const int32_t* pointerIds, const PointerCoords* pointerCoords) {
+    MotionEntry* entry = mMotionEntryPool.alloc();
+    initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime, policyFlags);
+
+    entry->eventTime = eventTime;
+    entry->deviceId = deviceId;
+    entry->source = source;
+    entry->action = action;
+    entry->flags = flags;
+    entry->metaState = metaState;
+    entry->edgeFlags = edgeFlags;
+    entry->xPrecision = xPrecision;
+    entry->yPrecision = yPrecision;
+    entry->downTime = downTime;
+    entry->pointerCount = pointerCount;
+    entry->firstSample.eventTime = eventTime;
+    entry->firstSample.next = NULL;
+    entry->lastSample = & entry->firstSample;
+    for (uint32_t i = 0; i < pointerCount; i++) {
+        entry->pointerIds[i] = pointerIds[i];
+        entry->firstSample.pointerCoords[i] = pointerCoords[i];
+    }
+    return entry;
+}
+
+InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
+        EventEntry* eventEntry,
+        int32_t targetFlags, float xOffset, float yOffset) {
+    DispatchEntry* entry = mDispatchEntryPool.alloc();
+    entry->eventEntry = eventEntry;
+    eventEntry->refCount += 1;
+    entry->targetFlags = targetFlags;
+    entry->xOffset = xOffset;
+    entry->yOffset = yOffset;
+    entry->inProgress = false;
+    entry->headMotionSample = NULL;
+    entry->tailMotionSample = NULL;
+    return entry;
+}
+
+InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
+    CommandEntry* entry = mCommandEntryPool.alloc();
+    entry->command = command;
+    return entry;
+}
+
+void InputDispatcher::Allocator::releaseInjectionState(InjectionState* injectionState) {
+    injectionState->refCount -= 1;
+    if (injectionState->refCount == 0) {
+        mInjectionStatePool.free(injectionState);
+    } else {
+        assert(injectionState->refCount > 0);
+    }
+}
+
+void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
+    switch (entry->type) {
+    case EventEntry::TYPE_CONFIGURATION_CHANGED:
+        releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
+        break;
+    case EventEntry::TYPE_KEY:
+        releaseKeyEntry(static_cast<KeyEntry*>(entry));
+        break;
+    case EventEntry::TYPE_MOTION:
+        releaseMotionEntry(static_cast<MotionEntry*>(entry));
+        break;
+    default:
+        assert(false);
+        break;
+    }
+}
+
+void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
+        ConfigurationChangedEntry* entry) {
+    entry->refCount -= 1;
+    if (entry->refCount == 0) {
+        releaseEventEntryInjectionState(entry);
+        mConfigurationChangeEntryPool.free(entry);
+    } else {
+        assert(entry->refCount > 0);
+    }
+}
+
+void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
+    entry->refCount -= 1;
+    if (entry->refCount == 0) {
+        releaseEventEntryInjectionState(entry);
+        mKeyEntryPool.free(entry);
+    } else {
+        assert(entry->refCount > 0);
+    }
+}
+
+void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
+    entry->refCount -= 1;
+    if (entry->refCount == 0) {
+        releaseEventEntryInjectionState(entry);
+        for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
+            MotionSample* next = sample->next;
+            mMotionSamplePool.free(sample);
+            sample = next;
+        }
+        mMotionEntryPool.free(entry);
+    } else {
+        assert(entry->refCount > 0);
+    }
+}
+
+void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
+    releaseEventEntry(entry->eventEntry);
+    mDispatchEntryPool.free(entry);
+}
+
+void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
+    mCommandEntryPool.free(entry);
+}
+
+void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
+        nsecs_t eventTime, const PointerCoords* pointerCoords) {
+    MotionSample* sample = mMotionSamplePool.alloc();
+    sample->eventTime = eventTime;
+    uint32_t pointerCount = motionEntry->pointerCount;
+    for (uint32_t i = 0; i < pointerCount; i++) {
+        sample->pointerCoords[i] = pointerCoords[i];
+    }
+
+    sample->next = NULL;
+    motionEntry->lastSample->next = sample;
+    motionEntry->lastSample = sample;
+}
+
+void InputDispatcher::Allocator::recycleKeyEntry(KeyEntry* keyEntry) {
+    releaseEventEntryInjectionState(keyEntry);
+
+    keyEntry->dispatchInProgress = false;
+    keyEntry->syntheticRepeat = false;
+    keyEntry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
+}
+
+
+// --- InputDispatcher::MotionEntry ---
+
+uint32_t InputDispatcher::MotionEntry::countSamples() const {
+    uint32_t count = 1;
+    for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
+        count += 1;
+    }
+    return count;
+}
+
+
+// --- InputDispatcher::InputState ---
+
+InputDispatcher::InputState::InputState() {
+}
+
+InputDispatcher::InputState::~InputState() {
+}
+
+bool InputDispatcher::InputState::isNeutral() const {
+    return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
+}
+
+InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackEvent(
+        const EventEntry* entry) {
+    switch (entry->type) {
+    case EventEntry::TYPE_KEY:
+        return trackKey(static_cast<const KeyEntry*>(entry));
+
+    case EventEntry::TYPE_MOTION:
+        return trackMotion(static_cast<const MotionEntry*>(entry));
+
+    default:
+        return CONSISTENT;
+    }
+}
+
+InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey(
+        const KeyEntry* entry) {
+    int32_t action = entry->action;
+    for (size_t i = 0; i < mKeyMementos.size(); i++) {
+        KeyMemento& memento = mKeyMementos.editItemAt(i);
+        if (memento.deviceId == entry->deviceId
+                && memento.source == entry->source
+                && memento.keyCode == entry->keyCode
+                && memento.scanCode == entry->scanCode) {
+            switch (action) {
+            case AKEY_EVENT_ACTION_UP:
+                mKeyMementos.removeAt(i);
+                return CONSISTENT;
+
+            case AKEY_EVENT_ACTION_DOWN:
+                return TOLERABLE;
+
+            default:
+                return BROKEN;
+            }
+        }
+    }
+
+    switch (action) {
+    case AKEY_EVENT_ACTION_DOWN: {
+        mKeyMementos.push();
+        KeyMemento& memento = mKeyMementos.editTop();
+        memento.deviceId = entry->deviceId;
+        memento.source = entry->source;
+        memento.keyCode = entry->keyCode;
+        memento.scanCode = entry->scanCode;
+        memento.flags = entry->flags;
+        memento.downTime = entry->downTime;
+        return CONSISTENT;
+    }
+
+    default:
+        return BROKEN;
+    }
+}
+
+InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotion(
+        const MotionEntry* entry) {
+    int32_t action = entry->action & AMOTION_EVENT_ACTION_MASK;
+    for (size_t i = 0; i < mMotionMementos.size(); i++) {
+        MotionMemento& memento = mMotionMementos.editItemAt(i);
+        if (memento.deviceId == entry->deviceId
+                && memento.source == entry->source) {
+            switch (action) {
+            case AMOTION_EVENT_ACTION_UP:
+            case AMOTION_EVENT_ACTION_CANCEL:
+                mMotionMementos.removeAt(i);
+                return CONSISTENT;
+
+            case AMOTION_EVENT_ACTION_DOWN:
+                return TOLERABLE;
+
+            case AMOTION_EVENT_ACTION_POINTER_DOWN:
+                if (entry->pointerCount == memento.pointerCount + 1) {
+                    memento.setPointers(entry);
+                    return CONSISTENT;
+                }
+                return BROKEN;
+
+            case AMOTION_EVENT_ACTION_POINTER_UP:
+                if (entry->pointerCount == memento.pointerCount - 1) {
+                    memento.setPointers(entry);
+                    return CONSISTENT;
+                }
+                return BROKEN;
+
+            case AMOTION_EVENT_ACTION_MOVE:
+                if (entry->pointerCount == memento.pointerCount) {
+                    return CONSISTENT;
+                }
+                return BROKEN;
+
+            default:
+                return BROKEN;
+            }
+        }
+    }
+
+    switch (action) {
+    case AMOTION_EVENT_ACTION_DOWN: {
+        mMotionMementos.push();
+        MotionMemento& memento = mMotionMementos.editTop();
+        memento.deviceId = entry->deviceId;
+        memento.source = entry->source;
+        memento.xPrecision = entry->xPrecision;
+        memento.yPrecision = entry->yPrecision;
+        memento.downTime = entry->downTime;
+        memento.setPointers(entry);
+        return CONSISTENT;
+    }
+
+    default:
+        return BROKEN;
+    }
+}
+
+void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
+    pointerCount = entry->pointerCount;
+    for (uint32_t i = 0; i < entry->pointerCount; i++) {
+        pointerIds[i] = entry->pointerIds[i];
+        pointerCoords[i] = entry->lastSample->pointerCoords[i];
+    }
+}
+
+void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
+        Allocator* allocator, Vector<EventEntry*>& outEvents,
+        CancelationOptions options) {
+    for (size_t i = 0; i < mKeyMementos.size(); ) {
+        const KeyMemento& memento = mKeyMementos.itemAt(i);
+        if (shouldCancelKey(memento, options)) {
+            outEvents.push(allocator->obtainKeyEntry(currentTime,
+                    memento.deviceId, memento.source, 0,
+                    AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
+                    memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
+            mKeyMementos.removeAt(i);
+        } else {
+            i += 1;
+        }
+    }
+
+    for (size_t i = 0; i < mMotionMementos.size(); ) {
+        const MotionMemento& memento = mMotionMementos.itemAt(i);
+        if (shouldCancelMotion(memento, options)) {
+            outEvents.push(allocator->obtainMotionEntry(currentTime,
+                    memento.deviceId, memento.source, 0,
+                    AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
+                    memento.xPrecision, memento.yPrecision, memento.downTime,
+                    memento.pointerCount, memento.pointerIds, memento.pointerCoords));
+            mMotionMementos.removeAt(i);
+        } else {
+            i += 1;
+        }
+    }
+}
+
+void InputDispatcher::InputState::clear() {
+    mKeyMementos.clear();
+    mMotionMementos.clear();
+}
+
+void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const {
+    for (size_t i = 0; i < mMotionMementos.size(); i++) {
+        const MotionMemento& memento = mMotionMementos.itemAt(i);
+        if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
+            for (size_t j = 0; j < other.mMotionMementos.size(); ) {
+                const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j);
+                if (memento.deviceId == otherMemento.deviceId
+                        && memento.source == otherMemento.source) {
+                    other.mMotionMementos.removeAt(j);
+                } else {
+                    j += 1;
+                }
+            }
+            other.mMotionMementos.push(memento);
+        }
+    }
+}
+
+bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
+        CancelationOptions options) {
+    switch (options) {
+    case CANCEL_ALL_EVENTS:
+    case CANCEL_NON_POINTER_EVENTS:
+        return true;
+    case CANCEL_FALLBACK_EVENTS:
+        return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
+    default:
+        return false;
+    }
+}
+
+bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
+        CancelationOptions options) {
+    switch (options) {
+    case CANCEL_ALL_EVENTS:
+        return true;
+    case CANCEL_POINTER_EVENTS:
+        return memento.source & AINPUT_SOURCE_CLASS_POINTER;
+    case CANCEL_NON_POINTER_EVENTS:
+        return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
+    default:
+        return false;
+    }
+}
+
+
+// --- InputDispatcher::Connection ---
+
+InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
+        const sp<InputWindowHandle>& inputWindowHandle) :
+        status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
+        inputPublisher(inputChannel),
+        lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
+}
+
+InputDispatcher::Connection::~Connection() {
+}
+
+status_t InputDispatcher::Connection::initialize() {
+    return inputPublisher.initialize();
+}
+
+const char* InputDispatcher::Connection::getStatusLabel() const {
+    switch (status) {
+    case STATUS_NORMAL:
+        return "NORMAL";
+
+    case STATUS_BROKEN:
+        return "BROKEN";
+
+    case STATUS_ZOMBIE:
+        return "ZOMBIE";
+
+    default:
+        return "UNKNOWN";
+    }
+}
+
+InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
+        const EventEntry* eventEntry) const {
+    for (DispatchEntry* dispatchEntry = outboundQueue.tailSentinel.prev;
+            dispatchEntry != & outboundQueue.headSentinel; dispatchEntry = dispatchEntry->prev) {
+        if (dispatchEntry->eventEntry == eventEntry) {
+            return dispatchEntry;
+        }
+    }
+    return NULL;
+}
+
+
+// --- InputDispatcher::CommandEntry ---
+
+InputDispatcher::CommandEntry::CommandEntry() :
+    keyEntry(NULL) {
+}
+
+InputDispatcher::CommandEntry::~CommandEntry() {
+}
+
+
+// --- InputDispatcher::TouchState ---
+
+InputDispatcher::TouchState::TouchState() :
+    down(false), split(false), deviceId(-1) {
+}
+
+InputDispatcher::TouchState::~TouchState() {
+}
+
+void InputDispatcher::TouchState::reset() {
+    down = false;
+    split = false;
+    deviceId = -1;
+    windows.clear();
+}
+
+void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
+    down = other.down;
+    split = other.split;
+    deviceId = other.deviceId;
+    windows.clear();
+    windows.appendVector(other.windows);
+}
+
+void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
+        int32_t targetFlags, BitSet32 pointerIds) {
+    if (targetFlags & InputTarget::FLAG_SPLIT) {
+        split = true;
+    }
+
+    for (size_t i = 0; i < windows.size(); i++) {
+        TouchedWindow& touchedWindow = windows.editItemAt(i);
+        if (touchedWindow.window == window) {
+            touchedWindow.targetFlags |= targetFlags;
+            touchedWindow.pointerIds.value |= pointerIds.value;
+            return;
+        }
+    }
+
+    windows.push();
+
+    TouchedWindow& touchedWindow = windows.editTop();
+    touchedWindow.window = window;
+    touchedWindow.targetFlags = targetFlags;
+    touchedWindow.pointerIds = pointerIds;
+    touchedWindow.channel = window->inputChannel;
+}
+
+void InputDispatcher::TouchState::removeOutsideTouchWindows() {
+    for (size_t i = 0 ; i < windows.size(); ) {
+        if (windows[i].targetFlags & InputTarget::FLAG_OUTSIDE) {
+            windows.removeAt(i);
+        } else {
+            i += 1;
+        }
+    }
+}
+
+const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() {
+    for (size_t i = 0; i < windows.size(); i++) {
+        if (windows[i].targetFlags & InputTarget::FLAG_FOREGROUND) {
+            return windows[i].window;
+        }
+    }
+    return NULL;
+}
+
+
+// --- InputDispatcherThread ---
+
+InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
+        Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
+}
+
+InputDispatcherThread::~InputDispatcherThread() {
+}
+
+bool InputDispatcherThread::threadLoop() {
+    mDispatcher->dispatchOnce();
+    return true;
+}
+
+} // namespace android
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
new file mode 100644
index 0000000..11e5117
--- /dev/null
+++ b/services/input/InputDispatcher.h
@@ -0,0 +1,1000 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UI_INPUT_DISPATCHER_H
+#define _UI_INPUT_DISPATCHER_H
+
+#include <ui/Input.h>
+#include <ui/InputTransport.h>
+#include <utils/KeyedVector.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Looper.h>
+#include <utils/Pool.h>
+#include <utils/BitSet.h>
+
+#include <stddef.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "InputWindow.h"
+#include "InputApplication.h"
+
+
+namespace android {
+
+/*
+ * Constants used to report the outcome of input event injection.
+ */
+enum {
+    /* (INTERNAL USE ONLY) Specifies that injection is pending and its outcome is unknown. */
+    INPUT_EVENT_INJECTION_PENDING = -1,
+
+    /* Injection succeeded. */
+    INPUT_EVENT_INJECTION_SUCCEEDED = 0,
+
+    /* Injection failed because the injector did not have permission to inject
+     * into the application with input focus. */
+    INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1,
+
+    /* Injection failed because there were no available input targets. */
+    INPUT_EVENT_INJECTION_FAILED = 2,
+
+    /* Injection failed due to a timeout. */
+    INPUT_EVENT_INJECTION_TIMED_OUT = 3
+};
+
+/*
+ * Constants used to determine the input event injection synchronization mode.
+ */
+enum {
+    /* Injection is asynchronous and is assumed always to be successful. */
+    INPUT_EVENT_INJECTION_SYNC_NONE = 0,
+
+    /* Waits for previous events to be dispatched so that the input dispatcher can determine
+     * whether input event injection willbe permitted based on the current input focus.
+     * Does not wait for the input event to finish processing. */
+    INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1,
+
+    /* Waits for the input event to be completely processed. */
+    INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED = 2,
+};
+
+
+/*
+ * An input target specifies how an input event is to be dispatched to a particular window
+ * including the window's input channel, control flags, a timeout, and an X / Y offset to
+ * be added to input event coordinates to compensate for the absolute position of the
+ * window area.
+ */
+struct InputTarget {
+    enum {
+        /* This flag indicates that the event is being delivered to a foreground application. */
+        FLAG_FOREGROUND = 0x01,
+
+        /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
+         * of the area of this target and so should instead be delivered as an
+         * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
+        FLAG_OUTSIDE = 0x02,
+
+        /* This flag indicates that the target of a MotionEvent is partly or wholly
+         * obscured by another visible window above it.  The motion event should be
+         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
+        FLAG_WINDOW_IS_OBSCURED = 0x04,
+
+        /* This flag indicates that a motion event is being split across multiple windows. */
+        FLAG_SPLIT = 0x08,
+    };
+
+    // The input channel to be targeted.
+    sp<InputChannel> inputChannel;
+
+    // Flags for the input target.
+    int32_t flags;
+
+    // The x and y offset to add to a MotionEvent as it is delivered.
+    // (ignored for KeyEvents)
+    float xOffset, yOffset;
+
+    // The subset of pointer ids to include in motion events dispatched to this input target
+    // if FLAG_SPLIT is set.
+    BitSet32 pointerIds;
+};
+
+
+/*
+ * Input dispatcher policy interface.
+ *
+ * The input reader policy is used by the input reader to interact with the Window Manager
+ * and other system components.
+ *
+ * The actual implementation is partially supported by callbacks into the DVM
+ * via JNI.  This interface is also mocked in the unit tests.
+ */
+class InputDispatcherPolicyInterface : public virtual RefBase {
+protected:
+    InputDispatcherPolicyInterface() { }
+    virtual ~InputDispatcherPolicyInterface() { }
+
+public:
+    /* Notifies the system that a configuration change has occurred. */
+    virtual void notifyConfigurationChanged(nsecs_t when) = 0;
+
+    /* Notifies the system that an application is not responding.
+     * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
+    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
+            const sp<InputWindowHandle>& inputWindowHandle) = 0;
+
+    /* Notifies the system that an input channel is unrecoverably broken. */
+    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
+
+    /* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */
+    virtual nsecs_t getKeyRepeatTimeout() = 0;
+
+    /* Gets the key repeat inter-key delay. */
+    virtual nsecs_t getKeyRepeatDelay() = 0;
+
+    /* Gets the maximum suggested event delivery rate per second.
+     * This value is used to throttle motion event movement actions on a per-device
+     * basis.  It is not intended to be a hard limit.
+     */
+    virtual int32_t getMaxEventsPerSecond() = 0;
+
+    /* Intercepts a key event immediately before queueing it.
+     * The policy can use this method as an opportunity to perform power management functions
+     * and early event preprocessing such as updating policy flags.
+     *
+     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
+     * should be dispatched to applications.
+     */
+    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;
+
+    /* Intercepts a generic touch, trackball or other event before queueing it.
+     * The policy can use this method as an opportunity to perform power management functions
+     * and early event preprocessing such as updating policy flags.
+     *
+     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
+     * should be dispatched to applications.
+     */
+    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
+
+    /* Allows the policy a chance to intercept a key before dispatching. */
+    virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
+            const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
+
+    /* Allows the policy a chance to perform default processing for an unhandled key.
+     * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
+    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
+            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
+
+    /* Notifies the policy about switch events.
+     */
+    virtual void notifySwitch(nsecs_t when,
+            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
+
+    /* Poke user activity for an event dispatched to a window. */
+    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;
+
+    /* Checks whether a given application pid/uid has permission to inject input events
+     * into other applications.
+     *
+     * This method is special in that its implementation promises to be non-reentrant and
+     * is safe to call while holding other locks.  (Most other methods make no such guarantees!)
+     */
+    virtual bool checkInjectEventsPermissionNonReentrant(
+            int32_t injectorPid, int32_t injectorUid) = 0;
+};
+
+
+/* Notifies the system about input events generated by the input reader.
+ * The dispatcher is expected to be mostly asynchronous. */
+class InputDispatcherInterface : public virtual RefBase {
+protected:
+    InputDispatcherInterface() { }
+    virtual ~InputDispatcherInterface() { }
+
+public:
+    /* Dumps the state of the input dispatcher.
+     *
+     * This method may be called on any thread (usually by the input manager). */
+    virtual void dump(String8& dump) = 0;
+
+    /* Runs a single iteration of the dispatch loop.
+     * Nominally processes one queued event, a timeout, or a response from an input consumer.
+     *
+     * This method should only be called on the input dispatcher thread.
+     */
+    virtual void dispatchOnce() = 0;
+
+    /* Notifies the dispatcher about new events.
+     *
+     * These methods should only be called on the input reader thread.
+     */
+    virtual void notifyConfigurationChanged(nsecs_t eventTime) = 0;
+    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
+            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
+            int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
+    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
+            uint32_t policyFlags, int32_t action, int32_t flags,
+            int32_t metaState, int32_t edgeFlags,
+            uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+            float xPrecision, float yPrecision, nsecs_t downTime) = 0;
+    virtual void notifySwitch(nsecs_t when,
+            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
+
+    /* Injects an input event and optionally waits for sync.
+     * The synchronization mode determines whether the method blocks while waiting for
+     * input injection to proceed.
+     * Returns one of the INPUT_EVENT_INJECTION_XXX constants.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual int32_t injectInputEvent(const InputEvent* event,
+            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) = 0;
+
+    /* Sets the list of input windows.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual void setInputWindows(const Vector<InputWindow>& inputWindows) = 0;
+
+    /* Sets the focused application.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual void setFocusedApplication(const InputApplication* inputApplication) = 0;
+
+    /* Sets the input dispatching mode.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;
+
+    /* Transfers touch focus from the window associated with one channel to the
+     * window associated with the other channel.
+     *
+     * Returns true on success.  False if the window did not actually have touch focus.
+     */
+    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
+            const sp<InputChannel>& toChannel) = 0;
+
+    /* Registers or unregister input channels that may be used as targets for input events.
+     * If monitor is true, the channel will receive a copy of all input events.
+     *
+     * These methods may be called on any thread (usually by the input manager).
+     */
+    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+            const sp<InputWindowHandle>& inputWindowHandle, bool monitor) = 0;
+    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
+};
+
+/* Dispatches events to input targets.  Some functions of the input dispatcher, such as
+ * identifying input targets, are controlled by a separate policy object.
+ *
+ * IMPORTANT INVARIANT:
+ *     Because the policy can potentially block or cause re-entrance into the input dispatcher,
+ *     the input dispatcher never calls into the policy while holding its internal locks.
+ *     The implementation is also carefully designed to recover from scenarios such as an
+ *     input channel becoming unregistered while identifying input targets or processing timeouts.
+ *
+ *     Methods marked 'Locked' must be called with the lock acquired.
+ *
+ *     Methods marked 'LockedInterruptible' must be called with the lock acquired but
+ *     may during the course of their execution release the lock, call into the policy, and
+ *     then reacquire the lock.  The caller is responsible for recovering gracefully.
+ *
+ *     A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa.
+ */
+class InputDispatcher : public InputDispatcherInterface {
+protected:
+    virtual ~InputDispatcher();
+
+public:
+    explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
+
+    virtual void dump(String8& dump);
+
+    virtual void dispatchOnce();
+
+    virtual void notifyConfigurationChanged(nsecs_t eventTime);
+    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
+            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
+            int32_t scanCode, int32_t metaState, nsecs_t downTime);
+    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
+            uint32_t policyFlags, int32_t action, int32_t flags,
+            int32_t metaState, int32_t edgeFlags,
+            uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+            float xPrecision, float yPrecision, nsecs_t downTime);
+    virtual void notifySwitch(nsecs_t when,
+            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) ;
+
+    virtual int32_t injectInputEvent(const InputEvent* event,
+            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis);
+
+    virtual void setInputWindows(const Vector<InputWindow>& inputWindows);
+    virtual void setFocusedApplication(const InputApplication* inputApplication);
+    virtual void setInputDispatchMode(bool enabled, bool frozen);
+
+    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
+            const sp<InputChannel>& toChannel);
+
+    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+            const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
+    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
+
+private:
+    template <typename T>
+    struct Link {
+        T* next;
+        T* prev;
+    };
+
+    struct InjectionState {
+        mutable int32_t refCount;
+
+        int32_t injectorPid;
+        int32_t injectorUid;
+        int32_t injectionResult;  // initially INPUT_EVENT_INJECTION_PENDING
+        bool injectionIsAsync; // set to true if injection is not waiting for the result
+        int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress
+    };
+
+    struct EventEntry : Link<EventEntry> {
+        enum {
+            TYPE_SENTINEL,
+            TYPE_CONFIGURATION_CHANGED,
+            TYPE_KEY,
+            TYPE_MOTION
+        };
+
+        mutable int32_t refCount;
+        int32_t type;
+        nsecs_t eventTime;
+        uint32_t policyFlags;
+        InjectionState* injectionState;
+
+        bool dispatchInProgress; // initially false, set to true while dispatching
+
+        inline bool isInjected() { return injectionState != NULL; }
+    };
+
+    struct ConfigurationChangedEntry : EventEntry {
+    };
+
+    struct KeyEntry : EventEntry {
+        int32_t deviceId;
+        int32_t source;
+        int32_t action;
+        int32_t flags;
+        int32_t keyCode;
+        int32_t scanCode;
+        int32_t metaState;
+        int32_t repeatCount;
+        nsecs_t downTime;
+
+        bool syntheticRepeat; // set to true for synthetic key repeats
+
+        enum InterceptKeyResult {
+            INTERCEPT_KEY_RESULT_UNKNOWN,
+            INTERCEPT_KEY_RESULT_SKIP,
+            INTERCEPT_KEY_RESULT_CONTINUE,
+        };
+        InterceptKeyResult interceptKeyResult; // set based on the interception result
+    };
+
+    struct MotionSample {
+        MotionSample* next;
+
+        nsecs_t eventTime;
+        PointerCoords pointerCoords[MAX_POINTERS];
+    };
+
+    struct MotionEntry : EventEntry {
+        int32_t deviceId;
+        int32_t source;
+        int32_t action;
+        int32_t flags;
+        int32_t metaState;
+        int32_t edgeFlags;
+        float xPrecision;
+        float yPrecision;
+        nsecs_t downTime;
+        uint32_t pointerCount;
+        int32_t pointerIds[MAX_POINTERS];
+
+        // Linked list of motion samples associated with this motion event.
+        MotionSample firstSample;
+        MotionSample* lastSample;
+
+        uint32_t countSamples() const;
+    };
+
+    // Tracks the progress of dispatching a particular event to a particular connection.
+    struct DispatchEntry : Link<DispatchEntry> {
+        EventEntry* eventEntry; // the event to dispatch
+        int32_t targetFlags;
+        float xOffset;
+        float yOffset;
+
+        // True if dispatch has started.
+        bool inProgress;
+
+        // For motion events:
+        //   Pointer to the first motion sample to dispatch in this cycle.
+        //   Usually NULL to indicate that the list of motion samples begins at
+        //   MotionEntry::firstSample.  Otherwise, some samples were dispatched in a previous
+        //   cycle and this pointer indicates the location of the first remainining sample
+        //   to dispatch during the current cycle.
+        MotionSample* headMotionSample;
+        //   Pointer to a motion sample to dispatch in the next cycle if the dispatcher was
+        //   unable to send all motion samples during this cycle.  On the next cycle,
+        //   headMotionSample will be initialized to tailMotionSample and tailMotionSample
+        //   will be set to NULL.
+        MotionSample* tailMotionSample;
+
+        inline bool hasForegroundTarget() const {
+            return targetFlags & InputTarget::FLAG_FOREGROUND;
+        }
+
+        inline bool isSplit() const {
+            return targetFlags & InputTarget::FLAG_SPLIT;
+        }
+    };
+
+    // A command entry captures state and behavior for an action to be performed in the
+    // dispatch loop after the initial processing has taken place.  It is essentially
+    // a kind of continuation used to postpone sensitive policy interactions to a point
+    // in the dispatch loop where it is safe to release the lock (generally after finishing
+    // the critical parts of the dispatch cycle).
+    //
+    // The special thing about commands is that they can voluntarily release and reacquire
+    // the dispatcher lock at will.  Initially when the command starts running, the
+    // dispatcher lock is held.  However, if the command needs to call into the policy to
+    // do some work, it can release the lock, do the work, then reacquire the lock again
+    // before returning.
+    //
+    // This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch
+    // never calls into the policy while holding its lock.
+    //
+    // Commands are implicitly 'LockedInterruptible'.
+    struct CommandEntry;
+    typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);
+
+    class Connection;
+    struct CommandEntry : Link<CommandEntry> {
+        CommandEntry();
+        ~CommandEntry();
+
+        Command command;
+
+        // parameters for the command (usage varies by command)
+        sp<Connection> connection;
+        nsecs_t eventTime;
+        KeyEntry* keyEntry;
+        sp<InputChannel> inputChannel;
+        sp<InputApplicationHandle> inputApplicationHandle;
+        sp<InputWindowHandle> inputWindowHandle;
+        int32_t userActivityEventType;
+        bool handled;
+    };
+
+    // Generic queue implementation.
+    template <typename T>
+    struct Queue {
+        T headSentinel;
+        T tailSentinel;
+
+        inline Queue() {
+            headSentinel.prev = NULL;
+            headSentinel.next = & tailSentinel;
+            tailSentinel.prev = & headSentinel;
+            tailSentinel.next = NULL;
+        }
+
+        inline bool isEmpty() const {
+            return headSentinel.next == & tailSentinel;
+        }
+
+        inline void enqueueAtTail(T* entry) {
+            T* last = tailSentinel.prev;
+            last->next = entry;
+            entry->prev = last;
+            entry->next = & tailSentinel;
+            tailSentinel.prev = entry;
+        }
+
+        inline void enqueueAtHead(T* entry) {
+            T* first = headSentinel.next;
+            headSentinel.next = entry;
+            entry->prev = & headSentinel;
+            entry->next = first;
+            first->prev = entry;
+        }
+
+        inline void dequeue(T* entry) {
+            entry->prev->next = entry->next;
+            entry->next->prev = entry->prev;
+        }
+
+        inline T* dequeueAtHead() {
+            T* first = headSentinel.next;
+            dequeue(first);
+            return first;
+        }
+
+        uint32_t count() const;
+    };
+
+    /* Allocates queue entries and performs reference counting as needed. */
+    class Allocator {
+    public:
+        Allocator();
+
+        InjectionState* obtainInjectionState(int32_t injectorPid, int32_t injectorUid);
+        ConfigurationChangedEntry* obtainConfigurationChangedEntry(nsecs_t eventTime);
+        KeyEntry* obtainKeyEntry(nsecs_t eventTime,
+                int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
+                int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
+                int32_t repeatCount, nsecs_t downTime);
+        MotionEntry* obtainMotionEntry(nsecs_t eventTime,
+                int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
+                int32_t flags, int32_t metaState, int32_t edgeFlags,
+                float xPrecision, float yPrecision,
+                nsecs_t downTime, uint32_t pointerCount,
+                const int32_t* pointerIds, const PointerCoords* pointerCoords);
+        DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry,
+                int32_t targetFlags, float xOffset, float yOffset);
+        CommandEntry* obtainCommandEntry(Command command);
+
+        void releaseInjectionState(InjectionState* injectionState);
+        void releaseEventEntry(EventEntry* entry);
+        void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry);
+        void releaseKeyEntry(KeyEntry* entry);
+        void releaseMotionEntry(MotionEntry* entry);
+        void releaseDispatchEntry(DispatchEntry* entry);
+        void releaseCommandEntry(CommandEntry* entry);
+
+        void recycleKeyEntry(KeyEntry* entry);
+
+        void appendMotionSample(MotionEntry* motionEntry,
+                nsecs_t eventTime, const PointerCoords* pointerCoords);
+
+    private:
+        Pool<InjectionState> mInjectionStatePool;
+        Pool<ConfigurationChangedEntry> mConfigurationChangeEntryPool;
+        Pool<KeyEntry> mKeyEntryPool;
+        Pool<MotionEntry> mMotionEntryPool;
+        Pool<MotionSample> mMotionSamplePool;
+        Pool<DispatchEntry> mDispatchEntryPool;
+        Pool<CommandEntry> mCommandEntryPool;
+
+        void initializeEventEntry(EventEntry* entry, int32_t type, nsecs_t eventTime,
+                uint32_t policyFlags);
+        void releaseEventEntryInjectionState(EventEntry* entry);
+    };
+
+    /* Tracks dispatched key and motion event state so that cancelation events can be
+     * synthesized when events are dropped. */
+    class InputState {
+    public:
+        // Specifies whether a given event will violate input state consistency.
+        enum Consistency {
+            // The event is consistent with the current input state.
+            CONSISTENT,
+            // The event is inconsistent with the current input state but applications
+            // will tolerate it.  eg. Down followed by another down.
+            TOLERABLE,
+            // The event is inconsistent with the current input state and will probably
+            // cause applications to crash.  eg. Up without prior down, move with
+            // unexpected number of pointers.
+            BROKEN
+        };
+
+        // Specifies the sources to cancel.
+        enum CancelationOptions {
+            CANCEL_ALL_EVENTS = 0,
+            CANCEL_POINTER_EVENTS = 1,
+            CANCEL_NON_POINTER_EVENTS = 2,
+            CANCEL_FALLBACK_EVENTS = 3,
+        };
+
+        InputState();
+        ~InputState();
+
+        // Returns true if there is no state to be canceled.
+        bool isNeutral() const;
+
+        // Records tracking information for an event that has just been published.
+        // Returns whether the event is consistent with the current input state.
+        Consistency trackEvent(const EventEntry* entry);
+
+        // Records tracking information for a key event that has just been published.
+        // Returns whether the event is consistent with the current input state.
+        Consistency trackKey(const KeyEntry* entry);
+
+        // Records tracking information for a motion event that has just been published.
+        // Returns whether the event is consistent with the current input state.
+        Consistency trackMotion(const MotionEntry* entry);
+
+        // Synthesizes cancelation events for the current state and resets the tracked state.
+        void synthesizeCancelationEvents(nsecs_t currentTime, Allocator* allocator,
+                Vector<EventEntry*>& outEvents, CancelationOptions options);
+
+        // Clears the current state.
+        void clear();
+
+        // Copies pointer-related parts of the input state to another instance.
+        void copyPointerStateTo(InputState& other) const;
+
+    private:
+        struct KeyMemento {
+            int32_t deviceId;
+            int32_t source;
+            int32_t keyCode;
+            int32_t scanCode;
+            int32_t flags;
+            nsecs_t downTime;
+        };
+
+        struct MotionMemento {
+            int32_t deviceId;
+            int32_t source;
+            float xPrecision;
+            float yPrecision;
+            nsecs_t downTime;
+            uint32_t pointerCount;
+            int32_t pointerIds[MAX_POINTERS];
+            PointerCoords pointerCoords[MAX_POINTERS];
+
+            void setPointers(const MotionEntry* entry);
+        };
+
+        Vector<KeyMemento> mKeyMementos;
+        Vector<MotionMemento> mMotionMementos;
+
+        static bool shouldCancelKey(const KeyMemento& memento,
+                CancelationOptions options);
+        static bool shouldCancelMotion(const MotionMemento& memento,
+                CancelationOptions options);
+    };
+
+    /* Manages the dispatch state associated with a single input channel. */
+    class Connection : public RefBase {
+    protected:
+        virtual ~Connection();
+
+    public:
+        enum Status {
+            // Everything is peachy.
+            STATUS_NORMAL,
+            // An unrecoverable communication error has occurred.
+            STATUS_BROKEN,
+            // The input channel has been unregistered.
+            STATUS_ZOMBIE
+        };
+
+        Status status;
+        sp<InputChannel> inputChannel; // never null
+        sp<InputWindowHandle> inputWindowHandle; // may be null
+        InputPublisher inputPublisher;
+        InputState inputState;
+        Queue<DispatchEntry> outboundQueue;
+
+        nsecs_t lastEventTime; // the time when the event was originally captured
+        nsecs_t lastDispatchTime; // the time when the last event was dispatched
+
+        explicit Connection(const sp<InputChannel>& inputChannel,
+                const sp<InputWindowHandle>& inputWindowHandle);
+
+        inline const char* getInputChannelName() const { return inputChannel->getName().string(); }
+
+        const char* getStatusLabel() const;
+
+        // Finds a DispatchEntry in the outbound queue associated with the specified event.
+        // Returns NULL if not found.
+        DispatchEntry* findQueuedDispatchEntryForEvent(const EventEntry* eventEntry) const;
+
+        // Gets the time since the current event was originally obtained from the input driver.
+        inline double getEventLatencyMillis(nsecs_t currentTime) const {
+            return (currentTime - lastEventTime) / 1000000.0;
+        }
+
+        // Gets the time since the current event entered the outbound dispatch queue.
+        inline double getDispatchLatencyMillis(nsecs_t currentTime) const {
+            return (currentTime - lastDispatchTime) / 1000000.0;
+        }
+
+        status_t initialize();
+    };
+
+    enum DropReason {
+        DROP_REASON_NOT_DROPPED = 0,
+        DROP_REASON_POLICY = 1,
+        DROP_REASON_APP_SWITCH = 2,
+        DROP_REASON_DISABLED = 3,
+        DROP_REASON_BLOCKED = 4,
+        DROP_REASON_STALE = 5,
+    };
+
+    sp<InputDispatcherPolicyInterface> mPolicy;
+
+    Mutex mLock;
+
+    Allocator mAllocator;
+    sp<Looper> mLooper;
+
+    EventEntry* mPendingEvent;
+    Queue<EventEntry> mInboundQueue;
+    Queue<CommandEntry> mCommandQueue;
+
+    Vector<EventEntry*> mTempCancelationEvents;
+
+    void dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, nsecs_t keyRepeatDelay,
+            nsecs_t* nextWakeupTime);
+
+    // Enqueues an inbound event.  Returns true if mLooper->wake() should be called.
+    bool enqueueInboundEventLocked(EventEntry* entry);
+
+    // Cleans up input state when dropping an inbound event.
+    void dropInboundEventLocked(EventEntry* entry, DropReason dropReason);
+
+    // App switch latency optimization.
+    bool mAppSwitchSawKeyDown;
+    nsecs_t mAppSwitchDueTime;
+
+    static bool isAppSwitchKeyCode(int32_t keyCode);
+    bool isAppSwitchKeyEventLocked(KeyEntry* keyEntry);
+    bool isAppSwitchPendingLocked();
+    void resetPendingAppSwitchLocked(bool handled);
+
+    // Stale event latency optimization.
+    static bool isStaleEventLocked(nsecs_t currentTime, EventEntry* entry);
+
+    // Blocked event latency optimization.  Drops old events when the user intends
+    // to transfer focus to a new application.
+    EventEntry* mNextUnblockedEvent;
+
+    const InputWindow* findTouchedWindowAtLocked(int32_t x, int32_t y);
+
+    // All registered connections mapped by receive pipe file descriptor.
+    KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
+
+    ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel);
+
+    // Active connections are connections that have a non-empty outbound queue.
+    // We don't use a ref-counted pointer here because we explicitly abort connections
+    // during unregistration which causes the connection's outbound queue to be cleared
+    // and the connection itself to be deactivated.
+    Vector<Connection*> mActiveConnections;
+
+    // Input channels that will receive a copy of all input events.
+    Vector<sp<InputChannel> > mMonitoringChannels;
+
+    // Event injection and synchronization.
+    Condition mInjectionResultAvailableCondition;
+    bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
+    void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult);
+
+    Condition mInjectionSyncFinishedCondition;
+    void incrementPendingForegroundDispatchesLocked(EventEntry* entry);
+    void decrementPendingForegroundDispatchesLocked(EventEntry* entry);
+
+    // Throttling state.
+    struct ThrottleState {
+        nsecs_t minTimeBetweenEvents;
+
+        nsecs_t lastEventTime;
+        int32_t lastDeviceId;
+        uint32_t lastSource;
+
+        uint32_t originalSampleCount; // only collected during debugging
+    } mThrottleState;
+
+    // Key repeat tracking.
+    struct KeyRepeatState {
+        KeyEntry* lastKeyEntry; // or null if no repeat
+        nsecs_t nextRepeatTime;
+    } mKeyRepeatState;
+
+    void resetKeyRepeatLocked();
+    KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime, nsecs_t keyRepeatTimeout);
+
+    // Deferred command processing.
+    bool runCommandsLockedInterruptible();
+    CommandEntry* postCommandLocked(Command command);
+
+    // Inbound event processing.
+    void drainInboundQueueLocked();
+    void releasePendingEventLocked();
+    void releaseInboundEventLocked(EventEntry* entry);
+
+    // Dispatch state.
+    bool mDispatchEnabled;
+    bool mDispatchFrozen;
+
+    Vector<InputWindow> mWindows;
+
+    const InputWindow* getWindowLocked(const sp<InputChannel>& inputChannel);
+
+    // Focus tracking for keys, trackball, etc.
+    const InputWindow* mFocusedWindow;
+
+    // Focus tracking for touch.
+    struct TouchedWindow {
+        const InputWindow* window;
+        int32_t targetFlags;
+        BitSet32 pointerIds;        // zero unless target flag FLAG_SPLIT is set
+        sp<InputChannel> channel;
+    };
+    struct TouchState {
+        bool down;
+        bool split;
+        int32_t deviceId; // id of the device that is currently down, others are rejected
+        Vector<TouchedWindow> windows;
+
+        TouchState();
+        ~TouchState();
+        void reset();
+        void copyFrom(const TouchState& other);
+        void addOrUpdateWindow(const InputWindow* window, int32_t targetFlags, BitSet32 pointerIds);
+        void removeOutsideTouchWindows();
+        const InputWindow* getFirstForegroundWindow();
+    };
+
+    TouchState mTouchState;
+    TouchState mTempTouchState;
+
+    // Focused application.
+    InputApplication* mFocusedApplication;
+    InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
+    void releaseFocusedApplicationLocked();
+
+    // Dispatch inbound events.
+    bool dispatchConfigurationChangedLocked(
+            nsecs_t currentTime, ConfigurationChangedEntry* entry);
+    bool dispatchKeyLocked(
+            nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
+            DropReason* dropReason, nsecs_t* nextWakeupTime);
+    bool dispatchMotionLocked(
+            nsecs_t currentTime, MotionEntry* entry,
+            DropReason* dropReason, nsecs_t* nextWakeupTime);
+    void dispatchEventToCurrentInputTargetsLocked(
+            nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);
+
+    void logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry);
+    void logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry);
+
+    // The input targets that were most recently identified for dispatch.
+    bool mCurrentInputTargetsValid; // false while targets are being recomputed
+    Vector<InputTarget> mCurrentInputTargets;
+
+    enum InputTargetWaitCause {
+        INPUT_TARGET_WAIT_CAUSE_NONE,
+        INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY,
+        INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,
+    };
+
+    InputTargetWaitCause mInputTargetWaitCause;
+    nsecs_t mInputTargetWaitStartTime;
+    nsecs_t mInputTargetWaitTimeoutTime;
+    bool mInputTargetWaitTimeoutExpired;
+    sp<InputApplicationHandle> mInputTargetWaitApplication;
+
+    // Finding targets for input events.
+    void resetTargetsLocked();
+    void commitTargetsLocked();
+    int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
+            const InputApplication* application, const InputWindow* window,
+            nsecs_t* nextWakeupTime);
+    void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
+            const sp<InputChannel>& inputChannel);
+    nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime);
+    void resetANRTimeoutsLocked();
+
+    int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
+            nsecs_t* nextWakeupTime);
+    int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
+            nsecs_t* nextWakeupTime);
+
+    void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
+            BitSet32 pointerIds);
+    void addMonitoringTargetsLocked();
+    void pokeUserActivityLocked(const EventEntry* eventEntry);
+    bool checkInjectionPermission(const InputWindow* window, const InjectionState* injectionState);
+    bool isWindowObscuredAtPointLocked(const InputWindow* window, int32_t x, int32_t y) const;
+    bool isWindowFinishedWithPreviousInputLocked(const InputWindow* window);
+    String8 getApplicationWindowLabelLocked(const InputApplication* application,
+            const InputWindow* window);
+
+    // Manage the dispatch cycle for a single connection.
+    // These methods are deliberately not Interruptible because doing all of the work
+    // with the mutex held makes it easier to ensure that connection invariants are maintained.
+    // If needed, the methods post commands to run later once the critical bits are done.
+    void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
+            EventEntry* eventEntry, const InputTarget* inputTarget,
+            bool resumeWithAppendedMotionSample);
+    void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
+    void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
+            bool handled);
+    void startNextDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
+    void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
+    void drainOutboundQueueLocked(Connection* connection);
+    static int handleReceiveCallback(int receiveFd, int events, void* data);
+
+    void synthesizeCancelationEventsForAllConnectionsLocked(
+            InputState::CancelationOptions options, const char* reason);
+    void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
+            InputState::CancelationOptions options, const char* reason);
+    void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
+            InputState::CancelationOptions options, const char* reason);
+
+    // Splitting motion events across windows.
+    MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
+
+    // Reset and drop everything the dispatcher is doing.
+    void resetAndDropEverythingLocked(const char* reason);
+
+    // Dump state.
+    void dumpDispatchStateLocked(String8& dump);
+    void logDispatchStateLocked();
+
+    // Add or remove a connection to the mActiveConnections vector.
+    void activateConnectionLocked(Connection* connection);
+    void deactivateConnectionLocked(Connection* connection);
+
+    // Interesting events that we might like to log or tell the framework about.
+    void onDispatchCycleStartedLocked(
+            nsecs_t currentTime, const sp<Connection>& connection);
+    void onDispatchCycleFinishedLocked(
+            nsecs_t currentTime, const sp<Connection>& connection, bool handled);
+    void onDispatchCycleBrokenLocked(
+            nsecs_t currentTime, const sp<Connection>& connection);
+    void onANRLocked(
+            nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
+            nsecs_t eventTime, nsecs_t waitStartTime);
+
+    // Outbound policy interactions.
+    void doNotifyConfigurationChangedInterruptible(CommandEntry* commandEntry);
+    void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);
+    void doNotifyANRLockedInterruptible(CommandEntry* commandEntry);
+    void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry);
+    void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry);
+    void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry);
+    void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);
+
+    // Statistics gathering.
+    void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
+            int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
+};
+
+/* Enqueues and dispatches input events, endlessly. */
+class InputDispatcherThread : public Thread {
+public:
+    explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher);
+    ~InputDispatcherThread();
+
+private:
+    virtual bool threadLoop();
+
+    sp<InputDispatcherInterface> mDispatcher;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_DISPATCHER_H
diff --git a/services/input/InputManager.cpp b/services/input/InputManager.cpp
new file mode 100644
index 0000000..5dfa5d5
--- /dev/null
+++ b/services/input/InputManager.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputManager"
+
+//#define LOG_NDEBUG 0
+
+#include "InputManager.h"
+
+#include <cutils/log.h>
+
+namespace android {
+
+InputManager::InputManager(
+        const sp<EventHubInterface>& eventHub,
+        const sp<InputReaderPolicyInterface>& readerPolicy,
+        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
+    mDispatcher = new InputDispatcher(dispatcherPolicy);
+    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
+    initialize();
+}
+
+InputManager::InputManager(
+        const sp<InputReaderInterface>& reader,
+        const sp<InputDispatcherInterface>& dispatcher) :
+        mReader(reader),
+        mDispatcher(dispatcher) {
+    initialize();
+}
+
+InputManager::~InputManager() {
+    stop();
+}
+
+void InputManager::initialize() {
+    mReaderThread = new InputReaderThread(mReader);
+    mDispatcherThread = new InputDispatcherThread(mDispatcher);
+}
+
+status_t InputManager::start() {
+    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
+    if (result) {
+        LOGE("Could not start InputDispatcher thread due to error %d.", result);
+        return result;
+    }
+
+    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
+    if (result) {
+        LOGE("Could not start InputReader thread due to error %d.", result);
+
+        mDispatcherThread->requestExit();
+        return result;
+    }
+
+    return OK;
+}
+
+status_t InputManager::stop() {
+    status_t result = mReaderThread->requestExitAndWait();
+    if (result) {
+        LOGW("Could not stop InputReader thread due to error %d.", result);
+    }
+
+    result = mDispatcherThread->requestExitAndWait();
+    if (result) {
+        LOGW("Could not stop InputDispatcher thread due to error %d.", result);
+    }
+
+    return OK;
+}
+
+sp<InputReaderInterface> InputManager::getReader() {
+    return mReader;
+}
+
+sp<InputDispatcherInterface> InputManager::getDispatcher() {
+    return mDispatcher;
+}
+
+} // namespace android
diff --git a/services/input/InputManager.h b/services/input/InputManager.h
new file mode 100644
index 0000000..df4d299
--- /dev/null
+++ b/services/input/InputManager.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UI_INPUT_MANAGER_H
+#define _UI_INPUT_MANAGER_H
+
+/**
+ * Native input manager.
+ */
+
+#include "EventHub.h"
+#include "InputReader.h"
+#include "InputDispatcher.h"
+
+#include <ui/Input.h>
+#include <ui/InputTransport.h>
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace android {
+
+/*
+ * The input manager is the core of the system event processing.
+ *
+ * The input manager uses two threads.
+ *
+ * 1. The InputReaderThread (called "InputReader") reads and preprocesses raw input events,
+ *    applies policy, and posts messages to a queue managed by the DispatcherThread.
+ * 2. The InputDispatcherThread (called "InputDispatcher") thread waits for new events on the
+ *    queue and asynchronously dispatches them to applications.
+ *
+ * By design, the InputReaderThread class and InputDispatcherThread class do not share any
+ * internal state.  Moreover, all communication is done one way from the InputReaderThread
+ * into the InputDispatcherThread and never the reverse.  Both classes may interact with the
+ * InputDispatchPolicy, however.
+ *
+ * The InputManager class never makes any calls into Java itself.  Instead, the
+ * InputDispatchPolicy is responsible for performing all external interactions with the
+ * system, including calling DVM services.
+ */
+class InputManagerInterface : public virtual RefBase {
+protected:
+    InputManagerInterface() { }
+    virtual ~InputManagerInterface() { }
+
+public:
+    /* Starts the input manager threads. */
+    virtual status_t start() = 0;
+
+    /* Stops the input manager threads and waits for them to exit. */
+    virtual status_t stop() = 0;
+
+    /* Gets the input reader. */
+    virtual sp<InputReaderInterface> getReader() = 0;
+
+    /* Gets the input dispatcher. */
+    virtual sp<InputDispatcherInterface> getDispatcher() = 0;
+};
+
+class InputManager : public InputManagerInterface {
+protected:
+    virtual ~InputManager();
+
+public:
+    InputManager(
+            const sp<EventHubInterface>& eventHub,
+            const sp<InputReaderPolicyInterface>& readerPolicy,
+            const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);
+
+    // (used for testing purposes)
+    InputManager(
+            const sp<InputReaderInterface>& reader,
+            const sp<InputDispatcherInterface>& dispatcher);
+
+    virtual status_t start();
+    virtual status_t stop();
+
+    virtual sp<InputReaderInterface> getReader();
+    virtual sp<InputDispatcherInterface> getDispatcher();
+
+private:
+    sp<InputReaderInterface> mReader;
+    sp<InputReaderThread> mReaderThread;
+
+    sp<InputDispatcherInterface> mDispatcher;
+    sp<InputDispatcherThread> mDispatcherThread;
+
+    void initialize();
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_MANAGER_H
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
new file mode 100644
index 0000000..6b66791
--- /dev/null
+++ b/services/input/InputReader.cpp
@@ -0,0 +1,3649 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputReader"
+
+//#define LOG_NDEBUG 0
+
+// Log debug messages for each raw event received from the EventHub.
+#define DEBUG_RAW_EVENTS 0
+
+// Log debug messages about touch screen filtering hacks.
+#define DEBUG_HACKS 0
+
+// Log debug messages about virtual key processing.
+#define DEBUG_VIRTUAL_KEYS 0
+
+// Log debug messages about pointers.
+#define DEBUG_POINTERS 0
+
+// Log debug messages about pointer assignment calculations.
+#define DEBUG_POINTER_ASSIGNMENT 0
+
+#include "InputReader.h"
+
+#include <cutils/log.h>
+#include <ui/Keyboard.h>
+#include <ui/VirtualKeyMap.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <math.h>
+
+#define INDENT "  "
+#define INDENT2 "    "
+#define INDENT3 "      "
+#define INDENT4 "        "
+
+namespace android {
+
+// --- Static Functions ---
+
+template<typename T>
+inline static T abs(const T& value) {
+    return value < 0 ? - value : value;
+}
+
+template<typename T>
+inline static T min(const T& a, const T& b) {
+    return a < b ? a : b;
+}
+
+template<typename T>
+inline static void swap(T& a, T& b) {
+    T temp = a;
+    a = b;
+    b = temp;
+}
+
+inline static float avg(float x, float y) {
+    return (x + y) / 2;
+}
+
+inline static float pythag(float x, float y) {
+    return sqrtf(x * x + y * y);
+}
+
+inline static int32_t signExtendNybble(int32_t value) {
+    return value >= 8 ? value - 16 : value;
+}
+
+static inline const char* toString(bool value) {
+    return value ? "true" : "false";
+}
+
+static const int32_t keyCodeRotationMap[][4] = {
+        // key codes enumerated counter-clockwise with the original (unrotated) key first
+        // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
+        { AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT },
+        { AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN },
+        { AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT },
+        { AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP },
+};
+static const int keyCodeRotationMapSize =
+        sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
+
+int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
+    if (orientation != DISPLAY_ORIENTATION_0) {
+        for (int i = 0; i < keyCodeRotationMapSize; i++) {
+            if (keyCode == keyCodeRotationMap[i][0]) {
+                return keyCodeRotationMap[i][orientation];
+            }
+        }
+    }
+    return keyCode;
+}
+
+static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
+    return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
+}
+
+
+// --- InputReader ---
+
+InputReader::InputReader(const sp<EventHubInterface>& eventHub,
+        const sp<InputReaderPolicyInterface>& policy,
+        const sp<InputDispatcherInterface>& dispatcher) :
+        mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
+        mGlobalMetaState(0) {
+    configureExcludedDevices();
+    updateGlobalMetaState();
+    updateInputConfiguration();
+}
+
+InputReader::~InputReader() {
+    for (size_t i = 0; i < mDevices.size(); i++) {
+        delete mDevices.valueAt(i);
+    }
+}
+
+void InputReader::loopOnce() {
+    RawEvent rawEvent;
+    mEventHub->getEvent(& rawEvent);
+
+#if DEBUG_RAW_EVENTS
+    LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
+            rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
+            rawEvent.value);
+#endif
+
+    process(& rawEvent);
+}
+
+void InputReader::process(const RawEvent* rawEvent) {
+    switch (rawEvent->type) {
+    case EventHubInterface::DEVICE_ADDED:
+        addDevice(rawEvent->deviceId);
+        break;
+
+    case EventHubInterface::DEVICE_REMOVED:
+        removeDevice(rawEvent->deviceId);
+        break;
+
+    case EventHubInterface::FINISHED_DEVICE_SCAN:
+        handleConfigurationChanged(rawEvent->when);
+        break;
+
+    default:
+        consumeEvent(rawEvent);
+        break;
+    }
+}
+
+void InputReader::addDevice(int32_t deviceId) {
+    String8 name = mEventHub->getDeviceName(deviceId);
+    uint32_t classes = mEventHub->getDeviceClasses(deviceId);
+
+    InputDevice* device = createDevice(deviceId, name, classes);
+    device->configure();
+
+    if (device->isIgnored()) {
+        LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
+    } else {
+        LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
+                device->getSources());
+    }
+
+    bool added = false;
+    { // acquire device registry writer lock
+        RWLock::AutoWLock _wl(mDeviceRegistryLock);
+
+        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+        if (deviceIndex < 0) {
+            mDevices.add(deviceId, device);
+            added = true;
+        }
+    } // release device registry writer lock
+
+    if (! added) {
+        LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
+        delete device;
+        return;
+    }
+}
+
+void InputReader::removeDevice(int32_t deviceId) {
+    bool removed = false;
+    InputDevice* device = NULL;
+    { // acquire device registry writer lock
+        RWLock::AutoWLock _wl(mDeviceRegistryLock);
+
+        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+        if (deviceIndex >= 0) {
+            device = mDevices.valueAt(deviceIndex);
+            mDevices.removeItemsAt(deviceIndex, 1);
+            removed = true;
+        }
+    } // release device registry writer lock
+
+    if (! removed) {
+        LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
+        return;
+    }
+
+    if (device->isIgnored()) {
+        LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
+                device->getId(), device->getName().string());
+    } else {
+        LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
+                device->getId(), device->getName().string(), device->getSources());
+    }
+
+    device->reset();
+
+    delete device;
+}
+
+InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
+    InputDevice* device = new InputDevice(this, deviceId, name);
+
+    // Switch-like devices.
+    if (classes & INPUT_DEVICE_CLASS_SWITCH) {
+        device->addMapper(new SwitchInputMapper(device));
+    }
+
+    // Keyboard-like devices.
+    uint32_t keyboardSources = 0;
+    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
+    if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
+        keyboardSources |= AINPUT_SOURCE_KEYBOARD;
+    }
+    if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
+        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
+    }
+    if (classes & INPUT_DEVICE_CLASS_DPAD) {
+        keyboardSources |= AINPUT_SOURCE_DPAD;
+    }
+
+    if (keyboardSources != 0) {
+        device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType));
+    }
+
+    // Cursor-like devices.
+    if (classes & INPUT_DEVICE_CLASS_CURSOR) {
+        device->addMapper(new CursorInputMapper(device));
+    }
+
+    // Touchscreen-like devices.
+    if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
+        device->addMapper(new MultiTouchInputMapper(device));
+    } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
+        device->addMapper(new SingleTouchInputMapper(device));
+    }
+
+    return device;
+}
+
+void InputReader::consumeEvent(const RawEvent* rawEvent) {
+    int32_t deviceId = rawEvent->deviceId;
+
+    { // acquire device registry reader lock
+        RWLock::AutoRLock _rl(mDeviceRegistryLock);
+
+        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+        if (deviceIndex < 0) {
+            LOGW("Discarding event for unknown deviceId %d.", deviceId);
+            return;
+        }
+
+        InputDevice* device = mDevices.valueAt(deviceIndex);
+        if (device->isIgnored()) {
+            //LOGD("Discarding event for ignored deviceId %d.", deviceId);
+            return;
+        }
+
+        device->process(rawEvent);
+    } // release device registry reader lock
+}
+
+void InputReader::handleConfigurationChanged(nsecs_t when) {
+    // Reset global meta state because it depends on the list of all configured devices.
+    updateGlobalMetaState();
+
+    // Update input configuration.
+    updateInputConfiguration();
+
+    // Enqueue configuration changed.
+    mDispatcher->notifyConfigurationChanged(when);
+}
+
+void InputReader::configureExcludedDevices() {
+    Vector<String8> excludedDeviceNames;
+    mPolicy->getExcludedDeviceNames(excludedDeviceNames);
+
+    for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
+        mEventHub->addExcludedDevice(excludedDeviceNames[i]);
+    }
+}
+
+void InputReader::updateGlobalMetaState() {
+    { // acquire state lock
+        AutoMutex _l(mStateLock);
+
+        mGlobalMetaState = 0;
+
+        { // acquire device registry reader lock
+            RWLock::AutoRLock _rl(mDeviceRegistryLock);
+
+            for (size_t i = 0; i < mDevices.size(); i++) {
+                InputDevice* device = mDevices.valueAt(i);
+                mGlobalMetaState |= device->getMetaState();
+            }
+        } // release device registry reader lock
+    } // release state lock
+}
+
+int32_t InputReader::getGlobalMetaState() {
+    { // acquire state lock
+        AutoMutex _l(mStateLock);
+
+        return mGlobalMetaState;
+    } // release state lock
+}
+
+void InputReader::updateInputConfiguration() {
+    { // acquire state lock
+        AutoMutex _l(mStateLock);
+
+        int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
+        int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
+        int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
+        { // acquire device registry reader lock
+            RWLock::AutoRLock _rl(mDeviceRegistryLock);
+
+            InputDeviceInfo deviceInfo;
+            for (size_t i = 0; i < mDevices.size(); i++) {
+                InputDevice* device = mDevices.valueAt(i);
+                device->getDeviceInfo(& deviceInfo);
+                uint32_t sources = deviceInfo.getSources();
+
+                if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
+                    touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
+                }
+                if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
+                    navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
+                } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
+                    navigationConfig = InputConfiguration::NAVIGATION_DPAD;
+                }
+                if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
+                    keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
+                }
+            }
+        } // release device registry reader lock
+
+        mInputConfiguration.touchScreen = touchScreenConfig;
+        mInputConfiguration.keyboard = keyboardConfig;
+        mInputConfiguration.navigation = navigationConfig;
+    } // release state lock
+}
+
+void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
+    { // acquire state lock
+        AutoMutex _l(mStateLock);
+
+        *outConfiguration = mInputConfiguration;
+    } // release state lock
+}
+
+status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
+    { // acquire device registry reader lock
+        RWLock::AutoRLock _rl(mDeviceRegistryLock);
+
+        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+        if (deviceIndex < 0) {
+            return NAME_NOT_FOUND;
+        }
+
+        InputDevice* device = mDevices.valueAt(deviceIndex);
+        if (device->isIgnored()) {
+            return NAME_NOT_FOUND;
+        }
+
+        device->getDeviceInfo(outDeviceInfo);
+        return OK;
+    } // release device registy reader lock
+}
+
+void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
+    outDeviceIds.clear();
+
+    { // acquire device registry reader lock
+        RWLock::AutoRLock _rl(mDeviceRegistryLock);
+
+        size_t numDevices = mDevices.size();
+        for (size_t i = 0; i < numDevices; i++) {
+            InputDevice* device = mDevices.valueAt(i);
+            if (! device->isIgnored()) {
+                outDeviceIds.add(device->getId());
+            }
+        }
+    } // release device registy reader lock
+}
+
+int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
+        int32_t keyCode) {
+    return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
+}
+
+int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
+        int32_t scanCode) {
+    return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
+}
+
+int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
+    return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
+}
+
+int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
+        GetStateFunc getStateFunc) {
+    { // acquire device registry reader lock
+        RWLock::AutoRLock _rl(mDeviceRegistryLock);
+
+        int32_t result = AKEY_STATE_UNKNOWN;
+        if (deviceId >= 0) {
+            ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+            if (deviceIndex >= 0) {
+                InputDevice* device = mDevices.valueAt(deviceIndex);
+                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+                    result = (device->*getStateFunc)(sourceMask, code);
+                }
+            }
+        } else {
+            size_t numDevices = mDevices.size();
+            for (size_t i = 0; i < numDevices; i++) {
+                InputDevice* device = mDevices.valueAt(i);
+                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+                    result = (device->*getStateFunc)(sourceMask, code);
+                    if (result >= AKEY_STATE_DOWN) {
+                        return result;
+                    }
+                }
+            }
+        }
+        return result;
+    } // release device registy reader lock
+}
+
+bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
+        size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
+    memset(outFlags, 0, numCodes);
+    return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
+}
+
+bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
+        const int32_t* keyCodes, uint8_t* outFlags) {
+    { // acquire device registry reader lock
+        RWLock::AutoRLock _rl(mDeviceRegistryLock);
+        bool result = false;
+        if (deviceId >= 0) {
+            ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+            if (deviceIndex >= 0) {
+                InputDevice* device = mDevices.valueAt(deviceIndex);
+                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+                    result = device->markSupportedKeyCodes(sourceMask,
+                            numCodes, keyCodes, outFlags);
+                }
+            }
+        } else {
+            size_t numDevices = mDevices.size();
+            for (size_t i = 0; i < numDevices; i++) {
+                InputDevice* device = mDevices.valueAt(i);
+                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+                    result |= device->markSupportedKeyCodes(sourceMask,
+                            numCodes, keyCodes, outFlags);
+                }
+            }
+        }
+        return result;
+    } // release device registy reader lock
+}
+
+void InputReader::dump(String8& dump) {
+    mEventHub->dump(dump);
+    dump.append("\n");
+
+    dump.append("Input Reader State:\n");
+
+    { // acquire device registry reader lock
+        RWLock::AutoRLock _rl(mDeviceRegistryLock);
+
+        for (size_t i = 0; i < mDevices.size(); i++) {
+            mDevices.valueAt(i)->dump(dump);
+        }
+    } // release device registy reader lock
+}
+
+
+// --- InputReaderThread ---
+
+InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
+        Thread(/*canCallJava*/ true), mReader(reader) {
+}
+
+InputReaderThread::~InputReaderThread() {
+}
+
+bool InputReaderThread::threadLoop() {
+    mReader->loopOnce();
+    return true;
+}
+
+
+// --- InputDevice ---
+
+InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
+        mContext(context), mId(id), mName(name), mSources(0) {
+}
+
+InputDevice::~InputDevice() {
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        delete mMappers[i];
+    }
+    mMappers.clear();
+}
+
+static void dumpMotionRange(String8& dump, const InputDeviceInfo& deviceInfo,
+        int32_t rangeType, const char* name) {
+    const InputDeviceInfo::MotionRange* range = deviceInfo.getMotionRange(rangeType);
+    if (range) {
+        dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
+                name, range->min, range->max, range->flat, range->fuzz);
+    }
+}
+
+void InputDevice::dump(String8& dump) {
+    InputDeviceInfo deviceInfo;
+    getDeviceInfo(& deviceInfo);
+
+    dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
+            deviceInfo.getName().string());
+    dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
+    dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
+    if (!deviceInfo.getMotionRanges().isEmpty()) {
+        dump.append(INDENT2 "Motion Ranges:\n");
+        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_X, "X");
+        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_Y, "Y");
+        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_PRESSURE, "Pressure");
+        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_SIZE, "Size");
+        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MAJOR, "TouchMajor");
+        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MINOR, "TouchMinor");
+        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MAJOR, "ToolMajor");
+        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MINOR, "ToolMinor");
+        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_ORIENTATION, "Orientation");
+    }
+
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        InputMapper* mapper = mMappers[i];
+        mapper->dump(dump);
+    }
+}
+
+void InputDevice::addMapper(InputMapper* mapper) {
+    mMappers.add(mapper);
+}
+
+void InputDevice::configure() {
+    if (! isIgnored()) {
+        mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
+    }
+
+    mSources = 0;
+
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        InputMapper* mapper = mMappers[i];
+        mapper->configure();
+        mSources |= mapper->getSources();
+    }
+}
+
+void InputDevice::reset() {
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        InputMapper* mapper = mMappers[i];
+        mapper->reset();
+    }
+}
+
+void InputDevice::process(const RawEvent* rawEvent) {
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        InputMapper* mapper = mMappers[i];
+        mapper->process(rawEvent);
+    }
+}
+
+void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
+    outDeviceInfo->initialize(mId, mName);
+
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        InputMapper* mapper = mMappers[i];
+        mapper->populateDeviceInfo(outDeviceInfo);
+    }
+}
+
+int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+    return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
+}
+
+int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+    return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
+}
+
+int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
+    return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
+}
+
+int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
+    int32_t result = AKEY_STATE_UNKNOWN;
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        InputMapper* mapper = mMappers[i];
+        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
+            result = (mapper->*getStateFunc)(sourceMask, code);
+            if (result >= AKEY_STATE_DOWN) {
+                return result;
+            }
+        }
+    }
+    return result;
+}
+
+bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+        const int32_t* keyCodes, uint8_t* outFlags) {
+    bool result = false;
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        InputMapper* mapper = mMappers[i];
+        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
+            result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
+        }
+    }
+    return result;
+}
+
+int32_t InputDevice::getMetaState() {
+    int32_t result = 0;
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        InputMapper* mapper = mMappers[i];
+        result |= mapper->getMetaState();
+    }
+    return result;
+}
+
+
+// --- InputMapper ---
+
+InputMapper::InputMapper(InputDevice* device) :
+        mDevice(device), mContext(device->getContext()) {
+}
+
+InputMapper::~InputMapper() {
+}
+
+void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    info->addSource(getSources());
+}
+
+void InputMapper::dump(String8& dump) {
+}
+
+void InputMapper::configure() {
+}
+
+void InputMapper::reset() {
+}
+
+int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+    return AKEY_STATE_UNKNOWN;
+}
+
+int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+    return AKEY_STATE_UNKNOWN;
+}
+
+int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
+    return AKEY_STATE_UNKNOWN;
+}
+
+bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+        const int32_t* keyCodes, uint8_t* outFlags) {
+    return false;
+}
+
+int32_t InputMapper::getMetaState() {
+    return 0;
+}
+
+
+// --- SwitchInputMapper ---
+
+SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
+        InputMapper(device) {
+}
+
+SwitchInputMapper::~SwitchInputMapper() {
+}
+
+uint32_t SwitchInputMapper::getSources() {
+    return 0;
+}
+
+void SwitchInputMapper::process(const RawEvent* rawEvent) {
+    switch (rawEvent->type) {
+    case EV_SW:
+        processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
+        break;
+    }
+}
+
+void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
+    getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
+}
+
+int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
+    return getEventHub()->getSwitchState(getDeviceId(), switchCode);
+}
+
+
+// --- KeyboardInputMapper ---
+
+KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
+        uint32_t sources, int32_t keyboardType) :
+        InputMapper(device), mSources(sources),
+        mKeyboardType(keyboardType) {
+    initializeLocked();
+}
+
+KeyboardInputMapper::~KeyboardInputMapper() {
+}
+
+void KeyboardInputMapper::initializeLocked() {
+    mLocked.metaState = AMETA_NONE;
+    mLocked.downTime = 0;
+}
+
+uint32_t KeyboardInputMapper::getSources() {
+    return mSources;
+}
+
+void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    InputMapper::populateDeviceInfo(info);
+
+    info->setKeyboardType(mKeyboardType);
+}
+
+void KeyboardInputMapper::dump(String8& dump) {
+    { // acquire lock
+        AutoMutex _l(mLock);
+        dump.append(INDENT2 "Keyboard Input Mapper:\n");
+        dumpParameters(dump);
+        dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
+        dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
+        dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
+        dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
+    } // release lock
+}
+
+
+void KeyboardInputMapper::configure() {
+    InputMapper::configure();
+
+    // Configure basic parameters.
+    configureParameters();
+
+    // Reset LEDs.
+    {
+        AutoMutex _l(mLock);
+        resetLedStateLocked();
+    }
+}
+
+void KeyboardInputMapper::configureParameters() {
+    mParameters.orientationAware = false;
+    getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
+            mParameters.orientationAware);
+
+    mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
+}
+
+void KeyboardInputMapper::dumpParameters(String8& dump) {
+    dump.append(INDENT3 "Parameters:\n");
+    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
+            mParameters.associatedDisplayId);
+    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
+            toString(mParameters.orientationAware));
+}
+
+void KeyboardInputMapper::reset() {
+    for (;;) {
+        int32_t keyCode, scanCode;
+        { // acquire lock
+            AutoMutex _l(mLock);
+
+            // Synthesize key up event on reset if keys are currently down.
+            if (mLocked.keyDowns.isEmpty()) {
+                initializeLocked();
+                resetLedStateLocked();
+                break; // done
+            }
+
+            const KeyDown& keyDown = mLocked.keyDowns.top();
+            keyCode = keyDown.keyCode;
+            scanCode = keyDown.scanCode;
+        } // release lock
+
+        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
+        processKey(when, false, keyCode, scanCode, 0);
+    }
+
+    InputMapper::reset();
+    getContext()->updateGlobalMetaState();
+}
+
+void KeyboardInputMapper::process(const RawEvent* rawEvent) {
+    switch (rawEvent->type) {
+    case EV_KEY: {
+        int32_t scanCode = rawEvent->scanCode;
+        if (isKeyboardOrGamepadKey(scanCode)) {
+            processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
+                    rawEvent->flags);
+        }
+        break;
+    }
+    }
+}
+
+bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
+    return scanCode < BTN_MOUSE
+        || scanCode >= KEY_OK
+        || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
+}
+
+void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
+        int32_t scanCode, uint32_t policyFlags) {
+    int32_t newMetaState;
+    nsecs_t downTime;
+    bool metaStateChanged = false;
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        if (down) {
+            // Rotate key codes according to orientation if needed.
+            // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
+            if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
+                int32_t orientation;
+                if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
+                        NULL, NULL, & orientation)) {
+                    orientation = DISPLAY_ORIENTATION_0;
+                }
+
+                keyCode = rotateKeyCode(keyCode, orientation);
+            }
+
+            // Add key down.
+            ssize_t keyDownIndex = findKeyDownLocked(scanCode);
+            if (keyDownIndex >= 0) {
+                // key repeat, be sure to use same keycode as before in case of rotation
+                keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
+            } else {
+                // key down
+                mLocked.keyDowns.push();
+                KeyDown& keyDown = mLocked.keyDowns.editTop();
+                keyDown.keyCode = keyCode;
+                keyDown.scanCode = scanCode;
+            }
+
+            mLocked.downTime = when;
+        } else {
+            // Remove key down.
+            ssize_t keyDownIndex = findKeyDownLocked(scanCode);
+            if (keyDownIndex >= 0) {
+                // key up, be sure to use same keycode as before in case of rotation
+                keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
+                mLocked.keyDowns.removeAt(size_t(keyDownIndex));
+            } else {
+                // key was not actually down
+                LOGI("Dropping key up from device %s because the key was not down.  "
+                        "keyCode=%d, scanCode=%d",
+                        getDeviceName().string(), keyCode, scanCode);
+                return;
+            }
+        }
+
+        int32_t oldMetaState = mLocked.metaState;
+        newMetaState = updateMetaState(keyCode, down, oldMetaState);
+        if (oldMetaState != newMetaState) {
+            mLocked.metaState = newMetaState;
+            metaStateChanged = true;
+            updateLedStateLocked(false);
+        }
+
+        downTime = mLocked.downTime;
+    } // release lock
+
+    if (metaStateChanged) {
+        getContext()->updateGlobalMetaState();
+    }
+
+    if (policyFlags & POLICY_FLAG_FUNCTION) {
+        newMetaState |= AMETA_FUNCTION_ON;
+    }
+    getDispatcher()->notifyKey(when, getDeviceId(), mSources, policyFlags,
+            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
+            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
+}
+
+ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
+    size_t n = mLocked.keyDowns.size();
+    for (size_t i = 0; i < n; i++) {
+        if (mLocked.keyDowns[i].scanCode == scanCode) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+    return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
+}
+
+int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+    return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
+}
+
+bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+        const int32_t* keyCodes, uint8_t* outFlags) {
+    return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
+}
+
+int32_t KeyboardInputMapper::getMetaState() {
+    { // acquire lock
+        AutoMutex _l(mLock);
+        return mLocked.metaState;
+    } // release lock
+}
+
+void KeyboardInputMapper::resetLedStateLocked() {
+    initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
+    initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
+    initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
+
+    updateLedStateLocked(true);
+}
+
+void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
+    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
+    ledState.on = false;
+}
+
+void KeyboardInputMapper::updateLedStateLocked(bool reset) {
+    updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
+            AMETA_CAPS_LOCK_ON, reset);
+    updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
+            AMETA_NUM_LOCK_ON, reset);
+    updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
+            AMETA_SCROLL_LOCK_ON, reset);
+}
+
+void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
+        int32_t led, int32_t modifier, bool reset) {
+    if (ledState.avail) {
+        bool desiredState = (mLocked.metaState & modifier) != 0;
+        if (reset || ledState.on != desiredState) {
+            getEventHub()->setLedState(getDeviceId(), led, desiredState);
+            ledState.on = desiredState;
+        }
+    }
+}
+
+
+// --- CursorInputMapper ---
+
+CursorInputMapper::CursorInputMapper(InputDevice* device) :
+        InputMapper(device) {
+    initializeLocked();
+}
+
+CursorInputMapper::~CursorInputMapper() {
+}
+
+uint32_t CursorInputMapper::getSources() {
+    return mSources;
+}
+
+void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    InputMapper::populateDeviceInfo(info);
+
+    if (mParameters.mode == Parameters::MODE_POINTER) {
+        float minX, minY, maxX, maxY;
+        if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
+            info->addMotionRange(AINPUT_MOTION_RANGE_X, minX, maxX, 0.0f, 0.0f);
+            info->addMotionRange(AINPUT_MOTION_RANGE_Y, minY, maxY, 0.0f, 0.0f);
+        }
+    } else {
+        info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
+        info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
+    }
+    info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE, 0.0f, 1.0f, 0.0f, 0.0f);
+}
+
+void CursorInputMapper::dump(String8& dump) {
+    { // acquire lock
+        AutoMutex _l(mLock);
+        dump.append(INDENT2 "Cursor Input Mapper:\n");
+        dumpParameters(dump);
+        dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
+        dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
+        dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
+        dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
+    } // release lock
+}
+
+void CursorInputMapper::configure() {
+    InputMapper::configure();
+
+    // Configure basic parameters.
+    configureParameters();
+
+    // Configure device mode.
+    switch (mParameters.mode) {
+    case Parameters::MODE_POINTER:
+        mSources = AINPUT_SOURCE_MOUSE;
+        mXPrecision = 1.0f;
+        mYPrecision = 1.0f;
+        mXScale = 1.0f;
+        mYScale = 1.0f;
+        mPointerController = getPolicy()->obtainPointerController(getDeviceId());
+        break;
+    case Parameters::MODE_NAVIGATION:
+        mSources = AINPUT_SOURCE_TRACKBALL;
+        mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
+        mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
+        mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
+        mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
+        break;
+    }
+}
+
+void CursorInputMapper::configureParameters() {
+    mParameters.mode = Parameters::MODE_POINTER;
+    String8 cursorModeString;
+    if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
+        if (cursorModeString == "navigation") {
+            mParameters.mode = Parameters::MODE_NAVIGATION;
+        } else if (cursorModeString != "pointer" && cursorModeString != "default") {
+            LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
+        }
+    }
+
+    mParameters.orientationAware = false;
+    getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
+            mParameters.orientationAware);
+
+    mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
+            || mParameters.orientationAware ? 0 : -1;
+}
+
+void CursorInputMapper::dumpParameters(String8& dump) {
+    dump.append(INDENT3 "Parameters:\n");
+    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
+            mParameters.associatedDisplayId);
+
+    switch (mParameters.mode) {
+    case Parameters::MODE_POINTER:
+        dump.append(INDENT4 "Mode: pointer\n");
+        break;
+    case Parameters::MODE_NAVIGATION:
+        dump.append(INDENT4 "Mode: navigation\n");
+        break;
+    default:
+        assert(false);
+    }
+
+    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
+            toString(mParameters.orientationAware));
+}
+
+void CursorInputMapper::initializeLocked() {
+    mAccumulator.clear();
+
+    mLocked.down = false;
+    mLocked.downTime = 0;
+}
+
+void CursorInputMapper::reset() {
+    for (;;) {
+        { // acquire lock
+            AutoMutex _l(mLock);
+
+            if (! mLocked.down) {
+                initializeLocked();
+                break; // done
+            }
+        } // release lock
+
+        // Synthesize button up event on reset.
+        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
+        mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
+        mAccumulator.btnMouse = false;
+        sync(when);
+    }
+
+    InputMapper::reset();
+}
+
+void CursorInputMapper::process(const RawEvent* rawEvent) {
+    switch (rawEvent->type) {
+    case EV_KEY:
+        switch (rawEvent->scanCode) {
+        case BTN_MOUSE:
+            mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
+            mAccumulator.btnMouse = rawEvent->value != 0;
+            // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
+            // we need to ensure that we report the up/down promptly.
+            sync(rawEvent->when);
+            break;
+        }
+        break;
+
+    case EV_REL:
+        switch (rawEvent->scanCode) {
+        case REL_X:
+            mAccumulator.fields |= Accumulator::FIELD_REL_X;
+            mAccumulator.relX = rawEvent->value;
+            break;
+        case REL_Y:
+            mAccumulator.fields |= Accumulator::FIELD_REL_Y;
+            mAccumulator.relY = rawEvent->value;
+            break;
+        }
+        break;
+
+    case EV_SYN:
+        switch (rawEvent->scanCode) {
+        case SYN_REPORT:
+            sync(rawEvent->when);
+            break;
+        }
+        break;
+    }
+}
+
+void CursorInputMapper::sync(nsecs_t when) {
+    uint32_t fields = mAccumulator.fields;
+    if (fields == 0) {
+        return; // no new state changes, so nothing to do
+    }
+
+    int motionEventAction;
+    PointerCoords pointerCoords;
+    nsecs_t downTime;
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
+
+        if (downChanged) {
+            if (mAccumulator.btnMouse) {
+                if (!mLocked.down) {
+                    mLocked.down = true;
+                    mLocked.downTime = when;
+                } else {
+                    downChanged = false;
+                }
+            } else {
+                if (mLocked.down) {
+                    mLocked.down = false;
+                } else {
+                    downChanged = false;
+                }
+            }
+        }
+
+        downTime = mLocked.downTime;
+        float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
+        float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
+
+        if (downChanged) {
+            motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
+        } else {
+            motionEventAction = AMOTION_EVENT_ACTION_MOVE;
+        }
+
+        if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
+                && (deltaX != 0.0f || deltaY != 0.0f)) {
+            // Rotate motion based on display orientation if needed.
+            // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
+            int32_t orientation;
+            if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
+                    NULL, NULL, & orientation)) {
+                orientation = DISPLAY_ORIENTATION_0;
+            }
+
+            float temp;
+            switch (orientation) {
+            case DISPLAY_ORIENTATION_90:
+                temp = deltaX;
+                deltaX = deltaY;
+                deltaY = -temp;
+                break;
+
+            case DISPLAY_ORIENTATION_180:
+                deltaX = -deltaX;
+                deltaY = -deltaY;
+                break;
+
+            case DISPLAY_ORIENTATION_270:
+                temp = deltaX;
+                deltaX = -deltaY;
+                deltaY = temp;
+                break;
+            }
+        }
+
+        if (mPointerController != NULL) {
+            mPointerController->move(deltaX, deltaY);
+            if (downChanged) {
+                mPointerController->setButtonState(mLocked.down ? POINTER_BUTTON_1 : 0);
+            }
+            mPointerController->getPosition(&pointerCoords.x, &pointerCoords.y);
+        } else {
+            pointerCoords.x = deltaX;
+            pointerCoords.y = deltaY;
+        }
+
+        pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
+        pointerCoords.size = 0;
+        pointerCoords.touchMajor = 0;
+        pointerCoords.touchMinor = 0;
+        pointerCoords.toolMajor = 0;
+        pointerCoords.toolMinor = 0;
+        pointerCoords.orientation = 0;
+    } // release lock
+
+    int32_t metaState = mContext->getGlobalMetaState();
+    int32_t pointerId = 0;
+    getDispatcher()->notifyMotion(when, getDeviceId(), mSources, 0,
+            motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
+            1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
+
+    mAccumulator.clear();
+}
+
+int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+    if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
+        return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
+    } else {
+        return AKEY_STATE_UNKNOWN;
+    }
+}
+
+
+// --- TouchInputMapper ---
+
+TouchInputMapper::TouchInputMapper(InputDevice* device) :
+        InputMapper(device) {
+    mLocked.surfaceOrientation = -1;
+    mLocked.surfaceWidth = -1;
+    mLocked.surfaceHeight = -1;
+
+    initializeLocked();
+}
+
+TouchInputMapper::~TouchInputMapper() {
+}
+
+uint32_t TouchInputMapper::getSources() {
+    return mSources;
+}
+
+void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    InputMapper::populateDeviceInfo(info);
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        // Ensure surface information is up to date so that orientation changes are
+        // noticed immediately.
+        configureSurfaceLocked();
+
+        info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
+        info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
+
+        if (mLocked.orientedRanges.havePressure) {
+            info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
+                    mLocked.orientedRanges.pressure);
+        }
+
+        if (mLocked.orientedRanges.haveSize) {
+            info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
+                    mLocked.orientedRanges.size);
+        }
+
+        if (mLocked.orientedRanges.haveTouchSize) {
+            info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
+                    mLocked.orientedRanges.touchMajor);
+            info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
+                    mLocked.orientedRanges.touchMinor);
+        }
+
+        if (mLocked.orientedRanges.haveToolSize) {
+            info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
+                    mLocked.orientedRanges.toolMajor);
+            info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
+                    mLocked.orientedRanges.toolMinor);
+        }
+
+        if (mLocked.orientedRanges.haveOrientation) {
+            info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
+                    mLocked.orientedRanges.orientation);
+        }
+    } // release lock
+}
+
+void TouchInputMapper::dump(String8& dump) {
+    { // acquire lock
+        AutoMutex _l(mLock);
+        dump.append(INDENT2 "Touch Input Mapper:\n");
+        dumpParameters(dump);
+        dumpVirtualKeysLocked(dump);
+        dumpRawAxes(dump);
+        dumpCalibration(dump);
+        dumpSurfaceLocked(dump);
+        dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
+        dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
+        dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
+        dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
+        dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
+        dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
+        dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
+        dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
+        dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
+        dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
+        dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
+        dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
+        dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
+        dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
+        dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
+    } // release lock
+}
+
+void TouchInputMapper::initializeLocked() {
+    mCurrentTouch.clear();
+    mLastTouch.clear();
+    mDownTime = 0;
+
+    for (uint32_t i = 0; i < MAX_POINTERS; i++) {
+        mAveragingTouchFilter.historyStart[i] = 0;
+        mAveragingTouchFilter.historyEnd[i] = 0;
+    }
+
+    mJumpyTouchFilter.jumpyPointsDropped = 0;
+
+    mLocked.currentVirtualKey.down = false;
+
+    mLocked.orientedRanges.havePressure = false;
+    mLocked.orientedRanges.haveSize = false;
+    mLocked.orientedRanges.haveTouchSize = false;
+    mLocked.orientedRanges.haveToolSize = false;
+    mLocked.orientedRanges.haveOrientation = false;
+}
+
+void TouchInputMapper::configure() {
+    InputMapper::configure();
+
+    // Configure basic parameters.
+    configureParameters();
+
+    // Configure sources.
+    switch (mParameters.deviceType) {
+    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
+        mSources = AINPUT_SOURCE_TOUCHSCREEN;
+        break;
+    case Parameters::DEVICE_TYPE_TOUCH_PAD:
+        mSources = AINPUT_SOURCE_TOUCHPAD;
+        break;
+    default:
+        assert(false);
+    }
+
+    // Configure absolute axis information.
+    configureRawAxes();
+
+    // Prepare input device calibration.
+    parseCalibration();
+    resolveCalibration();
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+         // Configure surface dimensions and orientation.
+        configureSurfaceLocked();
+    } // release lock
+}
+
+void TouchInputMapper::configureParameters() {
+    mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
+    mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
+    mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
+
+    String8 deviceTypeString;
+    mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
+            deviceTypeString)) {
+        if (deviceTypeString == "touchPad") {
+            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
+        } else if (deviceTypeString != "touchScreen") {
+            LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
+        }
+    }
+    bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+
+    mParameters.orientationAware = isTouchScreen;
+    getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
+            mParameters.orientationAware);
+
+    mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
+}
+
+void TouchInputMapper::dumpParameters(String8& dump) {
+    dump.append(INDENT3 "Parameters:\n");
+
+    switch (mParameters.deviceType) {
+    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
+        dump.append(INDENT4 "DeviceType: touchScreen\n");
+        break;
+    case Parameters::DEVICE_TYPE_TOUCH_PAD:
+        dump.append(INDENT4 "DeviceType: touchPad\n");
+        break;
+    default:
+        assert(false);
+    }
+
+    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
+            mParameters.associatedDisplayId);
+    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
+            toString(mParameters.orientationAware));
+
+    dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
+            toString(mParameters.useBadTouchFilter));
+    dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
+            toString(mParameters.useAveragingTouchFilter));
+    dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
+            toString(mParameters.useJumpyTouchFilter));
+}
+
+void TouchInputMapper::configureRawAxes() {
+    mRawAxes.x.clear();
+    mRawAxes.y.clear();
+    mRawAxes.pressure.clear();
+    mRawAxes.touchMajor.clear();
+    mRawAxes.touchMinor.clear();
+    mRawAxes.toolMajor.clear();
+    mRawAxes.toolMinor.clear();
+    mRawAxes.orientation.clear();
+}
+
+static void dumpAxisInfo(String8& dump, RawAbsoluteAxisInfo axis, const char* name) {
+    if (axis.valid) {
+        dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
+                name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
+    } else {
+        dump.appendFormat(INDENT4 "%s: unknown range\n", name);
+    }
+}
+
+void TouchInputMapper::dumpRawAxes(String8& dump) {
+    dump.append(INDENT3 "Raw Axes:\n");
+    dumpAxisInfo(dump, mRawAxes.x, "X");
+    dumpAxisInfo(dump, mRawAxes.y, "Y");
+    dumpAxisInfo(dump, mRawAxes.pressure, "Pressure");
+    dumpAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
+    dumpAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
+    dumpAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
+    dumpAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
+    dumpAxisInfo(dump, mRawAxes.orientation, "Orientation");
+}
+
+bool TouchInputMapper::configureSurfaceLocked() {
+    // Update orientation and dimensions if needed.
+    int32_t orientation = DISPLAY_ORIENTATION_0;
+    int32_t width = mRawAxes.x.getRange();
+    int32_t height = mRawAxes.y.getRange();
+
+    if (mParameters.associatedDisplayId >= 0) {
+        bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
+        bool wantOrientation = mParameters.orientationAware;
+
+        // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
+        if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
+                wantSize ? &width : NULL, wantSize ? &height : NULL,
+                wantOrientation ? &orientation : NULL)) {
+            return false;
+        }
+    }
+
+    bool orientationChanged = mLocked.surfaceOrientation != orientation;
+    if (orientationChanged) {
+        mLocked.surfaceOrientation = orientation;
+    }
+
+    bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
+    if (sizeChanged) {
+        LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
+                getDeviceId(), getDeviceName().string(), width, height);
+
+        mLocked.surfaceWidth = width;
+        mLocked.surfaceHeight = height;
+
+        // Configure X and Y factors.
+        if (mRawAxes.x.valid && mRawAxes.y.valid) {
+            mLocked.xOrigin = mCalibration.haveXOrigin
+                    ? mCalibration.xOrigin
+                    : mRawAxes.x.minValue;
+            mLocked.yOrigin = mCalibration.haveYOrigin
+                    ? mCalibration.yOrigin
+                    : mRawAxes.y.minValue;
+            mLocked.xScale = mCalibration.haveXScale
+                    ? mCalibration.xScale
+                    : float(width) / mRawAxes.x.getRange();
+            mLocked.yScale = mCalibration.haveYScale
+                    ? mCalibration.yScale
+                    : float(height) / mRawAxes.y.getRange();
+            mLocked.xPrecision = 1.0f / mLocked.xScale;
+            mLocked.yPrecision = 1.0f / mLocked.yScale;
+
+            configureVirtualKeysLocked();
+        } else {
+            LOGW(INDENT "Touch device did not report support for X or Y axis!");
+            mLocked.xOrigin = 0;
+            mLocked.yOrigin = 0;
+            mLocked.xScale = 1.0f;
+            mLocked.yScale = 1.0f;
+            mLocked.xPrecision = 1.0f;
+            mLocked.yPrecision = 1.0f;
+        }
+
+        // Scale factor for terms that are not oriented in a particular axis.
+        // If the pixels are square then xScale == yScale otherwise we fake it
+        // by choosing an average.
+        mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
+
+        // Size of diagonal axis.
+        float diagonalSize = pythag(width, height);
+
+        // TouchMajor and TouchMinor factors.
+        if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
+            mLocked.orientedRanges.haveTouchSize = true;
+            mLocked.orientedRanges.touchMajor.min = 0;
+            mLocked.orientedRanges.touchMajor.max = diagonalSize;
+            mLocked.orientedRanges.touchMajor.flat = 0;
+            mLocked.orientedRanges.touchMajor.fuzz = 0;
+            mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
+        }
+
+        // ToolMajor and ToolMinor factors.
+        mLocked.toolSizeLinearScale = 0;
+        mLocked.toolSizeLinearBias = 0;
+        mLocked.toolSizeAreaScale = 0;
+        mLocked.toolSizeAreaBias = 0;
+        if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
+            if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
+                if (mCalibration.haveToolSizeLinearScale) {
+                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
+                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
+                    mLocked.toolSizeLinearScale = float(min(width, height))
+                            / mRawAxes.toolMajor.maxValue;
+                }
+
+                if (mCalibration.haveToolSizeLinearBias) {
+                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
+                }
+            } else if (mCalibration.toolSizeCalibration ==
+                    Calibration::TOOL_SIZE_CALIBRATION_AREA) {
+                if (mCalibration.haveToolSizeLinearScale) {
+                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
+                } else {
+                    mLocked.toolSizeLinearScale = min(width, height);
+                }
+
+                if (mCalibration.haveToolSizeLinearBias) {
+                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
+                }
+
+                if (mCalibration.haveToolSizeAreaScale) {
+                    mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
+                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
+                    mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
+                }
+
+                if (mCalibration.haveToolSizeAreaBias) {
+                    mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
+                }
+            }
+
+            mLocked.orientedRanges.haveToolSize = true;
+            mLocked.orientedRanges.toolMajor.min = 0;
+            mLocked.orientedRanges.toolMajor.max = diagonalSize;
+            mLocked.orientedRanges.toolMajor.flat = 0;
+            mLocked.orientedRanges.toolMajor.fuzz = 0;
+            mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
+        }
+
+        // Pressure factors.
+        mLocked.pressureScale = 0;
+        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
+            RawAbsoluteAxisInfo rawPressureAxis;
+            switch (mCalibration.pressureSource) {
+            case Calibration::PRESSURE_SOURCE_PRESSURE:
+                rawPressureAxis = mRawAxes.pressure;
+                break;
+            case Calibration::PRESSURE_SOURCE_TOUCH:
+                rawPressureAxis = mRawAxes.touchMajor;
+                break;
+            default:
+                rawPressureAxis.clear();
+            }
+
+            if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
+                    || mCalibration.pressureCalibration
+                            == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
+                if (mCalibration.havePressureScale) {
+                    mLocked.pressureScale = mCalibration.pressureScale;
+                } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
+                    mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
+                }
+            }
+
+            mLocked.orientedRanges.havePressure = true;
+            mLocked.orientedRanges.pressure.min = 0;
+            mLocked.orientedRanges.pressure.max = 1.0;
+            mLocked.orientedRanges.pressure.flat = 0;
+            mLocked.orientedRanges.pressure.fuzz = 0;
+        }
+
+        // Size factors.
+        mLocked.sizeScale = 0;
+        if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
+            if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
+                if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
+                    mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
+                }
+            }
+
+            mLocked.orientedRanges.haveSize = true;
+            mLocked.orientedRanges.size.min = 0;
+            mLocked.orientedRanges.size.max = 1.0;
+            mLocked.orientedRanges.size.flat = 0;
+            mLocked.orientedRanges.size.fuzz = 0;
+        }
+
+        // Orientation
+        mLocked.orientationScale = 0;
+        if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
+            if (mCalibration.orientationCalibration
+                    == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
+                if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
+                    mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
+                }
+            }
+
+            mLocked.orientedRanges.orientation.min = - M_PI_2;
+            mLocked.orientedRanges.orientation.max = M_PI_2;
+            mLocked.orientedRanges.orientation.flat = 0;
+            mLocked.orientedRanges.orientation.fuzz = 0;
+        }
+    }
+
+    if (orientationChanged || sizeChanged) {
+        // Compute oriented surface dimensions, precision, and scales.
+        float orientedXScale, orientedYScale;
+        switch (mLocked.surfaceOrientation) {
+        case DISPLAY_ORIENTATION_90:
+        case DISPLAY_ORIENTATION_270:
+            mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
+            mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
+            mLocked.orientedXPrecision = mLocked.yPrecision;
+            mLocked.orientedYPrecision = mLocked.xPrecision;
+            orientedXScale = mLocked.yScale;
+            orientedYScale = mLocked.xScale;
+            break;
+        default:
+            mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
+            mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
+            mLocked.orientedXPrecision = mLocked.xPrecision;
+            mLocked.orientedYPrecision = mLocked.yPrecision;
+            orientedXScale = mLocked.xScale;
+            orientedYScale = mLocked.yScale;
+            break;
+        }
+
+        // Configure position ranges.
+        mLocked.orientedRanges.x.min = 0;
+        mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
+        mLocked.orientedRanges.x.flat = 0;
+        mLocked.orientedRanges.x.fuzz = orientedXScale;
+
+        mLocked.orientedRanges.y.min = 0;
+        mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
+        mLocked.orientedRanges.y.flat = 0;
+        mLocked.orientedRanges.y.fuzz = orientedYScale;
+    }
+
+    return true;
+}
+
+void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
+    dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
+    dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
+    dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
+}
+
+void TouchInputMapper::configureVirtualKeysLocked() {
+    assert(mRawAxes.x.valid && mRawAxes.y.valid);
+
+    Vector<VirtualKeyDefinition> virtualKeyDefinitions;
+    getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
+
+    mLocked.virtualKeys.clear();
+
+    if (virtualKeyDefinitions.size() == 0) {
+        return;
+    }
+
+    mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
+
+    int32_t touchScreenLeft = mRawAxes.x.minValue;
+    int32_t touchScreenTop = mRawAxes.y.minValue;
+    int32_t touchScreenWidth = mRawAxes.x.getRange();
+    int32_t touchScreenHeight = mRawAxes.y.getRange();
+
+    for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
+        const VirtualKeyDefinition& virtualKeyDefinition =
+                virtualKeyDefinitions[i];
+
+        mLocked.virtualKeys.add();
+        VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
+
+        virtualKey.scanCode = virtualKeyDefinition.scanCode;
+        int32_t keyCode;
+        uint32_t flags;
+        if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
+                & keyCode, & flags)) {
+            LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
+                    virtualKey.scanCode);
+            mLocked.virtualKeys.pop(); // drop the key
+            continue;
+        }
+
+        virtualKey.keyCode = keyCode;
+        virtualKey.flags = flags;
+
+        // convert the key definition's display coordinates into touch coordinates for a hit box
+        int32_t halfWidth = virtualKeyDefinition.width / 2;
+        int32_t halfHeight = virtualKeyDefinition.height / 2;
+
+        virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
+                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
+        virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
+                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
+        virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
+                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
+        virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
+                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
+
+    }
+}
+
+void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
+    if (!mLocked.virtualKeys.isEmpty()) {
+        dump.append(INDENT3 "Virtual Keys:\n");
+
+        for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
+            const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
+            dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
+                    "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
+                    i, virtualKey.scanCode, virtualKey.keyCode,
+                    virtualKey.hitLeft, virtualKey.hitRight,
+                    virtualKey.hitTop, virtualKey.hitBottom);
+        }
+    }
+}
+
+void TouchInputMapper::parseCalibration() {
+    const PropertyMap& in = getDevice()->getConfiguration();
+    Calibration& out = mCalibration;
+
+    // Position
+    out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin);
+    out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin);
+    out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale);
+    out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale);
+
+    // Touch Size
+    out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
+    String8 touchSizeCalibrationString;
+    if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
+        if (touchSizeCalibrationString == "none") {
+            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
+        } else if (touchSizeCalibrationString == "geometric") {
+            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
+        } else if (touchSizeCalibrationString == "pressure") {
+            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
+        } else if (touchSizeCalibrationString != "default") {
+            LOGW("Invalid value for touch.touchSize.calibration: '%s'",
+                    touchSizeCalibrationString.string());
+        }
+    }
+
+    // Tool Size
+    out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
+    String8 toolSizeCalibrationString;
+    if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
+        if (toolSizeCalibrationString == "none") {
+            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
+        } else if (toolSizeCalibrationString == "geometric") {
+            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
+        } else if (toolSizeCalibrationString == "linear") {
+            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
+        } else if (toolSizeCalibrationString == "area") {
+            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
+        } else if (toolSizeCalibrationString != "default") {
+            LOGW("Invalid value for touch.toolSize.calibration: '%s'",
+                    toolSizeCalibrationString.string());
+        }
+    }
+
+    out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
+            out.toolSizeLinearScale);
+    out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
+            out.toolSizeLinearBias);
+    out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
+            out.toolSizeAreaScale);
+    out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
+            out.toolSizeAreaBias);
+    out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
+            out.toolSizeIsSummed);
+
+    // Pressure
+    out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
+    String8 pressureCalibrationString;
+    if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
+        if (pressureCalibrationString == "none") {
+            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
+        } else if (pressureCalibrationString == "physical") {
+            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
+        } else if (pressureCalibrationString == "amplitude") {
+            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
+        } else if (pressureCalibrationString != "default") {
+            LOGW("Invalid value for touch.pressure.calibration: '%s'",
+                    pressureCalibrationString.string());
+        }
+    }
+
+    out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
+    String8 pressureSourceString;
+    if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
+        if (pressureSourceString == "pressure") {
+            out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
+        } else if (pressureSourceString == "touch") {
+            out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
+        } else if (pressureSourceString != "default") {
+            LOGW("Invalid value for touch.pressure.source: '%s'",
+                    pressureSourceString.string());
+        }
+    }
+
+    out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
+            out.pressureScale);
+
+    // Size
+    out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
+    String8 sizeCalibrationString;
+    if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
+        if (sizeCalibrationString == "none") {
+            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
+        } else if (sizeCalibrationString == "normalized") {
+            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
+        } else if (sizeCalibrationString != "default") {
+            LOGW("Invalid value for touch.size.calibration: '%s'",
+                    sizeCalibrationString.string());
+        }
+    }
+
+    // Orientation
+    out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
+    String8 orientationCalibrationString;
+    if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
+        if (orientationCalibrationString == "none") {
+            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
+        } else if (orientationCalibrationString == "interpolated") {
+            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
+        } else if (orientationCalibrationString == "vector") {
+            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
+        } else if (orientationCalibrationString != "default") {
+            LOGW("Invalid value for touch.orientation.calibration: '%s'",
+                    orientationCalibrationString.string());
+        }
+    }
+}
+
+void TouchInputMapper::resolveCalibration() {
+    // Pressure
+    switch (mCalibration.pressureSource) {
+    case Calibration::PRESSURE_SOURCE_DEFAULT:
+        if (mRawAxes.pressure.valid) {
+            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
+        } else if (mRawAxes.touchMajor.valid) {
+            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
+        }
+        break;
+
+    case Calibration::PRESSURE_SOURCE_PRESSURE:
+        if (! mRawAxes.pressure.valid) {
+            LOGW("Calibration property touch.pressure.source is 'pressure' but "
+                    "the pressure axis is not available.");
+        }
+        break;
+
+    case Calibration::PRESSURE_SOURCE_TOUCH:
+        if (! mRawAxes.touchMajor.valid) {
+            LOGW("Calibration property touch.pressure.source is 'touch' but "
+                    "the touchMajor axis is not available.");
+        }
+        break;
+
+    default:
+        break;
+    }
+
+    switch (mCalibration.pressureCalibration) {
+    case Calibration::PRESSURE_CALIBRATION_DEFAULT:
+        if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
+            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
+        } else {
+            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
+        }
+        break;
+
+    default:
+        break;
+    }
+
+    // Tool Size
+    switch (mCalibration.toolSizeCalibration) {
+    case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
+        if (mRawAxes.toolMajor.valid) {
+            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
+        } else {
+            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
+        }
+        break;
+
+    default:
+        break;
+    }
+
+    // Touch Size
+    switch (mCalibration.touchSizeCalibration) {
+    case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
+        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
+                && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
+            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
+        } else {
+            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
+        }
+        break;
+
+    default:
+        break;
+    }
+
+    // Size
+    switch (mCalibration.sizeCalibration) {
+    case Calibration::SIZE_CALIBRATION_DEFAULT:
+        if (mRawAxes.toolMajor.valid) {
+            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
+        } else {
+            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
+        }
+        break;
+
+    default:
+        break;
+    }
+
+    // Orientation
+    switch (mCalibration.orientationCalibration) {
+    case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
+        if (mRawAxes.orientation.valid) {
+            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
+        } else {
+            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
+        }
+        break;
+
+    default:
+        break;
+    }
+}
+
+void TouchInputMapper::dumpCalibration(String8& dump) {
+    dump.append(INDENT3 "Calibration:\n");
+
+    // Position
+    if (mCalibration.haveXOrigin) {
+        dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin);
+    }
+    if (mCalibration.haveYOrigin) {
+        dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin);
+    }
+    if (mCalibration.haveXScale) {
+        dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale);
+    }
+    if (mCalibration.haveYScale) {
+        dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale);
+    }
+
+    // Touch Size
+    switch (mCalibration.touchSizeCalibration) {
+    case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
+        dump.append(INDENT4 "touch.touchSize.calibration: none\n");
+        break;
+    case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
+        dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
+        break;
+    case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
+        dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
+        break;
+    default:
+        assert(false);
+    }
+
+    // Tool Size
+    switch (mCalibration.toolSizeCalibration) {
+    case Calibration::TOOL_SIZE_CALIBRATION_NONE:
+        dump.append(INDENT4 "touch.toolSize.calibration: none\n");
+        break;
+    case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
+        dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
+        break;
+    case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
+        dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
+        break;
+    case Calibration::TOOL_SIZE_CALIBRATION_AREA:
+        dump.append(INDENT4 "touch.toolSize.calibration: area\n");
+        break;
+    default:
+        assert(false);
+    }
+
+    if (mCalibration.haveToolSizeLinearScale) {
+        dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
+                mCalibration.toolSizeLinearScale);
+    }
+
+    if (mCalibration.haveToolSizeLinearBias) {
+        dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
+                mCalibration.toolSizeLinearBias);
+    }
+
+    if (mCalibration.haveToolSizeAreaScale) {
+        dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
+                mCalibration.toolSizeAreaScale);
+    }
+
+    if (mCalibration.haveToolSizeAreaBias) {
+        dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
+                mCalibration.toolSizeAreaBias);
+    }
+
+    if (mCalibration.haveToolSizeIsSummed) {
+        dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
+                toString(mCalibration.toolSizeIsSummed));
+    }
+
+    // Pressure
+    switch (mCalibration.pressureCalibration) {
+    case Calibration::PRESSURE_CALIBRATION_NONE:
+        dump.append(INDENT4 "touch.pressure.calibration: none\n");
+        break;
+    case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
+        dump.append(INDENT4 "touch.pressure.calibration: physical\n");
+        break;
+    case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
+        dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
+        break;
+    default:
+        assert(false);
+    }
+
+    switch (mCalibration.pressureSource) {
+    case Calibration::PRESSURE_SOURCE_PRESSURE:
+        dump.append(INDENT4 "touch.pressure.source: pressure\n");
+        break;
+    case Calibration::PRESSURE_SOURCE_TOUCH:
+        dump.append(INDENT4 "touch.pressure.source: touch\n");
+        break;
+    case Calibration::PRESSURE_SOURCE_DEFAULT:
+        break;
+    default:
+        assert(false);
+    }
+
+    if (mCalibration.havePressureScale) {
+        dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
+                mCalibration.pressureScale);
+    }
+
+    // Size
+    switch (mCalibration.sizeCalibration) {
+    case Calibration::SIZE_CALIBRATION_NONE:
+        dump.append(INDENT4 "touch.size.calibration: none\n");
+        break;
+    case Calibration::SIZE_CALIBRATION_NORMALIZED:
+        dump.append(INDENT4 "touch.size.calibration: normalized\n");
+        break;
+    default:
+        assert(false);
+    }
+
+    // Orientation
+    switch (mCalibration.orientationCalibration) {
+    case Calibration::ORIENTATION_CALIBRATION_NONE:
+        dump.append(INDENT4 "touch.orientation.calibration: none\n");
+        break;
+    case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
+        dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
+        break;
+    case Calibration::ORIENTATION_CALIBRATION_VECTOR:
+        dump.append(INDENT4 "touch.orientation.calibration: vector\n");
+        break;
+    default:
+        assert(false);
+    }
+}
+
+void TouchInputMapper::reset() {
+    // Synthesize touch up event if touch is currently down.
+    // This will also take care of finishing virtual key processing if needed.
+    if (mLastTouch.pointerCount != 0) {
+        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
+        mCurrentTouch.clear();
+        syncTouch(when, true);
+    }
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+        initializeLocked();
+    } // release lock
+
+    InputMapper::reset();
+}
+
+void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
+    uint32_t policyFlags = 0;
+
+    // Preprocess pointer data.
+
+    if (mParameters.useBadTouchFilter) {
+        if (applyBadTouchFilter()) {
+            havePointerIds = false;
+        }
+    }
+
+    if (mParameters.useJumpyTouchFilter) {
+        if (applyJumpyTouchFilter()) {
+            havePointerIds = false;
+        }
+    }
+
+    if (! havePointerIds) {
+        calculatePointerIds();
+    }
+
+    TouchData temp;
+    TouchData* savedTouch;
+    if (mParameters.useAveragingTouchFilter) {
+        temp.copyFrom(mCurrentTouch);
+        savedTouch = & temp;
+
+        applyAveragingTouchFilter();
+    } else {
+        savedTouch = & mCurrentTouch;
+    }
+
+    // Process touches and virtual keys.
+
+    TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
+    if (touchResult == DISPATCH_TOUCH) {
+        dispatchTouches(when, policyFlags);
+    }
+
+    // Copy current touch to last touch in preparation for the next cycle.
+
+    if (touchResult == DROP_STROKE) {
+        mLastTouch.clear();
+    } else {
+        mLastTouch.copyFrom(*savedTouch);
+    }
+}
+
+TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
+        nsecs_t when, uint32_t policyFlags) {
+    int32_t keyEventAction, keyEventFlags;
+    int32_t keyCode, scanCode, downTime;
+    TouchResult touchResult;
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        // Update surface size and orientation, including virtual key positions.
+        if (! configureSurfaceLocked()) {
+            return DROP_STROKE;
+        }
+
+        // Check for virtual key press.
+        if (mLocked.currentVirtualKey.down) {
+            if (mCurrentTouch.pointerCount == 0) {
+                // Pointer went up while virtual key was down.
+                mLocked.currentVirtualKey.down = false;
+#if DEBUG_VIRTUAL_KEYS
+                LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
+                        mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
+#endif
+                keyEventAction = AKEY_EVENT_ACTION_UP;
+                keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
+                touchResult = SKIP_TOUCH;
+                goto DispatchVirtualKey;
+            }
+
+            if (mCurrentTouch.pointerCount == 1) {
+                int32_t x = mCurrentTouch.pointers[0].x;
+                int32_t y = mCurrentTouch.pointers[0].y;
+                const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
+                if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
+                    // Pointer is still within the space of the virtual key.
+                    return SKIP_TOUCH;
+                }
+            }
+
+            // Pointer left virtual key area or another pointer also went down.
+            // Send key cancellation and drop the stroke so subsequent motions will be
+            // considered fresh downs.  This is useful when the user swipes away from the
+            // virtual key area into the main display surface.
+            mLocked.currentVirtualKey.down = false;
+#if DEBUG_VIRTUAL_KEYS
+            LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
+                    mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
+#endif
+            keyEventAction = AKEY_EVENT_ACTION_UP;
+            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
+                    | AKEY_EVENT_FLAG_CANCELED;
+
+            // Check whether the pointer moved inside the display area where we should
+            // start a new stroke.
+            int32_t x = mCurrentTouch.pointers[0].x;
+            int32_t y = mCurrentTouch.pointers[0].y;
+            if (isPointInsideSurfaceLocked(x, y)) {
+                mLastTouch.clear();
+                touchResult = DISPATCH_TOUCH;
+            } else {
+                touchResult = DROP_STROKE;
+            }
+        } else {
+            if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
+                // Pointer just went down.  Handle off-screen touches, if needed.
+                int32_t x = mCurrentTouch.pointers[0].x;
+                int32_t y = mCurrentTouch.pointers[0].y;
+                if (! isPointInsideSurfaceLocked(x, y)) {
+                    // If exactly one pointer went down, check for virtual key hit.
+                    // Otherwise we will drop the entire stroke.
+                    if (mCurrentTouch.pointerCount == 1) {
+                        const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
+                        if (virtualKey) {
+                            mLocked.currentVirtualKey.down = true;
+                            mLocked.currentVirtualKey.downTime = when;
+                            mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
+                            mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
+#if DEBUG_VIRTUAL_KEYS
+                            LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
+                                    mLocked.currentVirtualKey.keyCode,
+                                    mLocked.currentVirtualKey.scanCode);
+#endif
+                            keyEventAction = AKEY_EVENT_ACTION_DOWN;
+                            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
+                                    | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
+                            touchResult = SKIP_TOUCH;
+                            goto DispatchVirtualKey;
+                        }
+                    }
+                    return DROP_STROKE;
+                }
+            }
+            return DISPATCH_TOUCH;
+        }
+
+    DispatchVirtualKey:
+        // Collect remaining state needed to dispatch virtual key.
+        keyCode = mLocked.currentVirtualKey.keyCode;
+        scanCode = mLocked.currentVirtualKey.scanCode;
+        downTime = mLocked.currentVirtualKey.downTime;
+    } // release lock
+
+    // Dispatch virtual key.
+    int32_t metaState = mContext->getGlobalMetaState();
+    policyFlags |= POLICY_FLAG_VIRTUAL;
+    getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
+            keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
+    return touchResult;
+}
+
+void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
+    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
+    uint32_t lastPointerCount = mLastTouch.pointerCount;
+    if (currentPointerCount == 0 && lastPointerCount == 0) {
+        return; // nothing to do!
+    }
+
+    BitSet32 currentIdBits = mCurrentTouch.idBits;
+    BitSet32 lastIdBits = mLastTouch.idBits;
+
+    if (currentIdBits == lastIdBits) {
+        // No pointer id changes so this is a move event.
+        // The dispatcher takes care of batching moves so we don't have to deal with that here.
+        int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
+        dispatchTouch(when, policyFlags, & mCurrentTouch,
+                currentIdBits, -1, currentPointerCount, motionEventAction);
+    } else {
+        // There may be pointers going up and pointers going down and pointers moving
+        // all at the same time.
+        BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
+        BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
+        BitSet32 activeIdBits(lastIdBits.value);
+        uint32_t pointerCount = lastPointerCount;
+
+        // Produce an intermediate representation of the touch data that consists of the
+        // old location of pointers that have just gone up and the new location of pointers that
+        // have just moved but omits the location of pointers that have just gone down.
+        TouchData interimTouch;
+        interimTouch.copyFrom(mLastTouch);
+
+        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
+        bool moveNeeded = false;
+        while (!moveIdBits.isEmpty()) {
+            uint32_t moveId = moveIdBits.firstMarkedBit();
+            moveIdBits.clearBit(moveId);
+
+            int32_t oldIndex = mLastTouch.idToIndex[moveId];
+            int32_t newIndex = mCurrentTouch.idToIndex[moveId];
+            if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
+                interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
+                moveNeeded = true;
+            }
+        }
+
+        // Dispatch pointer up events using the interim pointer locations.
+        while (!upIdBits.isEmpty()) {
+            uint32_t upId = upIdBits.firstMarkedBit();
+            upIdBits.clearBit(upId);
+            BitSet32 oldActiveIdBits = activeIdBits;
+            activeIdBits.clearBit(upId);
+
+            int32_t motionEventAction;
+            if (activeIdBits.isEmpty()) {
+                motionEventAction = AMOTION_EVENT_ACTION_UP;
+            } else {
+                motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
+            }
+
+            dispatchTouch(when, policyFlags, &interimTouch,
+                    oldActiveIdBits, upId, pointerCount, motionEventAction);
+            pointerCount -= 1;
+        }
+
+        // Dispatch move events if any of the remaining pointers moved from their old locations.
+        // Although applications receive new locations as part of individual pointer up
+        // events, they do not generally handle them except when presented in a move event.
+        if (moveNeeded) {
+            dispatchTouch(when, policyFlags, &mCurrentTouch,
+                    activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
+        }
+
+        // Dispatch pointer down events using the new pointer locations.
+        while (!downIdBits.isEmpty()) {
+            uint32_t downId = downIdBits.firstMarkedBit();
+            downIdBits.clearBit(downId);
+            BitSet32 oldActiveIdBits = activeIdBits;
+            activeIdBits.markBit(downId);
+
+            int32_t motionEventAction;
+            if (oldActiveIdBits.isEmpty()) {
+                motionEventAction = AMOTION_EVENT_ACTION_DOWN;
+                mDownTime = when;
+            } else {
+                motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
+            }
+
+            pointerCount += 1;
+            dispatchTouch(when, policyFlags, &mCurrentTouch,
+                    activeIdBits, downId, pointerCount, motionEventAction);
+        }
+    }
+}
+
+void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
+        TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
+        int32_t motionEventAction) {
+    int32_t pointerIds[MAX_POINTERS];
+    PointerCoords pointerCoords[MAX_POINTERS];
+    int32_t motionEventEdgeFlags = 0;
+    float xPrecision, yPrecision;
+
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        // Walk through the the active pointers and map touch screen coordinates (TouchData) into
+        // display coordinates (PointerCoords) and adjust for display orientation.
+        for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
+            uint32_t id = idBits.firstMarkedBit();
+            idBits.clearBit(id);
+            uint32_t inIndex = touch->idToIndex[id];
+
+            const PointerData& in = touch->pointers[inIndex];
+
+            // X and Y
+            float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
+            float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
+
+            // ToolMajor and ToolMinor
+            float toolMajor, toolMinor;
+            switch (mCalibration.toolSizeCalibration) {
+            case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
+                toolMajor = in.toolMajor * mLocked.geometricScale;
+                if (mRawAxes.toolMinor.valid) {
+                    toolMinor = in.toolMinor * mLocked.geometricScale;
+                } else {
+                    toolMinor = toolMajor;
+                }
+                break;
+            case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
+                toolMajor = in.toolMajor != 0
+                        ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
+                        : 0;
+                if (mRawAxes.toolMinor.valid) {
+                    toolMinor = in.toolMinor != 0
+                            ? in.toolMinor * mLocked.toolSizeLinearScale
+                                    + mLocked.toolSizeLinearBias
+                            : 0;
+                } else {
+                    toolMinor = toolMajor;
+                }
+                break;
+            case Calibration::TOOL_SIZE_CALIBRATION_AREA:
+                if (in.toolMajor != 0) {
+                    float diameter = sqrtf(in.toolMajor
+                            * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
+                    toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
+                } else {
+                    toolMajor = 0;
+                }
+                toolMinor = toolMajor;
+                break;
+            default:
+                toolMajor = 0;
+                toolMinor = 0;
+                break;
+            }
+
+            if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
+                toolMajor /= pointerCount;
+                toolMinor /= pointerCount;
+            }
+
+            // Pressure
+            float rawPressure;
+            switch (mCalibration.pressureSource) {
+            case Calibration::PRESSURE_SOURCE_PRESSURE:
+                rawPressure = in.pressure;
+                break;
+            case Calibration::PRESSURE_SOURCE_TOUCH:
+                rawPressure = in.touchMajor;
+                break;
+            default:
+                rawPressure = 0;
+            }
+
+            float pressure;
+            switch (mCalibration.pressureCalibration) {
+            case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
+            case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
+                pressure = rawPressure * mLocked.pressureScale;
+                break;
+            default:
+                pressure = 1;
+                break;
+            }
+
+            // TouchMajor and TouchMinor
+            float touchMajor, touchMinor;
+            switch (mCalibration.touchSizeCalibration) {
+            case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
+                touchMajor = in.touchMajor * mLocked.geometricScale;
+                if (mRawAxes.touchMinor.valid) {
+                    touchMinor = in.touchMinor * mLocked.geometricScale;
+                } else {
+                    touchMinor = touchMajor;
+                }
+                break;
+            case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
+                touchMajor = toolMajor * pressure;
+                touchMinor = toolMinor * pressure;
+                break;
+            default:
+                touchMajor = 0;
+                touchMinor = 0;
+                break;
+            }
+
+            if (touchMajor > toolMajor) {
+                touchMajor = toolMajor;
+            }
+            if (touchMinor > toolMinor) {
+                touchMinor = toolMinor;
+            }
+
+            // Size
+            float size;
+            switch (mCalibration.sizeCalibration) {
+            case Calibration::SIZE_CALIBRATION_NORMALIZED: {
+                float rawSize = mRawAxes.toolMinor.valid
+                        ? avg(in.toolMajor, in.toolMinor)
+                        : in.toolMajor;
+                size = rawSize * mLocked.sizeScale;
+                break;
+            }
+            default:
+                size = 0;
+                break;
+            }
+
+            // Orientation
+            float orientation;
+            switch (mCalibration.orientationCalibration) {
+            case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
+                orientation = in.orientation * mLocked.orientationScale;
+                break;
+            case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
+                int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
+                int32_t c2 = signExtendNybble(in.orientation & 0x0f);
+                if (c1 != 0 || c2 != 0) {
+                    orientation = atan2f(c1, c2) * 0.5f;
+                    float minorAxisScale = (16.0f - pythag(c1, c2)) / 16.0f;
+                    toolMinor *= minorAxisScale;
+                    touchMinor *= minorAxisScale;
+                } else {
+                    orientation = 0;
+                }
+                break;
+            }
+            default:
+                orientation = 0;
+            }
+
+            // Adjust coords for orientation.
+            switch (mLocked.surfaceOrientation) {
+            case DISPLAY_ORIENTATION_90: {
+                float xTemp = x;
+                x = y;
+                y = mLocked.surfaceWidth - xTemp;
+                orientation -= M_PI_2;
+                if (orientation < - M_PI_2) {
+                    orientation += M_PI;
+                }
+                break;
+            }
+            case DISPLAY_ORIENTATION_180: {
+                x = mLocked.surfaceWidth - x;
+                y = mLocked.surfaceHeight - y;
+                break;
+            }
+            case DISPLAY_ORIENTATION_270: {
+                float xTemp = x;
+                x = mLocked.surfaceHeight - y;
+                y = xTemp;
+                orientation += M_PI_2;
+                if (orientation > M_PI_2) {
+                    orientation -= M_PI;
+                }
+                break;
+            }
+            }
+
+            // Write output coords.
+            PointerCoords& out = pointerCoords[outIndex];
+            out.x = x;
+            out.y = y;
+            out.pressure = pressure;
+            out.size = size;
+            out.touchMajor = touchMajor;
+            out.touchMinor = touchMinor;
+            out.toolMajor = toolMajor;
+            out.toolMinor = toolMinor;
+            out.orientation = orientation;
+
+            pointerIds[outIndex] = int32_t(id);
+
+            if (id == changedId) {
+                motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+            }
+        }
+
+        // Check edge flags by looking only at the first pointer since the flags are
+        // global to the event.
+        if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
+            if (pointerCoords[0].x <= 0) {
+                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
+            } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
+                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
+            }
+            if (pointerCoords[0].y <= 0) {
+                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
+            } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
+                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
+            }
+        }
+
+        xPrecision = mLocked.orientedXPrecision;
+        yPrecision = mLocked.orientedYPrecision;
+    } // release lock
+
+    getDispatcher()->notifyMotion(when, getDeviceId(), mSources, policyFlags,
+            motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
+            pointerCount, pointerIds, pointerCoords,
+            xPrecision, yPrecision, mDownTime);
+}
+
+bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
+    if (mRawAxes.x.valid && mRawAxes.y.valid) {
+        return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
+                && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
+    }
+    return true;
+}
+
+const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
+        int32_t x, int32_t y) {
+    size_t numVirtualKeys = mLocked.virtualKeys.size();
+    for (size_t i = 0; i < numVirtualKeys; i++) {
+        const VirtualKey& virtualKey = mLocked.virtualKeys[i];
+
+#if DEBUG_VIRTUAL_KEYS
+        LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
+                "left=%d, top=%d, right=%d, bottom=%d",
+                x, y,
+                virtualKey.keyCode, virtualKey.scanCode,
+                virtualKey.hitLeft, virtualKey.hitTop,
+                virtualKey.hitRight, virtualKey.hitBottom);
+#endif
+
+        if (virtualKey.isHit(x, y)) {
+            return & virtualKey;
+        }
+    }
+
+    return NULL;
+}
+
+void TouchInputMapper::calculatePointerIds() {
+    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
+    uint32_t lastPointerCount = mLastTouch.pointerCount;
+
+    if (currentPointerCount == 0) {
+        // No pointers to assign.
+        mCurrentTouch.idBits.clear();
+    } else if (lastPointerCount == 0) {
+        // All pointers are new.
+        mCurrentTouch.idBits.clear();
+        for (uint32_t i = 0; i < currentPointerCount; i++) {
+            mCurrentTouch.pointers[i].id = i;
+            mCurrentTouch.idToIndex[i] = i;
+            mCurrentTouch.idBits.markBit(i);
+        }
+    } else if (currentPointerCount == 1 && lastPointerCount == 1) {
+        // Only one pointer and no change in count so it must have the same id as before.
+        uint32_t id = mLastTouch.pointers[0].id;
+        mCurrentTouch.pointers[0].id = id;
+        mCurrentTouch.idToIndex[id] = 0;
+        mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
+    } else {
+        // General case.
+        // We build a heap of squared euclidean distances between current and last pointers
+        // associated with the current and last pointer indices.  Then, we find the best
+        // match (by distance) for each current pointer.
+        PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
+
+        uint32_t heapSize = 0;
+        for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
+                currentPointerIndex++) {
+            for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
+                    lastPointerIndex++) {
+                int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
+                        - mLastTouch.pointers[lastPointerIndex].x;
+                int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
+                        - mLastTouch.pointers[lastPointerIndex].y;
+
+                uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
+
+                // Insert new element into the heap (sift up).
+                heap[heapSize].currentPointerIndex = currentPointerIndex;
+                heap[heapSize].lastPointerIndex = lastPointerIndex;
+                heap[heapSize].distance = distance;
+                heapSize += 1;
+            }
+        }
+
+        // Heapify
+        for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
+            startIndex -= 1;
+            for (uint32_t parentIndex = startIndex; ;) {
+                uint32_t childIndex = parentIndex * 2 + 1;
+                if (childIndex >= heapSize) {
+                    break;
+                }
+
+                if (childIndex + 1 < heapSize
+                        && heap[childIndex + 1].distance < heap[childIndex].distance) {
+                    childIndex += 1;
+                }
+
+                if (heap[parentIndex].distance <= heap[childIndex].distance) {
+                    break;
+                }
+
+                swap(heap[parentIndex], heap[childIndex]);
+                parentIndex = childIndex;
+            }
+        }
+
+#if DEBUG_POINTER_ASSIGNMENT
+        LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
+        for (size_t i = 0; i < heapSize; i++) {
+            LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
+                    i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
+                    heap[i].distance);
+        }
+#endif
+
+        // Pull matches out by increasing order of distance.
+        // To avoid reassigning pointers that have already been matched, the loop keeps track
+        // of which last and current pointers have been matched using the matchedXXXBits variables.
+        // It also tracks the used pointer id bits.
+        BitSet32 matchedLastBits(0);
+        BitSet32 matchedCurrentBits(0);
+        BitSet32 usedIdBits(0);
+        bool first = true;
+        for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
+            for (;;) {
+                if (first) {
+                    // The first time through the loop, we just consume the root element of
+                    // the heap (the one with smallest distance).
+                    first = false;
+                } else {
+                    // Previous iterations consumed the root element of the heap.
+                    // Pop root element off of the heap (sift down).
+                    heapSize -= 1;
+                    assert(heapSize > 0);
+
+                    // Sift down.
+                    heap[0] = heap[heapSize];
+                    for (uint32_t parentIndex = 0; ;) {
+                        uint32_t childIndex = parentIndex * 2 + 1;
+                        if (childIndex >= heapSize) {
+                            break;
+                        }
+
+                        if (childIndex + 1 < heapSize
+                                && heap[childIndex + 1].distance < heap[childIndex].distance) {
+                            childIndex += 1;
+                        }
+
+                        if (heap[parentIndex].distance <= heap[childIndex].distance) {
+                            break;
+                        }
+
+                        swap(heap[parentIndex], heap[childIndex]);
+                        parentIndex = childIndex;
+                    }
+
+#if DEBUG_POINTER_ASSIGNMENT
+                    LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
+                    for (size_t i = 0; i < heapSize; i++) {
+                        LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
+                                i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
+                                heap[i].distance);
+                    }
+#endif
+                }
+
+                uint32_t currentPointerIndex = heap[0].currentPointerIndex;
+                if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
+
+                uint32_t lastPointerIndex = heap[0].lastPointerIndex;
+                if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
+
+                matchedCurrentBits.markBit(currentPointerIndex);
+                matchedLastBits.markBit(lastPointerIndex);
+
+                uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
+                mCurrentTouch.pointers[currentPointerIndex].id = id;
+                mCurrentTouch.idToIndex[id] = currentPointerIndex;
+                usedIdBits.markBit(id);
+
+#if DEBUG_POINTER_ASSIGNMENT
+                LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
+                        lastPointerIndex, currentPointerIndex, id, heap[0].distance);
+#endif
+                break;
+            }
+        }
+
+        // Assign fresh ids to new pointers.
+        if (currentPointerCount > lastPointerCount) {
+            for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
+                uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
+                uint32_t id = usedIdBits.firstUnmarkedBit();
+
+                mCurrentTouch.pointers[currentPointerIndex].id = id;
+                mCurrentTouch.idToIndex[id] = currentPointerIndex;
+                usedIdBits.markBit(id);
+
+#if DEBUG_POINTER_ASSIGNMENT
+                LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
+                        currentPointerIndex, id);
+#endif
+
+                if (--i == 0) break; // done
+                matchedCurrentBits.markBit(currentPointerIndex);
+            }
+        }
+
+        // Fix id bits.
+        mCurrentTouch.idBits = usedIdBits;
+    }
+}
+
+/* Special hack for devices that have bad screen data: if one of the
+ * points has moved more than a screen height from the last position,
+ * then drop it. */
+bool TouchInputMapper::applyBadTouchFilter() {
+    // This hack requires valid axis parameters.
+    if (! mRawAxes.y.valid) {
+        return false;
+    }
+
+    uint32_t pointerCount = mCurrentTouch.pointerCount;
+
+    // Nothing to do if there are no points.
+    if (pointerCount == 0) {
+        return false;
+    }
+
+    // Don't do anything if a finger is going down or up.  We run
+    // here before assigning pointer IDs, so there isn't a good
+    // way to do per-finger matching.
+    if (pointerCount != mLastTouch.pointerCount) {
+        return false;
+    }
+
+    // We consider a single movement across more than a 7/16 of
+    // the long size of the screen to be bad.  This was a magic value
+    // determined by looking at the maximum distance it is feasible
+    // to actually move in one sample.
+    int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
+
+    // XXX The original code in InputDevice.java included commented out
+    //     code for testing the X axis.  Note that when we drop a point
+    //     we don't actually restore the old X either.  Strange.
+    //     The old code also tries to track when bad points were previously
+    //     detected but it turns out that due to the placement of a "break"
+    //     at the end of the loop, we never set mDroppedBadPoint to true
+    //     so it is effectively dead code.
+    // Need to figure out if the old code is busted or just overcomplicated
+    // but working as intended.
+
+    // Look through all new points and see if any are farther than
+    // acceptable from all previous points.
+    for (uint32_t i = pointerCount; i-- > 0; ) {
+        int32_t y = mCurrentTouch.pointers[i].y;
+        int32_t closestY = INT_MAX;
+        int32_t closestDeltaY = 0;
+
+#if DEBUG_HACKS
+        LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
+#endif
+
+        for (uint32_t j = pointerCount; j-- > 0; ) {
+            int32_t lastY = mLastTouch.pointers[j].y;
+            int32_t deltaY = abs(y - lastY);
+
+#if DEBUG_HACKS
+            LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
+                    j, lastY, deltaY);
+#endif
+
+            if (deltaY < maxDeltaY) {
+                goto SkipSufficientlyClosePoint;
+            }
+            if (deltaY < closestDeltaY) {
+                closestDeltaY = deltaY;
+                closestY = lastY;
+            }
+        }
+
+        // Must not have found a close enough match.
+#if DEBUG_HACKS
+        LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
+                i, y, closestY, closestDeltaY, maxDeltaY);
+#endif
+
+        mCurrentTouch.pointers[i].y = closestY;
+        return true; // XXX original code only corrects one point
+
+    SkipSufficientlyClosePoint: ;
+    }
+
+    // No change.
+    return false;
+}
+
+/* Special hack for devices that have bad screen data: drop points where
+ * the coordinate value for one axis has jumped to the other pointer's location.
+ */
+bool TouchInputMapper::applyJumpyTouchFilter() {
+    // This hack requires valid axis parameters.
+    if (! mRawAxes.y.valid) {
+        return false;
+    }
+
+    uint32_t pointerCount = mCurrentTouch.pointerCount;
+    if (mLastTouch.pointerCount != pointerCount) {
+#if DEBUG_HACKS
+        LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
+                mLastTouch.pointerCount, pointerCount);
+        for (uint32_t i = 0; i < pointerCount; i++) {
+            LOGD("  Pointer %d (%d, %d)", i,
+                    mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
+        }
+#endif
+
+        if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
+            if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
+                // Just drop the first few events going from 1 to 2 pointers.
+                // They're bad often enough that they're not worth considering.
+                mCurrentTouch.pointerCount = 1;
+                mJumpyTouchFilter.jumpyPointsDropped += 1;
+
+#if DEBUG_HACKS
+                LOGD("JumpyTouchFilter: Pointer 2 dropped");
+#endif
+                return true;
+            } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
+                // The event when we go from 2 -> 1 tends to be messed up too
+                mCurrentTouch.pointerCount = 2;
+                mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
+                mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
+                mJumpyTouchFilter.jumpyPointsDropped += 1;
+
+#if DEBUG_HACKS
+                for (int32_t i = 0; i < 2; i++) {
+                    LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
+                            mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
+                }
+#endif
+                return true;
+            }
+        }
+        // Reset jumpy points dropped on other transitions or if limit exceeded.
+        mJumpyTouchFilter.jumpyPointsDropped = 0;
+
+#if DEBUG_HACKS
+        LOGD("JumpyTouchFilter: Transition - drop limit reset");
+#endif
+        return false;
+    }
+
+    // We have the same number of pointers as last time.
+    // A 'jumpy' point is one where the coordinate value for one axis
+    // has jumped to the other pointer's location. No need to do anything
+    // else if we only have one pointer.
+    if (pointerCount < 2) {
+        return false;
+    }
+
+    if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
+        int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
+
+        // We only replace the single worst jumpy point as characterized by pointer distance
+        // in a single axis.
+        int32_t badPointerIndex = -1;
+        int32_t badPointerReplacementIndex = -1;
+        int32_t badPointerDistance = INT_MIN; // distance to be corrected
+
+        for (uint32_t i = pointerCount; i-- > 0; ) {
+            int32_t x = mCurrentTouch.pointers[i].x;
+            int32_t y = mCurrentTouch.pointers[i].y;
+
+#if DEBUG_HACKS
+            LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
+#endif
+
+            // Check if a touch point is too close to another's coordinates
+            bool dropX = false, dropY = false;
+            for (uint32_t j = 0; j < pointerCount; j++) {
+                if (i == j) {
+                    continue;
+                }
+
+                if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
+                    dropX = true;
+                    break;
+                }
+
+                if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
+                    dropY = true;
+                    break;
+                }
+            }
+            if (! dropX && ! dropY) {
+                continue; // not jumpy
+            }
+
+            // Find a replacement candidate by comparing with older points on the
+            // complementary (non-jumpy) axis.
+            int32_t distance = INT_MIN; // distance to be corrected
+            int32_t replacementIndex = -1;
+
+            if (dropX) {
+                // X looks too close.  Find an older replacement point with a close Y.
+                int32_t smallestDeltaY = INT_MAX;
+                for (uint32_t j = 0; j < pointerCount; j++) {
+                    int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
+                    if (deltaY < smallestDeltaY) {
+                        smallestDeltaY = deltaY;
+                        replacementIndex = j;
+                    }
+                }
+                distance = abs(x - mLastTouch.pointers[replacementIndex].x);
+            } else {
+                // Y looks too close.  Find an older replacement point with a close X.
+                int32_t smallestDeltaX = INT_MAX;
+                for (uint32_t j = 0; j < pointerCount; j++) {
+                    int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
+                    if (deltaX < smallestDeltaX) {
+                        smallestDeltaX = deltaX;
+                        replacementIndex = j;
+                    }
+                }
+                distance = abs(y - mLastTouch.pointers[replacementIndex].y);
+            }
+
+            // If replacing this pointer would correct a worse error than the previous ones
+            // considered, then use this replacement instead.
+            if (distance > badPointerDistance) {
+                badPointerIndex = i;
+                badPointerReplacementIndex = replacementIndex;
+                badPointerDistance = distance;
+            }
+        }
+
+        // Correct the jumpy pointer if one was found.
+        if (badPointerIndex >= 0) {
+#if DEBUG_HACKS
+            LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
+                    badPointerIndex,
+                    mLastTouch.pointers[badPointerReplacementIndex].x,
+                    mLastTouch.pointers[badPointerReplacementIndex].y);
+#endif
+
+            mCurrentTouch.pointers[badPointerIndex].x =
+                    mLastTouch.pointers[badPointerReplacementIndex].x;
+            mCurrentTouch.pointers[badPointerIndex].y =
+                    mLastTouch.pointers[badPointerReplacementIndex].y;
+            mJumpyTouchFilter.jumpyPointsDropped += 1;
+            return true;
+        }
+    }
+
+    mJumpyTouchFilter.jumpyPointsDropped = 0;
+    return false;
+}
+
+/* Special hack for devices that have bad screen data: aggregate and
+ * compute averages of the coordinate data, to reduce the amount of
+ * jitter seen by applications. */
+void TouchInputMapper::applyAveragingTouchFilter() {
+    for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
+        uint32_t id = mCurrentTouch.pointers[currentIndex].id;
+        int32_t x = mCurrentTouch.pointers[currentIndex].x;
+        int32_t y = mCurrentTouch.pointers[currentIndex].y;
+        int32_t pressure;
+        switch (mCalibration.pressureSource) {
+        case Calibration::PRESSURE_SOURCE_PRESSURE:
+            pressure = mCurrentTouch.pointers[currentIndex].pressure;
+            break;
+        case Calibration::PRESSURE_SOURCE_TOUCH:
+            pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
+            break;
+        default:
+            pressure = 1;
+            break;
+        }
+
+        if (mLastTouch.idBits.hasBit(id)) {
+            // Pointer was down before and is still down now.
+            // Compute average over history trace.
+            uint32_t start = mAveragingTouchFilter.historyStart[id];
+            uint32_t end = mAveragingTouchFilter.historyEnd[id];
+
+            int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
+            int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
+            uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
+
+#if DEBUG_HACKS
+            LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
+                    id, distance);
+#endif
+
+            if (distance < AVERAGING_DISTANCE_LIMIT) {
+                // Increment end index in preparation for recording new historical data.
+                end += 1;
+                if (end > AVERAGING_HISTORY_SIZE) {
+                    end = 0;
+                }
+
+                // If the end index has looped back to the start index then we have filled
+                // the historical trace up to the desired size so we drop the historical
+                // data at the start of the trace.
+                if (end == start) {
+                    start += 1;
+                    if (start > AVERAGING_HISTORY_SIZE) {
+                        start = 0;
+                    }
+                }
+
+                // Add the raw data to the historical trace.
+                mAveragingTouchFilter.historyStart[id] = start;
+                mAveragingTouchFilter.historyEnd[id] = end;
+                mAveragingTouchFilter.historyData[end].pointers[id].x = x;
+                mAveragingTouchFilter.historyData[end].pointers[id].y = y;
+                mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
+
+                // Average over all historical positions in the trace by total pressure.
+                int32_t averagedX = 0;
+                int32_t averagedY = 0;
+                int32_t totalPressure = 0;
+                for (;;) {
+                    int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
+                    int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
+                    int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
+                            .pointers[id].pressure;
+
+                    averagedX += historicalX * historicalPressure;
+                    averagedY += historicalY * historicalPressure;
+                    totalPressure += historicalPressure;
+
+                    if (start == end) {
+                        break;
+                    }
+
+                    start += 1;
+                    if (start > AVERAGING_HISTORY_SIZE) {
+                        start = 0;
+                    }
+                }
+
+                if (totalPressure != 0) {
+                    averagedX /= totalPressure;
+                    averagedY /= totalPressure;
+
+#if DEBUG_HACKS
+                    LOGD("AveragingTouchFilter: Pointer id %d - "
+                            "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
+                            averagedX, averagedY);
+#endif
+
+                    mCurrentTouch.pointers[currentIndex].x = averagedX;
+                    mCurrentTouch.pointers[currentIndex].y = averagedY;
+                }
+            } else {
+#if DEBUG_HACKS
+                LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
+#endif
+            }
+        } else {
+#if DEBUG_HACKS
+            LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
+#endif
+        }
+
+        // Reset pointer history.
+        mAveragingTouchFilter.historyStart[id] = 0;
+        mAveragingTouchFilter.historyEnd[id] = 0;
+        mAveragingTouchFilter.historyData[0].pointers[id].x = x;
+        mAveragingTouchFilter.historyData[0].pointers[id].y = y;
+        mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
+    }
+}
+
+int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
+            return AKEY_STATE_VIRTUAL;
+        }
+
+        size_t numVirtualKeys = mLocked.virtualKeys.size();
+        for (size_t i = 0; i < numVirtualKeys; i++) {
+            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
+            if (virtualKey.keyCode == keyCode) {
+                return AKEY_STATE_UP;
+            }
+        }
+    } // release lock
+
+    return AKEY_STATE_UNKNOWN;
+}
+
+int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
+            return AKEY_STATE_VIRTUAL;
+        }
+
+        size_t numVirtualKeys = mLocked.virtualKeys.size();
+        for (size_t i = 0; i < numVirtualKeys; i++) {
+            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
+            if (virtualKey.scanCode == scanCode) {
+                return AKEY_STATE_UP;
+            }
+        }
+    } // release lock
+
+    return AKEY_STATE_UNKNOWN;
+}
+
+bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+        const int32_t* keyCodes, uint8_t* outFlags) {
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        size_t numVirtualKeys = mLocked.virtualKeys.size();
+        for (size_t i = 0; i < numVirtualKeys; i++) {
+            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
+
+            for (size_t i = 0; i < numCodes; i++) {
+                if (virtualKey.keyCode == keyCodes[i]) {
+                    outFlags[i] = 1;
+                }
+            }
+        }
+    } // release lock
+
+    return true;
+}
+
+
+// --- SingleTouchInputMapper ---
+
+SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
+        TouchInputMapper(device) {
+    initialize();
+}
+
+SingleTouchInputMapper::~SingleTouchInputMapper() {
+}
+
+void SingleTouchInputMapper::initialize() {
+    mAccumulator.clear();
+
+    mDown = false;
+    mX = 0;
+    mY = 0;
+    mPressure = 0; // default to 0 for devices that don't report pressure
+    mToolWidth = 0; // default to 0 for devices that don't report tool width
+}
+
+void SingleTouchInputMapper::reset() {
+    TouchInputMapper::reset();
+
+    initialize();
+ }
+
+void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
+    switch (rawEvent->type) {
+    case EV_KEY:
+        switch (rawEvent->scanCode) {
+        case BTN_TOUCH:
+            mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
+            mAccumulator.btnTouch = rawEvent->value != 0;
+            // Don't sync immediately.  Wait until the next SYN_REPORT since we might
+            // not have received valid position information yet.  This logic assumes that
+            // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
+            break;
+        }
+        break;
+
+    case EV_ABS:
+        switch (rawEvent->scanCode) {
+        case ABS_X:
+            mAccumulator.fields |= Accumulator::FIELD_ABS_X;
+            mAccumulator.absX = rawEvent->value;
+            break;
+        case ABS_Y:
+            mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
+            mAccumulator.absY = rawEvent->value;
+            break;
+        case ABS_PRESSURE:
+            mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
+            mAccumulator.absPressure = rawEvent->value;
+            break;
+        case ABS_TOOL_WIDTH:
+            mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
+            mAccumulator.absToolWidth = rawEvent->value;
+            break;
+        }
+        break;
+
+    case EV_SYN:
+        switch (rawEvent->scanCode) {
+        case SYN_REPORT:
+            sync(rawEvent->when);
+            break;
+        }
+        break;
+    }
+}
+
+void SingleTouchInputMapper::sync(nsecs_t when) {
+    uint32_t fields = mAccumulator.fields;
+    if (fields == 0) {
+        return; // no new state changes, so nothing to do
+    }
+
+    if (fields & Accumulator::FIELD_BTN_TOUCH) {
+        mDown = mAccumulator.btnTouch;
+    }
+
+    if (fields & Accumulator::FIELD_ABS_X) {
+        mX = mAccumulator.absX;
+    }
+
+    if (fields & Accumulator::FIELD_ABS_Y) {
+        mY = mAccumulator.absY;
+    }
+
+    if (fields & Accumulator::FIELD_ABS_PRESSURE) {
+        mPressure = mAccumulator.absPressure;
+    }
+
+    if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
+        mToolWidth = mAccumulator.absToolWidth;
+    }
+
+    mCurrentTouch.clear();
+
+    if (mDown) {
+        mCurrentTouch.pointerCount = 1;
+        mCurrentTouch.pointers[0].id = 0;
+        mCurrentTouch.pointers[0].x = mX;
+        mCurrentTouch.pointers[0].y = mY;
+        mCurrentTouch.pointers[0].pressure = mPressure;
+        mCurrentTouch.pointers[0].touchMajor = 0;
+        mCurrentTouch.pointers[0].touchMinor = 0;
+        mCurrentTouch.pointers[0].toolMajor = mToolWidth;
+        mCurrentTouch.pointers[0].toolMinor = mToolWidth;
+        mCurrentTouch.pointers[0].orientation = 0;
+        mCurrentTouch.idToIndex[0] = 0;
+        mCurrentTouch.idBits.markBit(0);
+    }
+
+    syncTouch(when, true);
+
+    mAccumulator.clear();
+}
+
+void SingleTouchInputMapper::configureRawAxes() {
+    TouchInputMapper::configureRawAxes();
+
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
+}
+
+
+// --- MultiTouchInputMapper ---
+
+MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
+        TouchInputMapper(device) {
+    initialize();
+}
+
+MultiTouchInputMapper::~MultiTouchInputMapper() {
+}
+
+void MultiTouchInputMapper::initialize() {
+    mAccumulator.clear();
+}
+
+void MultiTouchInputMapper::reset() {
+    TouchInputMapper::reset();
+
+    initialize();
+}
+
+void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
+    switch (rawEvent->type) {
+    case EV_ABS: {
+        uint32_t pointerIndex = mAccumulator.pointerCount;
+        Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
+
+        switch (rawEvent->scanCode) {
+        case ABS_MT_POSITION_X:
+            pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
+            pointer->absMTPositionX = rawEvent->value;
+            break;
+        case ABS_MT_POSITION_Y:
+            pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
+            pointer->absMTPositionY = rawEvent->value;
+            break;
+        case ABS_MT_TOUCH_MAJOR:
+            pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
+            pointer->absMTTouchMajor = rawEvent->value;
+            break;
+        case ABS_MT_TOUCH_MINOR:
+            pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
+            pointer->absMTTouchMinor = rawEvent->value;
+            break;
+        case ABS_MT_WIDTH_MAJOR:
+            pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
+            pointer->absMTWidthMajor = rawEvent->value;
+            break;
+        case ABS_MT_WIDTH_MINOR:
+            pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
+            pointer->absMTWidthMinor = rawEvent->value;
+            break;
+        case ABS_MT_ORIENTATION:
+            pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
+            pointer->absMTOrientation = rawEvent->value;
+            break;
+        case ABS_MT_TRACKING_ID:
+            pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
+            pointer->absMTTrackingId = rawEvent->value;
+            break;
+        case ABS_MT_PRESSURE:
+            pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
+            pointer->absMTPressure = rawEvent->value;
+            break;
+        }
+        break;
+    }
+
+    case EV_SYN:
+        switch (rawEvent->scanCode) {
+        case SYN_MT_REPORT: {
+            // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
+            uint32_t pointerIndex = mAccumulator.pointerCount;
+
+            if (mAccumulator.pointers[pointerIndex].fields) {
+                if (pointerIndex == MAX_POINTERS) {
+                    LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
+                            MAX_POINTERS);
+                } else {
+                    pointerIndex += 1;
+                    mAccumulator.pointerCount = pointerIndex;
+                }
+            }
+
+            mAccumulator.pointers[pointerIndex].clear();
+            break;
+        }
+
+        case SYN_REPORT:
+            sync(rawEvent->when);
+            break;
+        }
+        break;
+    }
+}
+
+void MultiTouchInputMapper::sync(nsecs_t when) {
+    static const uint32_t REQUIRED_FIELDS =
+            Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
+
+    uint32_t inCount = mAccumulator.pointerCount;
+    uint32_t outCount = 0;
+    bool havePointerIds = true;
+
+    mCurrentTouch.clear();
+
+    for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
+        const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
+        uint32_t fields = inPointer.fields;
+
+        if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
+            // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
+            // Drop this finger.
+            continue;
+        }
+
+        PointerData& outPointer = mCurrentTouch.pointers[outCount];
+        outPointer.x = inPointer.absMTPositionX;
+        outPointer.y = inPointer.absMTPositionY;
+
+        if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
+            if (inPointer.absMTPressure <= 0) {
+                // Some devices send sync packets with X / Y but with a 0 pressure to indicate
+                // a pointer going up.  Drop this finger.
+                continue;
+            }
+            outPointer.pressure = inPointer.absMTPressure;
+        } else {
+            // Default pressure to 0 if absent.
+            outPointer.pressure = 0;
+        }
+
+        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
+            if (inPointer.absMTTouchMajor <= 0) {
+                // Some devices send sync packets with X / Y but with a 0 touch major to indicate
+                // a pointer going up.  Drop this finger.
+                continue;
+            }
+            outPointer.touchMajor = inPointer.absMTTouchMajor;
+        } else {
+            // Default touch area to 0 if absent.
+            outPointer.touchMajor = 0;
+        }
+
+        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
+            outPointer.touchMinor = inPointer.absMTTouchMinor;
+        } else {
+            // Assume touch area is circular.
+            outPointer.touchMinor = outPointer.touchMajor;
+        }
+
+        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
+            outPointer.toolMajor = inPointer.absMTWidthMajor;
+        } else {
+            // Default tool area to 0 if absent.
+            outPointer.toolMajor = 0;
+        }
+
+        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
+            outPointer.toolMinor = inPointer.absMTWidthMinor;
+        } else {
+            // Assume tool area is circular.
+            outPointer.toolMinor = outPointer.toolMajor;
+        }
+
+        if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
+            outPointer.orientation = inPointer.absMTOrientation;
+        } else {
+            // Default orientation to vertical if absent.
+            outPointer.orientation = 0;
+        }
+
+        // Assign pointer id using tracking id if available.
+        if (havePointerIds) {
+            if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
+                uint32_t id = uint32_t(inPointer.absMTTrackingId);
+
+                if (id > MAX_POINTER_ID) {
+#if DEBUG_POINTERS
+                    LOGD("Pointers: Ignoring driver provided pointer id %d because "
+                            "it is larger than max supported id %d",
+                            id, MAX_POINTER_ID);
+#endif
+                    havePointerIds = false;
+                }
+                else {
+                    outPointer.id = id;
+                    mCurrentTouch.idToIndex[id] = outCount;
+                    mCurrentTouch.idBits.markBit(id);
+                }
+            } else {
+                havePointerIds = false;
+            }
+        }
+
+        outCount += 1;
+    }
+
+    mCurrentTouch.pointerCount = outCount;
+
+    syncTouch(when, havePointerIds);
+
+    mAccumulator.clear();
+}
+
+void MultiTouchInputMapper::configureRawAxes() {
+    TouchInputMapper::configureRawAxes();
+
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
+    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
+}
+
+
+} // namespace android
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
new file mode 100644
index 0000000..8b2d40a
--- /dev/null
+++ b/services/input/InputReader.h
@@ -0,0 +1,956 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UI_INPUT_READER_H
+#define _UI_INPUT_READER_H
+
+#include "EventHub.h"
+#include "InputDispatcher.h"
+#include "PointerController.h"
+
+#include <ui/Input.h>
+#include <ui/DisplayInfo.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/BitSet.h>
+
+#include <stddef.h>
+#include <unistd.h>
+
+namespace android {
+
+class InputDevice;
+class InputMapper;
+
+
+/*
+ * Input reader policy interface.
+ *
+ * The input reader policy is used by the input reader to interact with the Window Manager
+ * and other system components.
+ *
+ * The actual implementation is partially supported by callbacks into the DVM
+ * via JNI.  This interface is also mocked in the unit tests.
+ */
+class InputReaderPolicyInterface : public virtual RefBase {
+protected:
+    InputReaderPolicyInterface() { }
+    virtual ~InputReaderPolicyInterface() { }
+
+public:
+    /* Display orientations. */
+    enum {
+        ROTATION_0 = 0,
+        ROTATION_90 = 1,
+        ROTATION_180 = 2,
+        ROTATION_270 = 3
+    };
+
+    /* Gets information about the display with the specified id.
+     * Returns true if the display info is available, false otherwise.
+     */
+    virtual bool getDisplayInfo(int32_t displayId,
+            int32_t* width, int32_t* height, int32_t* orientation) = 0;
+
+    /* Determines whether to turn on some hacks we have to improve the touch interaction with a
+     * certain device whose screen currently is not all that good.
+     */
+    virtual bool filterTouchEvents() = 0;
+
+    /* Determines whether to turn on some hacks to improve touch interaction with another device
+     * where touch coordinate data can get corrupted.
+     */
+    virtual bool filterJumpyTouchEvents() = 0;
+
+    /* Gets the excluded device names for the platform. */
+    virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0;
+
+    /* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
+    virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
+};
+
+
+/* Processes raw input events and sends cooked event data to an input dispatcher. */
+class InputReaderInterface : public virtual RefBase {
+protected:
+    InputReaderInterface() { }
+    virtual ~InputReaderInterface() { }
+
+public:
+    /* Dumps the state of the input reader.
+     *
+     * This method may be called on any thread (usually by the input manager). */
+    virtual void dump(String8& dump) = 0;
+
+    /* Runs a single iteration of the processing loop.
+     * Nominally reads and processes one incoming message from the EventHub.
+     *
+     * This method should be called on the input reader thread.
+     */
+    virtual void loopOnce() = 0;
+
+    /* Gets the current input device configuration.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 0;
+
+    /* Gets information about the specified input device.
+     * Returns OK if the device information was obtained or NAME_NOT_FOUND if there
+     * was no such device.
+     *
+     * This method may be called on any thread (usually by the input manager).
+     */
+    virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) = 0;
+
+    /* Gets the list of all registered device ids. */
+    virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds) = 0;
+
+    /* Query current input state. */
+    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t scanCode) = 0;
+    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t keyCode) = 0;
+    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
+            int32_t sw) = 0;
+
+    /* Determine whether physical keys exist for the given framework-domain key codes. */
+    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
+            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
+};
+
+
+/* Internal interface used by individual input devices to access global input device state
+ * and parameters maintained by the input reader.
+ */
+class InputReaderContext {
+public:
+    InputReaderContext() { }
+    virtual ~InputReaderContext() { }
+
+    virtual void updateGlobalMetaState() = 0;
+    virtual int32_t getGlobalMetaState() = 0;
+
+    virtual InputReaderPolicyInterface* getPolicy() = 0;
+    virtual InputDispatcherInterface* getDispatcher() = 0;
+    virtual EventHubInterface* getEventHub() = 0;
+};
+
+
+/* The input reader reads raw event data from the event hub and processes it into input events
+ * that it sends to the input dispatcher.  Some functions of the input reader, such as early
+ * event filtering in low power states, are controlled by a separate policy object.
+ *
+ * IMPORTANT INVARIANT:
+ *     Because the policy and dispatcher can potentially block or cause re-entrance into
+ *     the input reader, the input reader never calls into other components while holding
+ *     an exclusive internal lock whenever re-entrance can happen.
+ */
+class InputReader : public InputReaderInterface, protected InputReaderContext {
+public:
+    InputReader(const sp<EventHubInterface>& eventHub,
+            const sp<InputReaderPolicyInterface>& policy,
+            const sp<InputDispatcherInterface>& dispatcher);
+    virtual ~InputReader();
+
+    virtual void dump(String8& dump);
+
+    virtual void loopOnce();
+
+    virtual void getInputConfiguration(InputConfiguration* outConfiguration);
+
+    virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo);
+    virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds);
+
+    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t scanCode);
+    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t keyCode);
+    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
+            int32_t sw);
+
+    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
+            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
+
+protected:
+    // These methods are protected virtual so they can be overridden and instrumented
+    // by test cases.
+    virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes);
+
+private:
+    sp<EventHubInterface> mEventHub;
+    sp<InputReaderPolicyInterface> mPolicy;
+    sp<InputDispatcherInterface> mDispatcher;
+
+    virtual InputReaderPolicyInterface* getPolicy() { return mPolicy.get(); }
+    virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); }
+    virtual EventHubInterface* getEventHub() { return mEventHub.get(); }
+
+    // This reader/writer lock guards the list of input devices.
+    // The writer lock must be held whenever the list of input devices is modified
+    //   and then promptly released.
+    // The reader lock must be held whenever the list of input devices is traversed or an
+    //   input device in the list is accessed.
+    // This lock only protects the registry and prevents inadvertent deletion of device objects
+    // that are in use.  Individual devices are responsible for guarding their own internal state
+    // as needed for concurrent operation.
+    RWLock mDeviceRegistryLock;
+    KeyedVector<int32_t, InputDevice*> mDevices;
+
+    // low-level input event decoding and device management
+    void process(const RawEvent* rawEvent);
+
+    void addDevice(int32_t deviceId);
+    void removeDevice(int32_t deviceId);
+    void configureExcludedDevices();
+
+    void consumeEvent(const RawEvent* rawEvent);
+
+    void handleConfigurationChanged(nsecs_t when);
+
+    // state management for all devices
+    Mutex mStateLock;
+
+    int32_t mGlobalMetaState;
+    virtual void updateGlobalMetaState();
+    virtual int32_t getGlobalMetaState();
+
+    InputConfiguration mInputConfiguration;
+    void updateInputConfiguration();
+
+    // state queries
+    typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
+    int32_t getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
+            GetStateFunc getStateFunc);
+    bool markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+};
+
+
+/* Reads raw events from the event hub and processes them, endlessly. */
+class InputReaderThread : public Thread {
+public:
+    InputReaderThread(const sp<InputReaderInterface>& reader);
+    virtual ~InputReaderThread();
+
+private:
+    sp<InputReaderInterface> mReader;
+
+    virtual bool threadLoop();
+};
+
+
+/* Represents the state of a single input device. */
+class InputDevice {
+public:
+    InputDevice(InputReaderContext* context, int32_t id, const String8& name);
+    ~InputDevice();
+
+    inline InputReaderContext* getContext() { return mContext; }
+    inline int32_t getId() { return mId; }
+    inline const String8& getName() { return mName; }
+    inline uint32_t getSources() { return mSources; }
+
+    inline bool isIgnored() { return mMappers.isEmpty(); }
+
+    void dump(String8& dump);
+    void addMapper(InputMapper* mapper);
+    void configure();
+    void reset();
+    void process(const RawEvent* rawEvent);
+
+    void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
+    int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+    int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+    int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+    bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+
+    int32_t getMetaState();
+
+    inline const PropertyMap& getConfiguration() {
+        return mConfiguration;
+    }
+
+private:
+    InputReaderContext* mContext;
+    int32_t mId;
+
+    Vector<InputMapper*> mMappers;
+
+    String8 mName;
+    uint32_t mSources;
+
+    typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
+    int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
+
+    PropertyMap mConfiguration;
+};
+
+
+/* An input mapper transforms raw input events into cooked event data.
+ * A single input device can have multiple associated input mappers in order to interpret
+ * different classes of events.
+ */
+class InputMapper {
+public:
+    InputMapper(InputDevice* device);
+    virtual ~InputMapper();
+
+    inline InputDevice* getDevice() { return mDevice; }
+    inline int32_t getDeviceId() { return mDevice->getId(); }
+    inline const String8 getDeviceName() { return mDevice->getName(); }
+    inline InputReaderContext* getContext() { return mContext; }
+    inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
+    inline InputDispatcherInterface* getDispatcher() { return mContext->getDispatcher(); }
+    inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
+
+    virtual uint32_t getSources() = 0;
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void dump(String8& dump);
+    virtual void configure();
+    virtual void reset();
+    virtual void process(const RawEvent* rawEvent) = 0;
+
+    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+
+    virtual int32_t getMetaState();
+
+protected:
+    InputDevice* mDevice;
+    InputReaderContext* mContext;
+};
+
+
+class SwitchInputMapper : public InputMapper {
+public:
+    SwitchInputMapper(InputDevice* device);
+    virtual ~SwitchInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void process(const RawEvent* rawEvent);
+
+    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+
+private:
+    void processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue);
+};
+
+
+class KeyboardInputMapper : public InputMapper {
+public:
+    KeyboardInputMapper(InputDevice* device, uint32_t sources, int32_t keyboardType);
+    virtual ~KeyboardInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void dump(String8& dump);
+    virtual void configure();
+    virtual void reset();
+    virtual void process(const RawEvent* rawEvent);
+
+    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+
+    virtual int32_t getMetaState();
+
+private:
+    Mutex mLock;
+
+    struct KeyDown {
+        int32_t keyCode;
+        int32_t scanCode;
+    };
+
+    uint32_t mSources;
+    int32_t mKeyboardType;
+
+    // Immutable configuration parameters.
+    struct Parameters {
+        int32_t associatedDisplayId;
+        bool orientationAware;
+    } mParameters;
+
+    struct LockedState {
+        Vector<KeyDown> keyDowns; // keys that are down
+        int32_t metaState;
+        nsecs_t downTime; // time of most recent key down
+
+        struct LedState {
+            bool avail; // led is available
+            bool on;    // we think the led is currently on
+        };
+        LedState capsLockLedState;
+        LedState numLockLedState;
+        LedState scrollLockLedState;
+    } mLocked;
+
+    void initializeLocked();
+
+    void configureParameters();
+    void dumpParameters(String8& dump);
+
+    bool isKeyboardOrGamepadKey(int32_t scanCode);
+
+    void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode,
+            uint32_t policyFlags);
+
+    ssize_t findKeyDownLocked(int32_t scanCode);
+
+    void resetLedStateLocked();
+    void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led);
+    void updateLedStateLocked(bool reset);
+    void updateLedStateForModifierLocked(LockedState::LedState& ledState, int32_t led,
+            int32_t modifier, bool reset);
+};
+
+
+class CursorInputMapper : public InputMapper {
+public:
+    CursorInputMapper(InputDevice* device);
+    virtual ~CursorInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void dump(String8& dump);
+    virtual void configure();
+    virtual void reset();
+    virtual void process(const RawEvent* rawEvent);
+
+    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+
+private:
+    // Amount that trackball needs to move in order to generate a key event.
+    static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
+
+    Mutex mLock;
+
+    // Immutable configuration parameters.
+    struct Parameters {
+        enum Mode {
+            MODE_POINTER,
+            MODE_NAVIGATION,
+        };
+
+        Mode mode;
+        int32_t associatedDisplayId;
+        bool orientationAware;
+    } mParameters;
+
+    struct Accumulator {
+        enum {
+            FIELD_BTN_MOUSE = 1,
+            FIELD_REL_X = 2,
+            FIELD_REL_Y = 4
+        };
+
+        uint32_t fields;
+
+        bool btnMouse;
+        int32_t relX;
+        int32_t relY;
+
+        inline void clear() {
+            fields = 0;
+        }
+    } mAccumulator;
+
+    int32_t mSources;
+    float mXScale;
+    float mYScale;
+    float mXPrecision;
+    float mYPrecision;
+    sp<PointerControllerInterface> mPointerController;
+
+    struct LockedState {
+        bool down;
+        nsecs_t downTime;
+    } mLocked;
+
+    void initializeLocked();
+
+    void configureParameters();
+    void dumpParameters(String8& dump);
+
+    void sync(nsecs_t when);
+};
+
+
+class TouchInputMapper : public InputMapper {
+public:
+    TouchInputMapper(InputDevice* device);
+    virtual ~TouchInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void dump(String8& dump);
+    virtual void configure();
+    virtual void reset();
+
+    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+
+protected:
+    Mutex mLock;
+
+    struct VirtualKey {
+        int32_t keyCode;
+        int32_t scanCode;
+        uint32_t flags;
+
+        // computed hit box, specified in touch screen coords based on known display size
+        int32_t hitLeft;
+        int32_t hitTop;
+        int32_t hitRight;
+        int32_t hitBottom;
+
+        inline bool isHit(int32_t x, int32_t y) const {
+            return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
+        }
+    };
+
+    // Raw data for a single pointer.
+    struct PointerData {
+        uint32_t id;
+        int32_t x;
+        int32_t y;
+        int32_t pressure;
+        int32_t touchMajor;
+        int32_t touchMinor;
+        int32_t toolMajor;
+        int32_t toolMinor;
+        int32_t orientation;
+
+        inline bool operator== (const PointerData& other) const {
+            return id == other.id
+                    && x == other.x
+                    && y == other.y
+                    && pressure == other.pressure
+                    && touchMajor == other.touchMajor
+                    && touchMinor == other.touchMinor
+                    && toolMajor == other.toolMajor
+                    && toolMinor == other.toolMinor
+                    && orientation == other.orientation;
+        }
+        inline bool operator!= (const PointerData& other) const {
+            return !(*this == other);
+        }
+    };
+
+    // Raw data for a collection of pointers including a pointer id mapping table.
+    struct TouchData {
+        uint32_t pointerCount;
+        PointerData pointers[MAX_POINTERS];
+        BitSet32 idBits;
+        uint32_t idToIndex[MAX_POINTER_ID + 1];
+
+        void copyFrom(const TouchData& other) {
+            pointerCount = other.pointerCount;
+            idBits = other.idBits;
+
+            for (uint32_t i = 0; i < pointerCount; i++) {
+                pointers[i] = other.pointers[i];
+
+                int id = pointers[i].id;
+                idToIndex[id] = other.idToIndex[id];
+            }
+        }
+
+        inline void clear() {
+            pointerCount = 0;
+            idBits.clear();
+        }
+    };
+
+    // Input sources supported by the device.
+    int32_t mSources;
+
+    // Immutable configuration parameters.
+    struct Parameters {
+        enum DeviceType {
+            DEVICE_TYPE_TOUCH_SCREEN,
+            DEVICE_TYPE_TOUCH_PAD,
+        };
+
+        DeviceType deviceType;
+        int32_t associatedDisplayId;
+        bool orientationAware;
+
+        bool useBadTouchFilter;
+        bool useJumpyTouchFilter;
+        bool useAveragingTouchFilter;
+    } mParameters;
+
+    // Immutable calibration parameters in parsed form.
+    struct Calibration {
+        // Position
+        bool haveXOrigin;
+        int32_t xOrigin;
+        bool haveYOrigin;
+        int32_t yOrigin;
+        bool haveXScale;
+        float xScale;
+        bool haveYScale;
+        float yScale;
+
+        // Touch Size
+        enum TouchSizeCalibration {
+            TOUCH_SIZE_CALIBRATION_DEFAULT,
+            TOUCH_SIZE_CALIBRATION_NONE,
+            TOUCH_SIZE_CALIBRATION_GEOMETRIC,
+            TOUCH_SIZE_CALIBRATION_PRESSURE,
+        };
+
+        TouchSizeCalibration touchSizeCalibration;
+
+        // Tool Size
+        enum ToolSizeCalibration {
+            TOOL_SIZE_CALIBRATION_DEFAULT,
+            TOOL_SIZE_CALIBRATION_NONE,
+            TOOL_SIZE_CALIBRATION_GEOMETRIC,
+            TOOL_SIZE_CALIBRATION_LINEAR,
+            TOOL_SIZE_CALIBRATION_AREA,
+        };
+
+        ToolSizeCalibration toolSizeCalibration;
+        bool haveToolSizeLinearScale;
+        float toolSizeLinearScale;
+        bool haveToolSizeLinearBias;
+        float toolSizeLinearBias;
+        bool haveToolSizeAreaScale;
+        float toolSizeAreaScale;
+        bool haveToolSizeAreaBias;
+        float toolSizeAreaBias;
+        bool haveToolSizeIsSummed;
+        bool toolSizeIsSummed;
+
+        // Pressure
+        enum PressureCalibration {
+            PRESSURE_CALIBRATION_DEFAULT,
+            PRESSURE_CALIBRATION_NONE,
+            PRESSURE_CALIBRATION_PHYSICAL,
+            PRESSURE_CALIBRATION_AMPLITUDE,
+        };
+        enum PressureSource {
+            PRESSURE_SOURCE_DEFAULT,
+            PRESSURE_SOURCE_PRESSURE,
+            PRESSURE_SOURCE_TOUCH,
+        };
+
+        PressureCalibration pressureCalibration;
+        PressureSource pressureSource;
+        bool havePressureScale;
+        float pressureScale;
+
+        // Size
+        enum SizeCalibration {
+            SIZE_CALIBRATION_DEFAULT,
+            SIZE_CALIBRATION_NONE,
+            SIZE_CALIBRATION_NORMALIZED,
+        };
+
+        SizeCalibration sizeCalibration;
+
+        // Orientation
+        enum OrientationCalibration {
+            ORIENTATION_CALIBRATION_DEFAULT,
+            ORIENTATION_CALIBRATION_NONE,
+            ORIENTATION_CALIBRATION_INTERPOLATED,
+            ORIENTATION_CALIBRATION_VECTOR,
+        };
+
+        OrientationCalibration orientationCalibration;
+    } mCalibration;
+
+    // Raw axis information from the driver.
+    struct RawAxes {
+        RawAbsoluteAxisInfo x;
+        RawAbsoluteAxisInfo y;
+        RawAbsoluteAxisInfo pressure;
+        RawAbsoluteAxisInfo touchMajor;
+        RawAbsoluteAxisInfo touchMinor;
+        RawAbsoluteAxisInfo toolMajor;
+        RawAbsoluteAxisInfo toolMinor;
+        RawAbsoluteAxisInfo orientation;
+    } mRawAxes;
+
+    // Current and previous touch sample data.
+    TouchData mCurrentTouch;
+    TouchData mLastTouch;
+
+    // The time the primary pointer last went down.
+    nsecs_t mDownTime;
+
+    struct LockedState {
+        Vector<VirtualKey> virtualKeys;
+
+        // The surface orientation and width and height set by configureSurfaceLocked().
+        int32_t surfaceOrientation;
+        int32_t surfaceWidth, surfaceHeight;
+
+        // Translation and scaling factors, orientation-independent.
+        int32_t xOrigin;
+        float xScale;
+        float xPrecision;
+
+        int32_t yOrigin;
+        float yScale;
+        float yPrecision;
+
+        float geometricScale;
+
+        float toolSizeLinearScale;
+        float toolSizeLinearBias;
+        float toolSizeAreaScale;
+        float toolSizeAreaBias;
+
+        float pressureScale;
+
+        float sizeScale;
+
+        float orientationScale;
+
+        // Oriented motion ranges for input device info.
+        struct OrientedRanges {
+            InputDeviceInfo::MotionRange x;
+            InputDeviceInfo::MotionRange y;
+
+            bool havePressure;
+            InputDeviceInfo::MotionRange pressure;
+
+            bool haveSize;
+            InputDeviceInfo::MotionRange size;
+
+            bool haveTouchSize;
+            InputDeviceInfo::MotionRange touchMajor;
+            InputDeviceInfo::MotionRange touchMinor;
+
+            bool haveToolSize;
+            InputDeviceInfo::MotionRange toolMajor;
+            InputDeviceInfo::MotionRange toolMinor;
+
+            bool haveOrientation;
+            InputDeviceInfo::MotionRange orientation;
+        } orientedRanges;
+
+        // Oriented dimensions and precision.
+        float orientedSurfaceWidth, orientedSurfaceHeight;
+        float orientedXPrecision, orientedYPrecision;
+
+        struct CurrentVirtualKeyState {
+            bool down;
+            nsecs_t downTime;
+            int32_t keyCode;
+            int32_t scanCode;
+        } currentVirtualKey;
+    } mLocked;
+
+    virtual void configureParameters();
+    virtual void dumpParameters(String8& dump);
+    virtual void configureRawAxes();
+    virtual void dumpRawAxes(String8& dump);
+    virtual bool configureSurfaceLocked();
+    virtual void dumpSurfaceLocked(String8& dump);
+    virtual void configureVirtualKeysLocked();
+    virtual void dumpVirtualKeysLocked(String8& dump);
+    virtual void parseCalibration();
+    virtual void resolveCalibration();
+    virtual void dumpCalibration(String8& dump);
+
+    enum TouchResult {
+        // Dispatch the touch normally.
+        DISPATCH_TOUCH,
+        // Do not dispatch the touch, but keep tracking the current stroke.
+        SKIP_TOUCH,
+        // Do not dispatch the touch, and drop all information associated with the current stoke
+        // so the next movement will appear as a new down.
+        DROP_STROKE
+    };
+
+    void syncTouch(nsecs_t when, bool havePointerIds);
+
+private:
+    /* Maximum number of historical samples to average. */
+    static const uint32_t AVERAGING_HISTORY_SIZE = 5;
+
+    /* Slop distance for jumpy pointer detection.
+     * The vertical range of the screen divided by this is our epsilon value. */
+    static const uint32_t JUMPY_EPSILON_DIVISOR = 212;
+
+    /* Number of jumpy points to drop for touchscreens that need it. */
+    static const uint32_t JUMPY_TRANSITION_DROPS = 3;
+    static const uint32_t JUMPY_DROP_LIMIT = 3;
+
+    /* Maximum squared distance for averaging.
+     * If moving farther than this, turn of averaging to avoid lag in response. */
+    static const uint64_t AVERAGING_DISTANCE_LIMIT = 75 * 75;
+
+    struct AveragingTouchFilterState {
+        // Individual history tracks are stored by pointer id
+        uint32_t historyStart[MAX_POINTERS];
+        uint32_t historyEnd[MAX_POINTERS];
+        struct {
+            struct {
+                int32_t x;
+                int32_t y;
+                int32_t pressure;
+            } pointers[MAX_POINTERS];
+        } historyData[AVERAGING_HISTORY_SIZE];
+    } mAveragingTouchFilter;
+
+    struct JumpyTouchFilterState {
+        uint32_t jumpyPointsDropped;
+    } mJumpyTouchFilter;
+
+    struct PointerDistanceHeapElement {
+        uint32_t currentPointerIndex : 8;
+        uint32_t lastPointerIndex : 8;
+        uint64_t distance : 48; // squared distance
+    };
+
+    void initializeLocked();
+
+    TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags);
+    void dispatchTouches(nsecs_t when, uint32_t policyFlags);
+    void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch,
+            BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
+            int32_t motionEventAction);
+
+    bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
+    const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y);
+
+    bool applyBadTouchFilter();
+    bool applyJumpyTouchFilter();
+    void applyAveragingTouchFilter();
+    void calculatePointerIds();
+};
+
+
+class SingleTouchInputMapper : public TouchInputMapper {
+public:
+    SingleTouchInputMapper(InputDevice* device);
+    virtual ~SingleTouchInputMapper();
+
+    virtual void reset();
+    virtual void process(const RawEvent* rawEvent);
+
+protected:
+    virtual void configureRawAxes();
+
+private:
+    struct Accumulator {
+        enum {
+            FIELD_BTN_TOUCH = 1,
+            FIELD_ABS_X = 2,
+            FIELD_ABS_Y = 4,
+            FIELD_ABS_PRESSURE = 8,
+            FIELD_ABS_TOOL_WIDTH = 16
+        };
+
+        uint32_t fields;
+
+        bool btnTouch;
+        int32_t absX;
+        int32_t absY;
+        int32_t absPressure;
+        int32_t absToolWidth;
+
+        inline void clear() {
+            fields = 0;
+        }
+    } mAccumulator;
+
+    bool mDown;
+    int32_t mX;
+    int32_t mY;
+    int32_t mPressure;
+    int32_t mToolWidth;
+
+    void initialize();
+
+    void sync(nsecs_t when);
+};
+
+
+class MultiTouchInputMapper : public TouchInputMapper {
+public:
+    MultiTouchInputMapper(InputDevice* device);
+    virtual ~MultiTouchInputMapper();
+
+    virtual void reset();
+    virtual void process(const RawEvent* rawEvent);
+
+protected:
+    virtual void configureRawAxes();
+
+private:
+    struct Accumulator {
+        enum {
+            FIELD_ABS_MT_POSITION_X = 1,
+            FIELD_ABS_MT_POSITION_Y = 2,
+            FIELD_ABS_MT_TOUCH_MAJOR = 4,
+            FIELD_ABS_MT_TOUCH_MINOR = 8,
+            FIELD_ABS_MT_WIDTH_MAJOR = 16,
+            FIELD_ABS_MT_WIDTH_MINOR = 32,
+            FIELD_ABS_MT_ORIENTATION = 64,
+            FIELD_ABS_MT_TRACKING_ID = 128,
+            FIELD_ABS_MT_PRESSURE = 256,
+        };
+
+        uint32_t pointerCount;
+        struct Pointer {
+            uint32_t fields;
+
+            int32_t absMTPositionX;
+            int32_t absMTPositionY;
+            int32_t absMTTouchMajor;
+            int32_t absMTTouchMinor;
+            int32_t absMTWidthMajor;
+            int32_t absMTWidthMinor;
+            int32_t absMTOrientation;
+            int32_t absMTTrackingId;
+            int32_t absMTPressure;
+
+            inline void clear() {
+                fields = 0;
+            }
+        } pointers[MAX_POINTERS + 1]; // + 1 to remove the need for extra range checks
+
+        inline void clear() {
+            pointerCount = 0;
+            pointers[0].clear();
+        }
+    } mAccumulator;
+
+    void initialize();
+
+    void sync(nsecs_t when);
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_READER_H
diff --git a/services/input/InputWindow.cpp b/services/input/InputWindow.cpp
new file mode 100644
index 0000000..9ce45f5
--- /dev/null
+++ b/services/input/InputWindow.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputWindow"
+
+#include "InputWindow.h"
+
+#include <cutils/log.h>
+
+namespace android {
+
+// --- InputWindow ---
+
+bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
+    return x >= touchableAreaLeft && x <= touchableAreaRight
+            && y >= touchableAreaTop && y <= touchableAreaBottom;
+}
+
+bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
+    return x >= frameLeft && x <= frameRight
+            && y >= frameTop && y <= frameBottom;
+}
+
+bool InputWindow::isTrustedOverlay() const {
+    return layoutParamsType == TYPE_INPUT_METHOD
+            || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
+            || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
+}
+
+bool InputWindow::supportsSplitTouch() const {
+    return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
+}
+
+} // namespace android
diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h
new file mode 100644
index 0000000..b3d5a65
--- /dev/null
+++ b/services/input/InputWindow.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UI_INPUT_WINDOW_H
+#define _UI_INPUT_WINDOW_H
+
+#include <ui/Input.h>
+#include <ui/InputTransport.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <utils/String8.h>
+
+#include "InputApplication.h"
+
+namespace android {
+
+/*
+ * A handle to a window that can receive input.
+ * Used by the native input dispatcher to indirectly refer to the window manager objects
+ * that describe a window.
+ */
+class InputWindowHandle : public RefBase {
+protected:
+    InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
+            mInputApplicationHandle(inputApplicationHandle) { }
+    virtual ~InputWindowHandle() { }
+
+public:
+    inline sp<InputApplicationHandle> getInputApplicationHandle() {
+        return mInputApplicationHandle;
+    }
+
+private:
+    sp<InputApplicationHandle> mInputApplicationHandle;
+};
+
+
+/*
+ * An input window describes the bounds of a window that can receive input.
+ */
+struct InputWindow {
+    // Window flags from WindowManager.LayoutParams
+    enum {
+        FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001,
+        FLAG_DIM_BEHIND        = 0x00000002,
+        FLAG_BLUR_BEHIND        = 0x00000004,
+        FLAG_NOT_FOCUSABLE      = 0x00000008,
+        FLAG_NOT_TOUCHABLE      = 0x00000010,
+        FLAG_NOT_TOUCH_MODAL    = 0x00000020,
+        FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
+        FLAG_KEEP_SCREEN_ON     = 0x00000080,
+        FLAG_LAYOUT_IN_SCREEN   = 0x00000100,
+        FLAG_LAYOUT_NO_LIMITS   = 0x00000200,
+        FLAG_FULLSCREEN      = 0x00000400,
+        FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800,
+        FLAG_DITHER             = 0x00001000,
+        FLAG_SECURE             = 0x00002000,
+        FLAG_SCALED             = 0x00004000,
+        FLAG_IGNORE_CHEEK_PRESSES    = 0x00008000,
+        FLAG_LAYOUT_INSET_DECOR = 0x00010000,
+        FLAG_ALT_FOCUSABLE_IM = 0x00020000,
+        FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
+        FLAG_SHOW_WHEN_LOCKED = 0x00080000,
+        FLAG_SHOW_WALLPAPER = 0x00100000,
+        FLAG_TURN_SCREEN_ON = 0x00200000,
+        FLAG_DISMISS_KEYGUARD = 0x00400000,
+        FLAG_SPLIT_TOUCH = 0x00800000,
+        FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
+        FLAG_COMPATIBLE_WINDOW = 0x20000000,
+        FLAG_SYSTEM_ERROR = 0x40000000,
+    };
+
+    // Window types from WindowManager.LayoutParams
+    enum {
+        FIRST_APPLICATION_WINDOW = 1,
+        TYPE_BASE_APPLICATION   = 1,
+        TYPE_APPLICATION        = 2,
+        TYPE_APPLICATION_STARTING = 3,
+        LAST_APPLICATION_WINDOW = 99,
+        FIRST_SUB_WINDOW        = 1000,
+        TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW,
+        TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1,
+        TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
+        TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
+        TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW+4,
+        LAST_SUB_WINDOW         = 1999,
+        FIRST_SYSTEM_WINDOW     = 2000,
+        TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW,
+        TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1,
+        TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2,
+        TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3,
+        TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4,
+        TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5,
+        TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6,
+        TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7,
+        TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8,
+        TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9,
+        TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10,
+        TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11,
+        TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
+        TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13,
+        TYPE_STATUS_BAR_SUB_PANEL  = FIRST_SYSTEM_WINDOW+14,
+        TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
+        TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16,
+        TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+17,
+        LAST_SYSTEM_WINDOW      = 2999,
+    };
+
+    sp<InputWindowHandle> inputWindowHandle;
+    sp<InputChannel> inputChannel;
+    String8 name;
+    int32_t layoutParamsFlags;
+    int32_t layoutParamsType;
+    nsecs_t dispatchingTimeout;
+    int32_t frameLeft;
+    int32_t frameTop;
+    int32_t frameRight;
+    int32_t frameBottom;
+    int32_t visibleFrameLeft;
+    int32_t visibleFrameTop;
+    int32_t visibleFrameRight;
+    int32_t visibleFrameBottom;
+    int32_t touchableAreaLeft;
+    int32_t touchableAreaTop;
+    int32_t touchableAreaRight;
+    int32_t touchableAreaBottom;
+    bool visible;
+    bool canReceiveKeys;
+    bool hasFocus;
+    bool hasWallpaper;
+    bool paused;
+    int32_t layer;
+    int32_t ownerPid;
+    int32_t ownerUid;
+
+    bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
+    bool frameContainsPoint(int32_t x, int32_t y) const;
+
+    /* Returns true if the window is of a trusted type that is allowed to silently
+     * overlay other windows for the purpose of implementing the secure views feature.
+     * Trusted overlays, such as IME windows, can partly obscure other windows without causing
+     * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
+     */
+    bool isTrustedOverlay() const;
+
+    bool supportsSplitTouch() const;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_WINDOW_H
diff --git a/services/input/PointerController.cpp b/services/input/PointerController.cpp
new file mode 100644
index 0000000..ebc58ee
--- /dev/null
+++ b/services/input/PointerController.cpp
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PointerController"
+
+//#define LOG_NDEBUG 0
+
+// Log debug messages about pointer updates
+#define DEBUG_POINTER_UPDATES 0
+
+#include "PointerController.h"
+
+#include <cutils/log.h>
+
+#include <SkBitmap.h>
+#include <SkCanvas.h>
+#include <SkColor.h>
+#include <SkPaint.h>
+#include <SkXfermode.h>
+
+namespace android {
+
+// --- PointerController ---
+
+PointerController::PointerController(int32_t pointerLayer) :
+    mPointerLayer(pointerLayer) {
+    AutoMutex _l(mLock);
+
+    mLocked.displayWidth = -1;
+    mLocked.displayHeight = -1;
+    mLocked.displayOrientation = DISPLAY_ORIENTATION_0;
+
+    mLocked.pointerX = 0;
+    mLocked.pointerY = 0;
+    mLocked.buttonState = 0;
+
+    mLocked.iconBitmap = NULL;
+    mLocked.iconHotSpotX = 0;
+    mLocked.iconHotSpotY = 0;
+
+    mLocked.wantVisible = false;
+    mLocked.visible = false;
+    mLocked.drawn = false;
+}
+
+PointerController::~PointerController() {
+    if (mSurfaceControl != NULL) {
+        mSurfaceControl->clear();
+        mSurfaceControl.clear();
+    }
+
+    if (mSurfaceComposerClient != NULL) {
+        mSurfaceComposerClient->dispose();
+        mSurfaceComposerClient.clear();
+    }
+
+    delete mLocked.iconBitmap;
+}
+
+bool PointerController::getBounds(float* outMinX, float* outMinY,
+        float* outMaxX, float* outMaxY) const {
+    AutoMutex _l(mLock);
+
+    return getBoundsLocked(outMinX, outMinY, outMaxX, outMaxY);
+}
+
+bool PointerController::getBoundsLocked(float* outMinX, float* outMinY,
+        float* outMaxX, float* outMaxY) const {
+    if (mLocked.displayWidth <= 0 || mLocked.displayHeight <= 0) {
+        return false;
+    }
+
+    *outMinX = 0;
+    *outMinY = 0;
+    switch (mLocked.displayOrientation) {
+    case DISPLAY_ORIENTATION_90:
+    case DISPLAY_ORIENTATION_270:
+        *outMaxX = mLocked.displayHeight;
+        *outMaxY = mLocked.displayWidth;
+        break;
+    default:
+        *outMaxX = mLocked.displayWidth;
+        *outMaxY = mLocked.displayHeight;
+        break;
+    }
+    return true;
+}
+
+void PointerController::move(float deltaX, float deltaY) {
+#if DEBUG_POINTER_UPDATES
+    LOGD("Move pointer by deltaX=%0.3f, deltaY=%0.3f", deltaX, deltaY);
+#endif
+    if (deltaX == 0.0f && deltaY == 0.0f) {
+        return;
+    }
+
+    AutoMutex _l(mLock);
+
+    setPositionLocked(mLocked.pointerX + deltaX, mLocked.pointerY + deltaY);
+}
+
+void PointerController::setButtonState(uint32_t buttonState) {
+#if DEBUG_POINTER_UPDATES
+    LOGD("Set button state 0x%08x", buttonState);
+#endif
+    AutoMutex _l(mLock);
+
+    if (mLocked.buttonState != buttonState) {
+        mLocked.buttonState = buttonState;
+        mLocked.wantVisible = true;
+        updateLocked();
+    }
+}
+
+uint32_t PointerController::getButtonState() const {
+    AutoMutex _l(mLock);
+
+    return mLocked.buttonState;
+}
+
+void PointerController::setPosition(float x, float y) {
+#if DEBUG_POINTER_UPDATES
+    LOGD("Set pointer position to x=%0.3f, y=%0.3f", x, y);
+#endif
+    AutoMutex _l(mLock);
+
+    setPositionLocked(x, y);
+}
+
+void PointerController::setPositionLocked(float x, float y) {
+    float minX, minY, maxX, maxY;
+    if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
+        if (x <= minX) {
+            mLocked.pointerX = minX;
+        } else if (x >= maxX) {
+            mLocked.pointerX = maxX;
+        } else {
+            mLocked.pointerX = x;
+        }
+        if (y <= minY) {
+            mLocked.pointerY = minY;
+        } else if (y >= maxY) {
+            mLocked.pointerY = maxY;
+        } else {
+            mLocked.pointerY = y;
+        }
+        mLocked.wantVisible = true;
+        updateLocked();
+    }
+}
+
+void PointerController::getPosition(float* outX, float* outY) const {
+    AutoMutex _l(mLock);
+
+    *outX = mLocked.pointerX;
+    *outY = mLocked.pointerY;
+}
+
+void PointerController::updateLocked() {
+    bool wantVisibleAndHavePointerIcon = mLocked.wantVisible && mLocked.iconBitmap;
+
+    if (wantVisibleAndHavePointerIcon) {
+        // Want the pointer to be visible.
+        // Ensure the surface is created and drawn.
+        if (!createSurfaceIfNeededLocked() || !drawPointerIfNeededLocked()) {
+            return;
+        }
+    } else {
+        // Don't want the pointer to be visible.
+        // If it is not visible then we are done.
+        if (mSurfaceControl == NULL || !mLocked.visible) {
+            return;
+        }
+    }
+
+    status_t status = mSurfaceComposerClient->openTransaction();
+    if (status) {
+        LOGE("Error opening surface transaction to update pointer surface.");
+        return;
+    }
+
+    if (wantVisibleAndHavePointerIcon) {
+        status = mSurfaceControl->setPosition(
+                mLocked.pointerX - mLocked.iconHotSpotX,
+                mLocked.pointerY - mLocked.iconHotSpotY);
+        if (status) {
+            LOGE("Error %d moving pointer surface.", status);
+            goto CloseTransaction;
+        }
+
+        if (!mLocked.visible) {
+            status = mSurfaceControl->setLayer(mPointerLayer);
+            if (status) {
+                LOGE("Error %d setting pointer surface layer.", status);
+                goto CloseTransaction;
+            }
+
+            status = mSurfaceControl->show(mPointerLayer);
+            if (status) {
+                LOGE("Error %d showing pointer surface.", status);
+                goto CloseTransaction;
+            }
+
+            mLocked.visible = true;
+        }
+    } else {
+        if (mLocked.visible) {
+            status = mSurfaceControl->hide();
+            if (status) {
+                LOGE("Error %d hiding pointer surface.", status);
+                goto CloseTransaction;
+            }
+
+            mLocked.visible = false;
+        }
+    }
+
+CloseTransaction:
+    status = mSurfaceComposerClient->closeTransaction();
+    if (status) {
+        LOGE("Error closing surface transaction to update pointer surface.");
+    }
+}
+
+void PointerController::setDisplaySize(int32_t width, int32_t height) {
+    AutoMutex _l(mLock);
+
+    if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
+        mLocked.displayWidth = width;
+        mLocked.displayHeight = height;
+
+        float minX, minY, maxX, maxY;
+        if (getBoundsLocked(&minX, &minY, &maxX, &maxY)) {
+            mLocked.pointerX = (minX + maxX) * 0.5f;
+            mLocked.pointerY = (minY + maxY) * 0.5f;
+        } else {
+            mLocked.pointerX = 0;
+            mLocked.pointerY = 0;
+        }
+
+        updateLocked();
+    }
+}
+
+void PointerController::setDisplayOrientation(int32_t orientation) {
+    AutoMutex _l(mLock);
+
+    if (mLocked.displayOrientation != orientation) {
+        float absoluteX, absoluteY;
+
+        // Map from oriented display coordinates to absolute display coordinates.
+        switch (mLocked.displayOrientation) {
+        case DISPLAY_ORIENTATION_90:
+            absoluteX = mLocked.displayWidth - mLocked.pointerY;
+            absoluteY = mLocked.pointerX;
+            break;
+        case DISPLAY_ORIENTATION_180:
+            absoluteX = mLocked.displayWidth - mLocked.pointerX;
+            absoluteY = mLocked.displayHeight - mLocked.pointerY;
+            break;
+        case DISPLAY_ORIENTATION_270:
+            absoluteX = mLocked.pointerY;
+            absoluteY = mLocked.displayHeight - mLocked.pointerX;
+            break;
+        default:
+            absoluteX = mLocked.pointerX;
+            absoluteY = mLocked.pointerY;
+            break;
+        }
+
+        // Map from absolute display coordinates to oriented display coordinates.
+        switch (orientation) {
+        case DISPLAY_ORIENTATION_90:
+            mLocked.pointerX = absoluteY;
+            mLocked.pointerY = mLocked.displayWidth - absoluteX;
+            break;
+        case DISPLAY_ORIENTATION_180:
+            mLocked.pointerX = mLocked.displayWidth - absoluteX;
+            mLocked.pointerY = mLocked.displayHeight - absoluteY;
+            break;
+        case DISPLAY_ORIENTATION_270:
+            mLocked.pointerX = mLocked.displayHeight - absoluteY;
+            mLocked.pointerY = absoluteX;
+            break;
+        default:
+            mLocked.pointerX = absoluteX;
+            mLocked.pointerY = absoluteY;
+            break;
+        }
+
+        mLocked.displayOrientation = orientation;
+
+        updateLocked();
+    }
+}
+
+void PointerController::setPointerIcon(const SkBitmap* bitmap, float hotSpotX, float hotSpotY) {
+    AutoMutex _l(mLock);
+
+    delete mLocked.iconBitmap;
+    mLocked.iconBitmap = bitmap ? new SkBitmap(*bitmap) : NULL;
+    mLocked.iconHotSpotX = hotSpotX;
+    mLocked.iconHotSpotY = hotSpotY;
+    mLocked.drawn = false;
+}
+
+bool PointerController::createSurfaceIfNeededLocked() {
+    if (!mLocked.iconBitmap) {
+        // If we don't have a pointer icon, then no point allocating a surface now.
+        return false;
+    }
+
+    if (mSurfaceComposerClient == NULL) {
+        mSurfaceComposerClient = new SurfaceComposerClient();
+    }
+
+    if (mSurfaceControl == NULL) {
+        mSurfaceControl = mSurfaceComposerClient->createSurface(getpid(),
+                String8("Pointer Icon"), 0,
+                mLocked.iconBitmap->width(), mLocked.iconBitmap->height(),
+                PIXEL_FORMAT_RGBA_8888);
+        if (mSurfaceControl == NULL) {
+            LOGE("Error creating pointer surface.");
+            return false;
+        }
+    }
+    return true;
+}
+
+bool PointerController::drawPointerIfNeededLocked() {
+    if (!mLocked.drawn) {
+        if (!mLocked.iconBitmap) {
+            return false;
+        }
+
+        if (!resizeSurfaceLocked(mLocked.iconBitmap->width(), mLocked.iconBitmap->height())) {
+            return false;
+        }
+
+        sp<Surface> surface = mSurfaceControl->getSurface();
+
+        Surface::SurfaceInfo surfaceInfo;
+        status_t status = surface->lock(&surfaceInfo);
+        if (status) {
+            LOGE("Error %d locking pointer surface before drawing.", status);
+            return false;
+        }
+
+        SkBitmap surfaceBitmap;
+        ssize_t bpr = surfaceInfo.s * bytesPerPixel(surfaceInfo.format);
+        surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config, surfaceInfo.w, surfaceInfo.h, bpr);
+        surfaceBitmap.setPixels(surfaceInfo.bits);
+
+        SkCanvas surfaceCanvas;
+        surfaceCanvas.setBitmapDevice(surfaceBitmap);
+
+        SkPaint paint;
+        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+        surfaceCanvas.drawBitmap(*mLocked.iconBitmap, 0, 0, &paint);
+
+        status = surface->unlockAndPost();
+        if (status) {
+            LOGE("Error %d unlocking pointer surface after drawing.", status);
+            return false;
+        }
+    }
+
+    mLocked.drawn = true;
+    return true;
+}
+
+bool PointerController::resizeSurfaceLocked(int32_t width, int32_t height) {
+    status_t status = mSurfaceComposerClient->openTransaction();
+    if (status) {
+        LOGE("Error opening surface transaction to resize pointer surface.");
+        return false;
+    }
+
+    status = mSurfaceControl->setSize(width, height);
+    if (status) {
+        LOGE("Error %d setting pointer surface size.", status);
+        return false;
+    }
+
+    status = mSurfaceComposerClient->closeTransaction();
+    if (status) {
+        LOGE("Error closing surface transaction to resize pointer surface.");
+        return false;
+    }
+
+    return true;
+}
+
+} // namespace android
diff --git a/services/input/PointerController.h b/services/input/PointerController.h
new file mode 100644
index 0000000..a2a9955
--- /dev/null
+++ b/services/input/PointerController.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UI_POINTER_CONTROLLER_H
+#define _UI_POINTER_CONTROLLER_H
+
+#include <ui/DisplayInfo.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+#include <surfaceflinger/Surface.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+
+#include <SkBitmap.h>
+
+namespace android {
+
+enum {
+    POINTER_BUTTON_1 = 1 << 0,
+};
+
+/**
+ * Interface for tracking a single (mouse) pointer.
+ *
+ * The pointer controller is responsible for providing synchronization and for tracking
+ * display orientation changes if needed.
+ */
+class PointerControllerInterface : public virtual RefBase {
+protected:
+    PointerControllerInterface() { }
+    virtual ~PointerControllerInterface() { }
+
+public:
+    /* Gets the bounds of the region that the pointer can traverse.
+     * Returns true if the bounds are available. */
+    virtual bool getBounds(float* outMinX, float* outMinY,
+            float* outMaxX, float* outMaxY) const = 0;
+
+    /* Move the pointer. */
+    virtual void move(float deltaX, float deltaY) = 0;
+
+    /* Sets a mask that indicates which buttons are pressed. */
+    virtual void setButtonState(uint32_t buttonState) = 0;
+
+    /* Gets a mask that indicates which buttons are pressed. */
+    virtual uint32_t getButtonState() const = 0;
+
+    /* Sets the absolute location of the pointer. */
+    virtual void setPosition(float x, float y) = 0;
+
+    /* Gets the absolute location of the pointer. */
+    virtual void getPosition(float* outX, float* outY) const = 0;
+};
+
+
+/*
+ * Tracks pointer movements and draws the pointer sprite to a surface.
+ *
+ * Handles pointer acceleration and animation.
+ */
+class PointerController : public PointerControllerInterface {
+protected:
+    virtual ~PointerController();
+
+public:
+    PointerController(int32_t pointerLayer);
+
+    virtual bool getBounds(float* outMinX, float* outMinY,
+            float* outMaxX, float* outMaxY) const;
+    virtual void move(float deltaX, float deltaY);
+    virtual void setButtonState(uint32_t buttonState);
+    virtual uint32_t getButtonState() const;
+    virtual void setPosition(float x, float y);
+    virtual void getPosition(float* outX, float* outY) const;
+
+    void setDisplaySize(int32_t width, int32_t height);
+    void setDisplayOrientation(int32_t orientation);
+    void setPointerIcon(const SkBitmap* bitmap, float hotSpotX, float hotSpotY);
+
+private:
+    mutable Mutex mLock;
+
+    int32_t mPointerLayer;
+    sp<SurfaceComposerClient> mSurfaceComposerClient;
+    sp<SurfaceControl> mSurfaceControl;
+
+    struct Locked {
+        int32_t displayWidth;
+        int32_t displayHeight;
+        int32_t displayOrientation;
+
+        float pointerX;
+        float pointerY;
+        uint32_t buttonState;
+
+        SkBitmap* iconBitmap;
+        float iconHotSpotX;
+        float iconHotSpotY;
+
+        bool wantVisible;
+        bool visible;
+        bool drawn;
+    } mLocked;
+
+    bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
+    void setPositionLocked(float x, float y);
+    void updateLocked();
+    bool createSurfaceIfNeededLocked();
+    bool drawPointerIfNeededLocked();
+    bool resizeSurfaceLocked(int32_t width, int32_t height);
+};
+
+} // namespace android
+
+#endif // _UI_POINTER_CONTROLLER_H
diff --git a/services/input/tests/Android.mk b/services/input/tests/Android.mk
new file mode 100644
index 0000000..799eb76
--- /dev/null
+++ b/services/input/tests/Android.mk
@@ -0,0 +1,50 @@
+# Build the unit tests.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+# Build the unit tests.
+test_src_files := \
+    InputReader_test.cpp \
+    InputDispatcher_test.cpp
+
+shared_libraries := \
+    libcutils \
+    libutils \
+    libhardware \
+    libhardware_legacy \
+    libui \
+    libsurfaceflinger_client \
+    libskia \
+    libstlport \
+    libinput
+
+static_libraries := \
+    libgtest \
+    libgtest_main
+
+c_includes := \
+    bionic \
+    bionic/libstdc++/include \
+    external/gtest/include \
+    external/stlport/stlport \
+    external/skia/include/core
+
+module_tags := eng tests
+
+$(foreach file,$(test_src_files), \
+    $(eval include $(CLEAR_VARS)) \
+    $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
+    $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \
+    $(eval LOCAL_C_INCLUDES := $(c_includes)) \
+    $(eval LOCAL_SRC_FILES := $(file)) \
+    $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
+    $(eval LOCAL_MODULE_TAGS := $(module_tags)) \
+    $(eval include $(BUILD_EXECUTABLE)) \
+)
+
+# Build the manual test programs.
+include $(call all-subdir-makefiles)
+
+endif
\ No newline at end of file
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
new file mode 100644
index 0000000..5ba1867
--- /dev/null
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -0,0 +1,230 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+
+#include "../InputDispatcher.h"
+
+#include <gtest/gtest.h>
+#include <linux/input.h>
+
+namespace android {
+
+// An arbitrary time value.
+static const nsecs_t ARBITRARY_TIME = 1234;
+
+// An arbitrary device id.
+static const int32_t DEVICE_ID = 1;
+
+// An arbitrary injector pid / uid pair that has permission to inject events.
+static const int32_t INJECTOR_PID = 999;
+static const int32_t INJECTOR_UID = 1001;
+
+
+// --- FakeInputDispatcherPolicy ---
+
+class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
+protected:
+    virtual ~FakeInputDispatcherPolicy() {
+    }
+
+public:
+    FakeInputDispatcherPolicy() {
+    }
+
+private:
+    virtual void notifyConfigurationChanged(nsecs_t when) {
+    }
+
+    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
+            const sp<InputWindowHandle>& inputWindowHandle) {
+        return 0;
+    }
+
+    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
+    }
+
+    virtual nsecs_t getKeyRepeatTimeout() {
+        return 500 * 1000000LL;
+    }
+
+    virtual nsecs_t getKeyRepeatDelay() {
+        return 50 * 1000000LL;
+    }
+
+    virtual int32_t getMaxEventsPerSecond() {
+        return 60;
+    }
+
+    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
+    }
+
+    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
+    }
+
+    virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
+            const KeyEvent* keyEvent, uint32_t policyFlags) {
+        return false;
+    }
+
+    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
+            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
+        return false;
+    }
+
+    virtual void notifySwitch(nsecs_t when,
+            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
+    }
+
+    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
+    }
+
+    virtual bool checkInjectEventsPermissionNonReentrant(
+            int32_t injectorPid, int32_t injectorUid) {
+        return false;
+    }
+};
+
+
+// --- InputDispatcherTest ---
+
+class InputDispatcherTest : public testing::Test {
+protected:
+    sp<FakeInputDispatcherPolicy> mFakePolicy;
+    sp<InputDispatcher> mDispatcher;
+
+    virtual void SetUp() {
+        mFakePolicy = new FakeInputDispatcherPolicy();
+        mDispatcher = new InputDispatcher(mFakePolicy);
+    }
+
+    virtual void TearDown() {
+        mFakePolicy.clear();
+        mDispatcher.clear();
+    }
+};
+
+
+TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
+    KeyEvent event;
+
+    // Rejects undefined key actions.
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
+            /*action*/ -1, 0,
+            AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+            << "Should reject key events with undefined action.";
+
+    // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
+            AKEY_EVENT_ACTION_MULTIPLE, 0,
+            AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+            << "Should reject key events with ACTION_MULTIPLE.";
+}
+
+TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
+    MotionEvent event;
+    int32_t pointerIds[MAX_POINTERS + 1];
+    PointerCoords pointerCoords[MAX_POINTERS + 1];
+    for (int i = 0; i <= MAX_POINTERS; i++) {
+        pointerIds[i] = i;
+    }
+
+    // Rejects undefined motion actions.
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+            /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME,
+            /*pointerCount*/ 1, pointerIds, pointerCoords);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+            << "Should reject motion events with undefined action.";
+
+    // Rejects pointer down with invalid index.
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+            AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            0, 0, AMETA_NONE, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME,
+            /*pointerCount*/ 1, pointerIds, pointerCoords);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+            << "Should reject motion events with pointer down index too large.";
+
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+            AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            0, 0, AMETA_NONE, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME,
+            /*pointerCount*/ 1, pointerIds, pointerCoords);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+            << "Should reject motion events with pointer down index too small.";
+
+    // Rejects pointer up with invalid index.
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+            AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            0, 0, AMETA_NONE, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME,
+            /*pointerCount*/ 1, pointerIds, pointerCoords);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+            << "Should reject motion events with pointer up index too large.";
+
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+            AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            0, 0, AMETA_NONE, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME,
+            /*pointerCount*/ 1, pointerIds, pointerCoords);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+            << "Should reject motion events with pointer up index too small.";
+
+    // Rejects motion events with invalid number of pointers.
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME,
+            /*pointerCount*/ 0, pointerIds, pointerCoords);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+            << "Should reject motion events with 0 pointers.";
+
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME,
+            /*pointerCount*/ MAX_POINTERS + 1, pointerIds, pointerCoords);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+            << "Should reject motion events with more than MAX_POINTERS pointers.";
+
+    // Rejects motion events with invalid pointer ids.
+    pointerIds[0] = -1;
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME,
+            /*pointerCount*/ 1, pointerIds, pointerCoords);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+            << "Should reject motion events with pointer ids less than 0.";
+
+    pointerIds[0] = MAX_POINTER_ID + 1;
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME,
+            /*pointerCount*/ 1, pointerIds, pointerCoords);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+            << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
+
+    // Rejects motion events with duplicate pointer ids.
+    pointerIds[0] = 1;
+    pointerIds[1] = 1;
+    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME,
+            /*pointerCount*/ 2, pointerIds, pointerCoords);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+            << "Should reject motion events with duplicate pointer ids.";
+}
+
+} // namespace android
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
new file mode 100644
index 0000000..8ec6f53
--- /dev/null
+++ b/services/input/tests/InputReader_test.cpp
@@ -0,0 +1,3644 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+
+#include "../InputReader.h"
+
+#include <utils/List.h>
+#include <gtest/gtest.h>
+#include <math.h>
+
+namespace android {
+
+// An arbitrary time value.
+static const nsecs_t ARBITRARY_TIME = 1234;
+
+// Arbitrary display properties.
+static const int32_t DISPLAY_ID = 0;
+static const int32_t DISPLAY_WIDTH = 480;
+static const int32_t DISPLAY_HEIGHT = 800;
+
+// Error tolerance for floating point assertions.
+static const float EPSILON = 0.001f;
+
+template<typename T>
+static inline T min(T a, T b) {
+    return a < b ? a : b;
+}
+
+static inline float avg(float x, float y) {
+    return (x + y) / 2;
+}
+
+
+// --- FakePointerController ---
+
+class FakePointerController : public PointerControllerInterface {
+    bool mHaveBounds;
+    float mMinX, mMinY, mMaxX, mMaxY;
+
+protected:
+    virtual ~FakePointerController() { }
+
+public:
+    FakePointerController() :
+        mHaveBounds(false), mMinX(0), mMinY(0), mMaxX(0), mMaxY(0) {
+    }
+
+    void setBounds(float minX, float minY, float maxX, float maxY) {
+        mHaveBounds = true;
+        mMinX = minX;
+        mMinY = minY;
+        mMaxX = maxX;
+        mMaxY = maxY;
+    }
+
+private:
+    virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const {
+        *outMinX = mMinX;
+        *outMinY = mMinY;
+        *outMaxX = mMaxX;
+        *outMaxY = mMaxY;
+        return mHaveBounds;
+    }
+
+    virtual void move(float deltaX, float deltaY) {
+    }
+
+    virtual void setButtonState(uint32_t buttonState) {
+    }
+
+    virtual uint32_t getButtonState() const {
+        return 0;
+    }
+
+    virtual void setPosition(float x, float y) {
+    }
+
+    virtual void getPosition(float* outX, float* outY) const {
+        *outX = 0;
+        *outY = 0;
+    }
+};
+
+
+// --- FakeInputReaderPolicy ---
+
+class FakeInputReaderPolicy : public InputReaderPolicyInterface {
+    struct DisplayInfo {
+        int32_t width;
+        int32_t height;
+        int32_t orientation;
+    };
+
+    KeyedVector<int32_t, DisplayInfo> mDisplayInfos;
+    bool mFilterTouchEvents;
+    bool mFilterJumpyTouchEvents;
+    Vector<String8> mExcludedDeviceNames;
+    KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers;
+
+protected:
+    virtual ~FakeInputReaderPolicy() { }
+
+public:
+    FakeInputReaderPolicy() :
+            mFilterTouchEvents(false), mFilterJumpyTouchEvents(false) {
+    }
+
+    void removeDisplayInfo(int32_t displayId) {
+        mDisplayInfos.removeItem(displayId);
+    }
+
+    void setDisplayInfo(int32_t displayId, int32_t width, int32_t height, int32_t orientation) {
+        removeDisplayInfo(displayId);
+
+        DisplayInfo info;
+        info.width = width;
+        info.height = height;
+        info.orientation = orientation;
+        mDisplayInfos.add(displayId, info);
+    }
+
+    void setFilterTouchEvents(bool enabled) {
+        mFilterTouchEvents = enabled;
+    }
+
+    void setFilterJumpyTouchEvents(bool enabled) {
+        mFilterJumpyTouchEvents = enabled;
+    }
+
+    void addExcludedDeviceName(const String8& deviceName) {
+        mExcludedDeviceNames.push(deviceName);
+    }
+
+    void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) {
+        mPointerControllers.add(deviceId, controller);
+    }
+
+private:
+    virtual bool getDisplayInfo(int32_t displayId,
+            int32_t* width, int32_t* height, int32_t* orientation) {
+        ssize_t index = mDisplayInfos.indexOfKey(displayId);
+        if (index >= 0) {
+            const DisplayInfo& info = mDisplayInfos.valueAt(index);
+            if (width) {
+                *width = info.width;
+            }
+            if (height) {
+                *height = info.height;
+            }
+            if (orientation) {
+                *orientation = info.orientation;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    virtual bool filterTouchEvents() {
+        return mFilterTouchEvents;
+    }
+
+    virtual bool filterJumpyTouchEvents() {
+        return mFilterJumpyTouchEvents;
+    }
+
+    virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
+        outExcludedDeviceNames.appendVector(mExcludedDeviceNames);
+    }
+
+    virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) {
+        return mPointerControllers.valueFor(deviceId);
+    }
+};
+
+
+// --- FakeInputDispatcher ---
+
+class FakeInputDispatcher : public InputDispatcherInterface {
+public:
+    struct NotifyConfigurationChangedArgs {
+        nsecs_t eventTime;
+    };
+
+    struct NotifyKeyArgs {
+        nsecs_t eventTime;
+        int32_t deviceId;
+        int32_t source;
+        uint32_t policyFlags;
+        int32_t action;
+        int32_t flags;
+        int32_t keyCode;
+        int32_t scanCode;
+        int32_t metaState;
+        nsecs_t downTime;
+    };
+
+    struct NotifyMotionArgs {
+        nsecs_t eventTime;
+        int32_t deviceId;
+        int32_t source;
+        uint32_t policyFlags;
+        int32_t action;
+        int32_t flags;
+        int32_t metaState;
+        int32_t edgeFlags;
+        uint32_t pointerCount;
+        Vector<int32_t> pointerIds;
+        Vector<PointerCoords> pointerCoords;
+        float xPrecision;
+        float yPrecision;
+        nsecs_t downTime;
+    };
+
+    struct NotifySwitchArgs {
+        nsecs_t when;
+        int32_t switchCode;
+        int32_t switchValue;
+        uint32_t policyFlags;
+    };
+
+private:
+    List<NotifyConfigurationChangedArgs> mNotifyConfigurationChangedArgs;
+    List<NotifyKeyArgs> mNotifyKeyArgs;
+    List<NotifyMotionArgs> mNotifyMotionArgs;
+    List<NotifySwitchArgs> mNotifySwitchArgs;
+
+protected:
+    virtual ~FakeInputDispatcher() { }
+
+public:
+    FakeInputDispatcher() {
+    }
+
+    void assertNotifyConfigurationChangedWasCalled(NotifyConfigurationChangedArgs* outArgs = NULL) {
+        ASSERT_FALSE(mNotifyConfigurationChangedArgs.empty())
+                << "Expected notifyConfigurationChanged() to have been called.";
+        if (outArgs) {
+            *outArgs = *mNotifyConfigurationChangedArgs.begin();
+        }
+        mNotifyConfigurationChangedArgs.erase(mNotifyConfigurationChangedArgs.begin());
+    }
+
+    void assertNotifyKeyWasCalled(NotifyKeyArgs* outArgs = NULL) {
+        ASSERT_FALSE(mNotifyKeyArgs.empty())
+                << "Expected notifyKey() to have been called.";
+        if (outArgs) {
+            *outArgs = *mNotifyKeyArgs.begin();
+        }
+        mNotifyKeyArgs.erase(mNotifyKeyArgs.begin());
+    }
+
+    void assertNotifyKeyWasNotCalled() {
+        ASSERT_TRUE(mNotifyKeyArgs.empty())
+                << "Expected notifyKey() to not have been called.";
+    }
+
+    void assertNotifyMotionWasCalled(NotifyMotionArgs* outArgs = NULL) {
+        ASSERT_FALSE(mNotifyMotionArgs.empty())
+                << "Expected notifyMotion() to have been called.";
+        if (outArgs) {
+            *outArgs = *mNotifyMotionArgs.begin();
+        }
+        mNotifyMotionArgs.erase(mNotifyMotionArgs.begin());
+    }
+
+    void assertNotifyMotionWasNotCalled() {
+        ASSERT_TRUE(mNotifyMotionArgs.empty())
+                << "Expected notifyMotion() to not have been called.";
+    }
+
+    void assertNotifySwitchWasCalled(NotifySwitchArgs* outArgs = NULL) {
+        ASSERT_FALSE(mNotifySwitchArgs.empty())
+                << "Expected notifySwitch() to have been called.";
+        if (outArgs) {
+            *outArgs = *mNotifySwitchArgs.begin();
+        }
+        mNotifySwitchArgs.erase(mNotifySwitchArgs.begin());
+    }
+
+private:
+    virtual void notifyConfigurationChanged(nsecs_t eventTime) {
+        NotifyConfigurationChangedArgs args;
+        args.eventTime = eventTime;
+        mNotifyConfigurationChangedArgs.push_back(args);
+    }
+
+    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
+            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
+            int32_t scanCode, int32_t metaState, nsecs_t downTime) {
+        NotifyKeyArgs args;
+        args.eventTime = eventTime;
+        args.deviceId = deviceId;
+        args.source = source;
+        args.policyFlags = policyFlags;
+        args.action = action;
+        args.flags = flags;
+        args.keyCode = keyCode;
+        args.scanCode = scanCode;
+        args.metaState = metaState;
+        args.downTime = downTime;
+        mNotifyKeyArgs.push_back(args);
+    }
+
+    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
+            uint32_t policyFlags, int32_t action, int32_t flags,
+            int32_t metaState, int32_t edgeFlags,
+            uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+            float xPrecision, float yPrecision, nsecs_t downTime) {
+        NotifyMotionArgs args;
+        args.eventTime = eventTime;
+        args.deviceId = deviceId;
+        args.source = source;
+        args.policyFlags = policyFlags;
+        args.action = action;
+        args.flags = flags;
+        args.metaState = metaState;
+        args.edgeFlags = edgeFlags;
+        args.pointerCount = pointerCount;
+        args.pointerIds.clear();
+        args.pointerIds.appendArray(pointerIds, pointerCount);
+        args.pointerCoords.clear();
+        args.pointerCoords.appendArray(pointerCoords, pointerCount);
+        args.xPrecision = xPrecision;
+        args.yPrecision = yPrecision;
+        args.downTime = downTime;
+        mNotifyMotionArgs.push_back(args);
+    }
+
+    virtual void notifySwitch(nsecs_t when,
+            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
+        NotifySwitchArgs args;
+        args.when = when;
+        args.switchCode = switchCode;
+        args.switchValue = switchValue;
+        args.policyFlags = policyFlags;
+        mNotifySwitchArgs.push_back(args);
+    }
+
+    virtual void dump(String8& dump) {
+        ADD_FAILURE() << "Should never be called by input reader.";
+    }
+
+    virtual void dispatchOnce() {
+        ADD_FAILURE() << "Should never be called by input reader.";
+    }
+
+    virtual int32_t injectInputEvent(const InputEvent* event,
+            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
+        ADD_FAILURE() << "Should never be called by input reader.";
+        return INPUT_EVENT_INJECTION_FAILED;
+    }
+
+    virtual void setInputWindows(const Vector<InputWindow>& inputWindows) {
+        ADD_FAILURE() << "Should never be called by input reader.";
+    }
+
+    virtual void setFocusedApplication(const InputApplication* inputApplication) {
+        ADD_FAILURE() << "Should never be called by input reader.";
+    }
+
+    virtual void setInputDispatchMode(bool enabled, bool frozen) {
+        ADD_FAILURE() << "Should never be called by input reader.";
+    }
+
+    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
+            const sp<InputChannel>& toChannel) {
+        ADD_FAILURE() << "Should never be called by input reader.";
+        return 0;
+    }
+
+    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
+            const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
+        ADD_FAILURE() << "Should never be called by input reader.";
+        return 0;
+    }
+
+    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) {
+        ADD_FAILURE() << "Should never be called by input reader.";
+        return 0;
+    }
+};
+
+
+// --- FakeEventHub ---
+
+class FakeEventHub : public EventHubInterface {
+    struct KeyInfo {
+        int32_t keyCode;
+        uint32_t flags;
+    };
+
+    struct Device {
+        String8 name;
+        uint32_t classes;
+        PropertyMap configuration;
+        KeyedVector<int, RawAbsoluteAxisInfo> axes;
+        KeyedVector<int32_t, int32_t> keyCodeStates;
+        KeyedVector<int32_t, int32_t> scanCodeStates;
+        KeyedVector<int32_t, int32_t> switchStates;
+        KeyedVector<int32_t, KeyInfo> keys;
+        KeyedVector<int32_t, bool> leds;
+        Vector<VirtualKeyDefinition> virtualKeys;
+
+        Device(const String8& name, uint32_t classes) :
+                name(name), classes(classes) {
+        }
+    };
+
+    KeyedVector<int32_t, Device*> mDevices;
+    Vector<String8> mExcludedDevices;
+    List<RawEvent> mEvents;
+
+protected:
+    virtual ~FakeEventHub() {
+        for (size_t i = 0; i < mDevices.size(); i++) {
+            delete mDevices.valueAt(i);
+        }
+    }
+
+public:
+    FakeEventHub() { }
+
+    void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
+        Device* device = new Device(name, classes);
+        mDevices.add(deviceId, device);
+
+        enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0, 0, 0);
+    }
+
+    void removeDevice(int32_t deviceId) {
+        delete mDevices.valueFor(deviceId);
+        mDevices.removeItem(deviceId);
+
+        enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0, 0, 0);
+    }
+
+    void finishDeviceScan() {
+        enqueueEvent(ARBITRARY_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0, 0, 0);
+    }
+
+    void addConfigurationProperty(int32_t deviceId, const String8& key, const String8& value) {
+        Device* device = getDevice(deviceId);
+        device->configuration.addProperty(key, value);
+    }
+
+    void addConfigurationMap(int32_t deviceId, const PropertyMap* configuration) {
+        Device* device = getDevice(deviceId);
+        device->configuration.addAll(configuration);
+    }
+
+    void addAxis(int32_t deviceId, int axis,
+            int32_t minValue, int32_t maxValue, int flat, int fuzz) {
+        Device* device = getDevice(deviceId);
+
+        RawAbsoluteAxisInfo info;
+        info.valid = true;
+        info.minValue = minValue;
+        info.maxValue = maxValue;
+        info.flat = flat;
+        info.fuzz = fuzz;
+        device->axes.add(axis, info);
+    }
+
+    void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state) {
+        Device* device = getDevice(deviceId);
+        device->keyCodeStates.replaceValueFor(keyCode, state);
+    }
+
+    void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) {
+        Device* device = getDevice(deviceId);
+        device->scanCodeStates.replaceValueFor(scanCode, state);
+    }
+
+    void setSwitchState(int32_t deviceId, int32_t switchCode, int32_t state) {
+        Device* device = getDevice(deviceId);
+        device->switchStates.replaceValueFor(switchCode, state);
+    }
+
+    void addKey(int32_t deviceId, int32_t scanCode, int32_t keyCode, uint32_t flags) {
+        Device* device = getDevice(deviceId);
+        KeyInfo info;
+        info.keyCode = keyCode;
+        info.flags = flags;
+        device->keys.add(scanCode, info);
+    }
+
+    void addLed(int32_t deviceId, int32_t led, bool initialState) {
+        Device* device = getDevice(deviceId);
+        device->leds.add(led, initialState);
+    }
+
+    bool getLedState(int32_t deviceId, int32_t led) {
+        Device* device = getDevice(deviceId);
+        return device->leds.valueFor(led);
+    }
+
+    Vector<String8>& getExcludedDevices() {
+        return mExcludedDevices;
+    }
+
+    void addVirtualKeyDefinition(int32_t deviceId, const VirtualKeyDefinition& definition) {
+        Device* device = getDevice(deviceId);
+        device->virtualKeys.push(definition);
+    }
+
+    void enqueueEvent(nsecs_t when, int32_t deviceId, int32_t type,
+            int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) {
+        RawEvent event;
+        event.when = when;
+        event.deviceId = deviceId;
+        event.type = type;
+        event.scanCode = scanCode;
+        event.keyCode = keyCode;
+        event.value = value;
+        event.flags = flags;
+        mEvents.push_back(event);
+    }
+
+    void assertQueueIsEmpty() {
+        ASSERT_EQ(size_t(0), mEvents.size())
+                << "Expected the event queue to be empty (fully consumed).";
+    }
+
+private:
+    Device* getDevice(int32_t deviceId) const {
+        ssize_t index = mDevices.indexOfKey(deviceId);
+        return index >= 0 ? mDevices.valueAt(index) : NULL;
+    }
+
+    virtual uint32_t getDeviceClasses(int32_t deviceId) const {
+        Device* device = getDevice(deviceId);
+        return device ? device->classes : 0;
+    }
+
+    virtual String8 getDeviceName(int32_t deviceId) const {
+        Device* device = getDevice(deviceId);
+        return device ? device->name : String8("unknown");
+    }
+
+    virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            *outConfiguration = device->configuration;
+        }
+    }
+
+    virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
+            RawAbsoluteAxisInfo* outAxisInfo) const {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->axes.indexOfKey(axis);
+            if (index >= 0) {
+                *outAxisInfo = device->axes.valueAt(index);
+                return OK;
+            }
+        }
+        return -1;
+    }
+
+    virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
+            int32_t* outKeycode, uint32_t* outFlags) const {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->keys.indexOfKey(scancode);
+            if (index >= 0) {
+                if (outKeycode) {
+                    *outKeycode = device->keys.valueAt(index).keyCode;
+                }
+                if (outFlags) {
+                    *outFlags = device->keys.valueAt(index).flags;
+                }
+                return OK;
+            }
+        }
+        return NAME_NOT_FOUND;
+    }
+
+    virtual void addExcludedDevice(const char* deviceName) {
+        mExcludedDevices.add(String8(deviceName));
+    }
+
+    virtual bool getEvent(RawEvent* outEvent) {
+        if (mEvents.empty()) {
+            return false;
+        }
+
+        *outEvent = *mEvents.begin();
+        mEvents.erase(mEvents.begin());
+        return true;
+    }
+
+    virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->scanCodeStates.indexOfKey(scanCode);
+            if (index >= 0) {
+                return device->scanCodeStates.valueAt(index);
+            }
+        }
+        return AKEY_STATE_UNKNOWN;
+    }
+
+    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->keyCodeStates.indexOfKey(keyCode);
+            if (index >= 0) {
+                return device->keyCodeStates.valueAt(index);
+            }
+        }
+        return AKEY_STATE_UNKNOWN;
+    }
+
+    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->switchStates.indexOfKey(sw);
+            if (index >= 0) {
+                return device->switchStates.valueAt(index);
+            }
+        }
+        return AKEY_STATE_UNKNOWN;
+    }
+
+    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
+            uint8_t* outFlags) const {
+        bool result = false;
+        Device* device = getDevice(deviceId);
+        if (device) {
+            for (size_t i = 0; i < numCodes; i++) {
+                for (size_t j = 0; j < device->keys.size(); j++) {
+                    if (keyCodes[i] == device->keys.valueAt(j).keyCode) {
+                        outFlags[i] = 1;
+                        result = true;
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    virtual bool hasLed(int32_t deviceId, int32_t led) const {
+        Device* device = getDevice(deviceId);
+        return device && device->leds.indexOfKey(led) >= 0;
+    }
+
+    virtual void setLedState(int32_t deviceId, int32_t led, bool on) {
+        Device* device = getDevice(deviceId);
+        if (device) {
+            ssize_t index = device->leds.indexOfKey(led);
+            if (index >= 0) {
+                device->leds.replaceValueAt(led, on);
+            } else {
+                ADD_FAILURE()
+                        << "Attempted to set the state of an LED that the EventHub declared "
+                        "was not present.  led=" << led;
+            }
+        }
+    }
+
+    virtual void getVirtualKeyDefinitions(int32_t deviceId,
+            Vector<VirtualKeyDefinition>& outVirtualKeys) const {
+        outVirtualKeys.clear();
+
+        Device* device = getDevice(deviceId);
+        if (device) {
+            outVirtualKeys.appendVector(device->virtualKeys);
+        }
+    }
+
+    virtual void dump(String8& dump) {
+    }
+};
+
+
+// --- FakeInputReaderContext ---
+
+class FakeInputReaderContext : public InputReaderContext {
+    sp<EventHubInterface> mEventHub;
+    sp<InputReaderPolicyInterface> mPolicy;
+    sp<InputDispatcherInterface> mDispatcher;
+    int32_t mGlobalMetaState;
+    bool mUpdateGlobalMetaStateWasCalled;
+
+public:
+    FakeInputReaderContext(const sp<EventHubInterface>& eventHub,
+            const sp<InputReaderPolicyInterface>& policy,
+            const sp<InputDispatcherInterface>& dispatcher) :
+            mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
+            mGlobalMetaState(0) {
+    }
+
+    virtual ~FakeInputReaderContext() { }
+
+    void assertUpdateGlobalMetaStateWasCalled() {
+        ASSERT_TRUE(mUpdateGlobalMetaStateWasCalled)
+                << "Expected updateGlobalMetaState() to have been called.";
+        mUpdateGlobalMetaStateWasCalled = false;
+    }
+
+    void setGlobalMetaState(int32_t state) {
+        mGlobalMetaState = state;
+    }
+
+private:
+    virtual void updateGlobalMetaState() {
+        mUpdateGlobalMetaStateWasCalled = true;
+    }
+
+    virtual int32_t getGlobalMetaState() {
+        return mGlobalMetaState;
+    }
+
+    virtual EventHubInterface* getEventHub() {
+        return mEventHub.get();
+    }
+
+    virtual InputReaderPolicyInterface* getPolicy() {
+        return mPolicy.get();
+    }
+
+    virtual InputDispatcherInterface* getDispatcher() {
+        return mDispatcher.get();
+    }
+};
+
+
+// --- FakeInputMapper ---
+
+class FakeInputMapper : public InputMapper {
+    uint32_t mSources;
+    int32_t mKeyboardType;
+    int32_t mMetaState;
+    KeyedVector<int32_t, int32_t> mKeyCodeStates;
+    KeyedVector<int32_t, int32_t> mScanCodeStates;
+    KeyedVector<int32_t, int32_t> mSwitchStates;
+    Vector<int32_t> mSupportedKeyCodes;
+    RawEvent mLastEvent;
+
+    bool mConfigureWasCalled;
+    bool mResetWasCalled;
+    bool mProcessWasCalled;
+
+public:
+    FakeInputMapper(InputDevice* device, uint32_t sources) :
+            InputMapper(device),
+            mSources(sources), mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
+            mMetaState(0),
+            mConfigureWasCalled(false), mResetWasCalled(false), mProcessWasCalled(false) {
+    }
+
+    virtual ~FakeInputMapper() { }
+
+    void setKeyboardType(int32_t keyboardType) {
+        mKeyboardType = keyboardType;
+    }
+
+    void setMetaState(int32_t metaState) {
+        mMetaState = metaState;
+    }
+
+    void assertConfigureWasCalled() {
+        ASSERT_TRUE(mConfigureWasCalled)
+                << "Expected configure() to have been called.";
+        mConfigureWasCalled = false;
+    }
+
+    void assertResetWasCalled() {
+        ASSERT_TRUE(mResetWasCalled)
+                << "Expected reset() to have been called.";
+        mResetWasCalled = false;
+    }
+
+    void assertProcessWasCalled(RawEvent* outLastEvent = NULL) {
+        ASSERT_TRUE(mProcessWasCalled)
+                << "Expected process() to have been called.";
+        if (outLastEvent) {
+            *outLastEvent = mLastEvent;
+        }
+        mProcessWasCalled = false;
+    }
+
+    void setKeyCodeState(int32_t keyCode, int32_t state) {
+        mKeyCodeStates.replaceValueFor(keyCode, state);
+    }
+
+    void setScanCodeState(int32_t scanCode, int32_t state) {
+        mScanCodeStates.replaceValueFor(scanCode, state);
+    }
+
+    void setSwitchState(int32_t switchCode, int32_t state) {
+        mSwitchStates.replaceValueFor(switchCode, state);
+    }
+
+    void addSupportedKeyCode(int32_t keyCode) {
+        mSupportedKeyCodes.add(keyCode);
+    }
+
+private:
+    virtual uint32_t getSources() {
+        return mSources;
+    }
+
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo) {
+        InputMapper::populateDeviceInfo(deviceInfo);
+
+        if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
+            deviceInfo->setKeyboardType(mKeyboardType);
+        }
+    }
+
+    virtual void configure() {
+        mConfigureWasCalled = true;
+    }
+
+    virtual void reset() {
+        mResetWasCalled = true;
+    }
+
+    virtual void process(const RawEvent* rawEvent) {
+        mLastEvent = *rawEvent;
+        mProcessWasCalled = true;
+    }
+
+    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+        ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
+        return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
+    }
+
+    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+        ssize_t index = mScanCodeStates.indexOfKey(scanCode);
+        return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
+    }
+
+    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode) {
+        ssize_t index = mSwitchStates.indexOfKey(switchCode);
+        return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
+    }
+
+    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags) {
+        bool result = false;
+        for (size_t i = 0; i < numCodes; i++) {
+            for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
+                if (keyCodes[i] == mSupportedKeyCodes[j]) {
+                    outFlags[i] = 1;
+                    result = true;
+                }
+            }
+        }
+        return result;
+    }
+
+    virtual int32_t getMetaState() {
+        return mMetaState;
+    }
+};
+
+
+// --- InstrumentedInputReader ---
+
+class InstrumentedInputReader : public InputReader {
+    InputDevice* mNextDevice;
+
+public:
+    InstrumentedInputReader(const sp<EventHubInterface>& eventHub,
+            const sp<InputReaderPolicyInterface>& policy,
+            const sp<InputDispatcherInterface>& dispatcher) :
+            InputReader(eventHub, policy, dispatcher) {
+    }
+
+    virtual ~InstrumentedInputReader() {
+        if (mNextDevice) {
+            delete mNextDevice;
+        }
+    }
+
+    void setNextDevice(InputDevice* device) {
+        mNextDevice = device;
+    }
+
+protected:
+    virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
+        if (mNextDevice) {
+            InputDevice* device = mNextDevice;
+            mNextDevice = NULL;
+            return device;
+        }
+        return InputReader::createDevice(deviceId, name, classes);
+    }
+
+    friend class InputReaderTest;
+};
+
+
+// --- InputReaderTest ---
+
+class InputReaderTest : public testing::Test {
+protected:
+    sp<FakeInputDispatcher> mFakeDispatcher;
+    sp<FakeInputReaderPolicy> mFakePolicy;
+    sp<FakeEventHub> mFakeEventHub;
+    sp<InstrumentedInputReader> mReader;
+
+    virtual void SetUp() {
+        mFakeEventHub = new FakeEventHub();
+        mFakePolicy = new FakeInputReaderPolicy();
+        mFakeDispatcher = new FakeInputDispatcher();
+
+        mReader = new InstrumentedInputReader(mFakeEventHub, mFakePolicy, mFakeDispatcher);
+    }
+
+    virtual void TearDown() {
+        mReader.clear();
+
+        mFakeDispatcher.clear();
+        mFakePolicy.clear();
+        mFakeEventHub.clear();
+    }
+
+    void addDevice(int32_t deviceId, const String8& name, uint32_t classes,
+            const PropertyMap* configuration) {
+        mFakeEventHub->addDevice(deviceId, name, classes);
+        if (configuration) {
+            mFakeEventHub->addConfigurationMap(deviceId, configuration);
+        }
+        mFakeEventHub->finishDeviceScan();
+        mReader->loopOnce();
+        mReader->loopOnce();
+        mFakeEventHub->assertQueueIsEmpty();
+    }
+
+    FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId,
+            const String8& name, uint32_t classes, uint32_t sources,
+            const PropertyMap* configuration) {
+        InputDevice* device = new InputDevice(mReader.get(), deviceId, name);
+        FakeInputMapper* mapper = new FakeInputMapper(device, sources);
+        device->addMapper(mapper);
+        mReader->setNextDevice(device);
+        addDevice(deviceId, name, classes, configuration);
+        return mapper;
+    }
+};
+
+TEST_F(InputReaderTest, GetInputConfiguration_WhenNoDevices_ReturnsDefaults) {
+    InputConfiguration config;
+    mReader->getInputConfiguration(&config);
+
+    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
+    ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
+    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
+}
+
+TEST_F(InputReaderTest, GetInputConfiguration_WhenAlphabeticKeyboardPresent_ReturnsQwertyKeyboard) {
+    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("keyboard"),
+            INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY, NULL));
+
+    InputConfiguration config;
+    mReader->getInputConfiguration(&config);
+
+    ASSERT_EQ(InputConfiguration::KEYBOARD_QWERTY, config.keyboard);
+    ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
+    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
+}
+
+TEST_F(InputReaderTest, GetInputConfiguration_WhenTouchScreenPresent_ReturnsFingerTouchScreen) {
+    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("touchscreen"),
+            INPUT_DEVICE_CLASS_TOUCHSCREEN, NULL));
+
+    InputConfiguration config;
+    mReader->getInputConfiguration(&config);
+
+    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
+    ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
+    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_FINGER, config.touchScreen);
+}
+
+TEST_F(InputReaderTest, GetInputConfiguration_WhenMousePresent_ReturnsNoNavigation) {
+    sp<FakePointerController> controller = new FakePointerController();
+    mFakePolicy->setPointerController(0, controller);
+
+    PropertyMap configuration;
+    configuration.addProperty(String8("cursor.mode"), String8("pointer"));
+    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("mouse"),
+            INPUT_DEVICE_CLASS_CURSOR, &configuration));
+
+    InputConfiguration config;
+    mReader->getInputConfiguration(&config);
+
+    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
+    ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
+    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
+}
+
+TEST_F(InputReaderTest, GetInputConfiguration_WhenTrackballPresent_ReturnsTrackballNavigation) {
+    PropertyMap configuration;
+    configuration.addProperty(String8("cursor.mode"), String8("navigation"));
+    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("trackball"),
+            INPUT_DEVICE_CLASS_CURSOR, &configuration));
+
+    InputConfiguration config;
+    mReader->getInputConfiguration(&config);
+
+    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
+    ASSERT_EQ(InputConfiguration::NAVIGATION_TRACKBALL, config.navigation);
+    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
+}
+
+TEST_F(InputReaderTest, GetInputConfiguration_WhenDPadPresent_ReturnsDPadNavigation) {
+    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("dpad"),
+            INPUT_DEVICE_CLASS_DPAD, NULL));
+
+    InputConfiguration config;
+    mReader->getInputConfiguration(&config);
+
+    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
+    ASSERT_EQ(InputConfiguration::NAVIGATION_DPAD, config.navigation);
+    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
+}
+
+TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsValid) {
+    ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
+            INPUT_DEVICE_CLASS_KEYBOARD, NULL));
+
+    InputDeviceInfo info;
+    status_t result = mReader->getInputDeviceInfo(1, &info);
+
+    ASSERT_EQ(OK, result);
+    ASSERT_EQ(1, info.getId());
+    ASSERT_STREQ("keyboard", info.getName().string());
+    ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, info.getKeyboardType());
+    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, info.getSources());
+    ASSERT_EQ(size_t(0), info.getMotionRanges().size());
+}
+
+TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsInvalid) {
+    InputDeviceInfo info;
+    status_t result = mReader->getInputDeviceInfo(-1, &info);
+
+    ASSERT_EQ(NAME_NOT_FOUND, result);
+}
+
+TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsIgnored) {
+    addDevice(1, String8("ignored"), 0, NULL); // no classes so device will be ignored
+
+    InputDeviceInfo info;
+    status_t result = mReader->getInputDeviceInfo(1, &info);
+
+    ASSERT_EQ(NAME_NOT_FOUND, result);
+}
+
+TEST_F(InputReaderTest, GetInputDeviceIds) {
+    sp<FakePointerController> controller = new FakePointerController();
+    mFakePolicy->setPointerController(2, controller);
+
+    ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
+            INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY, NULL));
+    ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("mouse"),
+            INPUT_DEVICE_CLASS_CURSOR, NULL));
+
+    Vector<int32_t> ids;
+    mReader->getInputDeviceIds(ids);
+
+    ASSERT_EQ(size_t(2), ids.size());
+    ASSERT_EQ(1, ids[0]);
+    ASSERT_EQ(2, ids[1]);
+}
+
+TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
+    FakeInputMapper* mapper = NULL;
+    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
+            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
+    mapper->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
+
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0,
+            AINPUT_SOURCE_ANY, AKEYCODE_A))
+            << "Should return unknown when the device id is >= 0 but unknown.";
+
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(1,
+            AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+            << "Should return unknown when the device id is valid but the sources are not supported by the device.";
+
+    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(1,
+            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+            << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
+
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
+            AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+            << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
+
+    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(-1,
+            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+            << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
+}
+
+TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
+    FakeInputMapper* mapper = NULL;
+    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
+            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
+    mapper->setScanCodeState(KEY_A, AKEY_STATE_DOWN);
+
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0,
+            AINPUT_SOURCE_ANY, KEY_A))
+            << "Should return unknown when the device id is >= 0 but unknown.";
+
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(1,
+            AINPUT_SOURCE_TRACKBALL, KEY_A))
+            << "Should return unknown when the device id is valid but the sources are not supported by the device.";
+
+    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(1,
+            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
+            << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
+
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
+            AINPUT_SOURCE_TRACKBALL, KEY_A))
+            << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
+
+    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(-1,
+            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
+            << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
+}
+
+TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
+    FakeInputMapper* mapper = NULL;
+    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
+            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
+    mapper->setSwitchState(SW_LID, AKEY_STATE_DOWN);
+
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0,
+            AINPUT_SOURCE_ANY, SW_LID))
+            << "Should return unknown when the device id is >= 0 but unknown.";
+
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(1,
+            AINPUT_SOURCE_TRACKBALL, SW_LID))
+            << "Should return unknown when the device id is valid but the sources are not supported by the device.";
+
+    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(1,
+            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
+            << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
+
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
+            AINPUT_SOURCE_TRACKBALL, SW_LID))
+            << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
+
+    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(-1,
+            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
+            << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
+}
+
+TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
+    FakeInputMapper* mapper = NULL;
+    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
+            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
+    mapper->addSupportedKeyCode(AKEYCODE_A);
+    mapper->addSupportedKeyCode(AKEYCODE_B);
+
+    const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
+    uint8_t flags[4] = { 0, 0, 0, 1 };
+
+    ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, 4, keyCodes, flags))
+            << "Should return false when device id is >= 0 but unknown.";
+    ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
+
+    flags[3] = 1;
+    ASSERT_FALSE(mReader->hasKeys(1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+            << "Should return false when device id is valid but the sources are not supported by the device.";
+    ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
+
+    flags[3] = 1;
+    ASSERT_TRUE(mReader->hasKeys(1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+            << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
+    ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
+
+    flags[3] = 1;
+    ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+            << "Should return false when the device id is < 0 but the sources are not supported by any device.";
+    ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
+
+    flags[3] = 1;
+    ASSERT_TRUE(mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+            << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
+    ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
+}
+
+TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
+    addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD, NULL);
+
+    FakeInputDispatcher::NotifyConfigurationChangedArgs args;
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyConfigurationChangedWasCalled(&args));
+    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+}
+
+TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
+    FakeInputMapper* mapper = NULL;
+    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
+            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
+
+    mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, AKEYCODE_A, 1, POLICY_FLAG_WAKE);
+    mReader->loopOnce();
+    ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
+
+    RawEvent event;
+    ASSERT_NO_FATAL_FAILURE(mapper->assertProcessWasCalled(&event));
+    ASSERT_EQ(0, event.when);
+    ASSERT_EQ(1, event.deviceId);
+    ASSERT_EQ(EV_KEY, event.type);
+    ASSERT_EQ(KEY_A, event.scanCode);
+    ASSERT_EQ(AKEYCODE_A, event.keyCode);
+    ASSERT_EQ(1, event.value);
+    ASSERT_EQ(POLICY_FLAG_WAKE, event.flags);
+}
+
+
+// --- InputDeviceTest ---
+
+class InputDeviceTest : public testing::Test {
+protected:
+    static const char* DEVICE_NAME;
+    static const int32_t DEVICE_ID;
+
+    sp<FakeEventHub> mFakeEventHub;
+    sp<FakeInputReaderPolicy> mFakePolicy;
+    sp<FakeInputDispatcher> mFakeDispatcher;
+    FakeInputReaderContext* mFakeContext;
+
+    InputDevice* mDevice;
+
+    virtual void SetUp() {
+        mFakeEventHub = new FakeEventHub();
+        mFakePolicy = new FakeInputReaderPolicy();
+        mFakeDispatcher = new FakeInputDispatcher();
+        mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
+
+        mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
+        mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
+    }
+
+    virtual void TearDown() {
+        delete mDevice;
+
+        delete mFakeContext;
+        mFakeDispatcher.clear();
+        mFakePolicy.clear();
+        mFakeEventHub.clear();
+    }
+};
+
+const char* InputDeviceTest::DEVICE_NAME = "device";
+const int32_t InputDeviceTest::DEVICE_ID = 1;
+
+TEST_F(InputDeviceTest, ImmutableProperties) {
+    ASSERT_EQ(DEVICE_ID, mDevice->getId());
+    ASSERT_STREQ(DEVICE_NAME, mDevice->getName());
+}
+
+TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
+    // Configuration.
+    mDevice->configure();
+
+    // Metadata.
+    ASSERT_TRUE(mDevice->isIgnored());
+    ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
+
+    InputDeviceInfo info;
+    mDevice->getDeviceInfo(&info);
+    ASSERT_EQ(DEVICE_ID, info.getId());
+    ASSERT_STREQ(DEVICE_NAME, info.getName().string());
+    ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
+    ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
+
+    // State queries.
+    ASSERT_EQ(0, mDevice->getMetaState());
+
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
+            << "Ignored device should return unknown key code state.";
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
+            << "Ignored device should return unknown scan code state.";
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
+            << "Ignored device should return unknown switch state.";
+
+    const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
+    uint8_t flags[2] = { 0, 1 };
+    ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 2, keyCodes, flags))
+            << "Ignored device should never mark any key codes.";
+    ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
+    ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
+
+    // Reset.
+    mDevice->reset();
+}
+
+TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
+    // Configuration.
+    mFakeEventHub->addConfigurationProperty(DEVICE_ID, String8("key"), String8("value"));
+
+    FakeInputMapper* mapper1 = new FakeInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD);
+    mapper1->setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+    mapper1->setMetaState(AMETA_ALT_ON);
+    mapper1->addSupportedKeyCode(AKEYCODE_A);
+    mapper1->addSupportedKeyCode(AKEYCODE_B);
+    mapper1->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
+    mapper1->setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
+    mapper1->setScanCodeState(2, AKEY_STATE_DOWN);
+    mapper1->setScanCodeState(3, AKEY_STATE_UP);
+    mapper1->setSwitchState(4, AKEY_STATE_DOWN);
+    mDevice->addMapper(mapper1);
+
+    FakeInputMapper* mapper2 = new FakeInputMapper(mDevice, AINPUT_SOURCE_TOUCHSCREEN);
+    mapper2->setMetaState(AMETA_SHIFT_ON);
+    mDevice->addMapper(mapper2);
+
+    mDevice->configure();
+
+    String8 propertyValue;
+    ASSERT_TRUE(mDevice->getConfiguration().tryGetProperty(String8("key"), propertyValue))
+            << "Device should have read configuration during configuration phase.";
+    ASSERT_STREQ("value", propertyValue.string());
+
+    ASSERT_NO_FATAL_FAILURE(mapper1->assertConfigureWasCalled());
+    ASSERT_NO_FATAL_FAILURE(mapper2->assertConfigureWasCalled());
+
+    // Metadata.
+    ASSERT_FALSE(mDevice->isIgnored());
+    ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
+
+    InputDeviceInfo info;
+    mDevice->getDeviceInfo(&info);
+    ASSERT_EQ(DEVICE_ID, info.getId());
+    ASSERT_STREQ(DEVICE_NAME, info.getName().string());
+    ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
+    ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
+
+    // State queries.
+    ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
+            << "Should query mappers and combine meta states.";
+
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+            << "Should return unknown key code state when source not supported.";
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+            << "Should return unknown scan code state when source not supported.";
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+            << "Should return unknown switch state when source not supported.";
+
+    ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
+            << "Should query mapper when source is supported.";
+    ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
+            << "Should query mapper when source is supported.";
+    ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
+            << "Should query mapper when source is supported.";
+
+    const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
+    uint8_t flags[4] = { 0, 0, 0, 1 };
+    ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+            << "Should do nothing when source is unsupported.";
+    ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
+    ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
+    ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
+    ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
+
+    ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 4, keyCodes, flags))
+            << "Should query mapper when source is supported.";
+    ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
+    ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
+    ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
+    ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
+
+    // Event handling.
+    RawEvent event;
+    mDevice->process(&event);
+
+    ASSERT_NO_FATAL_FAILURE(mapper1->assertProcessWasCalled());
+    ASSERT_NO_FATAL_FAILURE(mapper2->assertProcessWasCalled());
+
+    // Reset.
+    mDevice->reset();
+
+    ASSERT_NO_FATAL_FAILURE(mapper1->assertResetWasCalled());
+    ASSERT_NO_FATAL_FAILURE(mapper2->assertResetWasCalled());
+}
+
+
+// --- InputMapperTest ---
+
+class InputMapperTest : public testing::Test {
+protected:
+    static const char* DEVICE_NAME;
+    static const int32_t DEVICE_ID;
+
+    sp<FakeEventHub> mFakeEventHub;
+    sp<FakeInputReaderPolicy> mFakePolicy;
+    sp<FakeInputDispatcher> mFakeDispatcher;
+    FakeInputReaderContext* mFakeContext;
+    InputDevice* mDevice;
+
+    virtual void SetUp() {
+        mFakeEventHub = new FakeEventHub();
+        mFakePolicy = new FakeInputReaderPolicy();
+        mFakeDispatcher = new FakeInputDispatcher();
+        mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
+        mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
+
+        mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
+    }
+
+    virtual void TearDown() {
+        delete mDevice;
+        delete mFakeContext;
+        mFakeDispatcher.clear();
+        mFakePolicy.clear();
+        mFakeEventHub.clear();
+    }
+
+    void addConfigurationProperty(const char* key, const char* value) {
+        mFakeEventHub->addConfigurationProperty(DEVICE_ID, String8(key), String8(value));
+    }
+
+    void addMapperAndConfigure(InputMapper* mapper) {
+        mDevice->addMapper(mapper);
+        mDevice->configure();
+    }
+
+    static void process(InputMapper* mapper, nsecs_t when, int32_t deviceId, int32_t type,
+            int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) {
+        RawEvent event;
+        event.when = when;
+        event.deviceId = deviceId;
+        event.type = type;
+        event.scanCode = scanCode;
+        event.keyCode = keyCode;
+        event.value = value;
+        event.flags = flags;
+        mapper->process(&event);
+    }
+
+    static void assertMotionRange(const InputDeviceInfo& info,
+            int32_t rangeType, float min, float max, float flat, float fuzz) {
+        const InputDeviceInfo::MotionRange* range = info.getMotionRange(rangeType);
+        ASSERT_TRUE(range != NULL) << "Range: " << rangeType;
+        ASSERT_NEAR(min, range->min, EPSILON) << "Range: " << rangeType;
+        ASSERT_NEAR(max, range->max, EPSILON) << "Range: " << rangeType;
+        ASSERT_NEAR(flat, range->flat, EPSILON) << "Range: " << rangeType;
+        ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Range: " << rangeType;
+    }
+
+    static void assertPointerCoords(const PointerCoords& coords,
+            float x, float y, float pressure, float size,
+            float touchMajor, float touchMinor, float toolMajor, float toolMinor,
+            float orientation) {
+        ASSERT_NEAR(x, coords.x, 1);
+        ASSERT_NEAR(y, coords.y, 1);
+        ASSERT_NEAR(pressure, coords.pressure, EPSILON);
+        ASSERT_NEAR(size, coords.size, EPSILON);
+        ASSERT_NEAR(touchMajor, coords.touchMajor, 1);
+        ASSERT_NEAR(touchMinor, coords.touchMinor, 1);
+        ASSERT_NEAR(toolMajor, coords.toolMajor, 1);
+        ASSERT_NEAR(toolMinor, coords.toolMinor, 1);
+        ASSERT_NEAR(orientation, coords.orientation, EPSILON);
+    }
+};
+
+const char* InputMapperTest::DEVICE_NAME = "device";
+const int32_t InputMapperTest::DEVICE_ID = 1;
+
+
+// --- SwitchInputMapperTest ---
+
+class SwitchInputMapperTest : public InputMapperTest {
+protected:
+};
+
+TEST_F(SwitchInputMapperTest, GetSources) {
+    SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
+    addMapperAndConfigure(mapper);
+
+    ASSERT_EQ(uint32_t(0), mapper->getSources());
+}
+
+TEST_F(SwitchInputMapperTest, GetSwitchState) {
+    SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
+    addMapperAndConfigure(mapper);
+
+    mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 1);
+    ASSERT_EQ(1, mapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
+
+    mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 0);
+    ASSERT_EQ(0, mapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
+}
+
+TEST_F(SwitchInputMapperTest, Process) {
+    SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
+    addMapperAndConfigure(mapper);
+
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_LID, 0, 1, 0);
+
+    FakeInputDispatcher::NotifySwitchArgs args;
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifySwitchWasCalled(&args));
+    ASSERT_EQ(ARBITRARY_TIME, args.when);
+    ASSERT_EQ(SW_LID, args.switchCode);
+    ASSERT_EQ(1, args.switchValue);
+    ASSERT_EQ(uint32_t(0), args.policyFlags);
+}
+
+
+// --- KeyboardInputMapperTest ---
+
+class KeyboardInputMapperTest : public InputMapperTest {
+protected:
+    void testDPadKeyRotation(KeyboardInputMapper* mapper,
+            int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode);
+};
+
+void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper* mapper,
+        int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode) {
+    FakeInputDispatcher::NotifyKeyArgs args;
+
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 1, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+    ASSERT_EQ(originalScanCode, args.scanCode);
+    ASSERT_EQ(rotatedKeyCode, args.keyCode);
+
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+    ASSERT_EQ(originalScanCode, args.scanCode);
+    ASSERT_EQ(rotatedKeyCode, args.keyCode);
+}
+
+
+TEST_F(KeyboardInputMapperTest, GetSources) {
+    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
+            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+    addMapperAndConfigure(mapper);
+
+    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper->getSources());
+}
+
+TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
+    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
+            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+    addMapperAndConfigure(mapper);
+
+    // Key down.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE);
+    FakeInputDispatcher::NotifyKeyArgs args;
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(DEVICE_ID, args.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+    ASSERT_EQ(KEY_HOME, args.scanCode);
+    ASSERT_EQ(AMETA_NONE, args.metaState);
+    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+    ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
+    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+
+    // Key up.
+    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
+            EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(DEVICE_ID, args.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+    ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
+    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+    ASSERT_EQ(KEY_HOME, args.scanCode);
+    ASSERT_EQ(AMETA_NONE, args.metaState);
+    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+    ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
+    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+}
+
+TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreNotDown_DoesNotSynthesizeKeyUp) {
+    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
+            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+    addMapperAndConfigure(mapper);
+
+    // Key down.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+    // Key up.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+    // Reset.  Since no keys still down, should not synthesize any key ups.
+    mapper->reset();
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+}
+
+TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreDown_SynthesizesKeyUps) {
+    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
+            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+    addMapperAndConfigure(mapper);
+
+    // Metakey down.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+    // Key down.
+    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
+            EV_KEY, KEY_A, AKEYCODE_A, 1, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+    // Reset.  Since two keys are still down, should synthesize two key ups in reverse order.
+    mapper->reset();
+
+    FakeInputDispatcher::NotifyKeyArgs args;
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(DEVICE_ID, args.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+    ASSERT_EQ(AKEYCODE_A, args.keyCode);
+    ASSERT_EQ(KEY_A, args.scanCode);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+    ASSERT_EQ(uint32_t(0), args.policyFlags);
+    ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(DEVICE_ID, args.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+    ASSERT_EQ(AKEYCODE_SHIFT_LEFT, args.keyCode);
+    ASSERT_EQ(KEY_LEFTSHIFT, args.scanCode);
+    ASSERT_EQ(AMETA_NONE, args.metaState);
+    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+    ASSERT_EQ(uint32_t(0), args.policyFlags);
+    ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime);
+
+    // And that's it.
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+}
+
+TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
+    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
+            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+    addMapperAndConfigure(mapper);
+
+    // Initial metastate.
+    ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
+
+    // Metakey down.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0);
+    FakeInputDispatcher::NotifyKeyArgs args;
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
+    ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
+
+    // Key down.
+    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
+            EV_KEY, KEY_A, AKEYCODE_A, 1, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
+
+    // Key up.
+    process(mapper, ARBITRARY_TIME + 2, DEVICE_ID,
+            EV_KEY, KEY_A, AKEYCODE_A, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
+
+    // Metakey up.
+    process(mapper, ARBITRARY_TIME + 3, DEVICE_ID,
+            EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(AMETA_NONE, args.metaState);
+    ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
+    ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
+}
+
+TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
+    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
+            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+    addMapperAndConfigure(mapper);
+
+    mFakePolicy->setDisplayInfo(DISPLAY_ID,
+            DISPLAY_WIDTH, DISPLAY_HEIGHT,
+            DISPLAY_ORIENTATION_90);
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
+}
+
+TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
+    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
+            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+    addConfigurationProperty("keyboard.orientationAware", "1");
+    addMapperAndConfigure(mapper);
+
+    mFakePolicy->setDisplayInfo(DISPLAY_ID,
+            DISPLAY_WIDTH, DISPLAY_HEIGHT,
+            DISPLAY_ORIENTATION_0);
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
+
+    mFakePolicy->setDisplayInfo(DISPLAY_ID,
+            DISPLAY_WIDTH, DISPLAY_HEIGHT,
+            DISPLAY_ORIENTATION_90);
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN));
+
+    mFakePolicy->setDisplayInfo(DISPLAY_ID,
+            DISPLAY_WIDTH, DISPLAY_HEIGHT,
+            DISPLAY_ORIENTATION_180);
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_LEFT));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_UP));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT));
+
+    mFakePolicy->setDisplayInfo(DISPLAY_ID,
+            DISPLAY_WIDTH, DISPLAY_HEIGHT,
+            DISPLAY_ORIENTATION_270);
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_DOWN));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_LEFT));
+    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_UP));
+
+    // Special case: if orientation changes while key is down, we still emit the same keycode
+    // in the key up as we did in the key down.
+    FakeInputDispatcher::NotifyKeyArgs args;
+
+    mFakePolicy->setDisplayInfo(DISPLAY_ID,
+            DISPLAY_WIDTH, DISPLAY_HEIGHT,
+            DISPLAY_ORIENTATION_270);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 1, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+    ASSERT_EQ(KEY_UP, args.scanCode);
+    ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
+
+    mFakePolicy->setDisplayInfo(DISPLAY_ID,
+            DISPLAY_WIDTH, DISPLAY_HEIGHT,
+            DISPLAY_ORIENTATION_180);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+    ASSERT_EQ(KEY_UP, args.scanCode);
+    ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
+}
+
+TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
+    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
+            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+    addMapperAndConfigure(mapper);
+
+    mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 1);
+    ASSERT_EQ(1, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
+
+    mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 0);
+    ASSERT_EQ(0, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
+}
+
+TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
+    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
+            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+    addMapperAndConfigure(mapper);
+
+    mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 1);
+    ASSERT_EQ(1, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
+
+    mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 0);
+    ASSERT_EQ(0, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
+}
+
+TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
+    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
+            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+    addMapperAndConfigure(mapper);
+
+    mFakeEventHub->addKey(DEVICE_ID, KEY_A, AKEYCODE_A, 0);
+
+    const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
+    uint8_t flags[2] = { 0, 0 };
+    ASSERT_TRUE(mapper->markSupportedKeyCodes(AINPUT_SOURCE_ANY, 1, keyCodes, flags));
+    ASSERT_TRUE(flags[0]);
+    ASSERT_FALSE(flags[1]);
+}
+
+TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
+    mFakeEventHub->addLed(DEVICE_ID, LED_CAPSL, true /*initially on*/);
+    mFakeEventHub->addLed(DEVICE_ID, LED_NUML, false /*initially off*/);
+    mFakeEventHub->addLed(DEVICE_ID, LED_SCROLLL, false /*initially off*/);
+
+    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
+            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+    addMapperAndConfigure(mapper);
+
+    // Initialization should have turned all of the lights off.
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+
+    // Toggle caps lock on.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0);
+    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+    ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper->getMetaState());
+
+    // Toggle num lock on.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0, 0);
+    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
+    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+    ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper->getMetaState());
+
+    // Toggle caps lock off.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0);
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
+    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+    ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper->getMetaState());
+
+    // Toggle scroll lock on.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0, 0);
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
+    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
+    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+    ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper->getMetaState());
+
+    // Toggle num lock off.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0, 0);
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
+    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+    ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper->getMetaState());
+
+    // Toggle scroll lock off.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID,
+            EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0, 0);
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
+    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+    ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
+}
+
+
+// --- CursorInputMapperTest ---
+
+class CursorInputMapperTest : public InputMapperTest {
+protected:
+    static const int32_t TRACKBALL_MOVEMENT_THRESHOLD;
+
+    sp<FakePointerController> mFakePointerController;
+
+    virtual void SetUp() {
+        InputMapperTest::SetUp();
+
+        mFakePointerController = new FakePointerController();
+        mFakePolicy->setPointerController(DEVICE_ID, mFakePointerController);
+    }
+
+    void testMotionRotation(CursorInputMapper* mapper,
+            int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY);
+};
+
+const int32_t CursorInputMapperTest::TRACKBALL_MOVEMENT_THRESHOLD = 6;
+
+void CursorInputMapperTest::testMotionRotation(CursorInputMapper* mapper,
+        int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY) {
+    FakeInputDispatcher::NotifyMotionArgs args;
+
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, originalX, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, originalY, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            float(rotatedX) / TRACKBALL_MOVEMENT_THRESHOLD,
+            float(rotatedY) / TRACKBALL_MOVEMENT_THRESHOLD,
+            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+}
+
+TEST_F(CursorInputMapperTest, WhenModeIsPointer_GetSources_ReturnsMouse) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addConfigurationProperty("cursor.mode", "pointer");
+    addMapperAndConfigure(mapper);
+
+    ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper->getSources());
+}
+
+TEST_F(CursorInputMapperTest, WhenModeIsNavigation_GetSources_ReturnsTrackball) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addConfigurationProperty("cursor.mode", "navigation");
+    addMapperAndConfigure(mapper);
+
+    ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, mapper->getSources());
+}
+
+TEST_F(CursorInputMapperTest, WhenModeIsPointer_PopulateDeviceInfo_ReturnsRangeFromPointerController) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addConfigurationProperty("cursor.mode", "pointer");
+    addMapperAndConfigure(mapper);
+
+    InputDeviceInfo info;
+    mapper->populateDeviceInfo(&info);
+
+    // Initially there may not be a valid motion range.
+    ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_X));
+    ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_Y));
+    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_PRESSURE,
+            0.0f, 1.0f, 0.0f, 0.0f));
+
+    // When the bounds are set, then there should be a valid motion range.
+    mFakePointerController->setBounds(1, 2, 800, 480);
+
+    InputDeviceInfo info2;
+    mapper->populateDeviceInfo(&info2);
+
+    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_X,
+            1, 800, 0.0f, 0.0f));
+    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_Y,
+            2, 480, 0.0f, 0.0f));
+    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2, AINPUT_MOTION_RANGE_PRESSURE,
+            0.0f, 1.0f, 0.0f, 0.0f));
+}
+
+TEST_F(CursorInputMapperTest, WhenModeIsNavigation_PopulateDeviceInfo_ReturnsScaledRange) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addConfigurationProperty("cursor.mode", "navigation");
+    addMapperAndConfigure(mapper);
+
+    InputDeviceInfo info;
+    mapper->populateDeviceInfo(&info);
+
+    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_X,
+            -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
+    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_Y,
+            -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
+    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_PRESSURE,
+            0.0f, 1.0f, 0.0f, 0.0f));
+}
+
+TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaState) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addConfigurationProperty("cursor.mode", "navigation");
+    addMapperAndConfigure(mapper);
+
+    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+
+    // Button press.
+    // Mostly testing non x/y behavior here so we don't need to check again elsewhere.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+    ASSERT_EQ(DEVICE_ID, args.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source);
+    ASSERT_EQ(uint32_t(0), args.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+    ASSERT_EQ(0, args.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+    ASSERT_EQ(0, args.edgeFlags);
+    ASSERT_EQ(uint32_t(1), args.pointerCount);
+    ASSERT_EQ(0, args.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+    ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
+    ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision);
+    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+
+    // Button release.  Should have same down time.
+    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
+    ASSERT_EQ(DEVICE_ID, args.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source);
+    ASSERT_EQ(uint32_t(0), args.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
+    ASSERT_EQ(0, args.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+    ASSERT_EQ(0, args.edgeFlags);
+    ASSERT_EQ(uint32_t(1), args.pointerCount);
+    ASSERT_EQ(0, args.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+    ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
+    ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision);
+    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+}
+
+TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentXYUpdates) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addConfigurationProperty("cursor.mode", "navigation");
+    addMapperAndConfigure(mapper);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+
+    // Motion in X but not Y.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            1.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+
+    // Motion in Y but not X.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+    ASSERT_NEAR(0.0f, args.pointerCoords[0].x, EPSILON);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            0.0f, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+}
+
+TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addConfigurationProperty("cursor.mode", "navigation");
+    addMapperAndConfigure(mapper);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+
+    // Button press without following sync.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+
+    // Button release without following sync.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+}
+
+TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addConfigurationProperty("cursor.mode", "navigation");
+    addMapperAndConfigure(mapper);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+
+    // Combined X, Y and Button.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            1.0f / TRACKBALL_MOVEMENT_THRESHOLD, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD,
+            1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+
+    // Move X, Y a bit while pressed.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 2, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD,
+            1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+
+    // Release Button.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+}
+
+TEST_F(CursorInputMapperTest, Reset_WhenButtonIsNotDown_ShouldNotSynthesizeButtonUp) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addConfigurationProperty("cursor.mode", "navigation");
+    addMapperAndConfigure(mapper);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+
+    // Button press.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+
+    // Button release.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+
+    // Reset.  Should not synthesize button up since button is not pressed.
+    mapper->reset();
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(CursorInputMapperTest, Reset_WhenButtonIsDown_ShouldSynthesizeButtonUp) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addConfigurationProperty("cursor.mode", "navigation");
+    addMapperAndConfigure(mapper);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+
+    // Button press.
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+
+    // Reset.  Should synthesize button up.
+    mapper->reset();
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+}
+
+TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMotions) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addConfigurationProperty("cursor.mode", "navigation");
+    addMapperAndConfigure(mapper);
+
+    mFakePolicy->setDisplayInfo(DISPLAY_ID,
+            DISPLAY_WIDTH, DISPLAY_HEIGHT,
+            DISPLAY_ORIENTATION_90);
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1,  0,  1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1,  1,  1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0,  1,  0));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1,  1, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1,  0, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0, -1,  0));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1, -1,  1));
+}
+
+TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addConfigurationProperty("cursor.mode", "navigation");
+    addConfigurationProperty("cursor.orientationAware", "1");
+    addMapperAndConfigure(mapper);
+
+    mFakePolicy->setDisplayInfo(DISPLAY_ID,
+            DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0);
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1,  0,  1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1,  1,  1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0,  1,  0));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1,  1, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1,  0, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0, -1,  0));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1, -1,  1));
+
+    mFakePolicy->setDisplayInfo(DISPLAY_ID,
+            DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_90);
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1,  1,  0));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1,  1, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0,  0, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1, -1, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1, -1,  0));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1,  1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0,  0,  1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1,  1,  1));
+
+    mFakePolicy->setDisplayInfo(DISPLAY_ID,
+            DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_180);
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1,  0, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1, -1, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0, -1,  0));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1, -1,  1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1,  0,  1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1,  1,  1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0,  1,  0));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1,  1, -1));
+
+    mFakePolicy->setDisplayInfo(DISPLAY_ID,
+            DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_270);
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1, -1,  0));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1, -1,  1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0,  0,  1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1,  1,  1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1,  1,  0));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1,  1, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0,  0, -1));
+    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1, -1, -1));
+}
+
+
+// --- TouchInputMapperTest ---
+
+class TouchInputMapperTest : public InputMapperTest {
+protected:
+    static const int32_t RAW_X_MIN;
+    static const int32_t RAW_X_MAX;
+    static const int32_t RAW_Y_MIN;
+    static const int32_t RAW_Y_MAX;
+    static const int32_t RAW_TOUCH_MIN;
+    static const int32_t RAW_TOUCH_MAX;
+    static const int32_t RAW_TOOL_MIN;
+    static const int32_t RAW_TOOL_MAX;
+    static const int32_t RAW_PRESSURE_MIN;
+    static const int32_t RAW_PRESSURE_MAX;
+    static const int32_t RAW_ORIENTATION_MIN;
+    static const int32_t RAW_ORIENTATION_MAX;
+    static const int32_t RAW_ID_MIN;
+    static const int32_t RAW_ID_MAX;
+    static const float X_PRECISION;
+    static const float Y_PRECISION;
+
+    static const VirtualKeyDefinition VIRTUAL_KEYS[2];
+
+    enum Axes {
+        POSITION = 1 << 0,
+        TOUCH = 1 << 1,
+        TOOL = 1 << 2,
+        PRESSURE = 1 << 3,
+        ORIENTATION = 1 << 4,
+        MINOR = 1 << 5,
+        ID = 1 << 6,
+    };
+
+    void prepareDisplay(int32_t orientation);
+    void prepareVirtualKeys();
+    int32_t toRawX(float displayX);
+    int32_t toRawY(float displayY);
+    float toDisplayX(int32_t rawX);
+    float toDisplayY(int32_t rawY);
+};
+
+const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
+const int32_t TouchInputMapperTest::RAW_X_MAX = 1020;
+const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
+const int32_t TouchInputMapperTest::RAW_Y_MAX = 1010;
+const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
+const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
+const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
+const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
+const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = RAW_TOUCH_MIN;
+const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = RAW_TOUCH_MAX;
+const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
+const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
+const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
+const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
+const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN) / DISPLAY_WIDTH;
+const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN) / DISPLAY_HEIGHT;
+
+const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
+        { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
+        { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
+};
+
+void TouchInputMapperTest::prepareDisplay(int32_t orientation) {
+    mFakePolicy->setDisplayInfo(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation);
+}
+
+void TouchInputMapperTest::prepareVirtualKeys() {
+    mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[0]);
+    mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[1]);
+    mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, AKEYCODE_HOME, POLICY_FLAG_WAKE);
+    mFakeEventHub->addKey(DEVICE_ID, KEY_MENU, AKEYCODE_MENU, POLICY_FLAG_WAKE);
+}
+
+int32_t TouchInputMapperTest::toRawX(float displayX) {
+    return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN) / DISPLAY_WIDTH + RAW_X_MIN);
+}
+
+int32_t TouchInputMapperTest::toRawY(float displayY) {
+    return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN) / DISPLAY_HEIGHT + RAW_Y_MIN);
+}
+
+float TouchInputMapperTest::toDisplayX(int32_t rawX) {
+    return float(rawX - RAW_X_MIN) * DISPLAY_WIDTH / (RAW_X_MAX - RAW_X_MIN);
+}
+
+float TouchInputMapperTest::toDisplayY(int32_t rawY) {
+    return float(rawY - RAW_Y_MIN) * DISPLAY_HEIGHT / (RAW_Y_MAX - RAW_Y_MIN);
+}
+
+
+// --- SingleTouchInputMapperTest ---
+
+class SingleTouchInputMapperTest : public TouchInputMapperTest {
+protected:
+    void prepareAxes(int axes);
+
+    void processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
+    void processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
+    void processUp(SingleTouchInputMapper* mappery);
+    void processPressure(SingleTouchInputMapper* mapper, int32_t pressure);
+    void processToolMajor(SingleTouchInputMapper* mapper, int32_t toolMajor);
+    void processSync(SingleTouchInputMapper* mapper);
+};
+
+void SingleTouchInputMapperTest::prepareAxes(int axes) {
+    if (axes & POSITION) {
+        mFakeEventHub->addAxis(DEVICE_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
+        mFakeEventHub->addAxis(DEVICE_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
+    }
+    if (axes & PRESSURE) {
+        mFakeEventHub->addAxis(DEVICE_ID, ABS_PRESSURE, RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
+    }
+    if (axes & TOOL) {
+        mFakeEventHub->addAxis(DEVICE_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
+    }
+}
+
+void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0, 1, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, 0, x, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, 0, y, 0);
+}
+
+void SingleTouchInputMapperTest::processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, 0, x, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, 0, y, 0);
+}
+
+void SingleTouchInputMapperTest::processUp(SingleTouchInputMapper* mapper) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0, 0, 0);
+}
+
+void SingleTouchInputMapperTest::processPressure(
+        SingleTouchInputMapper* mapper, int32_t pressure) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_PRESSURE, 0, pressure, 0);
+}
+
+void SingleTouchInputMapperTest::processToolMajor(
+        SingleTouchInputMapper* mapper, int32_t toolMajor) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TOOL_WIDTH, 0, toolMajor, 0);
+}
+
+void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper* mapper) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+}
+
+
+TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareAxes(POSITION);
+    addConfigurationProperty("touch.deviceType", "touchPad");
+    addMapperAndConfigure(mapper);
+
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
+}
+
+TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareAxes(POSITION);
+    addConfigurationProperty("touch.deviceType", "touchScreen");
+    addMapperAndConfigure(mapper);
+
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper->getSources());
+}
+
+TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    prepareVirtualKeys();
+    addMapperAndConfigure(mapper);
+
+    // Unknown key.
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
+
+    // Virtual key is down.
+    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
+    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
+    processDown(mapper, x, y);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+    ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
+
+    // Virtual key is up.
+    processUp(mapper);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+    ASSERT_EQ(AKEY_STATE_UP, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
+}
+
+TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    prepareVirtualKeys();
+    addMapperAndConfigure(mapper);
+
+    // Unknown key.
+    ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
+
+    // Virtual key is down.
+    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
+    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
+    processDown(mapper, x, y);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+    ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
+
+    // Virtual key is up.
+    processUp(mapper);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+    ASSERT_EQ(AKEY_STATE_UP, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
+}
+
+TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    prepareVirtualKeys();
+    addMapperAndConfigure(mapper);
+
+    const int32_t keys[2] = { AKEYCODE_HOME, AKEYCODE_A };
+    uint8_t flags[2] = { 0, 0 };
+    ASSERT_TRUE(mapper->markSupportedKeyCodes(AINPUT_SOURCE_ANY, 2, keys, flags));
+    ASSERT_TRUE(flags[0]);
+    ASSERT_FALSE(flags[1]);
+}
+
+TEST_F(SingleTouchInputMapperTest, Reset_WhenVirtualKeysAreDown_SendsUp) {
+    // Note: Ideally we should send cancels but the implementation is more straightforward
+    // with up and this will only happen if a device is forcibly removed.
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    prepareVirtualKeys();
+    addMapperAndConfigure(mapper);
+
+    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+    // Press virtual key.
+    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
+    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
+    processDown(mapper, x, y);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+    // Reset.  Since key is down, synthesize key up.
+    mapper->reset();
+
+    FakeInputDispatcher::NotifyKeyArgs args;
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    //ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+    ASSERT_EQ(DEVICE_ID, args.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+    ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
+    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
+    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+    ASSERT_EQ(KEY_HOME, args.scanCode);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+}
+
+TEST_F(SingleTouchInputMapperTest, Reset_WhenNothingIsPressed_NothingMuchHappens) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    prepareVirtualKeys();
+    addMapperAndConfigure(mapper);
+
+    // Press virtual key.
+    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
+    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
+    processDown(mapper, x, y);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+    // Release virtual key.
+    processUp(mapper);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+    // Reset.  Since no key is down, nothing happens.
+    mapper->reset();
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    prepareVirtualKeys();
+    addMapperAndConfigure(mapper);
+
+    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+    FakeInputDispatcher::NotifyKeyArgs args;
+
+    // Press virtual key.
+    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
+    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
+    processDown(mapper, x, y);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+    ASSERT_EQ(DEVICE_ID, args.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+    ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
+    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
+    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+    ASSERT_EQ(KEY_HOME, args.scanCode);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+
+    // Release virtual key.
+    processUp(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+    ASSERT_EQ(DEVICE_ID, args.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+    ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
+    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
+    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+    ASSERT_EQ(KEY_HOME, args.scanCode);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+
+    // Should not have sent any motions.
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    prepareVirtualKeys();
+    addMapperAndConfigure(mapper);
+
+    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+    FakeInputDispatcher::NotifyKeyArgs keyArgs;
+
+    // Press virtual key.
+    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
+    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
+    processDown(mapper, x, y);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&keyArgs));
+    ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
+    ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
+    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
+    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
+    ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
+    ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
+    ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
+
+    // Move out of bounds.  This should generate a cancel and a pointer down since we moved
+    // into the display area.
+    y -= 100;
+    processMove(mapper, x, y);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&keyArgs));
+    ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
+    ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
+    ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
+    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
+            | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
+    ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
+    ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
+    ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
+
+    FakeInputDispatcher::NotifyMotionArgs motionArgs;
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Keep moving out of bounds.  Should generate a pointer move.
+    y -= 50;
+    processMove(mapper, x, y);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Release out of bounds.  Should generate a pointer up.
+    processUp(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Should not have sent any more keys or motions.
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    prepareVirtualKeys();
+    addMapperAndConfigure(mapper);
+
+    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+    FakeInputDispatcher::NotifyMotionArgs motionArgs;
+
+    // Initially go down out of bounds.
+    int32_t x = -10;
+    int32_t y = -10;
+    processDown(mapper, x, y);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+
+    // Move into the display area.  Should generate a pointer down.
+    x = 50;
+    y = 75;
+    processMove(mapper, x, y);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Release.  Should generate a pointer up.
+    processUp(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Should not have sent any more keys or motions.
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    prepareVirtualKeys();
+    addMapperAndConfigure(mapper);
+
+    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+    FakeInputDispatcher::NotifyMotionArgs motionArgs;
+
+    // Down.
+    int32_t x = 100;
+    int32_t y = 125;
+    processDown(mapper, x, y);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Move.
+    x += 50;
+    y += 75;
+    processMove(mapper, x, y);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Up.
+    processUp(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Should not have sent any more keys or motions.
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotateMotions) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareAxes(POSITION);
+    addConfigurationProperty("touch.orientationAware", "0");
+    addMapperAndConfigure(mapper);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+
+    // Rotation 90.
+    prepareDisplay(DISPLAY_ORIENTATION_90);
+    processDown(mapper, toRawX(50), toRawY(75));
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_NEAR(50, args.pointerCoords[0].x, 1);
+    ASSERT_NEAR(75, args.pointerCoords[0].y, 1);
+
+    processUp(mapper);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareAxes(POSITION);
+    addMapperAndConfigure(mapper);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+
+    // Rotation 0.
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    processDown(mapper, toRawX(50), toRawY(75));
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_NEAR(50, args.pointerCoords[0].x, 1);
+    ASSERT_NEAR(75, args.pointerCoords[0].y, 1);
+
+    processUp(mapper);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
+
+    // Rotation 90.
+    prepareDisplay(DISPLAY_ORIENTATION_90);
+    processDown(mapper, toRawX(50), toRawY(75));
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_NEAR(75, args.pointerCoords[0].x, 1);
+    ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].y, 1);
+
+    processUp(mapper);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
+
+    // Rotation 180.
+    prepareDisplay(DISPLAY_ORIENTATION_180);
+    processDown(mapper, toRawX(50), toRawY(75));
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].x, 1);
+    ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].y, 1);
+
+    processUp(mapper);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
+
+    // Rotation 270.
+    prepareDisplay(DISPLAY_ORIENTATION_270);
+    processDown(mapper, toRawX(50), toRawY(75));
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].x, 1);
+    ASSERT_NEAR(50, args.pointerCoords[0].y, 1);
+
+    processUp(mapper);
+    processSync(mapper);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION | PRESSURE | TOOL);
+    addMapperAndConfigure(mapper);
+
+    // These calculations are based on the input device calibration documentation.
+    int32_t rawX = 100;
+    int32_t rawY = 200;
+    int32_t rawPressure = 10;
+    int32_t rawToolMajor = 12;
+
+    float x = toDisplayX(rawX);
+    float y = toDisplayY(rawY);
+    float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
+    float size = float(rawToolMajor) / RAW_TOOL_MAX;
+    float tool = min(DISPLAY_WIDTH, DISPLAY_HEIGHT) * size;
+    float touch = min(tool * pressure, tool);
+
+    processDown(mapper, rawX, rawY);
+    processPressure(mapper, rawPressure);
+    processToolMajor(mapper, rawToolMajor);
+    processSync(mapper);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            x, y, pressure, size, touch, touch, tool, tool, 0));
+}
+
+
+// --- MultiTouchInputMapperTest ---
+
+class MultiTouchInputMapperTest : public TouchInputMapperTest {
+protected:
+    void prepareAxes(int axes);
+
+    void processPosition(MultiTouchInputMapper* mapper, int32_t x, int32_t y);
+    void processTouchMajor(MultiTouchInputMapper* mapper, int32_t touchMajor);
+    void processTouchMinor(MultiTouchInputMapper* mapper, int32_t touchMinor);
+    void processToolMajor(MultiTouchInputMapper* mapper, int32_t toolMajor);
+    void processToolMinor(MultiTouchInputMapper* mapper, int32_t toolMinor);
+    void processOrientation(MultiTouchInputMapper* mapper, int32_t orientation);
+    void processPressure(MultiTouchInputMapper* mapper, int32_t pressure);
+    void processId(MultiTouchInputMapper* mapper, int32_t id);
+    void processMTSync(MultiTouchInputMapper* mapper);
+    void processSync(MultiTouchInputMapper* mapper);
+};
+
+void MultiTouchInputMapperTest::prepareAxes(int axes) {
+    if (axes & POSITION) {
+        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
+        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
+    }
+    if (axes & TOUCH) {
+        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
+        if (axes & MINOR) {
+            mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MINOR,
+                    RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
+        }
+    }
+    if (axes & TOOL) {
+        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
+        if (axes & MINOR) {
+            mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MINOR,
+                    RAW_TOOL_MAX, RAW_TOOL_MAX, 0, 0);
+        }
+    }
+    if (axes & ORIENTATION) {
+        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_ORIENTATION,
+                RAW_ORIENTATION_MIN, RAW_ORIENTATION_MAX, 0, 0);
+    }
+    if (axes & PRESSURE) {
+        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_PRESSURE,
+                RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
+    }
+    if (axes & ID) {
+        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TRACKING_ID,
+                RAW_ID_MIN, RAW_ID_MAX, 0, 0);
+    }
+}
+
+void MultiTouchInputMapperTest::processPosition(
+        MultiTouchInputMapper* mapper, int32_t x, int32_t y) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_X, 0, x, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_Y, 0, y, 0);
+}
+
+void MultiTouchInputMapperTest::processTouchMajor(
+        MultiTouchInputMapper* mapper, int32_t touchMajor) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MAJOR, 0, touchMajor, 0);
+}
+
+void MultiTouchInputMapperTest::processTouchMinor(
+        MultiTouchInputMapper* mapper, int32_t touchMinor) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MINOR, 0, touchMinor, 0);
+}
+
+void MultiTouchInputMapperTest::processToolMajor(
+        MultiTouchInputMapper* mapper, int32_t toolMajor) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MAJOR, 0, toolMajor, 0);
+}
+
+void MultiTouchInputMapperTest::processToolMinor(
+        MultiTouchInputMapper* mapper, int32_t toolMinor) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MINOR, 0, toolMinor, 0);
+}
+
+void MultiTouchInputMapperTest::processOrientation(
+        MultiTouchInputMapper* mapper, int32_t orientation) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_ORIENTATION, 0, orientation, 0);
+}
+
+void MultiTouchInputMapperTest::processPressure(
+        MultiTouchInputMapper* mapper, int32_t pressure) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_PRESSURE, 0, pressure, 0);
+}
+
+void MultiTouchInputMapperTest::processId(
+        MultiTouchInputMapper* mapper, int32_t id) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TRACKING_ID, 0, id, 0);
+}
+
+void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper* mapper) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_MT_REPORT, 0, 0, 0);
+}
+
+void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper* mapper) {
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+}
+
+
+TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
+    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    prepareVirtualKeys();
+    addMapperAndConfigure(mapper);
+
+    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+    FakeInputDispatcher::NotifyMotionArgs motionArgs;
+
+    // Two fingers down at once.
+    int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
+    processPosition(mapper, x1, y1);
+    processMTSync(mapper);
+    processPosition(mapper, x2, y2);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_EQ(1, motionArgs.pointerIds[1]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Move.
+    x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
+    processPosition(mapper, x1, y1);
+    processMTSync(mapper);
+    processPosition(mapper, x2, y2);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_EQ(1, motionArgs.pointerIds[1]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // First finger up.
+    x2 += 15; y2 -= 20;
+    processPosition(mapper, x2, y2);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_EQ(1, motionArgs.pointerIds[1]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(1, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Move.
+    x2 += 20; y2 -= 25;
+    processPosition(mapper, x2, y2);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(1, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // New finger down.
+    int32_t x3 = 700, y3 = 300;
+    processPosition(mapper, x2, y2);
+    processMTSync(mapper);
+    processPosition(mapper, x3, y3);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_EQ(1, motionArgs.pointerIds[1]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Second finger up.
+    x3 += 30; y3 -= 20;
+    processPosition(mapper, x3, y3);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_EQ(1, motionArgs.pointerIds[1]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Last finger up.
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+    ASSERT_EQ(0, motionArgs.flags);
+    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+    ASSERT_EQ(0, motionArgs.edgeFlags);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(0, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+    // Should not have sent any more keys or motions.
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
+    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION | ID);
+    prepareVirtualKeys();
+    addMapperAndConfigure(mapper);
+
+    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+    FakeInputDispatcher::NotifyMotionArgs motionArgs;
+
+    // Two fingers down at once.
+    int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
+    processPosition(mapper, x1, y1);
+    processId(mapper, 1);
+    processMTSync(mapper);
+    processPosition(mapper, x2, y2);
+    processId(mapper, 2);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(1, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            motionArgs.action);
+    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+    ASSERT_EQ(1, motionArgs.pointerIds[0]);
+    ASSERT_EQ(2, motionArgs.pointerIds[1]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+
+    // Move.
+    x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
+    processPosition(mapper, x1, y1);
+    processId(mapper, 1);
+    processMTSync(mapper);
+    processPosition(mapper, x2, y2);
+    processId(mapper, 2);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+    ASSERT_EQ(1, motionArgs.pointerIds[0]);
+    ASSERT_EQ(2, motionArgs.pointerIds[1]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+
+    // First finger up.
+    x2 += 15; y2 -= 20;
+    processPosition(mapper, x2, y2);
+    processId(mapper, 2);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            motionArgs.action);
+    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+    ASSERT_EQ(1, motionArgs.pointerIds[0]);
+    ASSERT_EQ(2, motionArgs.pointerIds[1]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(2, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+
+    // Move.
+    x2 += 20; y2 -= 25;
+    processPosition(mapper, x2, y2);
+    processId(mapper, 2);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(2, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+
+    // New finger down.
+    int32_t x3 = 700, y3 = 300;
+    processPosition(mapper, x2, y2);
+    processId(mapper, 2);
+    processMTSync(mapper);
+    processPosition(mapper, x3, y3);
+    processId(mapper, 3);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            motionArgs.action);
+    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+    ASSERT_EQ(2, motionArgs.pointerIds[0]);
+    ASSERT_EQ(3, motionArgs.pointerIds[1]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+
+    // Second finger up.
+    x3 += 30; y3 -= 20;
+    processPosition(mapper, x3, y3);
+    processId(mapper, 3);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            motionArgs.action);
+    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+    ASSERT_EQ(2, motionArgs.pointerIds[0]);
+    ASSERT_EQ(3, motionArgs.pointerIds[1]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(3, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+
+    // Last finger up.
+    processMTSync(mapper);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+    ASSERT_EQ(3, motionArgs.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+
+    // Should not have sent any more keys or motions.
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
+    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR);
+    addMapperAndConfigure(mapper);
+
+    // These calculations are based on the input device calibration documentation.
+    int32_t rawX = 100;
+    int32_t rawY = 200;
+    int32_t rawTouchMajor = 7;
+    int32_t rawTouchMinor = 6;
+    int32_t rawToolMajor = 9;
+    int32_t rawToolMinor = 8;
+    int32_t rawPressure = 11;
+    int32_t rawOrientation = 3;
+    int32_t id = 5;
+
+    float x = toDisplayX(rawX);
+    float y = toDisplayY(rawY);
+    float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
+    float size = avg(rawToolMajor, rawToolMinor) / RAW_TOOL_MAX;
+    float toolMajor = float(min(DISPLAY_WIDTH, DISPLAY_HEIGHT)) * rawToolMajor / RAW_TOOL_MAX;
+    float toolMinor = float(min(DISPLAY_WIDTH, DISPLAY_HEIGHT)) * rawToolMinor / RAW_TOOL_MAX;
+    float touchMajor = min(toolMajor * pressure, toolMajor);
+    float touchMinor = min(toolMinor * pressure, toolMinor);
+    float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
+
+    processPosition(mapper, rawX, rawY);
+    processTouchMajor(mapper, rawTouchMajor);
+    processTouchMinor(mapper, rawTouchMinor);
+    processToolMajor(mapper, rawToolMajor);
+    processToolMinor(mapper, rawToolMinor);
+    processPressure(mapper, rawPressure);
+    processOrientation(mapper, rawOrientation);
+    processId(mapper, id);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(id, args.pointerIds[0]);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, orientation));
+}
+
+TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
+    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION | TOUCH | TOOL | MINOR);
+    addConfigurationProperty("touch.touchSize.calibration", "geometric");
+    addConfigurationProperty("touch.toolSize.calibration", "geometric");
+    addMapperAndConfigure(mapper);
+
+    // These calculations are based on the input device calibration documentation.
+    int32_t rawX = 100;
+    int32_t rawY = 200;
+    int32_t rawTouchMajor = 140;
+    int32_t rawTouchMinor = 120;
+    int32_t rawToolMajor = 180;
+    int32_t rawToolMinor = 160;
+
+    float x = toDisplayX(rawX);
+    float y = toDisplayY(rawY);
+    float pressure = float(rawTouchMajor) / RAW_TOUCH_MAX;
+    float size = avg(rawToolMajor, rawToolMinor) / RAW_TOOL_MAX;
+    float scale = avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN),
+            float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN));
+    float toolMajor = float(rawToolMajor) * scale;
+    float toolMinor = float(rawToolMinor) * scale;
+    float touchMajor = min(float(rawTouchMajor) * scale, toolMajor);
+    float touchMinor = min(float(rawTouchMinor) * scale, toolMinor);
+
+    processPosition(mapper, rawX, rawY);
+    processTouchMajor(mapper, rawTouchMajor);
+    processTouchMinor(mapper, rawTouchMinor);
+    processToolMajor(mapper, rawToolMajor);
+    processToolMinor(mapper, rawToolMinor);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, 0));
+}
+
+TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_SummedLinearCalibration) {
+    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION | TOUCH | TOOL);
+    addConfigurationProperty("touch.touchSize.calibration", "pressure");
+    addConfigurationProperty("touch.toolSize.calibration", "linear");
+    addConfigurationProperty("touch.toolSize.linearScale", "10");
+    addConfigurationProperty("touch.toolSize.linearBias", "160");
+    addConfigurationProperty("touch.toolSize.isSummed", "1");
+    addConfigurationProperty("touch.pressure.calibration", "amplitude");
+    addConfigurationProperty("touch.pressure.source", "touch");
+    addConfigurationProperty("touch.pressure.scale", "0.01");
+    addMapperAndConfigure(mapper);
+
+    // These calculations are based on the input device calibration documentation.
+    // Note: We only provide a single common touch/tool value because the device is assumed
+    //       not to emit separate values for each pointer (isSummed = 1).
+    int32_t rawX = 100;
+    int32_t rawY = 200;
+    int32_t rawX2 = 150;
+    int32_t rawY2 = 250;
+    int32_t rawTouchMajor = 60;
+    int32_t rawToolMajor = 5;
+
+    float x = toDisplayX(rawX);
+    float y = toDisplayY(rawY);
+    float x2 = toDisplayX(rawX2);
+    float y2 = toDisplayY(rawY2);
+    float pressure = float(rawTouchMajor) * 0.01f;
+    float size = float(rawToolMajor) / RAW_TOOL_MAX;
+    float tool = (float(rawToolMajor) * 10.0f + 160.0f) / 2;
+    float touch = min(tool * pressure, tool);
+
+    processPosition(mapper, rawX, rawY);
+    processTouchMajor(mapper, rawTouchMajor);
+    processToolMajor(mapper, rawToolMajor);
+    processMTSync(mapper);
+    processPosition(mapper, rawX2, rawY2);
+    processTouchMajor(mapper, rawTouchMajor);
+    processToolMajor(mapper, rawToolMajor);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            args.action);
+    ASSERT_EQ(size_t(2), args.pointerCount);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            x, y, pressure, size, touch, touch, tool, tool, 0));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
+            x2, y2, pressure, size, touch, touch, tool, tool, 0));
+}
+
+TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_AreaCalibration) {
+    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION | TOUCH | TOOL);
+    addConfigurationProperty("touch.touchSize.calibration", "pressure");
+    addConfigurationProperty("touch.toolSize.calibration", "area");
+    addConfigurationProperty("touch.toolSize.areaScale", "22");
+    addConfigurationProperty("touch.toolSize.areaBias", "1");
+    addConfigurationProperty("touch.toolSize.linearScale", "9.2");
+    addConfigurationProperty("touch.toolSize.linearBias", "3");
+    addConfigurationProperty("touch.pressure.calibration", "amplitude");
+    addConfigurationProperty("touch.pressure.source", "touch");
+    addConfigurationProperty("touch.pressure.scale", "0.01");
+    addMapperAndConfigure(mapper);
+
+    // These calculations are based on the input device calibration documentation.
+    int32_t rawX = 100;
+    int32_t rawY = 200;
+    int32_t rawTouchMajor = 60;
+    int32_t rawToolMajor = 5;
+
+    float x = toDisplayX(rawX);
+    float y = toDisplayY(rawY);
+    float pressure = float(rawTouchMajor) * 0.01f;
+    float size = float(rawToolMajor) / RAW_TOOL_MAX;
+    float tool = sqrtf(float(rawToolMajor) * 22.0f + 1.0f) * 9.2f + 3.0f;
+    float touch = min(tool * pressure, tool);
+
+    processPosition(mapper, rawX, rawY);
+    processTouchMajor(mapper, rawTouchMajor);
+    processToolMajor(mapper, rawToolMajor);
+    processMTSync(mapper);
+    processSync(mapper);
+
+    FakeInputDispatcher::NotifyMotionArgs args;
+    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            x, y, pressure, size, touch, touch, tool, tool, 0));
+}
+
+} // namespace android
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index 83ce3e3..04ae490 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -240,10 +240,9 @@
                 public void onChange(boolean selfChange) {
                     super.onChange(selfChange);
 
-                    mIsEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
-                        Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
-
                     synchronized (mLock) {
+                        mIsEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
+                                Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
                         if (mIsEnabled) {
                             manageServicesLocked();
                         } else {
@@ -452,9 +451,7 @@
         } catch (RemoteException re) {
             if (re instanceof DeadObjectException) {
                 Slog.w(LOG_TAG, "Dead " + service.mService + ". Cleaning up.");
-                synchronized (mLock) {
-                    removeDeadServiceLocked(service);
-                }
+                removeDeadServiceLocked(service);
             } else {
                 Slog.e(LOG_TAG, "Error during sending " + event + " to " + service.mService, re);
             }
@@ -468,19 +465,11 @@
      * @return True if the service was removed, false otherwise.
      */
     private boolean removeDeadServiceLocked(Service service) {
-        mServices.remove(service);
-        mHandler.removeMessages(service.mId);
-
         if (Config.DEBUG) {
             Slog.i(LOG_TAG, "Dead service " + service.mService + " removed");
         }
-
-        if (mServices.isEmpty()) {
-            mIsEnabled = false;
-            updateClientsLocked();
-        }
-
-        return true;
+        mHandler.removeMessages(service.mId);
+        return mServices.remove(service);
     }
 
     /**
@@ -543,11 +532,11 @@
 
         for (int i = 0, count = services.size(); i < count; i++) {
             Service service = services.get(i);
-
-            service.unbind();
-            mComponentNameToServiceMap.remove(service.mComponentName);
+            if (service.unbind()) {
+                i--;
+                count--;
+            }
         }
-        services.clear();
     }
 
     /**
@@ -589,7 +578,6 @@
             Set<ComponentName> enabledServices) {
 
         Map<ComponentName, Service> componentNameToServiceMap = mComponentNameToServiceMap;
-        List<Service> services = mServices;
         boolean isEnabled = mIsEnabled;
 
         for (int i = 0, count = installedServices.size(); i < count; i++) {
@@ -598,15 +586,20 @@
                     intalledService.name);
             Service service = componentNameToServiceMap.get(componentName);
 
-            if (isEnabled && enabledServices.contains(componentName)) {
-                if (service == null) {
-                    new Service(componentName).bind();
+            if (isEnabled) {
+                if (enabledServices.contains(componentName)) {
+                    if (service == null) {
+                        service = new Service(componentName);
+                    }
+                    service.bind();
+                } else if (!enabledServices.contains(componentName)) {
+                    if (service != null) {
+                        service.unbind();
+                    }
                 }
             } else {
                 if (service != null) {
                     service.unbind();
-                    componentNameToServiceMap.remove(componentName);
-                    services.remove(service);
                 }
             }
         }
@@ -674,21 +667,31 @@
 
         /**
          * Binds to the accessibility service.
+         *
+         * @return True if binding is successful.
          */
-        public void bind() {
+        public boolean bind() {
             if (mService == null) {
-                mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE);
+                return mContext.bindService(mIntent, this, Context.BIND_AUTO_CREATE);
             }
+            return false;
         }
 
         /**
          * Unbinds form the accessibility service and removes it from the data
          * structures for service management.
+         *
+         * @return True if unbinding is successful.
          */
-        public void unbind() {
+        public boolean unbind() {
             if (mService != null) {
+                mService = null;
                 mContext.unbindService(this);
+                mComponentNameToServiceMap.remove(mComponentName);
+                mServices.remove(this);
+                return true;
             }
+            return false;
         }
 
         /**
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index ae408fc..22dd804 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -144,6 +144,7 @@
         // update the provider list.
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         filter.addDataScheme("package");
         mContext.registerReceiver(mBroadcastReceiver, filter);
@@ -643,6 +644,12 @@
     }
 
     boolean addProviderLocked(ResolveInfo ri) {
+        if ((ri.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
+            return false;
+        }
+        if (!ri.activityInfo.isEnabled()) {
+            return false;
+        }
         Provider p = parseProviderInfoXml(new ComponentName(ri.activityInfo.packageName,
                     ri.activityInfo.name), ri);
         if (p != null) {
@@ -1160,6 +1167,7 @@
                 }
             } else {
                 boolean added = false;
+                boolean changed = false;
                 String pkgList[] = null;
                 if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -1178,14 +1186,16 @@
                     }
                     pkgList = new String[] { pkgName };
                     added = Intent.ACTION_PACKAGE_ADDED.equals(action);
+                    changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
                 }
                 if (pkgList == null || pkgList.length == 0) {
                     return;
                 }
-                if (added) {
+                if (added || changed) {
                     synchronized (mAppWidgetIds) {
                         Bundle extras = intent.getExtras();
-                        if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
+                        if (changed || (extras != null &&
+                                    extras.getBoolean(Intent.EXTRA_REPLACING, false))) {
                             for (String pkgName : pkgList) {
                                 // The package was just upgraded
                                 updateProvidersForPackageLocked(pkgName);
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 5b4fb1f..c48f360 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -84,7 +84,7 @@
 
 class BackupManagerService extends IBackupManager.Stub {
     private static final String TAG = "BackupManagerService";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
     // How often we perform a backup pass.  Privileged external callers can
     // trigger an immediate pass.
@@ -2768,6 +2768,15 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        long identityToken = Binder.clearCallingIdentity();
+        try {
+            dumpInternal(pw);
+        } finally {
+            Binder.restoreCallingIdentity(identityToken);
+        }
+    }
+
+    private void dumpInternal(PrintWriter pw) {
         synchronized (mQueueLock) {
             pw.println("Backup Manager is " + (mEnabled ? "enabled" : "disabled")
                     + " / " + (!mProvisioned ? "not " : "") + "provisioned / "
@@ -2781,12 +2790,15 @@
             for (String t : listAllTransports()) {
                 pw.println((t.equals(mCurrentTransport) ? "  * " : "    ") + t);
                 try {
-                    File dir = new File(mBaseStateDir, getTransport(t).transportDirName());
+                    IBackupTransport transport = getTransport(t);
+                    File dir = new File(mBaseStateDir, transport.transportDirName());
+                    pw.println("       destination: " + transport.currentDestinationString());
+                    pw.println("       intent: " + transport.configurationIntent());
                     for (File f : dir.listFiles()) {
                         pw.println("       " + f.getName() + " - " + f.length() + " state bytes");
                     }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Error in transportDirName()", e);
+                } catch (Exception e) {
+                    Slog.e(TAG, "Error in transport", e);
                     pw.println("        Error: " + e);
                 }
             }
diff --git a/services/java/com/android/server/ClipboardService.java b/services/java/com/android/server/ClipboardService.java
index 30ea48c..bec35d1 100644
--- a/services/java/com/android/server/ClipboardService.java
+++ b/services/java/com/android/server/ClipboardService.java
@@ -115,7 +115,7 @@
 
     public ClipDescription getPrimaryClipDescription() {
         synchronized (this) {
-            return mPrimaryClip.getDescription();
+            return mPrimaryClip != null ? mPrimaryClip.getDescription() : null;
         }
     }
 
@@ -211,7 +211,7 @@
         } catch (NameNotFoundException e) {
             throw new IllegalArgumentException("Unknown package " + pkg, e);
         }
-        if (!mActivePermissionOwners.contains(pkg)) {
+        if (mPrimaryClip != null && !mActivePermissionOwners.contains(pkg)) {
             final int N = mPrimaryClip.getItemCount();
             for (int i=0; i<N; i++) {
                 grantItemLocked(mPrimaryClip.getItem(i), pkg);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index f82a243..d0df6cf 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -16,8 +16,7 @@
 
 package com.android.server;
 
-import android.app.Notification;
-import android.app.NotificationManager;
+import android.bluetooth.BluetoothTetheringDataTracker;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -26,9 +25,9 @@
 import android.net.ConnectivityManager;
 import android.net.DummyDataStateTracker;
 import android.net.IConnectivityManager;
+import android.net.LinkProperties;
 import android.net.MobileDataStateTracker;
 import android.net.NetworkInfo;
-import android.net.LinkProperties;
 import android.net.NetworkStateTracker;
 import android.net.NetworkUtils;
 import android.net.Proxy;
@@ -50,7 +49,6 @@
 import android.util.Slog;
 
 import com.android.internal.telephony.Phone;
-
 import com.android.server.connectivity.Tethering;
 
 import java.io.FileDescriptor;
@@ -58,10 +56,10 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.InetAddress;
-import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.GregorianCalendar;
 import java.util.List;
 
@@ -116,6 +114,8 @@
     private boolean mTestMode;
     private static ConnectivityService sServiceInstance;
 
+    private AtomicBoolean mBackgroundDataEnabled = new AtomicBoolean(true);
+
     private static final int ENABLED  = 1;
     private static final int DISABLED = 0;
 
@@ -264,6 +264,9 @@
         handlerThread.start();
         mHandler = new MyHandler(handlerThread.getLooper());
 
+        mBackgroundDataEnabled.set(Settings.Secure.getInt(context.getContentResolver(),
+                Settings.Secure.BACKGROUND_DATA, 1) == 1);
+
         // setup our unique device name
         if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) {
             String id = Settings.Secure.getString(context.getContentResolver(),
@@ -412,6 +415,10 @@
                         mNetAttributes[netType].mName);
                 mNetTrackers[netType].startMonitoring(context, mHandler);
                 break;
+            case ConnectivityManager.TYPE_BLUETOOTH:
+                mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();
+                mNetTrackers[netType].startMonitoring(context, mHandler);
+                break;
             default:
                 loge("Trying to create a DataStateTracker for an unknown radio type " +
                         mNetAttributes[netType].mRadio);
@@ -690,7 +697,8 @@
                 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
             } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
                 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
-            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
+                    TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
                 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
             } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
                 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
@@ -705,7 +713,11 @@
 
                 if (ni.isAvailable() == false) {
                     if (DBG) log("special network not available");
-                    return Phone.APN_TYPE_NOT_AVAILABLE;
+                    if (!TextUtils.equals(feature,Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
+                        return Phone.APN_TYPE_NOT_AVAILABLE;
+                    } else {
+                        // else make the attempt anyway - probably giving REQUEST_STARTED below
+                    }
                 }
 
                 synchronized(this) {
@@ -837,7 +849,8 @@
                     usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
                 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
                     usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
-                } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
+                } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
+                        TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
                     usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
                 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
                     usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
@@ -858,6 +871,8 @@
                     return 1;
                 }
                 callTeardown = true;
+            } else {
+                if (DBG) log("not a known feature - dropping");
             }
         }
         if (DBG) log("Doing network teardown");
@@ -953,8 +968,7 @@
      * @see ConnectivityManager#getBackgroundDataSetting()
      */
     public boolean getBackgroundDataSetting() {
-        return Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.BACKGROUND_DATA, 1) == 1;
+        return mBackgroundDataEnabled.get();
     }
 
     /**
@@ -965,6 +979,8 @@
                 android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
                 "ConnectivityService");
 
+        mBackgroundDataEnabled.set(allowBackgroundDataUsage);
+
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA,
                 (allowBackgroundDataUsage ? ENABLED : DISABLED), 0));
     }
@@ -1087,17 +1103,10 @@
                     info.getExtraInfo());
         }
 
-        NetworkStateTracker newNet = null;
         if (mNetAttributes[prevNetType].isDefault()) {
-            newNet = tryFailover(prevNetType);
-            if (newNet != null) {
-                NetworkInfo switchTo = newNet.getNetworkInfo();
-                if (!switchTo.isConnected()) {
-                    // if the other net is connected they've already reset this and perhaps even
-                    // gotten a positive report we don't want to overwrite, but if not we need to
-                    // clear this now to turn our cellular sig strength white
-                    mDefaultInetConditionPublished = 0;
-                }
+            tryFailover(prevNetType);
+            if (mActiveDefaultNetwork != -1) {
+                NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
                 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
             } else {
                 mDefaultInetConditionPublished = 0; // we're not connected anymore
@@ -1113,77 +1122,45 @@
          * If the failover network is already connected, then immediately send
          * out a followup broadcast indicating successful failover
          */
-        if (newNet != null && newNet.getNetworkInfo().isConnected()) {
-            sendConnectedBroadcast(newNet.getNetworkInfo());
+        if (mActiveDefaultNetwork != -1) {
+            sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
         }
     }
 
-    // returns null if no failover available
-    private NetworkStateTracker tryFailover(int prevNetType) {
+    private void tryFailover(int prevNetType) {
         /*
-         * If this is a default network, check if other defaults are available
-         * or active
+         * If this is a default network, check if other defaults are available.
+         * Try to reconnect on all available and let them hash it out when
+         * more than one connects.
          */
-        NetworkStateTracker newNet = null;
         if (mNetAttributes[prevNetType].isDefault()) {
             if (mActiveDefaultNetwork == prevNetType) {
                 mActiveDefaultNetwork = -1;
             }
 
-            int newType = -1;
-            int newPriority = -1;
+            // don't signal a reconnect for anything lower or equal priority than our
+            // current connected default
+            // TODO - don't filter by priority now - nice optimization but risky
+//            int currentPriority = -1;
+//            if (mActiveDefaultNetwork != -1) {
+//                currentPriority = mNetAttributes[mActiveDefaultNetwork].mPriority;
+//            }
             for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
                 if (checkType == prevNetType) continue;
                 if (mNetAttributes[checkType] == null) continue;
-                if (mNetAttributes[checkType].isDefault()) {
-                    /* TODO - if we have multiple nets we could use
-                     * we may want to put more thought into which we choose
-                     */
-                    if (checkType == mNetworkPreference) {
-                        newType = checkType;
-                        break;
-                    }
-                    if (mNetAttributes[checkType].mPriority > newPriority) {
-                        newType = checkType;
-                        newPriority = mNetAttributes[newType].mPriority;
-                    }
-                }
-            }
+                if (!mNetAttributes[checkType].isDefault()) continue;
+                if (!mNetTrackers[checkType].isAvailable()) continue;
+//                if (currentPriority >= mNetAttributes[checkType].mPriority) continue;
 
-            if (newType != -1) {
-                newNet = mNetTrackers[newType];
-                /**
-                 * See if the other network is available to fail over to.
-                 * If is not available, we enable it anyway, so that it
-                 * will be able to connect when it does become available,
-                 * but we report a total loss of connectivity rather than
-                 * report that we are attempting to fail over.
-                 */
-                if (newNet.isAvailable()) {
-                    NetworkInfo switchTo = newNet.getNetworkInfo();
-                    switchTo.setFailover(true);
-                    if (!switchTo.isConnectedOrConnecting() ||
-                            newNet.isTeardownRequested()) {
-                        newNet.reconnect();
-                    }
-                    if (DBG) {
-                        if (switchTo.isConnected()) {
-                            log("Switching to already connected " + switchTo.getTypeName());
-                        } else {
-                            log("Attempting to switch to " + switchTo.getTypeName());
-                        }
-                    }
-                } else {
-                    newNet.reconnect();
-                    newNet = null; // not officially avail..  try anyway, but
-                                   // report no failover
+                NetworkStateTracker checkTracker = mNetTrackers[checkType];
+                NetworkInfo checkInfo = checkTracker.getNetworkInfo();
+                if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) {
+                    checkInfo.setFailover(true);
+                    checkTracker.reconnect();
                 }
-            } else {
-                loge("Network failover failing.");
+                if (DBG) log("Attempting to switch to " + checkInfo.getTypeName());
             }
         }
-
-        return newNet;
     }
 
     private void sendConnectedBroadcast(NetworkInfo info) {
@@ -1246,17 +1223,10 @@
             info.setFailover(false);
         }
 
-        NetworkStateTracker newNet = null;
         if (mNetAttributes[info.getType()].isDefault()) {
-            newNet = tryFailover(info.getType());
-            if (newNet != null) {
-                NetworkInfo switchTo = newNet.getNetworkInfo();
-                if (!switchTo.isConnected()) {
-                    // if the other net is connected they've already reset this and perhaps
-                    // even gotten a positive report we don't want to overwrite, but if not
-                    // we need to clear this now to turn our cellular sig strength white
-                    mDefaultInetConditionPublished = 0;
-                }
+            tryFailover(info.getType());
+            if (mActiveDefaultNetwork != -1) {
+                NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
                 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
             } else {
                 mDefaultInetConditionPublished = 0;
@@ -1270,8 +1240,8 @@
          * If the failover network is already connected, then immediately send
          * out a followup broadcast indicating successful failover
          */
-        if (newNet != null && newNet.getNetworkInfo().isConnected()) {
-            sendConnectedBroadcast(newNet.getNetworkInfo());
+        if (mActiveDefaultNetwork != -1) {
+            sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
         }
     }
 
@@ -1572,11 +1542,18 @@
         }
     }
 
-    private void writePidDns(Collection <InetAddress> dnses, int pid) {
+    // return true if results in a change
+    private boolean writePidDns(Collection <InetAddress> dnses, int pid) {
         int j = 1;
+        boolean changed = false;
         for (InetAddress dns : dnses) {
-            SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
+            String dnsString = dns.getHostAddress();
+            if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
+                changed = true;
+                SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
+            }
         }
+        return changed;
     }
 
     private void bumpDns() {
@@ -1597,6 +1574,10 @@
          */
         Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+        /*
+         * Connectivity events can happen before boot has completed ...
+         */
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         mContext.sendBroadcast(intent);
     }
 
@@ -1607,26 +1588,40 @@
             LinkProperties p = nt.getLinkProperties();
             if (p == null) return;
             Collection<InetAddress> dnses = p.getDnses();
+            boolean changed = false;
             if (mNetAttributes[netType].isDefault()) {
                 int j = 1;
                 if (dnses.size() == 0 && mDefaultDns != null) {
-                    if (DBG) {
-                        log("no dns provided - using " + mDefaultDns.getHostAddress());
+                    String dnsString = mDefaultDns.getHostAddress();
+                    if (!dnsString.equals(SystemProperties.get("net.dns1"))) {
+                        if (DBG) {
+                            log("no dns provided - using " + dnsString);
+                        }
+                        changed = true;
+                        SystemProperties.set("net.dns1", dnsString);
                     }
-                    SystemProperties.set("net.dns1", mDefaultDns.getHostAddress());
                     j++;
                 } else {
                     for (InetAddress dns : dnses) {
+                        String dnsString = dns.getHostAddress();
+                        if (!changed && dnsString.equals(SystemProperties.get("net.dns" + j))) {
+                            j++;
+                            continue;
+                        }
                         if (DBG) {
                             log("adding dns " + dns + " for " +
                                     nt.getNetworkInfo().getTypeName());
                         }
-                        SystemProperties.set("net.dns" + j++, dns.getHostAddress());
+                        changed = true;
+                        SystemProperties.set("net.dns" + j++, dnsString);
                     }
                 }
                 for (int k=j ; k<mNumDnsEntries; k++) {
-                    if (DBG) log("erasing net.dns" + k);
-                    SystemProperties.set("net.dns" + k, "");
+                    if (changed || !TextUtils.isEmpty(SystemProperties.get("net.dns" + k))) {
+                        if (DBG) log("erasing net.dns" + k);
+                        changed = true;
+                        SystemProperties.set("net.dns" + k, "");
+                    }
                 }
                 mNumDnsEntries = j;
             } else {
@@ -1634,10 +1629,10 @@
                 List pids = mNetRequestersPids[netType];
                 for (int y=0; y< pids.size(); y++) {
                     Integer pid = (Integer)pids.get(y);
-                    writePidDns(dnses, pid.intValue());
+                    changed = writePidDns(dnses, pid.intValue());
                 }
             }
-            bumpDns();
+            if (changed) bumpDns();
         }
     }
 
@@ -2131,9 +2126,11 @@
     }
 
     private void sendProxyBroadcast(ProxyProperties proxy) {
+        if (proxy == null) proxy = new ProxyProperties("", 0, "");
         log("sending Proxy Broadcast for " + proxy);
         Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
-        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
+            Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
         mContext.sendStickyBroadcast(intent);
     }
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 470af67..c0ce256 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -1822,6 +1822,41 @@
                 exclusionList);
     }
 
+    /**
+     * Set the storage encryption request.
+     */
+    public int setStorageEncryption(ComponentName who, boolean encrypt) {
+        synchronized (this) {
+            // Check for permissions
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_ENCRYPTED_STORAGE);
+
+            // TODO: (1) Record the value for the admin so it's sticky
+            // TODO: (2) Compute "max" for all admins (if any admin requests encryption, then
+            //           we enable it.
+            // TODO: (3) Work with filesystem / mount service to start/stop encryption
+            return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
+        }
+    }
+
+    /**
+     * Get the current storage encryption status for a given storage domain.
+     */
+    public int getStorageEncryption(ComponentName who) {
+        synchronized (this) {
+            // Check for permissions if a particular caller is specified
+            if (who != null) {
+                getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_ENCRYPTED_STORAGE);
+            }
+
+            // TODO: Work with filesystem / mount service to query encryption status
+            return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
+        }
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index 0b1a4a3..0fba7c3 100644
--- a/services/java/com/android/server/DeviceStorageMonitorService.java
+++ b/services/java/com/android/server/DeviceStorageMonitorService.java
@@ -16,7 +16,6 @@
 
 package com.android.server;
 
-import com.android.server.am.ActivityManagerService;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -38,7 +37,6 @@
 import android.util.Config;
 import android.util.EventLog;
 import android.util.Slog;
-import android.provider.Settings;
 
 /**
  * This class implements a service to monitor the amount of disk
@@ -66,6 +64,7 @@
     private static final int MONITOR_INTERVAL = 1; //in minutes
     private static final int LOW_MEMORY_NOTIFICATION_ID = 1;
     private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
+    private static final int DEFAULT_THRESHOLD_MAX_BYTES = 500*1024*1024; // 500MB
     private static final int DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES = 12*60; //in minutes
     private static final long DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD = 2 * 1024 * 1024; // 2MB
     private static final long DEFAULT_CHECK_INTERVAL = MONITOR_INTERVAL*60*1000;
@@ -271,13 +270,18 @@
      * any way
      */
     private long getMemThreshold() {
-        int value = Settings.Secure.getInt(
+        long value = Settings.Secure.getInt(
                               mContentResolver,
                               Settings.Secure.SYS_STORAGE_THRESHOLD_PERCENTAGE,
                               DEFAULT_THRESHOLD_PERCENTAGE);
         if(localLOGV) Slog.v(TAG, "Threshold Percentage="+value);
+        value *= mTotalMemory;
+        long maxValue = Settings.Secure.getInt(
+                mContentResolver,
+                Settings.Secure.SYS_STORAGE_THRESHOLD_MAX_BYTES,
+                DEFAULT_THRESHOLD_MAX_BYTES);
         //evaluate threshold value
-        return mTotalMemory*value;
+        return value < maxValue ? value : maxValue;
     }
 
     /*
diff --git a/services/java/com/android/server/InputApplication.java b/services/java/com/android/server/InputApplication.java
index 38420d4..ae09484 100644
--- a/services/java/com/android/server/InputApplication.java
+++ b/services/java/com/android/server/InputApplication.java
@@ -18,16 +18,19 @@
 
 /**
  * Describes input-related application properties for use by the input dispatcher.
- * 
  * @hide
  */
 public final class InputApplication {
+    // Application handle.
+    public InputApplicationHandle inputApplicationHandle;
+
     // Application name.
     public String name;
-    
+
     // Dispatching timeout.
     public long dispatchingTimeoutNanos;
-    
-    // The application window token.
-    public Object token;
+
+    public void recycle() {
+        inputApplicationHandle = null;
+    }
 }
diff --git a/services/java/com/android/server/InputApplicationHandle.java b/services/java/com/android/server/InputApplicationHandle.java
new file mode 100644
index 0000000..d396d11
--- /dev/null
+++ b/services/java/com/android/server/InputApplicationHandle.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+/**
+ * Functions as a handle for an application that can receive input.
+ * Enables the native input dispatcher to refer indirectly to the window manager's
+ * application window token.
+ * @hide
+ */
+public final class InputApplicationHandle {
+    // Pointer to the native input application handle.
+    // This field is lazily initialized via JNI.
+    @SuppressWarnings("unused")
+    private int ptr;
+
+    // The window manager's application window token.
+    public final WindowManagerService.AppWindowToken appWindowToken;
+
+    private native void nativeDispose();
+
+    public InputApplicationHandle(WindowManagerService.AppWindowToken appWindowToken) {
+        this.appWindowToken = appWindowToken;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        nativeDispose();
+        super.finalize();
+    }
+}
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 4c499cd..06595ae 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -19,10 +19,17 @@
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.os.Environment;
 import android.os.SystemProperties;
 import android.util.Slog;
@@ -32,6 +39,7 @@
 import android.view.InputEvent;
 import android.view.KeyEvent;
 import android.view.Surface;
+import android.view.WindowManager;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -69,7 +77,7 @@
     private static native boolean nativeHasKeys(int deviceId, int sourceMask,
             int[] keyCodes, boolean[] keyExists);
     private static native void nativeRegisterInputChannel(InputChannel inputChannel,
-            boolean monitor);
+            InputWindowHandle inputWindowHandle, boolean monitor);
     private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
     private static native int nativeInjectInputEvent(InputEvent event,
             int injectorPid, int injectorUid, int syncMode, int timeoutMillis);
@@ -232,7 +240,7 @@
         }
         
         InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
-        nativeRegisterInputChannel(inputChannels[0], true);
+        nativeRegisterInputChannel(inputChannels[0], null, true);
         inputChannels[0].dispose(); // don't need to retain the Java object reference
         return inputChannels[1];
     }
@@ -240,13 +248,16 @@
     /**
      * Registers an input channel so that it can be used as an input event target.
      * @param inputChannel The input channel to register.
+     * @param inputWindowHandle The handle of the input window associated with the
+     * input channel, or null if none.
      */
-    public void registerInputChannel(InputChannel inputChannel) {
+    public void registerInputChannel(InputChannel inputChannel,
+            InputWindowHandle inputWindowHandle) {
         if (inputChannel == null) {
             throw new IllegalArgumentException("inputChannel must not be null.");
         }
         
-        nativeRegisterInputChannel(inputChannel, false);
+        nativeRegisterInputChannel(inputChannel, inputWindowHandle, false);
     }
     
     /**
@@ -357,7 +368,49 @@
             pw.println(dumpStr);
         }
     }
-    
+
+    private static final class PointerIcon {
+        public Bitmap bitmap;
+        public float hotSpotX;
+        public float hotSpotY;
+
+        public static PointerIcon load(Resources resources, int resourceId) {
+            PointerIcon icon = new PointerIcon();
+
+            XmlResourceParser parser = resources.getXml(resourceId);
+            final int bitmapRes;
+            try {
+                XmlUtils.beginDocument(parser, "pointer-icon");
+
+                TypedArray a = resources.obtainAttributes(
+                        parser, com.android.internal.R.styleable.PointerIcon);
+                bitmapRes = a.getResourceId(com.android.internal.R.styleable.PointerIcon_bitmap, 0);
+                icon.hotSpotX = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotX, 0);
+                icon.hotSpotY = a.getFloat(com.android.internal.R.styleable.PointerIcon_hotSpotY, 0);
+                a.recycle();
+            } catch (Exception ex) {
+                Slog.e(TAG, "Exception parsing pointer icon resource.", ex);
+                return null;
+            } finally {
+                parser.close();
+            }
+
+            if (bitmapRes == 0) {
+                Slog.e(TAG, "<pointer-icon> is missing bitmap attribute");
+                return null;
+            }
+
+            Drawable drawable = resources.getDrawable(bitmapRes);
+            if (!(drawable instanceof BitmapDrawable)) {
+                Slog.e(TAG, "<pointer-icon> bitmap attribute must refer to a bitmap drawable");
+                return null;
+            }
+
+            icon.bitmap = ((BitmapDrawable)drawable).getBitmap();
+            return icon;
+        }
+    }
+
     /*
      * Callbacks from native.
      */
@@ -370,7 +423,7 @@
         
         @SuppressWarnings("unused")
         public void notifyConfigurationChanged(long whenNanos) {
-            mWindowManagerService.sendNewConfiguration();
+            mWindowManagerService.mInputMonitor.notifyConfigurationChanged();
         }
         
         @SuppressWarnings("unused")
@@ -379,13 +432,15 @@
         }
         
         @SuppressWarnings("unused")
-        public void notifyInputChannelBroken(InputChannel inputChannel) {
-            mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputChannel);
+        public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+            mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputWindowHandle);
         }
         
         @SuppressWarnings("unused")
-        public long notifyANR(Object token, InputChannel inputChannel) {
-            return mWindowManagerService.mInputMonitor.notifyANR(token, inputChannel);
+        public long notifyANR(InputApplicationHandle inputApplicationHandle,
+                InputWindowHandle inputWindowHandle) {
+            return mWindowManagerService.mInputMonitor.notifyANR(
+                    inputApplicationHandle, inputWindowHandle);
         }
         
         @SuppressWarnings("unused")
@@ -395,14 +450,14 @@
         }
         
         @SuppressWarnings("unused")
-        public boolean interceptKeyBeforeDispatching(InputChannel focus,
+        public boolean interceptKeyBeforeDispatching(InputWindowHandle focus,
                 KeyEvent event, int policyFlags) {
             return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(
                     focus, event, policyFlags);
         }
         
         @SuppressWarnings("unused")
-        public KeyEvent dispatchUnhandledKey(InputChannel focus,
+        public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
                 KeyEvent event, int policyFlags) {
             return mWindowManagerService.mInputMonitor.dispatchUnhandledKey(
                     focus, event, policyFlags);
@@ -475,5 +530,19 @@
             }
             return result;
         }
+
+        @SuppressWarnings("unused")
+        public int getPointerLayer() {
+            return mWindowManagerService.mPolicy.windowTypeToLayerLw(
+                    WindowManager.LayoutParams.TYPE_POINTER)
+                    * WindowManagerService.TYPE_LAYER_MULTIPLIER
+                    + WindowManagerService.TYPE_LAYER_OFFSET;
+        }
+
+        @SuppressWarnings("unused")
+        public PointerIcon getPointerIcon() {
+            return PointerIcon.load(mContext.getResources(),
+                    com.android.internal.R.drawable.pointer_arrow_icon);
+        }
     }
 }
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 95200fa..2b98795 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -99,6 +99,7 @@
     static final int MSG_SHOW_IM_PICKER = 1;
     static final int MSG_SHOW_IM_SUBTYPE_PICKER = 2;
     static final int MSG_SHOW_IM_SUBTYPE_ENABLER = 3;
+    static final int MSG_SHOW_IM_CONFIG = 4;
 
     static final int MSG_UNBIND_INPUT = 1000;
     static final int MSG_BIND_INPUT = 1010;
@@ -117,9 +118,7 @@
 
     private static final int NOT_A_SUBTYPE_ID = -1;
     private static final String NOT_A_SUBTYPE_ID_STR = String.valueOf(NOT_A_SUBTYPE_ID);
-    // If IME doesn't support the system locale, the default subtype will be the first defined one.
-    private static final int DEFAULT_SUBTYPE_ID = 0;
-
+    private static final String EXTRA_INPUT_METHOD_ID = "input_method_id";
     private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
     private static final String SUBTYPE_MODE_VOICE = "voice";
 
@@ -428,6 +427,7 @@
                             // Uh oh, current input method is no longer around!
                             // Pick another one...
                             Slog.i(TAG, "Current input method removed: " + curInputMethodId);
+                            mStatusBar.setIMEButtonVisible(mCurToken, false);
                             if (!chooseNewDefaultIMELocked()) {
                                 changed = true;
                                 curIm = null;
@@ -490,7 +490,8 @@
         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();
 
@@ -564,12 +565,19 @@
         }
     }
 
-    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi) {
+    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
+            boolean allowsImplicitlySelectedSubtypes) {
         synchronized (mMethodMap) {
             if (imi == null && mCurMethodId != null) {
                 imi = mMethodMap.get(mCurMethodId);
             }
-            return mSettings.getEnabledInputMethodSubtypeListLocked(imi);
+            final List<InputMethodSubtype> enabledSubtypes =
+                    mSettings.getEnabledInputMethodSubtypeListLocked(imi);
+            if (!allowsImplicitlySelectedSubtypes || enabledSubtypes.size() > 0) {
+                return enabledSubtypes;
+            } else {
+                return getApplicableSubtypesLocked(mRes, imi.getSubtypes());
+            }
         }
     }
 
@@ -1014,9 +1022,11 @@
             }
             if (subtype != mCurrentSubtype) {
                 synchronized (mMethodMap) {
+                    if (subtype != null) {
+                        setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
+                    }
                     if (mCurMethod != null) {
                         try {
-                            setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
                             if (mInputShown) {
                                 // If mInputShown is false, there is no IME button on the
                                 // system bar.
@@ -1313,14 +1323,14 @@
     }
 
     public void showInputMethodAndSubtypeEnablerFromClient(
-            IInputMethodClient client, String topId) {
-        // TODO: Handle topId for setting the top position of the list ActivityManagerNative
+            IInputMethodClient client, String inputMethodId) {
         synchronized (mMethodMap) {
             if (mCurClient == null || client == null
                 || mCurClient.client.asBinder() != client.asBinder()) {
                 Slog.w(TAG, "Ignoring showInputMethodAndSubtypeEnablerFromClient of: " + client);
             }
-            mHandler.sendEmptyMessage(MSG_SHOW_IM_SUBTYPE_ENABLER);
+            executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
+                    MSG_SHOW_IM_SUBTYPE_ENABLER, inputMethodId));
         }
     }
 
@@ -1428,7 +1438,12 @@
                 return true;
 
             case MSG_SHOW_IM_SUBTYPE_ENABLER:
-                showInputMethodAndSubtypeEnabler();
+                args = (HandlerCaller.SomeArgs)msg.obj;
+                showInputMethodAndSubtypeEnabler((String)args.arg1);
+                return true;
+
+            case MSG_SHOW_IM_CONFIG:
+                showConfigureInputMethods();
                 return true;
 
             // ---------------------------------------------------------
@@ -1624,11 +1639,22 @@
         showInputMethodMenuInternal(true);
     }
 
-    private void showInputMethodAndSubtypeEnabler() {
+    private void showInputMethodAndSubtypeEnabler(String inputMethodId) {
         Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_AND_SUBTYPE_ENABLER);
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        if (!TextUtils.isEmpty(inputMethodId)) {
+            intent.putExtra(EXTRA_INPUT_METHOD_ID, inputMethodId);
+        }
+        mContext.startActivity(intent);
+    }
+
+    private void showConfigureInputMethods() {
+        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
         mContext.startActivity(intent);
     }
 
@@ -1647,6 +1673,22 @@
         synchronized (mMethodMap) {
             final List<Pair<InputMethodInfo, ArrayList<String>>> immis =
                     mSettings.getEnabledInputMethodAndSubtypeHashCodeListLocked();
+            int N = immis.size();
+
+            // Add applicable subtypes if no subtype for each IME is enabled.
+            for (int i = 0; i < N; ++i) {
+                InputMethodInfo imi = immis.get(i).first;
+                ArrayList<String> subtypes = immis.get(i).second;
+                if (subtypes != null && subtypes.size() == 0) {
+                    ArrayList<InputMethodSubtype> applicableSubtypes =
+                            getApplicableSubtypesLocked(mRes, imi.getSubtypes());
+                    final int numSubtypes = applicableSubtypes.size();
+                    for (int j = 0; j < numSubtypes; ++j) {
+                        subtypes.add(String.valueOf(applicableSubtypes.get(j).hashCode()));
+                    }
+                }
+            }
+
             ArrayList<Integer> subtypeIds = new ArrayList<Integer>();
 
             if (immis == null || immis.size() == 0) {
@@ -1655,7 +1697,6 @@
 
             hideInputMethodMenuLocked();
 
-            int N = immis.size();
 
             final Map<CharSequence, Pair<InputMethodInfo, Integer>> imMap =
                 new TreeMap<CharSequence, Pair<InputMethodInfo, Integer>>(Collator.getInstance());
@@ -1760,19 +1801,14 @@
                     });
 
             if (showSubtypes) {
-                mDialogBuilder.setPositiveButton(com.android.internal.R.string.more_item_label,
+                mDialogBuilder.setPositiveButton(
+                        com.android.internal.R.string.configure_input_methods,
                         new DialogInterface.OnClickListener() {
                             public void onClick(DialogInterface dialog, int whichButton) {
-                                showInputMethodAndSubtypeEnabler();
+                                showConfigureInputMethods();
                             }
                         });
             }
-            mDialogBuilder.setNegativeButton(com.android.internal.R.string.cancel,
-                    new DialogInterface.OnClickListener() {
-                        public void onClick(DialogInterface dialog, int whichButton) {
-                            hideInputMethodMenu();
-                        }
-                    });
             mSwitchingDialog = mDialogBuilder.create();
             mSwitchingDialog.getWindow().setType(
                     WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
@@ -1942,32 +1978,82 @@
         return NOT_A_SUBTYPE_ID;
     }
 
+    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>();
+        final int N = subtypes.size();
+        boolean containsKeyboardSubtype = false;
+        for (int i = 0; i < N; ++i) {
+            InputMethodSubtype subtype = subtypes.get(i);
+            final String locale = subtype.getLocale();
+            final String mode = subtype.getMode();
+            // When system locale starts with subtype's locale, that subtype will be applicable
+            // for system locale
+            // For instance, it's clearly applicable for cases like system locale = en_US and
+            // subtype = en, but it is not necessarily considered applicable for cases like system
+            // locale = en and subtype = en_US.
+            // We just call systemLocale.startsWith(locale) in this function because there is no
+            // need to find applicable subtypes aggressively unlike
+            // findLastResortApplicableSubtypeLocked.
+            if (systemLocale.startsWith(locale)) {
+                InputMethodSubtype applicableSubtype = applicableModeAndSubtypesMap.get(mode);
+                // If more applicable subtypes are contained, skip.
+                if (applicableSubtype != null
+                        && systemLocale.equals(applicableSubtype.getLocale())) continue;
+                applicableModeAndSubtypesMap.put(mode, subtype);
+                if (!containsKeyboardSubtype
+                        && SUBTYPE_MODE_KEYBOARD.equalsIgnoreCase(subtype.getMode())) {
+                    containsKeyboardSubtype = true;
+                }
+            }
+        }
+        ArrayList<InputMethodSubtype> applicableSubtypes = new ArrayList<InputMethodSubtype>(
+                applicableModeAndSubtypesMap.values());
+        if (!containsKeyboardSubtype) {
+            InputMethodSubtype lastResortKeyboardSubtype = findLastResortApplicableSubtypeLocked(
+                    res, subtypes, SUBTYPE_MODE_KEYBOARD, systemLocale, true);
+            if (lastResortKeyboardSubtype != null) {
+                applicableSubtypes.add(lastResortKeyboardSubtype);
+            }
+        }
+        return applicableSubtypes;
+    }
+
     /**
      * If there are no selected subtypes, tries finding the most applicable one according to the
      * given locale.
      * @param subtypes this function will search the most applicable subtype in subtypes
      * @param mode subtypes will be filtered by mode
      * @param locale subtypes will be filtered by locale
-     * @param defaultSubtypeId if this function can't find the most applicable subtype, it will
-     * return defaultSubtypeId
+     * @param canIgnoreLocaleAsLastResort if this function can't find the most applicable subtype,
+     * it will return the first subtype matched with mode
      * @return the most applicable subtypeId
      */
-    private InputMethodSubtype findLastResortApplicableSubtypeLocked(
-            List<InputMethodSubtype> subtypes, String mode, String locale, int defaultSubtypeId) {
+    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;
         InputMethodSubtype applicableSubtype = null;
-        for (int i = 0; i < subtypes.size(); ++i) {
+        InputMethodSubtype firstMatchedModeSubtype = null;
+        final int N = subtypes.size();
+        for (int i = 0; i < N; ++i) {
             InputMethodSubtype subtype = subtypes.get(i);
             final String subtypeLocale = subtype.getLocale();
             // An applicable subtype should match "mode".
             if (subtypes.get(i).getMode().equalsIgnoreCase(mode)) {
+                if (firstMatchedModeSubtype == null) {
+                    firstMatchedModeSubtype = subtype;
+                }
                 if (locale.equals(subtypeLocale)) {
                     // Exact match (e.g. system locale is "en_US" and subtype locale is "en_US")
                     applicableSubtype = subtype;
@@ -1980,11 +2066,17 @@
             }
         }
 
+        if (applicableSubtype == null && canIgnoreLocaleAsLastResort) {
+            return firstMatchedModeSubtype;
+        }
+
         // The first subtype applicable to the system locale will be defined as the most applicable
         // subtype.
         if (DEBUG) {
-            Slog.d(TAG, "Applicable InputMethodSubtype was found: " + applicableSubtype.getMode()
-                    + "," + applicableSubtype.getLocale());
+            if (applicableSubtype != null) {
+                Slog.d(TAG, "Applicable InputMethodSubtype was found: "
+                        + applicableSubtype.getMode() + "," + applicableSubtype.getLocale());
+            }
         }
         return applicableSubtype;
     }
@@ -1999,44 +2091,49 @@
 
         // Search applicable subtype for each InputMethodInfo
         for (InputMethodInfo imi: imis) {
+            final String imiId = imi.getId();
+            if (foundInSystemIME && !imiId.equals(mCurMethodId)) {
+                continue;
+            }
             InputMethodSubtype subtype = null;
+            final List<InputMethodSubtype> enabledSubtypes =
+                    getEnabledInputMethodSubtypeList(imi, true);
+            // 1. Search by the current subtype's locale from enabledSubtypes.
             if (mCurrentSubtype != null) {
-                // 1. Search with the current subtype's locale and the enabled subtypes
                 subtype = findLastResortApplicableSubtypeLocked(
-                        mSettings.getEnabledInputMethodSubtypeListLocked(
-                        imi), mode, mCurrentSubtype.getLocale(), NOT_A_SUBTYPE_ID);
-                if (subtype == null) {
-                    // 2. Search with the current subtype's locale and all subtypes
-                    subtype = findLastResortApplicableSubtypeLocked(imi.getSubtypes(),
-                            mode, mCurrentSubtype.getLocale(), NOT_A_SUBTYPE_ID);
-                }
+                        mRes, enabledSubtypes, mode, mCurrentSubtype.getLocale(), false);
             }
-            // 3. Search with the system locale and the enabled subtypes
+            // 2. Search by the system locale from enabledSubtypes.
+            // 3. Search the first enabled subtype matched with mode from enabledSubtypes.
             if (subtype == null) {
                 subtype = findLastResortApplicableSubtypeLocked(
-                        mSettings.getEnabledInputMethodSubtypeListLocked(
-                        imi), mode, null, NOT_A_SUBTYPE_ID);
+                        mRes, enabledSubtypes, mode, null, true);
             }
+            // 4. Search by the current subtype's locale from all subtypes.
+            if (subtype == null && mCurrentSubtype != null) {
+                subtype = findLastResortApplicableSubtypeLocked(
+                        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) {
-                // 4. Search with the system locale and all subtypes
-                subtype = findLastResortApplicableSubtypeLocked(imi.getSubtypes(),
-                        mode, null, NOT_A_SUBTYPE_ID);
+                subtype = findLastResortApplicableSubtypeLocked(
+                        mRes, imi.getSubtypes(), mode, null, true);
             }
             if (subtype != null) {
-                if (imi.getId().equals(mCurMethodId)) {
+                if (imiId.equals(mCurMethodId)) {
                     // The current input method is the most applicable IME.
                     mostApplicableIMI = imi;
                     mostApplicableSubtype = subtype;
                     break;
-                } else if ((imi.getServiceInfo().applicationInfo.flags
-                        & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                } else if (!foundInSystemIME) {
                     // The system input method is 2nd applicable IME.
                     mostApplicableIMI = imi;
                     mostApplicableSubtype = subtype;
-                    foundInSystemIME = true;
-                } else if (!foundInSystemIME) {
-                    mostApplicableIMI = imi;
-                    mostApplicableSubtype = subtype;
+                    if ((imi.getServiceInfo().applicationInfo.flags
+                            & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                        foundInSystemIME = true;
+                    }
                 }
             }
         }
@@ -2081,8 +2178,8 @@
                         // 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, DEFAULT_SUBTYPE_ID);
+                        mCurrentSubtype = findLastResortApplicableSubtypeLocked(
+                                mRes, imi.getSubtypes(), SUBTYPE_MODE_KEYBOARD, null, true);
                     }
                 } else {
                     mCurrentSubtype =
@@ -2107,6 +2204,7 @@
     // TODO: We should change the return type from List to List<Parcelable>
     public List getShortcutInputMethodsAndSubtypes() {
         synchronized (mMethodMap) {
+            ArrayList<Object> ret = new ArrayList<Object>();
             if (mShortcutInputMethodsAndSubtypes.size() == 0) {
                 // If there are no selected shortcut subtypes, the framework will try to find
                 // the most applicable subtype from all subtypes whose mode is
@@ -2114,9 +2212,12 @@
                 Pair<InputMethodInfo, InputMethodSubtype> info =
                     findLastResortApplicableShortcutInputMethodAndSubtypeLocked(
                             SUBTYPE_MODE_VOICE);
-                addShortcutInputMethodAndSubtypes(info.first, info.second);
+                if (info != null) {
+                    ret.add(info.first);
+                    ret.add(info.second);
+                }
+                return ret;
             }
-            ArrayList<Object> ret = new ArrayList<Object>();
             for (InputMethodInfo imi: mShortcutInputMethodsAndSubtypes.keySet()) {
                 ret.add(imi);
                 for (InputMethodSubtype subtype: mShortcutInputMethodsAndSubtypes.get(imi)) {
@@ -2156,6 +2257,7 @@
         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;
@@ -2175,8 +2277,9 @@
         }
 
         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;
@@ -2416,8 +2519,9 @@
                 // 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);
@@ -2432,14 +2536,36 @@
             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/InputWindow.java b/services/java/com/android/server/InputWindow.java
index befc770..1515290 100644
--- a/services/java/com/android/server/InputWindow.java
+++ b/services/java/com/android/server/InputWindow.java
@@ -20,64 +20,67 @@
 
 /**
  * Describes input-related window properties for use by the input dispatcher.
- * 
  * @hide
  */
 public final class InputWindow {
+    // The window handle.
+    public InputWindowHandle inputWindowHandle;
+
     // The input channel associated with the window.
     public InputChannel inputChannel;
-    
+
     // The window name.
     public String name;
-    
+
     // Window layout params attributes.  (WindowManager.LayoutParams)
     public int layoutParamsFlags;
     public int layoutParamsType;
-    
+
     // Dispatching timeout.
     public long dispatchingTimeoutNanos;
-    
+
     // Window frame area.
     public int frameLeft;
     public int frameTop;
     public int frameRight;
     public int frameBottom;
-    
+
     // Window visible frame area.
     public int visibleFrameLeft;
     public int visibleFrameTop;
     public int visibleFrameRight;
     public int visibleFrameBottom;
-    
+
     // Window touchable area.
     public int touchableAreaLeft;
     public int touchableAreaTop;
     public int touchableAreaRight;
     public int touchableAreaBottom;
-    
+
     // Window is visible.
     public boolean visible;
-    
+
     // Window can receive keys.
     public boolean canReceiveKeys;
-    
+
     // Window has focus.
     public boolean hasFocus;
-    
+
     // Window has wallpaper.  (window is the current wallpaper target)
     public boolean hasWallpaper;
-    
+
     // Input event dispatching is paused.
     public boolean paused;
-    
+
     // Window layer.
     public int layer;
-    
+
     // Id of process and user that owns the window.
     public int ownerPid;
     public int ownerUid;
-    
+
     public void recycle() {
+        inputWindowHandle = null;
         inputChannel = null;
     }
 }
diff --git a/services/java/com/android/server/InputWindowHandle.java b/services/java/com/android/server/InputWindowHandle.java
new file mode 100644
index 0000000..4b92939
--- /dev/null
+++ b/services/java/com/android/server/InputWindowHandle.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.view.WindowManagerPolicy;
+
+/**
+ * Functions as a handle for a window that can receive input.
+ * Enables the native input dispatcher to refer indirectly to the window manager's window state.
+ * @hide
+ */
+public final class InputWindowHandle {
+    // Pointer to the native input window handle.
+    // This field is lazily initialized via JNI.
+    @SuppressWarnings("unused")
+    private int ptr;
+
+    // The input application handle.
+    public final InputApplicationHandle inputApplicationHandle;
+
+    // The window manager's window state.
+    public final WindowManagerPolicy.WindowState windowState;
+
+    private native void nativeDispose();
+
+    public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
+            WindowManagerPolicy.WindowState windowState) {
+        this.inputApplicationHandle = inputApplicationHandle;
+        this.windowState = windowState;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        nativeDispose();
+        super.finalize();
+    }
+}
diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java
index e47de13..a8b2840 100644
--- a/services/java/com/android/server/IntentResolver.java
+++ b/services/java/com/android/server/IntentResolver.java
@@ -346,7 +346,7 @@
 
         int num = 0;
         while (i.hasNext()) {
-            String name = (String)i.next();
+            String name = i.next();
             num++;
             if (localLOGV) Slog.v(TAG, prefix + name);
             String baseName = name;
@@ -395,7 +395,7 @@
 
         int num = 0;
         while (i.hasNext()) {
-            String name = (String)i.next();
+            String name = i.next();
             num++;
             if (localLOGV) Slog.v(TAG, prefix + name);
             String baseName = name;
@@ -534,8 +534,8 @@
     // Sorts a List of IntentFilter objects into descending priority order.
     private static final Comparator mResolvePrioritySorter = new Comparator() {
         public int compare(Object o1, Object o2) {
-            float q1 = ((IntentFilter)o1).getPriority();
-            float q2 = ((IntentFilter)o2).getPriority();
+            final int q1 = ((IntentFilter) o1).getPriority();
+            final int q2 = ((IntentFilter) o2).getPriority();
             return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0);
         }
     };
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 64cd661..d6804f9 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -73,8 +73,8 @@
  * @hide - Applications should use android.os.storage.StorageManager
  * to access the MountService.
  */
-class MountService extends IMountService.Stub
-        implements INativeDaemonConnectorCallbacks {
+class MountService extends IMountService.Stub implements INativeDaemonConnectorCallbacks {
+
     private static final boolean LOCAL_LOGD = false;
     private static final boolean DEBUG_UNMOUNT = false;
     private static final boolean DEBUG_EVENTS = false;
@@ -334,6 +334,7 @@
             super(l);
         }
 
+        @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case H_UNMOUNT_PM_UPDATE: {
@@ -427,6 +428,7 @@
     }
 
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
 
@@ -442,6 +444,7 @@
                     return;
                 }
                 new Thread() {
+                    @Override
                     public void run() {
                         try {
                             String path = Environment.getExternalStorageDirectory().getPath();
@@ -565,6 +568,7 @@
          * we need to do our work in a new thread.
          */
         new Thread() {
+            @Override
             public void run() {
                 /**
                  * Determine media state and UMS detection status
@@ -678,6 +682,7 @@
 
             if (code == VoldResponseCode.VolumeDiskInserted) {
                 new Thread() {
+                    @Override
                     public void run() {
                         try {
                             int rc;
@@ -1007,6 +1012,7 @@
              * USB mass storage disconnected while enabled
              */
             new Thread() {
+                @Override
                 public void run() {
                     try {
                         int rc;
@@ -1624,6 +1630,52 @@
             Slog.i(TAG, "Send to OBB handler: " + action.toString());
     }
 
+    public int decryptStorage(String password) {
+        if (password == null) {
+            throw new IllegalArgumentException("password cannot be null");
+        }
+
+        // TODO: Enforce a permission
+
+        waitForReady();
+
+        if (DEBUG_EVENTS) {
+            Slog.i(TAG, "decrypting storage...");
+        }
+
+        try {
+            mConnector.doCommand(String.format("cryptfs checkpw %s", password));
+        } catch (NativeDaemonConnectorException e) {
+            // Decryption failed
+            return e.getCode();
+        }
+
+        return 0;
+    }
+
+    public int encryptStorage(String password) {
+        if (password == null) {
+            throw new IllegalArgumentException("password cannot be null");
+        }
+
+        // TODO: Enforce a permission
+
+        waitForReady();
+
+        if (DEBUG_EVENTS) {
+            Slog.i(TAG, "decrypting storage...");
+        }
+
+        try {
+            mConnector.doCommand(String.format("cryptfs enablecrypto wipe %s", password));
+        } catch (NativeDaemonConnectorException e) {
+            // Encryption failed
+            return e.getCode();
+        }
+
+        return 0;
+    }
+
     private void addObbStateLocked(ObbState obbState) throws RemoteException {
         final IBinder binder = obbState.getBinder();
         List<ObbState> obbStates = mObbMounts.get(binder);
@@ -1911,6 +1963,7 @@
             mKey = key;
         }
 
+        @Override
         public void handleExecute() throws IOException, RemoteException {
             waitForReady();
             warnOnNotMounted();
@@ -1991,6 +2044,7 @@
             }
         }
 
+        @Override
         public void handleError() {
             sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
         }
@@ -2020,6 +2074,7 @@
             mForceUnmount = force;
         }
 
+        @Override
         public void handleExecute() throws IOException {
             waitForReady();
             warnOnNotMounted();
@@ -2074,6 +2129,7 @@
             }
         }
 
+        @Override
         public void handleError() {
             sendNewStatusOrIgnore(OnObbStateChangeListener.ERROR_INTERNAL);
         }
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 4290ce7..152605f 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -295,7 +295,7 @@
             mConnector.doCommand(cmd);
         } catch (NativeDaemonConnectorException e) {
             throw new IllegalStateException(
-                    "Unable to communicate with native daemon to interface setcfg");
+                    "Unable to communicate with native daemon to interface setcfg - " + e);
         }
     }
 
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 2691e1d..1efc645 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -2882,13 +2882,13 @@
         SharedUserSetting suid = null;
         PackageSetting pkgSetting = null;
 
-        if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
+        if (!isSystemApp(pkg)) {
             // Only system apps can use these features.
             pkg.mOriginalPackages = null;
             pkg.mRealPackage = null;
             pkg.mAdoptPermissions = null;
         }
-        
+
         synchronized (mPackages) {
             // Check all shared libraries and map to their actual file path.
             if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
@@ -2927,24 +2927,23 @@
                     System.arraycopy(mTmpSharedLibraries, 0,
                             pkg.usesLibraryFiles, 0, num);
                 }
+            }
 
-                if (pkg.reqFeatures != null) {
-                    N = pkg.reqFeatures.size();
-                    for (int i=0; i<N; i++) {
-                        FeatureInfo fi = pkg.reqFeatures.get(i);
-                        if ((fi.flags&FeatureInfo.FLAG_REQUIRED) == 0) {
-                            // Don't care.
-                            continue;
-                        }
+            if (pkg.reqFeatures != null) {
+                int N = pkg.reqFeatures.size();
+                for (int i = 0; i < N; i++) {
+                    FeatureInfo fi = pkg.reqFeatures.get(i);
+                    if ((fi.flags & FeatureInfo.FLAG_REQUIRED) == 0) {
+                        // Don't care.
+                        continue;
+                    }
 
-                        if (fi.name != null) {
-                            if (mAvailableFeatures.get(fi.name) == null) {
-                                Slog.e(TAG, "Package " + pkg.packageName
-                                        + " requires unavailable feature "
-                                        + fi.name + "; failing!");
-                                mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
-                                return null;
-                            }
+                    if (fi.name != null) {
+                        if (mAvailableFeatures.get(fi.name) == null) {
+                            Slog.e(TAG, "Package " + pkg.packageName
+                                    + " requires unavailable feature " + fi.name + "; failing!");
+                            mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE;
+                            return null;
                         }
                     }
                 }
@@ -3664,17 +3663,6 @@
                 mAppDirs.remove(pkg.mPath);
             }
 
-            PackageSetting ps = (PackageSetting)pkg.mExtras;
-            if (ps != null && ps.sharedUser != null) {
-                // XXX don't do this until the data is removed.
-                if (false) {
-                    ps.sharedUser.packages.remove(ps);
-                    if (ps.sharedUser.packages.size() == 0) {
-                        // Remove.
-                    }
-                }
-            }
-
             int N = pkg.providers.size();
             StringBuilder r = null;
             int i;
@@ -4092,6 +4080,7 @@
         }
 
         public final void addActivity(PackageParser.Activity a, String type) {
+            final boolean systemApp = isSystemApp(a.info.applicationInfo);
             mActivities.put(a.getComponentName(), a);
             if (SHOW_INFO || Config.LOGV) Log.v(
                 TAG, "  " + type + " " +
@@ -4100,6 +4089,11 @@
             int NI = a.intents.size();
             for (int j=0; j<NI; j++) {
                 PackageParser.ActivityIntentInfo intent = a.intents.get(j);
+                if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
+                    intent.setPriority(0);
+                    Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
+                            + a.className + " with priority > 0, forcing to 0");
+                }
                 if (SHOW_INFO || Config.LOGV) {
                     Log.v(TAG, "    IntentFilter:");
                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
@@ -4652,16 +4646,52 @@
         }
     }
 
-    public void setPackageObbPath(String packageName, String path) {
+    public void setPackageObbPaths(String packageName, String[] paths) {
         if (DEBUG_OBB)
-            Log.v(TAG, "Setting .obb path for " + packageName + " to: " + path);
-        PackageSetting pkgSetting;
+            Log.v(TAG, "Setting .obb paths for " + packageName + " to: " + Arrays.toString(paths));
+        final int uid = Binder.getCallingUid();
+        final int permission = mContext.checkCallingPermission(
+                android.Manifest.permission.INSTALL_PACKAGES);
+        final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
+        if (!allowedByPermission) {
+            throw new SecurityException("Permission denial: attempt to set .obb file from pid="
+                    + Binder.getCallingPid());
+        }
+        synchronized (mPackages) {
+            final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
+            if (pkgSetting == null) {
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
+
+            if (paths != null) {
+                if (paths.length == 0) {
+                    // Don't bother storing an empty array.
+                    paths = null;
+                } else {
+                    // Don't allow the caller to manipulate our copy of the
+                    // list.
+                    paths = paths.clone();
+                }
+            }
+
+            // Only write settings file if the new and old settings are not the
+            // same.
+            if (!Arrays.equals(paths, pkgSetting.obbPathStrings)) {
+                pkgSetting.obbPathStrings = paths;
+                mSettings.writeLP();
+            }
+        }
+    }
+
+    public String[] getPackageObbPaths(String packageName) {
+        if (DEBUG_OBB)
+            Log.v(TAG, "Getting .obb paths for " + packageName);
         final int uid = Binder.getCallingUid();
         final int permission = mContext.checkCallingPermission(
                 android.Manifest.permission.INSTALL_PACKAGES);
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
         synchronized (mPackages) {
-            pkgSetting = mSettings.mPackages.get(packageName);
+            final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
             if (pkgSetting == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
@@ -4670,8 +4700,7 @@
                         + Binder.getCallingPid() + ", uid=" + uid + ", package uid="
                         + pkgSetting.userId);
             }
-            pkgSetting.obbPathString = path;
-            mSettings.writeLP();
+            return pkgSetting.obbPathStrings;
         }
     }
 
@@ -5770,11 +5799,28 @@
                 return;
             }
         }
+
+        killApplication(packageName, oldPkg.applicationInfo.uid);
+
         res.removedInfo.uid = oldPkg.applicationInfo.uid;
         res.removedInfo.removedPackage = packageName;
         // Remove existing system package
         removePackageLI(oldPkg, true);
-
+        synchronized (mPackages) {
+            if (!mSettings.disableSystemPackageLP(packageName) && deletedPackage != null) {
+                // We didn't need to disable the .apk as a current system package,
+                // which means we are replacing another update that is already
+                // installed.  We need to make sure to delete the older one's .apk.
+                res.removedInfo.args = createInstallArgs(isExternal(pkg)
+                        ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL,
+                        deletedPackage.applicationInfo.sourceDir,
+                        deletedPackage.applicationInfo.publicSourceDir,
+                        deletedPackage.applicationInfo.nativeLibraryDir);
+            } else {
+                res.removedInfo.args = null;
+            }
+        }
+        
         // Successfully disabled the old package. Now proceed with re-installation
         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
@@ -5811,17 +5857,6 @@
                 }
                 mSettings.writeLP();
             }
-        } else {
-            // If this is an update to an existing update, setup 
-            // to remove the existing update.
-            synchronized (mPackages) {
-                PackageSetting ps = mSettings.getDisabledSystemPkg(packageName);
-                if (ps != null && ps.codePathString != null &&
-                        !ps.codePathString.equals(oldPkgSetting.codePathString)) {
-                    res.removedInfo.args = createInstallArgs(0, oldPkgSetting.codePathString,
-                            oldPkgSetting.resourcePathString, oldPkgSetting.nativeLibraryPathString);
-                }
-            }
         }
     }
 
@@ -6032,6 +6067,10 @@
         return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
     }
 
+    private static boolean isSystemApp(ApplicationInfo info) {
+        return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+    }
+
     private static boolean isUpdatedSystemApp(PackageParser.Package pkg) {
         return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
     }
@@ -6324,24 +6363,21 @@
             ps = mSettings.getDisabledSystemPkg(p.packageName);
         }
         if (ps == null) {
-            Slog.w(TAG, "Attempt to delete system package "+ p.packageName);
+            Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName);
             return false;
         } else {
             Log.i(TAG, "Deleting system pkg from data partition");
         }
         // Delete the updated package
         outInfo.isRemovedPackageSystemUpdate = true;
-        final boolean deleteCodeAndResources;
         if (ps.versionCode < p.mVersionCode) {
-            // Delete code and resources for downgrades
-            deleteCodeAndResources = true;
+            // Delete data for downgrades
             flags &= ~PackageManager.DONT_DELETE_DATA;
         } else {
             // Preserve data by setting flag
-            deleteCodeAndResources = false;
             flags |= PackageManager.DONT_DELETE_DATA;
         }
-        boolean ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo,
+        boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo,
                 writeSettings);
         if (!ret) {
             return false;
@@ -7237,7 +7273,7 @@
                     pw.print("    codePath="); pw.println(ps.codePathString);
                     pw.print("    resourcePath="); pw.println(ps.resourcePathString);
                     pw.print("    nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
-                    pw.print("    obbPath="); pw.println(ps.obbPathString);
+                    pw.print("    obbPaths="); pw.println(Arrays.toString(ps.obbPathStrings));
                     pw.print("    versionCode="); pw.println(ps.versionCode);
                     if (ps.pkg != null) {
                         pw.print("    versionName="); pw.println(ps.pkg.mVersionName);
@@ -7452,6 +7488,12 @@
     static class PackageSignatures {
         private Signature[] mSignatures;
 
+        PackageSignatures(PackageSignatures orig) {
+            if (orig != null && orig.mSignatures != null) {
+                mSignatures = orig.mSignatures.clone();
+            }
+        }
+
         PackageSignatures(Signature[] sigs) {
             assignSignatures(sigs);
         }
@@ -7787,6 +7829,15 @@
             setFlags(pkgFlags);
         }
 
+        GrantedPermissions(GrantedPermissions base) {
+            pkgFlags = base.pkgFlags;
+            grantedPermissions = (HashSet<String>) base.grantedPermissions.clone();
+
+            if (base.gids != null) {
+                gids = base.gids.clone();
+            }
+        }
+
         void setFlags(int pkgFlags) {
             this.pkgFlags = pkgFlags & (
                     ApplicationInfo.FLAG_SYSTEM |
@@ -7807,14 +7858,14 @@
         File resourcePath;
         String resourcePathString;
         String nativeLibraryPathString;
-        String obbPathString;
+        String[] obbPathStrings;
         long timeStamp;
         long firstInstallTime;
         long lastUpdateTime;
         int versionCode;
 
         boolean uidError;
-        
+
         PackageSignatures signatures = new PackageSignatures();
 
         boolean permissionsFixed;
@@ -7840,6 +7891,48 @@
             init(codePath, resourcePath, nativeLibraryPathString, pVersionCode);
         }
 
+        /**
+         * New instance of PackageSetting with one-level-deep cloning.
+         */
+        PackageSettingBase(PackageSettingBase base) {
+            super(base);
+
+            name = base.name;
+            realName = base.realName;
+            codePath = base.codePath;
+            codePathString = base.codePathString;
+            resourcePath = base.resourcePath;
+            resourcePathString = base.resourcePathString;
+            nativeLibraryPathString = base.nativeLibraryPathString;
+
+            if (base.obbPathStrings != null) {
+                obbPathStrings = base.obbPathStrings.clone();
+            }
+
+            timeStamp = base.timeStamp;
+            firstInstallTime = base.firstInstallTime;
+            lastUpdateTime = base.lastUpdateTime;
+            versionCode = base.versionCode;
+
+            uidError = base.uidError;
+
+            signatures = new PackageSignatures(base.signatures);
+
+            permissionsFixed = base.permissionsFixed;
+            haveGids = base.haveGids;
+
+            disabledComponents = (HashSet<String>) base.disabledComponents.clone();
+
+            enabledComponents = (HashSet<String>) base.enabledComponents.clone();
+
+            enabled = base.enabled;
+            installStatus = base.installStatus;
+
+            origPackage = base.origPackage;
+
+            installerPackageName = base.installerPackageName;
+        }
+
         void init(File codePath, File resourcePath, String nativeLibraryPathString,
                 int pVersionCode) {
             this.codePath = codePath;
@@ -7870,6 +7963,9 @@
             timeStamp = newStamp;
         }
 
+        /**
+         * Make a shallow copy of this package settings.
+         */
         public void copyFrom(PackageSettingBase base) {
             grantedPermissions = base.grantedPermissions;
             gids = base.gids;
@@ -7929,6 +8025,18 @@
                     pkgFlags);
         }
 
+        /**
+         * New instance of PackageSetting replicating the original settings.
+         * Note that it keeps the same PackageParser.Package instance.
+         */
+        PackageSetting(PackageSetting orig) {
+            super(orig);
+
+            userId = orig.userId;
+            pkg = orig.pkg;
+            sharedUser = orig.sharedUser;
+        }
+
         @Override
         public String toString() {
             return "PackageSetting{"
@@ -8141,21 +8249,29 @@
             return s;
         }
 
-        int disableSystemPackageLP(String name) {
+        boolean disableSystemPackageLP(String name) {
             PackageSetting p = mPackages.get(name);
             if(p == null) {
                 Log.w(TAG, "Package:"+name+" is not an installed package");
-                return -1;
+                return false;
             }
             PackageSetting dp = mDisabledSysPackages.get(name);
             // always make sure the system package code and resource paths dont change
-            if(dp == null) {
+            if (dp == null) {
                 if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
                     p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
                 }
                 mDisabledSysPackages.put(name, p);
+
+                // a little trick...  when we install the new package, we don't
+                // want to modify the existing PackageSetting for the built-in
+                // version.  so at this point we need a new PackageSetting that
+                // is okay to muck with.
+                PackageSetting newp = new PackageSetting(p);
+                replacePackageLP(name, newp);
+                return true;
             }
-            return removePackageLP(name);
+            return false;
         }
 
         PackageSetting enableSystemPackageLP(String name) {
@@ -8489,6 +8605,19 @@
             return -1;
         }
 
+        private void replacePackageLP(String name, PackageSetting newp) {
+            PackageSetting p = mPackages.get(name);
+            if (p != null) {
+                if (p.sharedUser != null) {
+                    p.sharedUser.packages.remove(p);
+                    p.sharedUser.packages.add(newp);
+                } else {
+                    replaceUserIdLP(p.userId, newp);
+                }
+            }
+            mPackages.put(name, newp);
+        }
+
         private boolean addUserIdLP(int uid, Object obj, Object name) {
             if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) {
                 return false;
@@ -8551,6 +8680,16 @@
             }
         }
 
+        private void replaceUserIdLP(int uid, Object obj) {
+            if (uid >= FIRST_APPLICATION_UID) {
+                int N = mUserIds.size();
+                final int index = uid - FIRST_APPLICATION_UID;
+                if (index < N) mUserIds.set(index, obj);
+            } else {
+                mOtherUserIds.put(uid, obj);
+            }
+        }
+
         void writeLP() {
             //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
 
@@ -8828,8 +8967,15 @@
             if (pkg.installerPackageName != null) {
                 serializer.attribute(null, "installer", pkg.installerPackageName);
             }
-            if (pkg.obbPathString != null) {
-                serializer.attribute(null, "obbPath", pkg.obbPathString);
+            if (pkg.obbPathStrings != null && pkg.obbPathStrings.length > 0) {
+                int N = pkg.obbPathStrings.length;
+                serializer.startTag(null, "obbs");
+                for (int i = 0; i < N; i++) {
+                    serializer.startTag(null, "obb");
+                    serializer.attribute(null, "path", pkg.obbPathStrings[i]);
+                    serializer.endTag(null, "obb");
+                }
+                serializer.endTag(null, "obbs");
             }
             pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
             if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
@@ -9233,7 +9379,6 @@
             String codePathStr = null;
             String resourcePathStr = null;
             String nativeLibraryPathStr = null;
-            String obbPathStr = null;
             String systemStr = null;
             String installerPackageName = null;
             String uidError = null;
@@ -9253,7 +9398,6 @@
                 codePathStr = parser.getAttributeValue(null, "codePath");
                 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
                 nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
-                obbPathStr = parser.getAttributeValue(null, "obbPath");
                 version = parser.getAttributeValue(null, "version");
                 if (version != null) {
                     try {
@@ -9378,7 +9522,6 @@
                 packageSetting.uidError = "true".equals(uidError);
                 packageSetting.installerPackageName = installerPackageName;
                 packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
-                packageSetting.obbPathString = obbPathStr;
                 final String enabledStr = parser.getAttributeValue(null, "enabled");
                 if (enabledStr != null) {
                     if (enabledStr.equalsIgnoreCase("true")) {
@@ -9426,6 +9569,8 @@
                         readGrantedPermissionsLP(parser,
                                 packageSetting.grantedPermissions);
                         packageSetting.permissionsFixed = true;
+                    } else if (tagName.equals("obbs")) {
+                        readObbPathsLP(packageSetting, parser);
                     } else {
                         reportSettingsProblem(Log.WARN,
                                 "Unknown element under <package>: "
@@ -9630,6 +9775,34 @@
             }
         }
 
+        private void readObbPathsLP(PackageSettingBase packageSetting, XmlPullParser parser)
+                throws XmlPullParserException, IOException {
+            final List<String> obbPaths = new ArrayList<String>();
+            final int outerDepth = parser.getDepth();
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                    continue;
+                }
+
+                final String tagName = parser.getName();
+                if (tagName.equals("obb")) {
+                    final String path = parser.getAttributeValue(null, "path");
+                    obbPaths.add(path);
+                } else {
+                    reportSettingsProblem(Log.WARN, "Unknown element under <obbs>: "
+                            + parser.getName());
+                }
+                XmlUtils.skipCurrentTag(parser);
+            }
+            if (obbPaths.size() == 0) {
+                return;
+            } else {
+                packageSetting.obbPathStrings = obbPaths.toArray(new String[obbPaths.size()]);
+            }
+        }
+
         // Returns -1 if we could not find an available UserId to assign
         private int newUserIdLP(Object obj) {
             // Let's be stupidly inefficient for now...
diff --git a/services/java/com/android/server/ScreenRotationAnimation.java b/services/java/com/android/server/ScreenRotationAnimation.java
index ced7c7b..2ad9cbe 100644
--- a/services/java/com/android/server/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/ScreenRotationAnimation.java
@@ -40,6 +40,7 @@
     final Context mContext;
     final Display mDisplay;
     Surface mSurface;
+    Surface mBlackSurface;
     int mWidth, mHeight;
 
     int mSnapshotRotation;
@@ -59,7 +60,8 @@
     final Matrix mSnapshotFinalMatrix = new Matrix();
     final float[] mTmpFloats = new float[9];
 
-    public ScreenRotationAnimation(Context context, Display display, SurfaceSession session) {
+    public ScreenRotationAnimation(Context context, Display display, SurfaceSession session,
+            boolean inTransaction) {
         mContext = context;
         mDisplay = display;
 
@@ -83,47 +85,70 @@
         mOriginalWidth = mDisplayMetrics.widthPixels;
         mOriginalHeight = mDisplayMetrics.heightPixels;
 
-        Surface.openTransaction();
-        if (mSurface != null) {
-            mSurface.destroy();
-            mSurface = null;
+        if (!inTransaction) {
+            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
+                    ">>> OPEN TRANSACTION ScreenRotationAnimation");
+            Surface.openTransaction();
         }
+        
         try {
-            mSurface = new Surface(session, 0, "FreezeSurface",
-                    -1, mWidth, mHeight, PixelFormat.OPAQUE, 0);
-        } catch (Surface.OutOfResourcesException e) {
-            Slog.w(TAG, "Unable to allocate freeze surface", e);
-        }
-        mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 200);
-        setRotation(display.getRotation());
+            try {
+                mSurface = new Surface(session, 0, "FreezeSurface",
+                        -1, mWidth, mHeight, PixelFormat.OPAQUE, 0);
+                mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 200);
+            } catch (Surface.OutOfResourcesException e) {
+                Slog.w(TAG, "Unable to allocate freeze surface", e);
+            }
 
-        Rect dirty = new Rect(0, 0, mWidth, mHeight);
-        Canvas c = null;
-        try {
-            c = mSurface.lockCanvas(dirty);
-        } catch (IllegalArgumentException e) {
-            Slog.w(TAG, "Unable to lock surface", e);
-            return;
-        } catch (Surface.OutOfResourcesException e) {
-            Slog.w(TAG, "Unable to lock surface", e);
-            return;
-        }
-        if (c == null) {
-            Slog.w(TAG, "Null surface");
-            return;
-        }
+            if (false) {
+                try {
+                    int size = mOriginalWidth > mOriginalHeight ? mOriginalWidth : mOriginalHeight;
+                    mBlackSurface = new Surface(session, 0, "BlackSurface",
+                            -1, size, size, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM);
+                    mBlackSurface.setAlpha(1.0f);
+                    mBlackSurface.setLayer(0);
+                } catch (Surface.OutOfResourcesException e) {
+                    Slog.w(TAG, "Unable to allocate black surface", e);
+                }
+            }
 
-        if (screenshot != null) {
-            c.drawBitmap(screenshot, 0, 0, new Paint(0));
-        } else {
-            c.drawColor(Color.GREEN);
-        }
+            setRotation(display.getRotation());
 
-        mSurface.unlockCanvasAndPost(c);
-        Surface.closeTransaction();
+            if (mSurface != null) {
+                Rect dirty = new Rect(0, 0, mWidth, mHeight);
+                Canvas c = null;
+                try {
+                    c = mSurface.lockCanvas(dirty);
+                } catch (IllegalArgumentException e) {
+                    Slog.w(TAG, "Unable to lock surface", e);
+                    return;
+                } catch (Surface.OutOfResourcesException e) {
+                    Slog.w(TAG, "Unable to lock surface", e);
+                    return;
+                }
+                if (c == null) {
+                    Slog.w(TAG, "Null surface");
+                    return;
+                }
+        
+                if (screenshot != null) {
+                    c.drawBitmap(screenshot, 0, 0, new Paint(0));
+                } else {
+                    c.drawColor(Color.GREEN);
+                }
 
-        if (screenshot != null) {
-            screenshot.recycle();
+                mSurface.unlockCanvasAndPost(c);
+            }
+        } finally {
+            if (!inTransaction) {
+                Surface.closeTransaction();
+                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
+                        "<<< CLOSE TRANSACTION ScreenRotationAnimation");
+            }
+    
+            if (screenshot != null) {
+                screenshot.recycle();
+            }
         }
     }
 
@@ -134,21 +159,23 @@
     }
 
     void setSnapshotTransform(Matrix matrix, float alpha) {
-        matrix.getValues(mTmpFloats);
-        mSurface.setPosition((int)mTmpFloats[Matrix.MTRANS_X],
-                (int)mTmpFloats[Matrix.MTRANS_Y]);
-        mSurface.setMatrix(
-                mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
-                mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
-        mSurface.setAlpha(alpha);
-        if (DEBUG) {
-            float[] srcPnts = new float[] { 0, 0, mWidth, mHeight };
-            float[] dstPnts = new float[4];
-            matrix.mapPoints(dstPnts, srcPnts);
-            Slog.i(TAG, "Original  : (" + srcPnts[0] + "," + srcPnts[1]
-                    + ")-(" + srcPnts[2] + "," + srcPnts[3] + ")");
-            Slog.i(TAG, "Transformed: (" + dstPnts[0] + "," + dstPnts[1]
-                    + ")-(" + dstPnts[2] + "," + dstPnts[3] + ")");
+        if (mSurface != null) {
+            matrix.getValues(mTmpFloats);
+            mSurface.setPosition((int)mTmpFloats[Matrix.MTRANS_X],
+                    (int)mTmpFloats[Matrix.MTRANS_Y]);
+            mSurface.setMatrix(
+                    mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
+                    mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
+            mSurface.setAlpha(alpha);
+            if (DEBUG) {
+                float[] srcPnts = new float[] { 0, 0, mWidth, mHeight };
+                float[] dstPnts = new float[4];
+                matrix.mapPoints(dstPnts, srcPnts);
+                Slog.i(TAG, "Original  : (" + srcPnts[0] + "," + srcPnts[1]
+                        + ")-(" + srcPnts[2] + "," + srcPnts[3] + ")");
+                Slog.i(TAG, "Transformed: (" + dstPnts[0] + "," + dstPnts[1]
+                        + ")-(" + dstPnts[2] + "," + dstPnts[3] + ")");
+            }
         }
     }
 
@@ -254,6 +281,10 @@
             mSurface.destroy();
             mSurface = null;
         }
+        if (mBlackSurface != null) {
+            mBlackSurface.destroy();
+            mBlackSurface = null;
+        }
         if (mExitAnimation != null) {
             mExitAnimation.cancel();
             mExitAnimation = null;
@@ -293,6 +324,10 @@
                     mSurface.destroy();
                     mSurface = null;
                 }
+                if (mBlackSurface != null) {
+                    mBlackSurface.destroy();
+                    mBlackSurface = null;
+                }
             }
         }
 
@@ -307,10 +342,8 @@
             }
         }
 
-        if (mSurface != null) {
-            mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
-            setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
-        }
+        mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
+        setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
 
         return moreEnter || moreExit;
     }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 95534e3..6f4b4c5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -481,14 +481,11 @@
         // 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 @@
 
         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/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index e881523..eb14180 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -43,6 +43,7 @@
 import com.android.internal.telephony.IPhoneStateListener;
 import com.android.internal.telephony.DefaultPhoneNotifier;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.server.am.BatteryStatsService;
 
@@ -103,7 +104,7 @@
 
     private int mDataConnectionNetworkType;
 
-    private int mOtaspMode;
+    private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN;
 
     static final int PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
diff --git a/services/java/com/android/server/UsbService.java b/services/java/com/android/server/UsbService.java
index a2bf75d..77ddf3b 100644
--- a/services/java/com/android/server/UsbService.java
+++ b/services/java/com/android/server/UsbService.java
@@ -24,7 +24,6 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.UEventObserver;
-import android.provider.Ptp;
 import android.provider.Settings;
 import android.util.Log;
 import android.util.Slog;
@@ -182,33 +181,8 @@
         }
     }
 
-    private native void monitorUsbHostBus();
-
-    // called from JNI in monitorUsbHostBus()
-    private void usbCameraAdded(int deviceID) {
-        Intent intent = new Intent(UsbManager.ACTION_USB_CAMERA_ATTACHED,
-                                Ptp.Device.getContentUri(deviceID));
-        Log.d(TAG, "usbCameraAdded, sending " + intent);
-        mContext.sendBroadcast(intent);
-    }
-
-    // called from JNI in monitorUsbHostBus()
-    private void usbCameraRemoved(int deviceID) {
-        Intent intent = new Intent(UsbManager.ACTION_USB_CAMERA_DETACHED,
-                                Ptp.Device.getContentUri(deviceID));
-        Log.d(TAG, "usbCameraRemoved, sending " + intent);
-        mContext.sendBroadcast(intent);
-    }
-
     private void initHostSupport() {
-        // Create a thread to call into native code to wait for USB host events.
-        // This thread will call us back on usbCameraAdded and usbCameraRemoved.
-        Runnable runnable = new Runnable() {
-            public void run() {
-                monitorUsbHostBus();
-            }
-        };
-        new Thread(null, runnable, "UsbService host thread").start();
+        // temporarily disabled
     }
 
     void systemReady() {
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 859c85c..997e750 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -587,6 +587,8 @@
                 mIWindowManager.removeWindowToken(mWallpaperConnection.mToken);
             } catch (RemoteException e) {
             }
+            mWallpaperConnection.mService = null;
+            mWallpaperConnection.mEngine = null;
             mWallpaperConnection = null;
         }
     }
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index 1b885f5..2a25c2a 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -425,7 +425,7 @@
             // First collect stack traces from all threads of the system process.
             // Then kill this process so that the system will restart.
 
-            String name = (mCurrentMonitor != null) ?
+            final String name = (mCurrentMonitor != null) ?
                     mCurrentMonitor.getClass().getName() : "null";
             EventLog.writeEvent(EventLogTags.WATCHDOG, name);
 
@@ -434,7 +434,8 @@
             if (mPhonePid > 0) pids.add(mPhonePid);
             // Pass !waitedHalf so that just in case we somehow wind up here without having
             // dumped the halfway stacks, we properly re-initialize the trace file.
-            File stack = ActivityManagerService.dumpStackTraces(!waitedHalf, pids, null, null);
+            final File stack = ActivityManagerService.dumpStackTraces(
+                    !waitedHalf, pids, null, null);
 
             // Give some extra time to make sure the stack traces get written.
             // The system's been hanging for a minute, another second or two won't hurt much.
@@ -445,7 +446,19 @@
                 dumpKernelStackTraces();
             }
 
-            mActivity.addErrorToDropBox("watchdog", null, null, null, name, null, stack, null);
+            // Try to add the error to the dropbox, but assuming that the ActivityManager
+            // itself may be deadlocked.  (which has happened, causing this statement to
+            // deadlock and the watchdog as a whole to be ineffective)
+            Thread dropboxThread = new Thread("watchdogWriteToDropbox") {
+                    public void run() {
+                        mActivity.addErrorToDropBox(
+                                "watchdog", null, null, null, name, null, stack, null);
+                    }
+                };
+            dropboxThread.start();
+            try {
+                dropboxThread.join(2000);  // wait up to 2 seconds for it to return.
+            } catch (InterruptedException ignored) {}
 
             // Only kill the process if the debugger is not attached.
             if (!Debug.isDebuggerConnected()) {
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index ff703fd..1b590ba 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -20,10 +20,7 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothProfile;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -91,7 +88,6 @@
 
     private AlarmManager mAlarmManager;
     private PendingIntent mIdleIntent;
-    private BluetoothA2dp mBluetoothA2dp;
     private static final int IDLE_REQUEST = 0;
     private boolean mScreenOff;
     private boolean mDeviceIdle;
@@ -877,6 +873,7 @@
                 // because of any locks so clear that tracking immediately.
                 reportStartWorkSource();
                 mWifiStateMachine.enableRssiPolling(true);
+                mWifiStateMachine.enableAllNetworks();
                 updateWifiState();
             } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
                 if (DBG) {
@@ -942,10 +939,10 @@
                     mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
                 }
                 mPluggedType = pluggedType;
-            } else if (action.equals(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED)) {
-                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
-                                               BluetoothA2dp.STATE_NOT_PLAYING);
-                mWifiStateMachine.setBluetoothScanMode(state == BluetoothA2dp.STATE_PLAYING);
+            } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
+                int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
+                        BluetoothAdapter.STATE_DISCONNECTED);
+                mWifiStateMachine.sendBluetoothAdapterStateChange(state);
             }
         }
 
@@ -957,8 +954,10 @@
          * @see #shouldDeviceStayAwake(int, int)
          */
         private boolean shouldWifiStayAwake(int stayAwakeConditions, int pluggedType) {
+            //Never sleep when plugged in as long as the user has not changed the settings
             int wifiSleepPolicy = Settings.System.getInt(mContext.getContentResolver(),
-                    Settings.System.WIFI_SLEEP_POLICY, Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
+                    Settings.System.WIFI_SLEEP_POLICY,
+                    Settings.System.WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED);
 
             if (wifiSleepPolicy == Settings.System.WIFI_SLEEP_POLICY_NEVER) {
                 // Never sleep
@@ -1047,7 +1046,7 @@
         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
         intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
         intentFilter.addAction(ACTION_DEVICE_IDLE);
-        intentFilter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED);
+        intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
         mContext.registerReceiver(mReceiver, intentFilter);
     }
 
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index ba7692d..bdc779c 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -149,6 +149,7 @@
         implements Watchdog.Monitor {
     static final String TAG = "WindowManager";
     static final boolean DEBUG = false;
+    static final boolean DEBUG_ADD_REMOVE = false;
     static final boolean DEBUG_FOCUS = false;
     static final boolean DEBUG_ANIM = false;
     static final boolean DEBUG_LAYOUT = false;
@@ -158,13 +159,14 @@
     static final boolean DEBUG_INPUT_METHOD = false;
     static final boolean DEBUG_VISIBILITY = false;
     static final boolean DEBUG_WINDOW_MOVEMENT = false;
+    static final boolean DEBUG_TOKEN_MOVEMENT = false;
     static final boolean DEBUG_ORIENTATION = false;
     static final boolean DEBUG_CONFIGURATION = false;
     static final boolean DEBUG_APP_TRANSITIONS = false;
     static final boolean DEBUG_STARTING_WINDOW = false;
     static final boolean DEBUG_REORDER = false;
     static final boolean DEBUG_WALLPAPER = false;
-    static final boolean DEBUG_DRAG = true;
+    static final boolean DEBUG_DRAG = false;
     static final boolean SHOW_TRANSACTIONS = false;
     static final boolean HIDE_STACK_CRAWLS = true;
 
@@ -210,6 +212,10 @@
     // 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;
@@ -296,12 +302,6 @@
             new HashMap<IBinder, WindowToken>();
 
     /**
-     * The same tokens as mTokenMap, stored in a list for efficient iteration
-     * over them.
-     */
-    final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>();
-
-    /**
      * Window tokens that are in the process of exiting, but still
      * on screen for animations.
      */
@@ -310,7 +310,7 @@
     /**
      * Z-ordered (bottom-most first) list of all application tokens, for
      * controlling the ordering of windows in different applications.  This
-     * contains WindowToken objects.
+     * contains AppWindowToken objects.
      */
     final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
 
@@ -344,6 +344,11 @@
     final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
 
     /**
+     * Used when processing mPendingRemove to avoid working on the original array.
+     */
+    WindowState[] mPendingRemoveTmp = new WindowState[20];
+
+    /**
      * Windows whose surface should be destroyed.
      */
     final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
@@ -360,6 +365,12 @@
      */
     ArrayList<WindowState> mForceRemoves;
 
+    /**
+     * Used when rebuilding window list to keep track of windows that have
+     * been removed.
+     */
+    WindowState[] mRebuildTmp = new WindowState[20];
+
     IInputMethodManager mInputMethodManager;
 
     SurfaceSession mFxSession;
@@ -435,7 +446,6 @@
     // This just indicates the window the input method is on top of, not
     // necessarily the window its input is going to.
     WindowState mInputMethodTarget = null;
-    WindowState mUpcomingInputMethodTarget = null;
     boolean mInputMethodTargetWaitingAnim;
     int mInputMethodAnimLayerAdjustment;
 
@@ -494,7 +504,7 @@
     class DragState {
         IBinder mToken;
         Surface mSurface;
-        boolean mLocalOnly;
+        int mFlags;
         IBinder mLocalWin;
         ClipData mData;
         ClipDescription mDataDescription;
@@ -506,12 +516,16 @@
         ArrayList<WindowState> mNotifiedWindows;
         boolean mDragInProgress;
 
+        boolean mPerformDeferredRotation;
+        int mRotation;
+        int mAnimFlags;
+
         private final Rect tmpRect = new Rect();
 
-        DragState(IBinder token, Surface surface, boolean localOnly, IBinder localWin) {
+        DragState(IBinder token, Surface surface, int flags, IBinder localWin) {
             mToken = token;
             mSurface = surface;
-            mLocalOnly = localOnly;
+            mFlags = flags;
             mLocalWin = localWin;
             mNotifiedWindows = new ArrayList<WindowState>();
         }
@@ -521,12 +535,13 @@
                 mSurface.destroy();
             }
             mSurface = null;
-            mLocalOnly = false;
+            mFlags = 0;
             mLocalWin = null;
             mToken = null;
             mData = null;
             mThumbOffsetX = mThumbOffsetY = 0;
             mNotifiedWindows = null;
+            mPerformDeferredRotation = false;
         }
 
         void register() {
@@ -537,7 +552,7 @@
                 InputChannel[] channels = InputChannel.openInputChannelPair("drag");
                 mServerChannel = channels[0];
                 mClientChannel = channels[1];
-                mInputManager.registerInputChannel(mServerChannel);
+                mInputManager.registerInputChannel(mServerChannel, null);
                 InputQueue.registerInputChannel(mClientChannel, mDragInputHandler,
                         mH.getLooper().getQueue());
             }
@@ -594,7 +609,7 @@
                 ClipDescription desc) {
             // Don't actually send the event if the drag is supposed to be pinned
             // to the originating window but 'newWin' is not that window.
-            if (mLocalOnly) {
+            if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
                 final IBinder winBinder = newWin.mClient.asBinder();
                 if (winBinder != mLocalWin) {
                     if (DEBUG_DRAG) {
@@ -667,22 +682,43 @@
             mDragState.unregister();
             mInputMonitor.updateInputWindowsLw();
 
+            // Retain the parameters of any deferred rotation operation so
+            // that we can perform it after the reset / unref of the drag state
+            final boolean performRotation = mPerformDeferredRotation;
+            final int rotation = mRotation;
+            final int animFlags = mAnimFlags;
+
             // free our resources and drop all the object references
             mDragState.reset();
             mDragState = null;
+
+            // Now that we've officially ended the drag, execute any
+            // deferred rotation
+            if (performRotation) {
+                if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-drag rotation");
+                boolean changed = setRotationUncheckedLocked(rotation, animFlags, false);
+                if (changed) {
+                    sendNewConfiguration();
+                }
+            }
         }
 
         void notifyMoveLw(float x, float y) {
             final int myPid = Process.myPid();
 
             // Move the surface to the given touch
+            if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION notifyMoveLw");
             mSurface.openTransaction();
-            mSurface.setPosition((int)(x - mThumbOffsetX), (int)(y - mThumbOffsetY));
-            mSurface.closeTransaction();
+            try {
+                mSurface.setPosition((int)(x - mThumbOffsetX), (int)(y - mThumbOffsetY));
+            } finally {
+                mSurface.closeTransaction();
+                if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION notifyMoveLw");
+            }
 
             // Tell the affected window
             WindowState touchedWin = getTouchedWinAtPointLw(x, y);
-            if (mLocalOnly) {
+            if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
                 final IBinder touchedBinder = touchedWin.mClient.asBinder();
                 if (touchedBinder != mLocalWin) {
                     // This drag is pinned only to the originating window, but the drag
@@ -813,6 +849,12 @@
 
             return touchedWin;
         }
+
+        void setDeferredRotation(int rotation, int animFlags) {
+            mRotation = rotation;
+            mAnimFlags = animFlags;
+            mPerformDeferredRotation = true;
+        }
     }
 
     DragState mDragState = null;
@@ -1063,7 +1105,7 @@
 
     private void placeWindowAfter(WindowState pos, WindowState window) {
         final int i = mWindows.indexOf(pos);
-        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
+        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
             TAG, "Adding window " + window + " at "
             + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
         mWindows.add(i+1, window);
@@ -1072,7 +1114,7 @@
 
     private void placeWindowBefore(WindowState pos, WindowState window) {
         final int i = mWindows.indexOf(pos);
-        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
+        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
             TAG, "Adding window " + window + " at "
             + i + " of " + mWindows.size() + " (before " + pos + ")");
         mWindows.add(i, window);
@@ -1130,9 +1172,10 @@
                                 //apptoken note that the window could be a floating window
                                 //that was created later or a window at the top of the list of
                                 //windows associated with this token.
-                                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
-                                        TAG, "Adding window " + win + " at "
-                                        + (newIdx+1) + " of " + N);
+                                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
+                                    Slog.v(TAG, "Adding window " + win + " at "
+                                            + (newIdx+1) + " of " + N);
+                                }
                                 localmWindows.add(newIdx+1, win);
                                 mWindowsChanged = true;
                             }
@@ -1211,9 +1254,10 @@
                                     break;
                                 }
                             }
-                            if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
-                                    TAG, "Adding window " + win + " at "
-                                    + i + " of " + N);
+                            if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
+                                Slog.v(TAG, "Adding window " + win + " at "
+                                        + i + " of " + N);
+                            }
                             localmWindows.add(i, win);
                             mWindowsChanged = true;
                         }
@@ -1229,13 +1273,14 @@
                     }
                 }
                 if (i < 0) i = 0;
-                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
+                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
                         TAG, "Adding window " + win + " at "
                         + i + " of " + N);
                 localmWindows.add(i, win);
                 mWindowsChanged = true;
             }
             if (addToToken) {
+                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
                 token.windows.add(tokenWindowsPos, win);
             }
 
@@ -1258,6 +1303,7 @@
                     // in the same sublayer.
                     if (wSublayer >= sublayer) {
                         if (addToToken) {
+                            if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
                             token.windows.add(i, win);
                         }
                         placeWindowBefore(
@@ -1269,6 +1315,7 @@
                     // in the same sublayer.
                     if (wSublayer > sublayer) {
                         if (addToToken) {
+                            if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
                             token.windows.add(i, win);
                         }
                         placeWindowBefore(w, win);
@@ -1278,6 +1325,7 @@
             }
             if (i >= NA) {
                 if (addToToken) {
+                    if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
                     token.windows.add(win);
                 }
                 if (sublayer < 0) {
@@ -1337,7 +1385,20 @@
             }
         }
 
-        mUpcomingInputMethodTarget = w;
+        // Now, a special case -- if the last target's window is in the
+        // process of exiting, and is above the new target, keep on the
+        // last target to avoid flicker.  Consider for example a Dialog with
+        // the IME shown: when the Dialog is dismissed, we want to keep
+        // the IME above it until it is completely gone so it doesn't drop
+        // behind the dialog or its full-screen scrim.
+        if (mInputMethodTarget != null && w != null
+                && mInputMethodTarget.isDisplayedLw()
+                && mInputMethodTarget.mExiting) {
+            if (mInputMethodTarget.mAnimLayer > w.mAnimLayer) {
+                w = mInputMethodTarget;
+                i = localmWindows.indexOf(w);
+            }
+        }
 
         if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
                 + w + " willMove=" + willMove);
@@ -1439,7 +1500,7 @@
         int pos = findDesiredInputMethodWindowIndexLocked(true);
         if (pos >= 0) {
             win.mTargetAppToken = mInputMethodTarget.mAppToken;
-            if (DEBUG_WINDOW_MOVEMENT) Slog.v(
+            if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
                     TAG, "Adding input method window " + win + " at " + pos);
             mWindows.add(pos, win);
             mWindowsChanged = true;
@@ -1626,7 +1687,7 @@
                 }
                 imPos = tmpRemoveWindowLocked(imPos, imWin);
                 if (DEBUG_INPUT_METHOD) {
-                    Slog.v(TAG, "List after moving with new pos " + imPos + ":");
+                    Slog.v(TAG, "List after removing with new pos " + imPos + ":");
                     logWindowList("  ");
                 }
                 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
@@ -1989,9 +2050,10 @@
                 }
 
                 // Now stick it in.
-                if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
-                        "Moving wallpaper " + wallpaper
-                        + " from " + oldIndex + " to " + foundI);
+                if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
+                    Slog.v(TAG, "Moving wallpaper " + wallpaper
+                            + " from " + oldIndex + " to " + foundI);
+                }
 
                 localmWindows.add(foundI, wallpaper);
                 mWindowsChanged = true;
@@ -2299,7 +2361,7 @@
                 win.mInputChannel = inputChannels[0];
                 inputChannels[1].transferToBinderOutParameter(outInputChannel);
                 
-                mInputManager.registerInputChannel(win.mInputChannel);
+                mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
             }
 
             // From now on, no exceptions or errors allowed!
@@ -2310,7 +2372,6 @@
 
             if (addToken) {
                 mTokenMap.put(attrs.token, token);
-                mTokenList.add(token);
             }
             win.attach();
             mWindowMap.put(client.asBinder(), win);
@@ -2378,7 +2439,7 @@
                 TAG, "New client " + client.asBinder()
                 + ": window=" + win);
             
-            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked()) {
+            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
                 reportNewConfig = true;
             }
         }
@@ -2465,7 +2526,7 @@
         // So just update orientation if needed.
         if (wasVisible && computeForcedAppOrientationLocked()
                 != mForcedAppOrientation
-                && updateOrientationFromAppTokensLocked()) {
+                && updateOrientationFromAppTokensLocked(false)) {
             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
         }
         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
@@ -2473,6 +2534,18 @@
     }
 
     private void removeWindowInnerLocked(Session session, WindowState win) {
+        if (win.mRemoved) {
+            // Nothing to do.
+            return;
+        }
+
+        for (int i=win.mChildWindows.size()-1; i>=0; i--) {
+            WindowState cwin = win.mChildWindows.get(i);
+            Slog.w(TAG, "Force-removing child win " + cwin + " from container "
+                    + win);
+            removeWindowInnerLocked(cwin.mSession, cwin);
+        }
+
         win.mRemoved = true;
 
         if (mInputMethodTarget == win) {
@@ -2488,8 +2561,10 @@
         mPolicy.removeWindowLw(win);
         win.removeLocked();
 
+        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
         mWindowMap.remove(win.mClient.asBinder());
         mWindows.remove(win);
+        mPendingRemove.remove(win);
         mWindowsChanged = true;
         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
 
@@ -2501,6 +2576,7 @@
 
         final WindowToken token = win.mToken;
         final AppWindowToken atoken = win.mAppToken;
+        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token);
         token.windows.remove(win);
         if (atoken != null) {
             atoken.allAppWindows.remove(win);
@@ -2511,7 +2587,6 @@
         if (token.windows.size() == 0) {
             if (!token.explicit) {
                 mTokenMap.remove(token.token);
-                mTokenList.remove(token);
             } else if (atoken != null) {
                 atoken.firstWindowDrawn = false;
             }
@@ -2571,15 +2646,17 @@
             synchronized (mWindowMap) {
                 WindowState w = windowForClientLocked(session, client, false);
                 if ((w != null) && (w.mSurface != null)) {
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
+                    if (SHOW_TRANSACTIONS) Slog.i(TAG,
+                            ">>> OPEN TRANSACTION setTransparentRegion");
                     Surface.openTransaction();
                     try {
                         if (SHOW_TRANSACTIONS) logSurface(w,
                                 "transparentRegionHint=" + region, null);
                         w.mSurface.setTransparentRegionHint(region);
                     } finally {
-                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
                         Surface.closeTransaction();
+                        if (SHOW_TRANSACTIONS) Slog.i(TAG,
+                                "<<< CLOSE TRANSACTION setTransparentRegion");
                     }
                 }
             }
@@ -2917,7 +2994,7 @@
             if (assignLayers) {
                 assignLayersLocked();
             }
-            configChanged = updateOrientationFromAppTokensLocked();
+            configChanged = updateOrientationFromAppTokensLocked(false);
             performLayoutAndPlaceSurfacesLocked();
             if (displayed && win.mIsWallpaper) {
                 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
@@ -3274,7 +3351,6 @@
             }
             wtoken = new WindowToken(token, type, true);
             mTokenMap.put(token, wtoken);
-            mTokenList.add(wtoken);
             if (type == TYPE_WALLPAPER) {
                 mWallpaperTokens.add(wtoken);
             }
@@ -3290,7 +3366,6 @@
         final long origId = Binder.clearCallingIdentity();
         synchronized(mWindowMap) {
             WindowToken wtoken = mTokenMap.remove(token);
-            mTokenList.remove(wtoken);
             if (wtoken != null) {
                 boolean delayed = false;
                 if (!wtoken.hidden) {
@@ -3366,10 +3441,9 @@
             wtoken.groupId = groupId;
             wtoken.appFullscreen = fullscreen;
             wtoken.requestedOrientation = requestedOrientation;
+            if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + wtoken);
             mAppTokens.add(addPos, wtoken);
-            if (localLOGV) Slog.v(TAG, "Adding new app token: " + wtoken);
             mTokenMap.put(token.asBinder(), wtoken);
-            mTokenList.add(wtoken);
 
             // Application tokens start out hidden.
             wtoken.hidden = true;
@@ -3486,7 +3560,7 @@
         long ident = Binder.clearCallingIdentity();
         
         synchronized(mWindowMap) {
-            if (updateOrientationFromAppTokensLocked()) {
+            if (updateOrientationFromAppTokensLocked(false)) {
                 if (freezeThisOneIfNeeded != null) {
                     AppWindowToken wtoken = findAppWindowToken(
                             freezeThisOneIfNeeded);
@@ -3508,7 +3582,7 @@
                     if (currentConfig.diff(mTempConfiguration) != 0) {
                         mWaitingForConfig = true;
                         mLayoutNeeded = true;
-                        startFreezingDisplayLocked();
+                        startFreezingDisplayLocked(false);
                         config = new Configuration(mTempConfiguration);
                     }
                 }
@@ -3533,8 +3607,8 @@
      * @see android.view.IWindowManager#updateOrientationFromAppTokens(
      * android.os.IBinder)
      */
-    boolean updateOrientationFromAppTokensLocked() {
-        if (mDisplayFrozen) {
+    boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
+        if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
             // If the display is frozen, some activities may be in the middle
             // of restarting, and thus have removed their old window.  If the
             // window has the flag to hide the lock screen, then the lock screen
@@ -3554,7 +3628,8 @@
                 //action like disabling/enabling sensors etc.,
                 mPolicy.setCurrentOrientationLw(req);
                 if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION,
-                        mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE)) {
+                        mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE,
+                        inTransaction)) {
                     changed = true;
                 }
             }
@@ -3780,10 +3855,12 @@
                         startingWindow.mToken = wtoken;
                         startingWindow.mRootToken = wtoken;
                         startingWindow.mAppToken = wtoken;
-                        if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
+                        if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
                                 "Removing starting window: " + startingWindow);
                         mWindows.remove(startingWindow);
                         mWindowsChanged = true;
+                        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing starting " + startingWindow
+                                + " from " + ttoken);
                         ttoken.windows.remove(startingWindow);
                         ttoken.allAppWindows.remove(startingWindow);
                         addWindowToListInOrderLocked(startingWindow, true);
@@ -4129,7 +4206,7 @@
                 wtoken.freezingScreen = true;
                 mAppsFreezingScreen++;
                 if (mAppsFreezingScreen == 1) {
-                    startFreezingDisplayLocked();
+                    startFreezingDisplayLocked(false);
                     mH.removeMessages(H.APP_FREEZE_TIMEOUT);
                     mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
                             5000);
@@ -4198,7 +4275,6 @@
         final long origId = Binder.clearCallingIdentity();
         synchronized(mWindowMap) {
             WindowToken basewtoken = mTokenMap.remove(token);
-            mTokenList.remove(basewtoken);
             if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
                 delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_UNSET, true);
@@ -4218,6 +4294,8 @@
                         + " animating=" + wtoken.animating);
                 if (delayed) {
                     // set the token aside because it has an active animation to be finished
+                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                            "removeAppToken make exiting: " + wtoken);
                     mExitingAppTokens.add(wtoken);
                 } else {
                     // Make sure there is no animation running on this token,
@@ -4226,6 +4304,8 @@
                     wtoken.animation = null;
                     wtoken.animating = false;
                 }
+                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                        "removeAppToken: " + wtoken);
                 mAppTokens.remove(wtoken);
                 wtoken.removed = true;
                 if (wtoken.startingData != null) {
@@ -4352,18 +4432,21 @@
             if (!added && cwin.mSubLayer >= 0) {
                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
                         + index + ": " + cwin);
+                win.mRebuilding = false;
                 mWindows.add(index, win);
                 index++;
                 added = true;
             }
             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
                     + index + ": " + cwin);
+            cwin.mRebuilding = false;
             mWindows.add(index, cwin);
             index++;
         }
         if (!added) {
             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
                     + index + ": " + win);
+            win.mRebuilding = false;
             mWindows.add(index, win);
             index++;
         }
@@ -4389,6 +4472,9 @@
             if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:");
             if (DEBUG_REORDER) dumpAppTokensLocked();
             final AppWindowToken wtoken = findAppWindowToken(token);
+            if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG,
+                    "Start moving token " + wtoken + " initially at "
+                    + mAppTokens.indexOf(wtoken));
             if (wtoken == null || !mAppTokens.remove(wtoken)) {
                 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
                       + token + " (" + wtoken + ")");
@@ -4396,6 +4482,7 @@
             }
             mAppTokens.add(index, wtoken);
             if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":");
+            else if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "Moved " + token + " to " + index);
             if (DEBUG_REORDER) dumpAppTokensLocked();
 
             final long origId = Binder.clearCallingIdentity();
@@ -4423,6 +4510,8 @@
         for (int i=0; i<N; i++) {
             IBinder token = tokens.get(i);
             final AppWindowToken wtoken = findAppWindowToken(token);
+            if (DEBUG_REORDER || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                    "Temporarily removing " + wtoken + " from " + mAppTokens.indexOf(wtoken));
             if (!mAppTokens.remove(wtoken)) {
                 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
                       + token + " (" + wtoken + ")");
@@ -4496,6 +4585,8 @@
             for (int i=0; i<N; i++) {
                 AppWindowToken wt = findAppWindowToken(tokens.get(i));
                 if (wt != null) {
+                    if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG,
+                            "Adding next to top: " + wt);
                     mAppTokens.add(wt);
                     if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
                         mToTopApps.remove(wt);
@@ -4528,6 +4619,8 @@
             for (int i=0; i<N; i++) {
                 AppWindowToken wt = findAppWindowToken(tokens.get(i));
                 if (wt != null) {
+                    if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                            "Adding next to bottom: " + wt + " at " + pos);
                     mAppTokens.add(pos, wt);
                     if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
                         mToTopApps.remove(wt);
@@ -4895,12 +4988,17 @@
                 }
             }
 
+            if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION showStrictModeViolation");
             Surface.openTransaction();
-            if (mStrictModeFlash == null) {
-                mStrictModeFlash = new StrictModeFlash(mDisplay, mFxSession);
+            try {
+                if (mStrictModeFlash == null) {
+                    mStrictModeFlash = new StrictModeFlash(mDisplay, mFxSession);
+                }
+                mStrictModeFlash.setVisibility(on);
+            } finally {
+                Surface.closeTransaction();
+                if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION showStrictModeViolation");
             }
-            mStrictModeFlash.setVisibility(on);
-            Surface.closeTransaction();
         }
     }
 
@@ -4958,7 +5056,7 @@
             }
             Binder.restoreCallingIdentity(ident);
 
-            if (frame.isEmpty()) {
+            if (frame.isEmpty() || maxLayer == 0) {
                 return null;
             }
 
@@ -4990,6 +5088,12 @@
             rawss = Surface.screenshot(dw, dh, 0, maxLayer);
         }
 
+        if (rawss == null) {
+            Log.w(TAG, "Failure taking screenshot for (" + dw + "x" + dh
+                    + ") to layer " + maxLayer);
+            return null;
+        }
+        
         Bitmap bm = Bitmap.createBitmap(sw, sh, rawss.getConfig());
         Matrix matrix = new Matrix();
         ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
@@ -5039,7 +5143,7 @@
         long origId = Binder.clearCallingIdentity();
         boolean changed;
         synchronized(mWindowMap) {
-            changed = setRotationUncheckedLocked(rotation, animFlags);
+            changed = setRotationUncheckedLocked(rotation, animFlags, false);
         }
 
         if (changed || alwaysSendConfiguration) {
@@ -5057,7 +5161,15 @@
      * Returns null if the rotation has been changed.  In this case YOU
      * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN.
      */
-    public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
+    public boolean setRotationUncheckedLocked(int rotation, int animFlags, boolean inTransaction) {
+        if (mDragState != null) {
+            // Potential rotation during a drag.  Don't do the rotation now, but make
+            // a note to perform the rotation later.
+            if (DEBUG_ORIENTATION) Slog.v(TAG, "Deferring rotation during drag");
+            mDragState.setDeferredRotation(rotation, animFlags);
+            return false;
+        }
+
         boolean changed;
         if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
             rotation = mRequestedRotation;
@@ -5084,17 +5196,28 @@
                     2000);
             mWaitingForConfig = true;
             mLayoutNeeded = true;
-            startFreezingDisplayLocked();
+            startFreezingDisplayLocked(inTransaction);
             Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
             mInputManager.setDisplayOrientation(0, rotation);
             if (mDisplayEnabled) {
                 if (CUSTOM_SCREEN_ROTATION) {
                     Surface.freezeDisplay(0);
-                    Surface.openTransaction();
-                    if (mScreenRotationAnimation != null) {
-                        mScreenRotationAnimation.setRotation(rotation);
+                    if (!inTransaction) {
+                        if (SHOW_TRANSACTIONS) Slog.i(TAG,
+                                ">>> OPEN TRANSACTION setRotationUnchecked");
+                        Surface.openTransaction();
                     }
-                    Surface.closeTransaction();
+                    try {
+                        if (mScreenRotationAnimation != null) {
+                            mScreenRotationAnimation.setRotation(rotation);
+                        }
+                    } finally {
+                        if (!inTransaction) {
+                            Surface.closeTransaction();
+                            if (SHOW_TRANSACTIONS) Slog.i(TAG,
+                                    "<<< CLOSE TRANSACTION setRotationUnchecked");
+                        }
+                    }
                     Surface.setOrientation(0, rotation, animFlags);
                     Surface.unfreezeDisplay(0);
                 } else {
@@ -5513,7 +5636,13 @@
 
     public Configuration computeNewConfiguration() {
         synchronized (mWindowMap) {
-            return computeNewConfigurationLocked();
+            Configuration config = computeNewConfigurationLocked();
+            if (config == null && mWaitingForConfig) {
+                // Nothing changed but we are waiting for something... stop that!
+                mWaitingForConfig = false;
+                performLayoutAndPlaceSurfacesLocked();
+            }
+            return config;
         }
     }
 
@@ -5615,10 +5744,10 @@
     // -------------------------------------------------------------
 
     IBinder prepareDragSurface(IWindow window, SurfaceSession session,
-            boolean localOnly, int width, int height, Surface outSurface) {
+            int flags, int width, int height, Surface outSurface) {
         if (DEBUG_DRAG) {
             Slog.d(TAG, "prepare drag surface: w=" + width + " h=" + height
-                    + " local=" + localOnly + " win=" + window
+                    + " flags=" + Integer.toHexString(flags) + " win=" + window
                     + " asbinder=" + window.asBinder());
         }
 
@@ -5629,17 +5758,15 @@
         try {
             synchronized (mWindowMap) {
                 try {
-                    // !!! TODO: fail if the given window does not currently have touch focus?
-
                     if (mDragState == null) {
                         Surface surface = new Surface(session, callerPid, "drag surface", 0,
                                 width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
                         outSurface.copyFrom(surface);
                         final IBinder winBinder = window.asBinder();
                         token = new Binder();
-                        mDragState = new DragState(token, surface, localOnly, winBinder);
+                        // TODO: preserve flags param in DragState
+                        mDragState = new DragState(token, surface, 0, winBinder);
                         mDragState.mSurface = surface;
-                        mDragState.mLocalOnly = localOnly;
                         token = mDragState.mToken = new Binder();
 
                         // 5 second timeout for this window to actually begin the drag
@@ -5689,17 +5816,22 @@
         // 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.
          */
-        public void notifyInputChannelBroken(InputChannel inputChannel) {
+        public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+            if (inputWindowHandle == null) {
+                return;
+            }
+
             synchronized (mWindowMap) {
-                WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
-                if (windowState == null) {
-                    return; // irrelevant
-                }
-                
+                WindowState windowState = (WindowState) inputWindowHandle.windowState;
                 Slog.i(TAG, "WINDOW DIED " + windowState);
                 removeWindowLocked(windowState.mSession, windowState);
             }
@@ -5710,11 +5842,12 @@
          * 
          * Called by the InputManager.
          */
-        public long notifyANR(Object token, InputChannel inputChannel) {
+        public long notifyANR(InputApplicationHandle inputApplicationHandle,
+                InputWindowHandle inputWindowHandle) {
             AppWindowToken appWindowToken = null;
-            if (inputChannel != null) {
+            if (inputWindowHandle != null) {
                 synchronized (mWindowMap) {
-                    WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
+                    WindowState windowState = (WindowState) inputWindowHandle.windowState;
                     if (windowState != null) {
                         Slog.i(TAG, "Input event dispatching timed out sending to "
                                 + windowState.mAttrs.getTitle());
@@ -5723,8 +5856,8 @@
                 }
             }
             
-            if (appWindowToken == null && token != null) {
-                appWindowToken = (AppWindowToken) token;
+            if (appWindowToken == null && inputApplicationHandle != null) {
+                appWindowToken = inputApplicationHandle.appWindowToken;
                 Slog.i(TAG, "Input event dispatching timed out sending to application "
                         + appWindowToken.stringName);
             }
@@ -5744,24 +5877,6 @@
             }
             return 0; // abort dispatching
         }
-        
-        private WindowState getWindowStateForInputChannel(InputChannel inputChannel) {
-            synchronized (mWindowMap) {
-                return getWindowStateForInputChannelLocked(inputChannel);
-            }
-        }
-        
-        private WindowState getWindowStateForInputChannelLocked(InputChannel inputChannel) {
-            int windowCount = mWindows.size();
-            for (int i = 0; i < windowCount; i++) {
-                WindowState windowState = mWindows.get(i);
-                if (windowState.mInputChannel == inputChannel) {
-                    return windowState;
-                }
-            }
-            
-            return null;
-        }
 
         private void addDragInputWindowLw(InputWindowList windowList) {
             final InputWindow inputWindow = windowList.add();
@@ -5838,6 +5953,7 @@
 
                 // Add a window to our list of input windows.
                 final InputWindow inputWindow = mTempInputWindows.add();
+                inputWindow.inputWindowHandle = child.mInputWindowHandle;
                 inputWindow.inputChannel = child.mInputChannel;
                 inputWindow.name = child.toString();
                 inputWindow.layoutParamsFlags = flags;
@@ -5900,7 +6016,32 @@
             // 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);
@@ -5916,16 +6057,16 @@
         /* Provides an opportunity for the window manager policy to process a key before
          * ordinary dispatch. */
         public boolean interceptKeyBeforeDispatching(
-                InputChannel focus, KeyEvent event, int policyFlags) {
-            WindowState windowState = getWindowStateForInputChannel(focus);
+                InputWindowHandle focus, KeyEvent event, int policyFlags) {
+            WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
             return mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
         }
         
         /* Provides an opportunity for the window manager policy to process a key that
          * the application did not handle. */
         public KeyEvent dispatchUnhandledKey(
-                InputChannel focus, KeyEvent event, int policyFlags) {
-            WindowState windowState = getWindowStateForInputChannel(focus);
+                InputWindowHandle focus, KeyEvent event, int policyFlags) {
+            WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
             return mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
         }
         
@@ -5955,12 +6096,14 @@
             if (newApp == null) {
                 mInputManager.setFocusedApplication(null);
             } else {
+                mTempInputApplication.inputApplicationHandle = newApp.mInputApplicationHandle;
                 mTempInputApplication.name = newApp.toString();
                 mTempInputApplication.dispatchingTimeoutNanos =
                         newApp.inputDispatchingTimeoutNanos;
-                mTempInputApplication.token = newApp;
-                
+
                 mInputManager.setFocusedApplication(mTempInputApplication);
+
+                mTempInputApplication.recycle();
             }
         }
         
@@ -6220,6 +6363,13 @@
     }
 
     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;
     }
@@ -6233,7 +6383,8 @@
             mDisplay = wm.getDefaultDisplay();
             mInitialDisplayWidth = mDisplay.getWidth();
             mInitialDisplayHeight = mDisplay.getHeight();
-            mInputManager.setDisplaySize(0, mInitialDisplayWidth, mInitialDisplayHeight);
+            mInputManager.setDisplaySize(0, Display.unmapDisplaySize(mInitialDisplayWidth),
+                    Display.unmapDisplaySize(mInitialDisplayHeight));
         }
 
         try {
@@ -6407,9 +6558,9 @@
         }
 
         /* Drag/drop */
-        public IBinder prepareDrag(IWindow window, boolean localOnly,
+        public IBinder prepareDrag(IWindow window, int flags,
                 int width, int height, Surface outSurface) {
-            return prepareDragSurface(window, mSurfaceSession, localOnly,
+            return prepareDragSurface(window, mSurfaceSession, flags,
                     width, height, outSurface);
         }
 
@@ -6471,6 +6622,7 @@
 
                 // Make the surface visible at the proper location
                 final Surface surface = mDragState.mSurface;
+                if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION performDrag");
                 Surface.openTransaction();
                 try {
                     surface.setPosition((int)(touchX - thumbCenterX),
@@ -6480,6 +6632,7 @@
                     surface.show();
                 } finally {
                     Surface.closeTransaction();
+                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performDrag");
                 }
             }
 
@@ -6493,24 +6646,28 @@
             }
 
             synchronized (mWindowMap) {
-                if (mDragState.mToken != token) {
-                    Slog.w(TAG, "Invalid drop-result claim by " + window);
-                    throw new IllegalStateException("reportDropResult() by non-recipient");
+                long ident = Binder.clearCallingIdentity();
+                try {
+                    if (mDragState.mToken != token) {
+                        Slog.w(TAG, "Invalid drop-result claim by " + window);
+                        throw new IllegalStateException("reportDropResult() by non-recipient");
+                    }
+
+                    // The right window has responded, even if it's no longer around,
+                    // so be sure to halt the timeout even if the later WindowState
+                    // lookup fails.
+                    mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());
+                    WindowState callingWin = windowForClientLocked(null, window, false);
+                    if (callingWin == null) {
+                        Slog.w(TAG, "Bad result-reporting window " + window);
+                        return;  // !!! TODO: throw here?
+                    }
+
+                    mDragState.mDragResult = consumed;
+                    mDragState.endDragLw();
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
                 }
-
-                // The right window has responded, even if it's no longer around,
-                // so be sure to halt the timeout even if the later WindowState
-                // lookup fails.
-                mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());
-
-                WindowState callingWin = windowForClientLocked(null, window, false);
-                if (callingWin == null) {
-                    Slog.w(TAG, "Bad result-reporting window " + window);
-                    return;  // !!! TODO: throw here?
-                }
-
-                mDragState.mDragResult = consumed;
-                mDragState.endDragLw();
             }
         }
 
@@ -6798,15 +6955,25 @@
         // Is this window now (or just being) removed?
         boolean mRemoved;
 
+        // Temp for keeping track of windows that have been removed when
+        // rebuilding window list.
+        boolean mRebuilding;
+
         // For debugging, this is the last information given to the surface flinger.
         boolean mSurfaceShown;
         int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
         int mSurfaceLayer;
         float mSurfaceAlpha;
         
-        // Input channel
+        // Input channel and input window handle used by the input dispatcher.
+        InputWindowHandle mInputWindowHandle;
         InputChannel mInputChannel;
         
+        // Used to improve performance of toString()
+        String mStringNameCache;
+        CharSequence mLastTitle;
+        boolean mWasPaused;
+
         WindowState(Session s, IWindow c, WindowToken token,
                WindowState attachedWindow, WindowManager.LayoutParams a,
                int viewVisibility) {
@@ -6844,6 +7011,7 @@
                         + TYPE_LAYER_OFFSET;
                 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
                 mAttachedWindow = attachedWindow;
+                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow);
                 mAttachedWindow.mChildWindows.add(this);
                 mLayoutAttached = mAttrs.type !=
                         WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -6891,6 +7059,8 @@
             mLayer = 0;
             mAnimLayer = 0;
             mLastLayer = 0;
+            mInputWindowHandle = new InputWindowHandle(
+                    mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
         }
 
         void attach() {
@@ -7147,9 +7317,8 @@
                     + ", set left=" + mFrame.left + " top=" + mFrame.top
                     + ", animLayer=" + mAnimLayer);
                 if (SHOW_TRANSACTIONS) {
-                    Slog.i(TAG, ">>> OPEN TRANSACTION");
-                    if (SHOW_TRANSACTIONS) logSurface(this,
-                            "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
+                    Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
+                    logSurface(this, "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
                             mFrame.width() + "x" + mFrame.height() + "), layer=" +
                             mAnimLayer + " HIDE", null);
                 }
@@ -7174,8 +7343,8 @@
                     }
                     mLastHidden = true;
                 } finally {
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
                     Surface.closeTransaction();
+                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION createSurfaceLocked");
                 }
                 if (localLOGV) Slog.v(
                         TAG, "Created surface " + this);
@@ -7847,6 +8016,7 @@
             disposeInputChannel();
             
             if (mAttachedWindow != null) {
+                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow);
                 mAttachedWindow.mChildWindows.remove(this);
             }
             destroySurfaceLocked();
@@ -8124,9 +8294,14 @@
 
         @Override
         public String toString() {
-            return "Window{"
-                + Integer.toHexString(System.identityHashCode(this))
-                + " " + mAttrs.getTitle() + " paused=" + mToken.paused + "}";
+            if (mStringNameCache == null || mLastTitle != mAttrs.getTitle()
+                    || mWasPaused != mToken.paused) {
+                mLastTitle = mAttrs.getTitle();
+                mWasPaused = mToken.paused;
+                mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
+                        + " " + mLastTitle + " paused=" + mWasPaused + "}";
+            }
+            return mStringNameCache;
         }
     }
 
@@ -8275,11 +8450,15 @@
         boolean startingMoved;
         boolean firstWindowDrawn;
 
+        // Input application handle used by the input dispatcher.
+        InputApplicationHandle mInputApplicationHandle;
+
         AppWindowToken(IApplicationToken _token) {
             super(_token.asBinder(),
                     WindowManager.LayoutParams.TYPE_APPLICATION, true);
             appWindowToken = this;
             appToken = _token;
+            mInputApplicationHandle = new InputApplicationHandle(this);
         }
 
         public void setAnimation(Animation anim) {
@@ -9087,12 +9266,18 @@
         int lastWallpaper = -1;
         int numRemoved = 0;
 
+        if (mRebuildTmp.length < NW) {
+            mRebuildTmp = new WindowState[NW+10];
+        }
+
         // First remove all existing app windows.
         i=0;
         while (i < NW) {
             WindowState w = mWindows.get(i);
             if (w.mAppToken != null) {
                 WindowState win = mWindows.remove(i);
+                win.mRebuilding = true;
+                mRebuildTmp[numRemoved] = win;
                 mWindowsChanged = true;
                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
                         "Rebuild removing window: " + win);
@@ -9130,6 +9315,21 @@
         if (i != numRemoved) {
             Slog.w(TAG, "Rebuild removed " + numRemoved
                     + " windows but added " + i);
+            for (i=0; i<numRemoved; i++) {
+                WindowState ws = mRebuildTmp[i];
+                if (ws.mRebuilding) {
+                    StringWriter sw = new StringWriter();
+                    PrintWriter pw = new PrintWriter(sw);
+                    ws.dump(pw, "");
+                    pw.flush();
+                    Slog.w(TAG, "This window was lost: " + ws);
+                    Slog.w(TAG, sw.toString());
+                }
+            }
+            Slog.w(TAG, "Current app token list:");
+            dumpAppTokensLocked();
+            Slog.w(TAG, "Final window list:");
+            dumpWindowsLocked();
         }
     }
 
@@ -9196,38 +9396,46 @@
             return;
         }
 
+        mInLayout = true;
         boolean recoveringMemory = false;
-        if (mForceRemoves != null) {
-            recoveringMemory = true;
-            // Wait a little it for things to settle down, and off we go.
-            for (int i=0; i<mForceRemoves.size(); i++) {
-                WindowState ws = mForceRemoves.get(i);
-                Slog.i(TAG, "Force removing: " + ws);
-                removeWindowInnerLocked(ws.mSession, ws);
-            }
-            mForceRemoves = null;
-            Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
-            Object tmp = new Object();
-            synchronized (tmp) {
-                try {
-                    tmp.wait(250);
-                } catch (InterruptedException e) {
+        
+        try {
+            if (mForceRemoves != null) {
+                recoveringMemory = true;
+                // Wait a little bit for things to settle down, and off we go.
+                for (int i=0; i<mForceRemoves.size(); i++) {
+                    WindowState ws = mForceRemoves.get(i);
+                    Slog.i(TAG, "Force removing: " + ws);
+                    removeWindowInnerLocked(ws.mSession, ws);
+                }
+                mForceRemoves = null;
+                Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
+                Object tmp = new Object();
+                synchronized (tmp) {
+                    try {
+                        tmp.wait(250);
+                    } catch (InterruptedException e) {
+                    }
                 }
             }
+        } catch (RuntimeException e) {
+            Slog.e(TAG, "Unhandled exception while force removing for memory", e);
         }
-
-        mInLayout = true;
+        
         try {
             performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
 
-            int i = mPendingRemove.size()-1;
-            if (i >= 0) {
-                while (i >= 0) {
-                    WindowState w = mPendingRemove.get(i);
-                    removeWindowInnerLocked(w.mSession, w);
-                    i--;
+            int N = mPendingRemove.size();
+            if (N > 0) {
+                if (mPendingRemoveTmp.length < N) {
+                    mPendingRemoveTmp = new WindowState[N+10];
                 }
+                mPendingRemove.toArray(mPendingRemoveTmp);
                 mPendingRemove.clear();
+                for (int i=0; i<N; i++) {
+                    WindowState w = mPendingRemoveTmp[i];
+                    removeWindowInnerLocked(w.mSession, w);
+                }
 
                 mInLayout = false;
                 assignLayersLocked();
@@ -9405,7 +9613,7 @@
             createWatermark = true;
         }
 
-        if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
+        if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
 
         Surface.openTransaction();
 
@@ -9443,7 +9651,7 @@
                     }
                     if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
                         if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
-                        if (updateOrientationFromAppTokensLocked()) {
+                        if (updateOrientationFromAppTokensLocked(true)) {
                             mLayoutNeeded = true;
                             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
                         }
@@ -9671,12 +9879,9 @@
                 if (tokenMayBeDrawn) {
                     // See if any windows have been drawn, so they (and others
                     // associated with them) can now be shown.
-                    final int NT = mTokenList.size();
+                    final int NT = mAppTokens.size();
                     for (i=0; i<NT; i++) {
-                        AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
-                        if (wtoken == null) {
-                            continue;
-                        }
+                        AppWindowToken wtoken = mAppTokens.get(i);
                         if (wtoken.freezingScreen) {
                             int numInteresting = wtoken.numInterestingWindows;
                             if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
@@ -9902,7 +10107,8 @@
 
                         // This has changed the visibility of windows, so perform
                         // a new layout to get them all up-to-date.
-                        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
+                        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT
+                                | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
                         mLayoutNeeded = true;
                         if (!moveInputMethodWindowsIfNeededLocked(true)) {
                             assignLayersLocked();
@@ -10128,7 +10334,7 @@
                                 // as running out of memory), don't take down the
                                 // entire system.
                                 Slog.e(TAG, "Failure updating surface of " + w
-                                        + "size=(" + width + "x" + height
+                                        + " size=(" + width + "x" + height
                                         + "), pos=(" + w.mShownFrame.left
                                         + "," + w.mShownFrame.top + ")", e);
                                 if (!recoveringMemory) {
@@ -10479,8 +10685,6 @@
                 }
                 mBlurShown = false;
             }
-
-            if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
         } catch (RuntimeException e) {
             Slog.e(TAG, "Unhandled exception in Window Manager", e);
         }
@@ -10489,6 +10693,8 @@
         
         Surface.closeTransaction();
 
+        if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
+
         if (mWatermark != null) {
             mWatermark.drawIfNeeded();
         }
@@ -10578,6 +10784,8 @@
                 // soon as their animations are complete
                 token.animation = null;
                 token.animating = false;
+                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                        "performLayout: App token exiting now removed" + token);
                 mAppTokens.remove(token);
                 mExitingAppTokens.remove(i);
             }
@@ -10689,7 +10897,7 @@
             }
             return true;
         } catch (RuntimeException e) {
-            Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
+            Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win, e);
         }
 
         reclaimSomeSurfaceMemoryLocked(win, "show");
@@ -10724,6 +10932,7 @@
                                 + " token=" + win.mToken
                                 + " pid=" + ws.mSession.mPid
                                 + " uid=" + ws.mSession.mUid);
+                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
                         ws.mSurface.destroy();
                         ws.mSurfaceShown = false;
                         ws.mSurface = null;
@@ -10731,10 +10940,11 @@
                         i--;
                         N--;
                         leakedSurface = true;
-                    } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
+                    } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
                         Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
                                 + ws + " surface=" + ws.mSurface
                                 + " token=" + win.mAppToken);
+                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
                         ws.mSurface.destroy();
                         ws.mSurfaceShown = false;
                         ws.mSurface = null;
@@ -10772,6 +10982,7 @@
                 // surface and ask the app to request another one.
                 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
                 if (surface != null) {
+                    if (SHOW_TRANSACTIONS) logSurface(win, "RECOVER DESTROY", null);
                     surface.destroy();
                     win.mSurfaceShown = false;
                     win.mSurface = null;
@@ -10899,7 +11110,7 @@
         return result;
     }
 
-    private void startFreezingDisplayLocked() {
+    private void startFreezingDisplayLocked(boolean inTransaction) {
         if (mDisplayFrozen) {
             return;
         }
@@ -10941,7 +11152,7 @@
             }
             if (mScreenRotationAnimation == null) {
                 mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
-                        mDisplay, mFxSession);
+                        mDisplay, mFxSession, inTransaction);
             }
         } else {
             Surface.freezeDisplay(0);
@@ -10982,7 +11193,7 @@
         // to avoid inconsistent states.  However, something interesting
         // could have actually changed during that time so re-evaluate it
         // now to catch that.
-        if (updateOrientationFromAppTokensLocked()) {
+        if (updateOrientationFromAppTokensLocked(false)) {
             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
         }
 
@@ -11287,14 +11498,6 @@
                     token.dump(pw, "    ");
                 }
             }
-            if (mTokenList.size() > 0) {
-                pw.println(" ");
-                pw.println("  Window token list:");
-                for (int i=0; i<mTokenList.size(); i++) {
-                    pw.print("  #"); pw.print(i); pw.print(": ");
-                            pw.println(mTokenList.get(i));
-                }
-            }
             if (mWallpaperTokens.size() > 0) {
                 pw.println(" ");
                 pw.println("  Wallpaper tokens:");
@@ -11418,6 +11621,8 @@
             } else {
                 pw.println("  NO DISPLAY");
             }
+            pw.println("  Policy:");
+            mPolicy.dump("    ", fd, pw, args);
         }
     }
 
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index a26fe5f..3b1b8c4 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -129,7 +129,6 @@
 import java.io.PrintWriter;
 import java.lang.IllegalStateException;
 import java.lang.ref.WeakReference;
-import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -1325,6 +1324,7 @@
         ActivityThread at = ActivityThread.systemMain();
         mSystemThread = at;
         Context context = at.getSystemContext();
+        context.setTheme(android.R.style.Theme_Holo);
         m.mContext = context;
         m.mFactoryTest = factoryTest;
         m.mMainStack = new ActivityStack(m, context, true);
@@ -2314,8 +2314,12 @@
     }
 
     final void addRecentTaskLocked(TaskRecord task) {
-        // Remove any existing entries that are the same kind of task.
         int N = mRecentTasks.size();
+        // Quick case: check if the top-most recent task is the same.
+        if (N > 0 && mRecentTasks.get(0) == task) {
+            return;
+        }
+        // Remove any existing entries that are the same kind of task.
         for (int i=0; i<N; i++) {
             TaskRecord tr = mRecentTasks.get(i);
             if ((task.affinity != null && task.affinity.equals(tr.affinity))
@@ -2608,6 +2612,7 @@
                     if (localLOGV) Slog.v(
                         TAG, "Removing this entry!  frozen=" + r.haveState
                         + " finishing=" + r.finishing);
+                    r.makeFinishing();
                     mMainStack.mHistory.remove(i);
 
                     r.inHistory = false;
@@ -6070,23 +6075,25 @@
                     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;
@@ -6558,7 +6565,6 @@
                     + " has crashed too many times: killing!");
             EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
                     app.info.processName, app.info.uid);
-            killServicesLocked(app, false);
             for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
                 ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
                 if (r.app == app) {
@@ -6568,6 +6574,10 @@
                 }
             }
             if (!app.persistent) {
+                // Don't let services in this process be restarted and potentially
+                // annoy the user repeatedly.  Unless it is persistent, since those
+                // processes run critical code.
+                killServicesLocked(app, false);
                 // We don't want to start this process again until the user
                 // explicitly does so...  but for persistent process, we really
                 // need to keep it running.  If a persistent process is actually
@@ -6591,7 +6601,7 @@
                 int index = mMainStack.indexOfTokenLocked(r);
                 r.stack.finishActivityLocked(r, index,
                         Activity.RESULT_CANCELED, null, "crashed");
-                // Also terminate an activities below it that aren't yet
+                // Also terminate any activities below it that aren't yet
                 // stopped, to avoid a situation where one will get
                 // re-start our crashing activity once it gets resumed again.
                 index--;
@@ -6600,7 +6610,7 @@
                     if (r.state == ActivityState.RESUMED
                             || r.state == ActivityState.PAUSING
                             || r.state == ActivityState.PAUSED) {
-                        if (!r.isHomeActivity) {
+                        if (!r.isHomeActivity || mHomeProcess != r.app) {
                             Slog.w(TAG, "  Force finishing activity "
                                     + r.intent.getComponent().flattenToShortString());
                             r.stack.finishActivityLocked(r, index,
@@ -8473,7 +8483,8 @@
                     }
                 }
 
-                if (sr.crashCount >= 2) {
+                if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags
+                        &ApplicationInfo.FLAG_PERSISTENT) == 0) {
                     Slog.w(TAG, "Service crashed " + sr.crashCount
                             + " times, stopping: " + sr);
                     EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
@@ -9135,6 +9146,11 @@
         long minDuration = SERVICE_RESTART_DURATION;
         long resetTime = SERVICE_RESET_RUN_DURATION;
         
+        if ((r.serviceInfo.applicationInfo.flags
+                &ApplicationInfo.FLAG_PERSISTENT) != 0) {
+            minDuration /= 4;
+        }
+        
         // Any delivered but not yet finished starts should be put back
         // on the pending list.
         final int N = r.deliveredStarts.size();
@@ -9174,9 +9190,16 @@
                 r.restartCount = 1;
                 r.restartDelay = minDuration;
             } else {
-                r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
-                if (r.restartDelay < minDuration) {
-                    r.restartDelay = minDuration;
+                if ((r.serviceInfo.applicationInfo.flags
+                        &ApplicationInfo.FLAG_PERSISTENT) != 0) {
+                    // Services in peristent processes will restart much more
+                    // quickly, since they are pretty important.  (Think SystemUI).
+                    r.restartDelay += minDuration/2;
+                } else {
+                    r.restartDelay *= SERVICE_RESTART_DURATION_FACTOR;
+                    if (r.restartDelay < minDuration) {
+                        r.restartDelay = minDuration;
+                    }
                 }
             }
         }
@@ -9408,6 +9431,14 @@
             if (DEBUG_SERVICE) Slog.v(
                 TAG, "Removed service that is not running: " + r);
         }
+
+        if (r.bindings.size() > 0) {
+            r.bindings.clear();
+        }
+
+        if (r.restarter instanceof ServiceRestarter) {
+           ((ServiceRestarter)r.restarter).setService(null);
+        }
     }
 
     ComponentName startServiceLocked(IApplicationThread caller,
@@ -10082,6 +10113,7 @@
                 if (DEBUG_SERVICE) Slog.v(TAG,
                         "doneExecuting remove stopping " + r);
                 mStoppingServices.remove(r);
+                r.bindings.clear();
             }
             updateOomAdjLocked(r.app);
         }
@@ -11324,6 +11356,9 @@
                             performReceiveLocked(r.callerApp, r.resultTo,
                                 new Intent(r.intent), r.resultCode,
                                 r.resultData, r.resultExtras, false, false);
+                            // Set this to null so that the reference
+                            // (local and remote) isnt kept in the mBroadcastHistory.
+                            r.resultTo = null;
                         } catch (RemoteException e) {
                             Slog.w(TAG, "Failure sending broadcast result of " + r.intent, e);
                         }
@@ -11746,14 +11781,9 @@
         
         if (starting != null) {
             kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);
-            if (kept) {
-                // If this didn't result in the starting activity being
-                // destroyed, then we need to make sure at this point that all
-                // other activities are made visible.
-                if (DEBUG_SWITCH) Slog.i(TAG, "Config didn't destroy " + starting
-                        + ", ensuring others are correct.");
-                mMainStack.ensureActivitiesVisibleLocked(starting, changes);
-            }
+            // And we need to make sure at this point that all other activities
+            // are made visible with the correct configuration.
+            mMainStack.ensureActivitiesVisibleLocked(starting, changes);
         }
         
         if (values != null && mWindowManager != null) {
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index b4e426f..e29da1c 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -26,6 +26,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Message;
 import android.os.Process;
@@ -69,6 +70,7 @@
     int labelRes;           // the label information from the package mgr.
     int icon;               // resource identifier of activity's icon.
     int theme;              // resource identifier of activity's theme.
+    int realTheme;          // actual theme resource we will use, never 0.
     int windowFlags;        // custom window flags for preview window.
     TaskRecord task;        // the task this is in.
     long launchTime;        // when we starting launching this activity
@@ -246,6 +248,13 @@
             }
             icon = aInfo.getIconResource();
             theme = aInfo.getThemeResource();
+            realTheme = theme;
+            if (realTheme == 0) {
+                realTheme = aInfo.applicationInfo.targetSdkVersion
+                        < Build.VERSION_CODES.HONEYCOMB
+                        ? android.R.style.Theme
+                        : android.R.style.Theme_Holo;
+            }
             if ((aInfo.flags&ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
                 windowFlags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
             }
@@ -266,8 +275,7 @@
             launchMode = aInfo.launchMode;
             
             AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
-                    theme != 0 ? theme : android.R.style.Theme,
-                    com.android.internal.R.styleable.Window);
+                    realTheme, com.android.internal.R.styleable.Window);
             fullscreen = ent != null && !ent.array.getBoolean(
                     com.android.internal.R.styleable.Window_windowIsFloating, false)
                     && !ent.array.getBoolean(
@@ -313,6 +321,15 @@
         }
     }
 
+    void makeFinishing() {
+        if (!finishing) {
+            finishing = true;
+            if (task != null) {
+                task.numActivities--;
+            }
+        }
+    }
+
     UriPermissionOwner getUriPermissionsLocked() {
         if (uriPermissions == null) {
             uriPermissions = new UriPermissionOwner(service, this);
@@ -413,7 +430,7 @@
         // an application, and that application is not blocked or unresponding.
         // In any other case, we can't count on getting the screen unfrozen,
         // so it is best to leave as-is.
-        return app == null || (!app.crashing && !app.notResponding);
+        return app != null && !app.crashing && !app.notResponding;
     }
     
     public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 516dfa2..bc00478 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -50,7 +50,6 @@
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -572,6 +571,9 @@
             r.stopped = false;
             mResumedActivity = r;
             r.task.touchActiveTime();
+            if (mMainStack) {
+                mService.addRecentTaskLocked(r.task);
+            }
             completeResumeLocked(r);
             pauseIfSleepingLocked();                
         } else {
@@ -1249,6 +1251,9 @@
             next.state = ActivityState.RESUMED;
             mResumedActivity = next;
             next.task.touchActiveTime();
+            if (mMainStack) {
+                mService.addRecentTaskLocked(next.task);
+            }
             mService.updateLruProcessLocked(next.app, true, true);
             updateLRUListLocked(next);
 
@@ -1638,9 +1643,6 @@
                             taskTopI = -1;
                         }
                         replyChainEnd = -1;
-                        if (mMainStack) {
-                            mService.addRecentTaskLocked(target.task);
-                        }
                     } else if (forceReset || finishOnTaskLaunch
                             || clearWhenTaskReset) {
                         // If the activity should just be removed -- either
@@ -2409,9 +2411,6 @@
                 r.task = reuseTask;
             }
             newTask = true;
-            if (mMainStack) {
-                mService.addRecentTaskLocked(r.task);
-            }
             moveHomeToFrontFromLaunchLocked(launchFlags);
             
         } else if (sourceRecord != null) {
@@ -3071,7 +3070,7 @@
             return false;
         }
 
-        r.finishing = true;
+        r.makeFinishing();
         EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
                 System.identityHashCode(r),
                 r.task.taskId, r.shortComponentName, reason);
@@ -3276,6 +3275,7 @@
 
     private final void removeActivityFromHistoryLocked(ActivityRecord r) {
         if (r.state != ActivityState.DESTROYED) {
+            r.makeFinishing();
             mHistory.remove(r);
             r.inHistory = false;
             r.state = ActivityState.DESTROYED;
@@ -3440,6 +3440,7 @@
             ActivityRecord hr = (ActivityRecord)mHistory.get(i);
             if (hr.isHomeActivity) {
                 homeTask = hr.task;
+                break;
             }
         }
         if (homeTask != null) {
@@ -3472,17 +3473,12 @@
             ActivityRecord r = (ActivityRecord)mHistory.get(pos);
             if (localLOGV) Slog.v(
                 TAG, "At " + pos + " ckp " + r.task + ": " + r);
-            boolean first = true;
             if (r.task.taskId == task) {
                 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
                 mHistory.remove(pos);
                 mHistory.add(top, r);
                 moved.add(0, r);
                 top--;
-                if (first && mMainStack) {
-                    mService.addRecentTaskLocked(r.task);
-                    first = false;
-                }
             }
             pos--;
         }
diff --git a/services/java/com/android/server/am/BaseErrorDialog.java b/services/java/com/android/server/am/BaseErrorDialog.java
index 03e3272..d1e89bc 100644
--- a/services/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/java/com/android/server/am/BaseErrorDialog.java
@@ -34,7 +34,7 @@
         getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
         getWindow().setTitle("Error Dialog");
-        setIcon(R.drawable.ic_dialog_alert);
+        setIconAttribute(R.attr.alertDialogIcon);
     }
 
     public void onStart() {
diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java
index b268efa..c95053e 100644
--- a/services/java/com/android/server/am/BroadcastRecord.java
+++ b/services/java/com/android/server/am/BroadcastRecord.java
@@ -45,7 +45,7 @@
     final boolean initialSticky; // initial broadcast from register to sticky?
     final String requiredPermission; // a permission the caller has required
     final List receivers;   // contains BroadcastFilter and ResolveInfo
-    final IIntentReceiver resultTo; // who receives final result if non-null
+    IIntentReceiver resultTo; // who receives final result if non-null
     long dispatchTime;      // when dispatch started on this set of receivers
     long receiverTime;      // when current receiver started for timeouts.
     long finishTime;        // when we finished the broadcast.
diff --git a/services/java/com/android/server/am/LaunchWarningWindow.java b/services/java/com/android/server/am/LaunchWarningWindow.java
index 4130e33..1114a31 100644
--- a/services/java/com/android/server/am/LaunchWarningWindow.java
+++ b/services/java/com/android/server/am/LaunchWarningWindow.java
@@ -4,6 +4,7 @@
 
 import android.app.Dialog;
 import android.content.Context;
+import android.util.TypedValue;
 import android.view.Window;
 import android.view.WindowManager;
 import android.widget.ImageView;
@@ -20,8 +21,11 @@
         
         setContentView(R.layout.launch_warning);
         setTitle(context.getText(R.string.launch_warning_title));
-        getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
-                R.drawable.ic_dialog_alert);
+
+        TypedValue out = new TypedValue();
+        getContext().getTheme().resolveAttribute(android.R.attr.alertDialogIcon, out, true);
+        getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, out.resourceId);
+
         ImageView icon = (ImageView)findViewById(R.id.replace_app_icon);
         icon.setImageDrawable(next.info.applicationInfo.loadIcon(context.getPackageManager()));
         TextView text = (TextView)findViewById(R.id.replace_message);
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index a93d596..134b91e 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -68,7 +68,7 @@
 
     private Context mContext;
     private final static String TAG = "Tethering";
-    private final static boolean DEBUG = false;
+    private final static boolean DEBUG = true;
 
     private boolean mBooted = false;
     //used to remember if we got connected before boot finished
@@ -942,7 +942,12 @@
                         String newUpstreamIfaceName = (String)(message.obj);
                         b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
                         service = INetworkManagementService.Stub.asInterface(b);
-
+                        if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) ||
+                                (mMyUpstreamIfaceName != null &&
+                                mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) {
+                            if (DEBUG) Log.d(TAG, "Connection changed noop - dropping");
+                            break;
+                        }
                         if (mMyUpstreamIfaceName != null) {
                             try {
                                 service.disableNat(mIfaceName, mMyUpstreamIfaceName);
@@ -1085,7 +1090,8 @@
 
         private ArrayList mNotifyList;
 
-        private boolean mConnectionRequested = false;
+        private int mCurrentConnectionSequence;
+        private boolean mMobileReserved = false;
 
         private String mUpstreamIfaceName = null;
 
@@ -1124,43 +1130,47 @@
             public boolean processMessage(Message m) {
                 return false;
             }
-            protected int turnOnMobileConnection() {
+            protected boolean turnOnMobileConnection() {
+                boolean retValue = true;
+                if (mMobileReserved) return retValue;
                 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
-                int retValue = Phone.APN_REQUEST_FAILED;
+                int result = Phone.APN_REQUEST_FAILED;
                 try {
-                    retValue = service.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
-                            (mDunRequired ? Phone.FEATURE_ENABLE_DUN : Phone.FEATURE_ENABLE_HIPRI),
-                            new Binder());
+                    result = service.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
+                            (mDunRequired ? Phone.FEATURE_ENABLE_DUN_ALWAYS :
+                            Phone.FEATURE_ENABLE_HIPRI), new Binder());
                 } catch (Exception e) {
                 }
-                switch (retValue) {
+                switch (result) {
                 case Phone.APN_ALREADY_ACTIVE:
                 case Phone.APN_REQUEST_STARTED:
-                    sendMessageDelayed(CMD_CELL_CONNECTION_RENEW, CELL_CONNECTION_RENEW_MS);
-                    mConnectionRequested = true;
+                    mMobileReserved = true;
+                    Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
+                    m.arg1 = ++mCurrentConnectionSequence;
+                    sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
                     break;
                 case Phone.APN_REQUEST_FAILED:
                 default:
-                    mConnectionRequested = false;
+                    retValue = false;
                     break;
                 }
 
                 return retValue;
             }
             protected boolean turnOffMobileConnection() {
-                if (mConnectionRequested) {
+                if (mMobileReserved) {
                     IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                     IConnectivityManager service =
                             IConnectivityManager.Stub.asInterface(b);
                     try {
                         service.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
-                                (mDunRequired? Phone.FEATURE_ENABLE_DUN :
+                                (mDunRequired? Phone.FEATURE_ENABLE_DUN_ALWAYS :
                                              Phone.FEATURE_ENABLE_HIPRI));
                     } catch (Exception e) {
                         return false;
                     }
-                    mConnectionRequested = false;
+                    mMobileReserved = false;
                 }
                 return true;
             }
@@ -1240,13 +1250,14 @@
                 }
                 return null;
             }
+
             protected void chooseUpstreamType(boolean tryCell) {
                 // decide if the current upstream is good or not and if not
                 // do something about it (start up DUN if required or HiPri if not)
                 String iface = findActiveUpstreamIface();
                 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                 IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
-                mConnectionRequested = false;
+                mMobileReserved = false;
                 if (DEBUG) {
                     Log.d(TAG, "chooseUpstreamType(" + tryCell + "),  dunRequired ="
                             + mDunRequired + ", iface=" + iface);
@@ -1287,11 +1298,14 @@
                 }
                 // may have been set to null in the if above
                 if (iface == null ) {
+                    boolean success = false;
                     if (tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) {
-                        turnOnMobileConnection();
+                        success = turnOnMobileConnection();
                     }
-                    // wait for things to settle and retry
-                    sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
+                    if (!success) {
+                        // wait for things to settle and retry
+                        sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
+                    }
                 }
                 notifyTetheredOfNewUpstreamIface(iface);
             }
@@ -1309,7 +1323,7 @@
         class InitialState extends TetherMasterUtilState {
             @Override
             public void enter() {
-                mConnectionRequested = false;
+                mMobileReserved = false;
             }
             @Override
             public boolean processMessage(Message message) {
@@ -1340,10 +1354,11 @@
         }
 
         class TetherModeAliveState extends TetherMasterUtilState {
-            boolean mTryCell = WAIT_FOR_NETWORK_TO_SETTLE;
+            boolean mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
             @Override
             public void enter() {
-                mTryCell = WAIT_FOR_NETWORK_TO_SETTLE;  // first pass lets just see what we have.
+                mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass
+                                                        // or crazy tests cases will fail
                 chooseUpstreamType(mTryCell);
                 mTryCell = !mTryCell;
                 turnOnMasterTetherSettings(); // may transition us out
@@ -1382,11 +1397,12 @@
                     case CMD_CELL_CONNECTION_RENEW:
                         // make sure we're still using a requested connection - may have found
                         // wifi or something since then.
-                        if (mConnectionRequested) {
+                        if (mCurrentConnectionSequence == message.arg1) {
                             if (DEBUG) {
                                 Log.d(TAG, "renewing mobile connection - requeuing for another " +
                                         CELL_CONNECTION_RENEW_MS + "ms");
                             }
+                            mMobileReserved = false; // need to renew it
                             turnOnMobileConnection();
                         }
                         break;
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index 89ead82..f5a5b4d 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -4,30 +4,37 @@
 LOCAL_SRC_FILES:= \
     com_android_server_AlarmManagerService.cpp \
     com_android_server_BatteryService.cpp \
+    com_android_server_InputApplication.cpp \
+    com_android_server_InputApplicationHandle.cpp \
     com_android_server_InputManager.cpp \
+    com_android_server_InputWindow.cpp \
+    com_android_server_InputWindowHandle.cpp \
     com_android_server_LightsService.cpp \
     com_android_server_PowerManagerService.cpp \
     com_android_server_SystemServer.cpp \
-    com_android_server_UsbService.cpp \
     com_android_server_VibratorService.cpp \
-	com_android_server_location_GpsLocationProvider.cpp \
+    com_android_server_location_GpsLocationProvider.cpp \
     onload.cpp
 
 LOCAL_C_INCLUDES += \
-	$(JNI_H_INCLUDE)
+    $(JNI_H_INCLUDE) \
+    frameworks/base/services \
+    frameworks/base/core/jni \
+    external/skia/include/core
 
 LOCAL_SHARED_LIBRARIES := \
     libandroid_runtime \
-	libcutils \
-	libhardware \
-	libhardware_legacy \
-	libnativehelper \
+    libcutils \
+    libhardware \
+    libhardware_legacy \
+    libnativehelper \
     libsystem_server \
-	libutils \
-	libui \
-    libsurfaceflinger_client
-
-LOCAL_STATIC_LIBRARIES := libusbhost
+    libutils \
+    libui \
+    libinput \
+    libskia \
+    libsurfaceflinger_client \
+    libusbhost
 
 ifeq ($(TARGET_SIMULATOR),true)
 ifeq ($(TARGET_OS),linux)
@@ -38,10 +45,9 @@
 endif
 
 ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
-	LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
+    LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
 endif
 
 LOCAL_MODULE:= libandroid_servers
 
 include $(BUILD_SHARED_LIBRARY)
-    
diff --git a/services/jni/com_android_server_InputApplication.cpp b/services/jni/com_android_server_InputApplication.cpp
new file mode 100644
index 0000000..a46a162
--- /dev/null
+++ b/services/jni/com_android_server_InputApplication.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputApplication"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include "com_android_server_InputApplication.h"
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+    jclass clazz;
+
+    jfieldID inputApplicationHandle;
+    jfieldID name;
+    jfieldID dispatchingTimeoutNanos;
+} gInputApplicationClassInfo;
+
+
+// --- Global functions ---
+
+void android_server_InputApplication_toNative(
+        JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication) {
+    jobject inputApplicationHandleObj = env->GetObjectField(inputApplicationObj,
+            gInputApplicationClassInfo.inputApplicationHandle);
+    if (inputApplicationHandleObj) {
+        outInputApplication->inputApplicationHandle =
+                android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
+        env->DeleteLocalRef(inputApplicationHandleObj);
+    } else {
+        outInputApplication->inputApplicationHandle = NULL;
+    }
+
+    jstring nameObj = jstring(env->GetObjectField(inputApplicationObj,
+            gInputApplicationClassInfo.name));
+    if (nameObj) {
+        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+        outInputApplication->name.setTo(nameStr);
+        env->ReleaseStringUTFChars(nameObj, nameStr);
+        env->DeleteLocalRef(nameObj);
+    } else {
+        LOGE("InputApplication.name should not be null.");
+        outInputApplication->name.setTo("unknown");
+    }
+
+    outInputApplication->dispatchingTimeout = env->GetLongField(inputApplicationObj,
+            gInputApplicationClassInfo.dispatchingTimeoutNanos);
+}
+
+
+// --- JNI ---
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputApplication(JNIEnv* env) {
+    FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
+
+    GET_FIELD_ID(gInputApplicationClassInfo.inputApplicationHandle,
+            gInputApplicationClassInfo.clazz,
+            "inputApplicationHandle", "Lcom/android/server/InputApplicationHandle;");
+
+    GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
+            "name", "Ljava/lang/String;");
+
+    GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
+            gInputApplicationClassInfo.clazz,
+            "dispatchingTimeoutNanos", "J");
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputApplication.h b/services/jni/com_android_server_InputApplication.h
new file mode 100644
index 0000000..85fb891
--- /dev/null
+++ b/services/jni/com_android_server_InputApplication.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_APPLICATION_H
+#define _ANDROID_SERVER_INPUT_APPLICATION_H
+
+#include <input/InputApplication.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+extern void android_server_InputApplication_toNative(
+        JNIEnv* env, jobject inputApplicationObj, InputApplication* outInputApplication);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_APPLICATION_H
diff --git a/services/jni/com_android_server_InputApplicationHandle.cpp b/services/jni/com_android_server_InputApplicationHandle.cpp
new file mode 100644
index 0000000..ab82635
--- /dev/null
+++ b/services/jni/com_android_server_InputApplicationHandle.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputApplicationHandle"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/threads.h>
+
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+    jclass clazz;
+
+    jfieldID ptr;
+} gInputApplicationHandleClassInfo;
+
+static Mutex gHandleMutex;
+
+
+// --- NativeInputApplicationHandle ---
+
+NativeInputApplicationHandle::NativeInputApplicationHandle(jweak objWeak) :
+        mObjWeak(objWeak) {
+}
+
+NativeInputApplicationHandle::~NativeInputApplicationHandle() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->DeleteWeakGlobalRef(mObjWeak);
+}
+
+jobject NativeInputApplicationHandle::getInputApplicationHandleObjLocalRef(JNIEnv* env) {
+    return env->NewLocalRef(mObjWeak);
+}
+
+
+// --- Global functions ---
+
+sp<InputApplicationHandle> android_server_InputApplicationHandle_getHandle(
+        JNIEnv* env, jobject inputApplicationHandleObj) {
+    if (!inputApplicationHandleObj) {
+        return NULL;
+    }
+
+    AutoMutex _l(gHandleMutex);
+
+    int ptr = env->GetIntField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr);
+    NativeInputApplicationHandle* handle;
+    if (ptr) {
+        handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
+    } else {
+        jweak objWeak = env->NewWeakGlobalRef(inputApplicationHandleObj);
+        handle = new NativeInputApplicationHandle(objWeak);
+        handle->incStrong(inputApplicationHandleObj);
+        env->SetIntField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr,
+                reinterpret_cast<int>(handle));
+    }
+    return handle;
+}
+
+
+// --- JNI ---
+
+static void android_server_InputApplicationHandle_nativeDispose(JNIEnv* env, jobject obj) {
+    AutoMutex _l(gHandleMutex);
+
+    int ptr = env->GetIntField(obj, gInputApplicationHandleClassInfo.ptr);
+    if (ptr) {
+        env->SetIntField(obj, gInputApplicationHandleClassInfo.ptr, 0);
+
+        NativeInputApplicationHandle* handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
+        handle->decStrong(obj);
+    }
+}
+
+
+static JNINativeMethod gInputApplicationHandleMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeDispose", "()V",
+            (void*) android_server_InputApplicationHandle_nativeDispose },
+};
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputApplicationHandle(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "com/android/server/InputApplicationHandle",
+            gInputApplicationHandleMethods, NELEM(gInputApplicationHandleMethods));
+    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    FIND_CLASS(gInputApplicationHandleClassInfo.clazz, "com/android/server/InputApplicationHandle");
+
+    GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, gInputApplicationHandleClassInfo.clazz,
+            "ptr", "I");
+
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputApplicationHandle.h b/services/jni/com_android_server_InputApplicationHandle.h
new file mode 100644
index 0000000..9d18721
--- /dev/null
+++ b/services/jni/com_android_server_InputApplicationHandle.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
+#define _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
+
+#include <input/InputApplication.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+class NativeInputApplicationHandle : public InputApplicationHandle {
+public:
+    NativeInputApplicationHandle(jweak objWeak);
+    virtual ~NativeInputApplicationHandle();
+
+    jobject getInputApplicationHandleObjLocalRef(JNIEnv* env);
+
+private:
+    jweak mObjWeak;
+};
+
+
+extern sp<InputApplicationHandle> android_server_InputApplicationHandle_getHandle(
+        JNIEnv* env, jobject inputApplicationHandleObj);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 9156249..e04e4c3 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -24,25 +24,31 @@
 // Log debug messages about InputDispatcherPolicy
 #define DEBUG_INPUT_DISPATCHER_POLICY 0
 
+
 #include "JNIHelp.h"
 #include "jni.h"
 #include <limits.h>
 #include <android_runtime/AndroidRuntime.h>
-#include <ui/InputReader.h>
-#include <ui/InputDispatcher.h>
-#include <ui/InputManager.h>
-#include <ui/InputTransport.h>
+
 #include <utils/Log.h>
 #include <utils/threads.h>
-#include "../../core/jni/android_view_KeyEvent.h"
-#include "../../core/jni/android_view_MotionEvent.h"
-#include "../../core/jni/android_view_InputChannel.h"
+
+#include <input/InputManager.h>
+#include <input/PointerController.h>
+
+#include <android_view_KeyEvent.h>
+#include <android_view_MotionEvent.h>
+#include <android_view_InputChannel.h>
+#include <android/graphics/GraphicsJNI.h>
+
 #include "com_android_server_PowerManagerService.h"
+#include "com_android_server_InputApplication.h"
+#include "com_android_server_InputApplicationHandle.h"
+#include "com_android_server_InputWindow.h"
+#include "com_android_server_InputWindowHandle.h"
 
 namespace android {
 
-// ----------------------------------------------------------------------------
-
 static struct {
     jclass clazz;
 
@@ -58,48 +64,12 @@
     jmethodID filterJumpyTouchEvents;
     jmethodID getExcludedDeviceNames;
     jmethodID getMaxEventsPerSecond;
+    jmethodID getPointerLayer;
+    jmethodID getPointerIcon;
 } gCallbacksClassInfo;
 
 static struct {
     jclass clazz;
-
-    jfieldID inputChannel;
-    jfieldID name;
-    jfieldID layoutParamsFlags;
-    jfieldID layoutParamsType;
-    jfieldID dispatchingTimeoutNanos;
-    jfieldID frameLeft;
-    jfieldID frameTop;
-    jfieldID frameRight;
-    jfieldID frameBottom;
-    jfieldID visibleFrameLeft;
-    jfieldID visibleFrameTop;
-    jfieldID visibleFrameRight;
-    jfieldID visibleFrameBottom;
-    jfieldID touchableAreaLeft;
-    jfieldID touchableAreaTop;
-    jfieldID touchableAreaRight;
-    jfieldID touchableAreaBottom;
-    jfieldID visible;
-    jfieldID canReceiveKeys;
-    jfieldID hasFocus;
-    jfieldID hasWallpaper;
-    jfieldID paused;
-    jfieldID layer;
-    jfieldID ownerPid;
-    jfieldID ownerUid;
-} gInputWindowClassInfo;
-
-static struct {
-    jclass clazz;
-
-    jfieldID name;
-    jfieldID dispatchingTimeoutNanos;
-    jfieldID token;
-} gInputApplicationClassInfo;
-
-static struct {
-    jclass clazz;
 } gKeyEventClassInfo;
 
 static struct {
@@ -127,13 +97,37 @@
     jfieldID navigation;
 } gConfigurationClassInfo;
 
-// ----------------------------------------------------------------------------
+static struct {
+    jclass clazz;
 
-static inline nsecs_t now() {
-    return systemTime(SYSTEM_TIME_MONOTONIC);
+    jfieldID bitmap;
+    jfieldID hotSpotX;
+    jfieldID hotSpotY;
+} gPointerIconClassInfo;
+
+
+// --- Global functions ---
+
+static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
+        const sp<InputApplicationHandle>& inputApplicationHandle) {
+    if (inputApplicationHandle == NULL) {
+        return NULL;
+    }
+    return static_cast<NativeInputApplicationHandle*>(inputApplicationHandle.get())->
+            getInputApplicationHandleObjLocalRef(env);
 }
 
-// ----------------------------------------------------------------------------
+static jobject getInputWindowHandleObjLocalRef(JNIEnv* env,
+        const sp<InputWindowHandle>& inputWindowHandle) {
+    if (inputWindowHandle == NULL) {
+        return NULL;
+    }
+    return static_cast<NativeInputWindowHandle*>(inputWindowHandle.get())->
+            getInputWindowHandleObjLocalRef(env);
+}
+
+
+// --- NativeInputManager ---
 
 class NativeInputManager : public virtual RefBase,
     public virtual InputReaderPolicyInterface,
@@ -152,7 +146,7 @@
     void setDisplayOrientation(int32_t displayId, int32_t orientation);
 
     status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
-            jweak inputChannelObjWeak, bool monitor);
+            const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
     status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
 
     void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
@@ -166,6 +160,7 @@
     virtual bool filterTouchEvents();
     virtual bool filterJumpyTouchEvents();
     virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
+    virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
 
     /* --- InputDispatcherPolicyInterface implementation --- */
 
@@ -173,37 +168,22 @@
             uint32_t policyFlags);
     virtual void notifyConfigurationChanged(nsecs_t when);
     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-            const sp<InputChannel>& inputChannel);
-    virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel);
+            const sp<InputWindowHandle>& inputWindowHandle);
+    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
     virtual nsecs_t getKeyRepeatTimeout();
     virtual nsecs_t getKeyRepeatDelay();
     virtual int32_t getMaxEventsPerSecond();
     virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
     virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
-    virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+    virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags);
-    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
             const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
     virtual bool checkInjectEventsPermissionNonReentrant(
             int32_t injectorPid, int32_t injectorUid);
 
 private:
-    class ApplicationToken : public InputApplicationHandle {
-        jweak mTokenObjWeak;
-
-    public:
-        ApplicationToken(jweak tokenObjWeak) :
-            mTokenObjWeak(tokenObjWeak) { }
-
-        virtual ~ApplicationToken() {
-            JNIEnv* env = NativeInputManager::jniEnv();
-            env->DeleteWeakGlobalRef(mTokenObjWeak);
-        }
-
-        inline jweak getTokenObj() { return mTokenObjWeak; }
-    };
-
     sp<InputManager> mInputManager;
 
     jobject mCallbacksObj;
@@ -215,23 +195,20 @@
     // Cached throttling policy.
     int32_t mMaxEventsPerSecond;
 
-    // Cached display state.  (lock mDisplayLock)
-    Mutex mDisplayLock;
-    int32_t mDisplayWidth, mDisplayHeight;
-    int32_t mDisplayOrientation;
+    Mutex mLock;
+    struct Locked {
+        // Display size information.
+        int32_t displayWidth, displayHeight; // -1 when initialized
+        int32_t displayOrientation;
+
+        // Pointer controller singleton, created and destroyed as needed.
+        wp<PointerController> pointerController;
+    } mLocked;
 
     // Power manager interactions.
     bool isScreenOn();
     bool isScreenBright();
 
-    // Weak references to all currently registered input channels by connection pointer.
-    Mutex mInputChannelRegistryLock;
-    KeyedVector<InputChannel*, jweak> mInputChannelObjWeakTable;
-
-    jobject getInputChannelObjLocal(JNIEnv* env, const sp<InputChannel>& inputChannel);
-
-    static bool populateWindow(JNIEnv* env, jobject windowObj, InputWindow& outWindow);
-
     static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
 
     static inline JNIEnv* jniEnv() {
@@ -239,16 +216,22 @@
     }
 };
 
-// ----------------------------------------------------------------------------
+
 
 NativeInputManager::NativeInputManager(jobject callbacksObj) :
     mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1),
-    mMaxEventsPerSecond(-1),
-    mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0) {
+    mMaxEventsPerSecond(-1) {
     JNIEnv* env = jniEnv();
 
     mCallbacksObj = env->NewGlobalRef(callbacksObj);
 
+    {
+        AutoMutex _l(mLock);
+        mLocked.displayWidth = -1;
+        mLocked.displayHeight = -1;
+        mLocked.displayOrientation = ROTATION_0;
+    }
+
     sp<EventHub> eventHub = new EventHub();
     mInputManager = new InputManager(eventHub, this, this);
 }
@@ -279,119 +262,62 @@
 
 void NativeInputManager::setDisplaySize(int32_t displayId, int32_t width, int32_t height) {
     if (displayId == 0) {
-        AutoMutex _l(mDisplayLock);
+        AutoMutex _l(mLock);
 
-        mDisplayWidth = width;
-        mDisplayHeight = height;
+        if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
+            mLocked.displayWidth = width;
+            mLocked.displayHeight = height;
+
+            sp<PointerController> controller = mLocked.pointerController.promote();
+            if (controller != NULL) {
+                controller->setDisplaySize(width, height);
+            }
+        }
     }
 }
 
 void NativeInputManager::setDisplayOrientation(int32_t displayId, int32_t orientation) {
     if (displayId == 0) {
-        AutoMutex _l(mDisplayLock);
+        AutoMutex _l(mLock);
 
-        mDisplayOrientation = orientation;
+        if (mLocked.displayOrientation != orientation) {
+            mLocked.displayOrientation = orientation;
+
+            sp<PointerController> controller = mLocked.pointerController.promote();
+            if (controller != NULL) {
+                controller->setDisplayOrientation(orientation);
+            }
+        }
     }
 }
 
 status_t NativeInputManager::registerInputChannel(JNIEnv* env,
-        const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) {
-    jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
-    if (! inputChannelObjWeak) {
-        LOGE("Could not create weak reference for input channel.");
-        LOGE_EX(env);
-        return NO_MEMORY;
-    }
-
-    status_t status;
-    {
-        AutoMutex _l(mInputChannelRegistryLock);
-
-        ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
-        if (index >= 0) {
-            LOGE("Input channel object '%s' has already been registered",
-                    inputChannel->getName().string());
-            status = INVALID_OPERATION;
-            goto DeleteWeakRef;
-        }
-
-        mInputChannelObjWeakTable.add(inputChannel.get(), inputChannelObjWeak);
-    }
-
-    status = mInputManager->getDispatcher()->registerInputChannel(inputChannel, monitor);
-    if (! status) {
-        // Success.
-        return OK;
-    }
-
-    // Failed!
-    {
-        AutoMutex _l(mInputChannelRegistryLock);
-        mInputChannelObjWeakTable.removeItem(inputChannel.get());
-    }
-
-DeleteWeakRef:
-    env->DeleteWeakGlobalRef(inputChannelObjWeak);
-    return status;
+        const sp<InputChannel>& inputChannel,
+        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
+    return mInputManager->getDispatcher()->registerInputChannel(
+            inputChannel, inputWindowHandle, monitor);
 }
 
 status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
         const sp<InputChannel>& inputChannel) {
-    jweak inputChannelObjWeak;
-    {
-        AutoMutex _l(mInputChannelRegistryLock);
-
-        ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannel.get());
-        if (index < 0) {
-            LOGE("Input channel object '%s' is not currently registered",
-                    inputChannel->getName().string());
-            return INVALID_OPERATION;
-        }
-
-        inputChannelObjWeak = mInputChannelObjWeakTable.valueAt(index);
-        mInputChannelObjWeakTable.removeItemsAt(index);
-    }
-
-    env->DeleteWeakGlobalRef(inputChannelObjWeak);
-
     return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel);
 }
 
-jobject NativeInputManager::getInputChannelObjLocal(JNIEnv* env,
-        const sp<InputChannel>& inputChannel) {
-    InputChannel* inputChannelPtr = inputChannel.get();
-    if (! inputChannelPtr) {
-        return NULL;
-    }
-
-    {
-        AutoMutex _l(mInputChannelRegistryLock);
-
-        ssize_t index = mInputChannelObjWeakTable.indexOfKey(inputChannelPtr);
-        if (index < 0) {
-            return NULL;
-        }
-
-        jweak inputChannelObjWeak = mInputChannelObjWeakTable.valueAt(index);
-        return env->NewLocalRef(inputChannelObjWeak);
-    }
-}
-
 bool NativeInputManager::getDisplayInfo(int32_t displayId,
         int32_t* width, int32_t* height, int32_t* orientation) {
     bool result = false;
     if (displayId == 0) {
-        AutoMutex _l(mDisplayLock);
+        AutoMutex _l(mLock);
 
-        if (mDisplayWidth > 0) {
+        if (mLocked.displayWidth > 0 && mLocked.displayHeight > 0) {
             if (width) {
-                *width = mDisplayWidth;
+                *width = mLocked.displayWidth;
             }
             if (height) {
-                *height = mDisplayHeight;
+                *height = mLocked.displayHeight;
             }
             if (orientation) {
-                *orientation = mDisplayOrientation;
+                *orientation = mLocked.displayOrientation;
             }
             result = true;
         }
@@ -451,6 +377,41 @@
     }
 }
 
+sp<PointerControllerInterface> NativeInputManager::obtainPointerController(int32_t deviceId) {
+    AutoMutex _l(mLock);
+
+    sp<PointerController> controller = mLocked.pointerController.promote();
+    if (controller == NULL) {
+        JNIEnv* env = jniEnv();
+        jint layer = env->CallIntMethod(mCallbacksObj, gCallbacksClassInfo.getPointerLayer);
+        if (checkAndClearExceptionFromCallback(env, "getPointerLayer")) {
+            layer = -1;
+        }
+
+        controller = new PointerController(layer);
+        mLocked.pointerController = controller;
+
+        controller->setDisplaySize(mLocked.displayWidth, mLocked.displayHeight);
+        controller->setDisplayOrientation(mLocked.displayOrientation);
+
+        jobject iconObj = env->CallObjectMethod(mCallbacksObj, gCallbacksClassInfo.getPointerIcon);
+        if (!checkAndClearExceptionFromCallback(env, "getPointerIcon") && iconObj) {
+            jfloat iconHotSpotX = env->GetFloatField(iconObj, gPointerIconClassInfo.hotSpotX);
+            jfloat iconHotSpotY = env->GetFloatField(iconObj, gPointerIconClassInfo.hotSpotY);
+            jobject iconBitmapObj = env->GetObjectField(iconObj, gPointerIconClassInfo.bitmap);
+            if (iconBitmapObj) {
+                SkBitmap* iconBitmap = GraphicsJNI::getNativeBitmap(env, iconBitmapObj);
+                if (iconBitmap) {
+                    controller->setPointerIcon(iconBitmap, iconHotSpotX, iconHotSpotY);
+                }
+                env->DeleteLocalRef(iconBitmapObj);
+            }
+            env->DeleteLocalRef(iconObj);
+        }
+    }
+    return controller;
+}
+
 void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode,
         int32_t switchValue, uint32_t policyFlags) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
@@ -481,50 +442,46 @@
 }
 
 nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-        const sp<InputChannel>& inputChannel) {
+        const sp<InputWindowHandle>& inputWindowHandle) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
     LOGD("notifyANR");
 #endif
 
     JNIEnv* env = jniEnv();
 
-    jobject tokenObjLocal;
-    if (inputApplicationHandle.get()) {
-        ApplicationToken* token = static_cast<ApplicationToken*>(inputApplicationHandle.get());
-        jweak tokenObjWeak = token->getTokenObj();
-        tokenObjLocal = env->NewLocalRef(tokenObjWeak);
-    } else {
-        tokenObjLocal = NULL;
-    }
+    jobject inputApplicationHandleObj =
+            getInputApplicationHandleObjLocalRef(env, inputApplicationHandle);
+    jobject inputWindowHandleObj =
+            getInputWindowHandleObjLocalRef(env, inputWindowHandle);
 
-    jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
     jlong newTimeout = env->CallLongMethod(mCallbacksObj,
-                gCallbacksClassInfo.notifyANR, tokenObjLocal, inputChannelObjLocal);
+                gCallbacksClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj);
     if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
         newTimeout = 0; // abort dispatch
     } else {
         assert(newTimeout >= 0);
     }
 
-    env->DeleteLocalRef(tokenObjLocal);
-    env->DeleteLocalRef(inputChannelObjLocal);
+    env->DeleteLocalRef(inputWindowHandleObj);
+    env->DeleteLocalRef(inputApplicationHandleObj);
     return newTimeout;
 }
 
-void NativeInputManager::notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
+void NativeInputManager::notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
-    LOGD("notifyInputChannelBroken - inputChannel='%s'", inputChannel->getName().string());
+    LOGD("notifyInputChannelBroken");
 #endif
 
     JNIEnv* env = jniEnv();
 
-    jobject inputChannelObjLocal = getInputChannelObjLocal(env, inputChannel);
-    if (inputChannelObjLocal) {
+    jobject inputWindowHandleObj =
+            getInputWindowHandleObjLocalRef(env, inputWindowHandle);
+    if (inputWindowHandleObj) {
         env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
-                inputChannelObjLocal);
+                inputWindowHandleObj);
         checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
 
-        env->DeleteLocalRef(inputChannelObjLocal);
+        env->DeleteLocalRef(inputWindowHandleObj);
     }
 }
 
@@ -562,160 +519,32 @@
 
     jsize length = env->GetArrayLength(windowObjArray);
     for (jsize i = 0; i < length; i++) {
-        jobject inputTargetObj = env->GetObjectArrayElement(windowObjArray, i);
-        if (! inputTargetObj) {
+        jobject windowObj = env->GetObjectArrayElement(windowObjArray, i);
+        if (! windowObj) {
             break; // found null element indicating end of used portion of the array
         }
 
         windows.push();
         InputWindow& window = windows.editTop();
-        bool valid = populateWindow(env, inputTargetObj, window);
-        if (! valid) {
+        android_server_InputWindow_toNative(env, windowObj, &window);
+        if (window.inputChannel == NULL) {
             windows.pop();
         }
-
-        env->DeleteLocalRef(inputTargetObj);
+        env->DeleteLocalRef(windowObj);
     }
 
     mInputManager->getDispatcher()->setInputWindows(windows);
 }
 
-bool NativeInputManager::populateWindow(JNIEnv* env, jobject windowObj,
-        InputWindow& outWindow) {
-    bool valid = false;
-
-    jobject inputChannelObj = env->GetObjectField(windowObj,
-            gInputWindowClassInfo.inputChannel);
-    if (inputChannelObj) {
-        sp<InputChannel> inputChannel =
-                android_view_InputChannel_getInputChannel(env, inputChannelObj);
-        if (inputChannel != NULL) {
-            jstring name = jstring(env->GetObjectField(windowObj,
-                    gInputWindowClassInfo.name));
-            jint layoutParamsFlags = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.layoutParamsFlags);
-            jint layoutParamsType = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.layoutParamsType);
-            jlong dispatchingTimeoutNanos = env->GetLongField(windowObj,
-                    gInputWindowClassInfo.dispatchingTimeoutNanos);
-            jint frameLeft = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.frameLeft);
-            jint frameTop = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.frameTop);
-            jint frameRight = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.frameRight);
-            jint frameBottom = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.frameBottom);
-            jint visibleFrameLeft = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.visibleFrameLeft);
-            jint visibleFrameTop = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.visibleFrameTop);
-            jint visibleFrameRight = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.visibleFrameRight);
-            jint visibleFrameBottom = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.visibleFrameBottom);
-            jint touchableAreaLeft = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.touchableAreaLeft);
-            jint touchableAreaTop = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.touchableAreaTop);
-            jint touchableAreaRight = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.touchableAreaRight);
-            jint touchableAreaBottom = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.touchableAreaBottom);
-            jboolean visible = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.visible);
-            jboolean canReceiveKeys = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.canReceiveKeys);
-            jboolean hasFocus = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.hasFocus);
-            jboolean hasWallpaper = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.hasWallpaper);
-            jboolean paused = env->GetBooleanField(windowObj,
-                    gInputWindowClassInfo.paused);
-            jint layer = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.layer);
-            jint ownerPid = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.ownerPid);
-            jint ownerUid = env->GetIntField(windowObj,
-                    gInputWindowClassInfo.ownerUid);
-
-            const char* nameStr = env->GetStringUTFChars(name, NULL);
-
-            outWindow.inputChannel = inputChannel;
-            outWindow.name.setTo(nameStr);
-            outWindow.layoutParamsFlags = layoutParamsFlags;
-            outWindow.layoutParamsType = layoutParamsType;
-            outWindow.dispatchingTimeout = dispatchingTimeoutNanos;
-            outWindow.frameLeft = frameLeft;
-            outWindow.frameTop = frameTop;
-            outWindow.frameRight = frameRight;
-            outWindow.frameBottom = frameBottom;
-            outWindow.visibleFrameLeft = visibleFrameLeft;
-            outWindow.visibleFrameTop = visibleFrameTop;
-            outWindow.visibleFrameRight = visibleFrameRight;
-            outWindow.visibleFrameBottom = visibleFrameBottom;
-            outWindow.touchableAreaLeft = touchableAreaLeft;
-            outWindow.touchableAreaTop = touchableAreaTop;
-            outWindow.touchableAreaRight = touchableAreaRight;
-            outWindow.touchableAreaBottom = touchableAreaBottom;
-            outWindow.visible = visible;
-            outWindow.canReceiveKeys = canReceiveKeys;
-            outWindow.hasFocus = hasFocus;
-            outWindow.hasWallpaper = hasWallpaper;
-            outWindow.paused = paused;
-            outWindow.layer = layer;
-            outWindow.ownerPid = ownerPid;
-            outWindow.ownerUid = ownerUid;
-
-            env->ReleaseStringUTFChars(name, nameStr);
-            env->DeleteLocalRef(name);
-            valid = true;
-        } else {
-            LOGW("Dropping input target because its input channel is not initialized.");
-        }
-
-        env->DeleteLocalRef(inputChannelObj);
-    } else {
-        LOGW("Dropping input target because the input channel object was null.");
-    }
-    return valid;
-}
-
 void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) {
     if (applicationObj) {
-        jstring nameObj = jstring(env->GetObjectField(applicationObj,
-                gInputApplicationClassInfo.name));
-        jlong dispatchingTimeoutNanos = env->GetLongField(applicationObj,
-                gInputApplicationClassInfo.dispatchingTimeoutNanos);
-        jobject tokenObj = env->GetObjectField(applicationObj,
-                gInputApplicationClassInfo.token);
-        jweak tokenObjWeak = env->NewWeakGlobalRef(tokenObj);
-        if (! tokenObjWeak) {
-            LOGE("Could not create weak reference for application token.");
-            LOGE_EX(env);
-            env->ExceptionClear();
-        }
-        env->DeleteLocalRef(tokenObj);
-
-        String8 name;
-        if (nameObj) {
-            const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
-            name.setTo(nameStr);
-            env->ReleaseStringUTFChars(nameObj, nameStr);
-            env->DeleteLocalRef(nameObj);
-        } else {
-            LOGE("InputApplication.name should not be null.");
-            name.setTo("unknown");
-        }
-
         InputApplication application;
-        application.name = name;
-        application.dispatchingTimeout = dispatchingTimeoutNanos;
-        application.handle = new ApplicationToken(tokenObjWeak);
-        mInputManager->getDispatcher()->setFocusedApplication(& application);
-    } else {
-        mInputManager->getDispatcher()->setFocusedApplication(NULL);
+        android_server_InputApplication_toNative(env, applicationObj, &application);
+        if (application.inputApplicationHandle != NULL) {
+            mInputManager->getDispatcher()->setFocusedApplication(&application);
+        }
     }
+    mInputManager->getDispatcher()->setFocusedApplication(NULL);
 }
 
 void NativeInputManager::setInputDispatchMode(bool enabled, bool frozen) {
@@ -807,7 +636,8 @@
     }
 }
 
-bool NativeInputManager::interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+bool NativeInputManager::interceptKeyBeforeDispatching(
+        const sp<InputWindowHandle>& inputWindowHandle,
         const KeyEvent* keyEvent, uint32_t policyFlags) {
     // Policy:
     // - Ignore untrusted events and pass them along.
@@ -817,13 +647,13 @@
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
-        // Note: inputChannel may be null.
-        jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
+        // Note: inputWindowHandle may be null.
+        jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
             jboolean consumed = env->CallBooleanMethod(mCallbacksObj,
                     gCallbacksClassInfo.interceptKeyBeforeDispatching,
-                    inputChannelObj, keyEventObj, policyFlags);
+                    inputWindowHandleObj, keyEventObj, policyFlags);
             bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
             android_view_KeyEvent_recycle(env, keyEventObj);
             env->DeleteLocalRef(keyEventObj);
@@ -831,12 +661,12 @@
         } else {
             LOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
         }
-        env->DeleteLocalRef(inputChannelObj);
+        env->DeleteLocalRef(inputWindowHandleObj);
     }
     return result;
 }
 
-bool NativeInputManager::dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
+bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
         const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
     // Policy:
     // - Ignore untrusted events and do not perform default handling.
@@ -844,13 +674,13 @@
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
-        // Note: inputChannel may be null.
-        jobject inputChannelObj = getInputChannelObjLocal(env, inputChannel);
+        // Note: inputWindowHandle may be null.
+        jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
             jobject fallbackKeyEventObj = env->CallObjectMethod(mCallbacksObj,
                     gCallbacksClassInfo.dispatchUnhandledKey,
-                    inputChannelObj, keyEventObj, policyFlags);
+                    inputWindowHandleObj, keyEventObj, policyFlags);
             checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey");
             android_view_KeyEvent_recycle(env, keyEventObj);
             env->DeleteLocalRef(keyEventObj);
@@ -867,7 +697,7 @@
         } else {
             LOGE("Failed to obtain key event object for dispatchUnhandledKey.");
         }
-        env->DeleteLocalRef(inputChannelObj);
+        env->DeleteLocalRef(inputWindowHandleObj);
     }
     return result;
 }
@@ -886,6 +716,7 @@
     return result;
 }
 
+
 // ----------------------------------------------------------------------------
 
 static sp<NativeInputManager> gNativeInputManager;
@@ -1010,7 +841,7 @@
 }
 
 static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
-        jobject inputChannelObj, jboolean monitor) {
+        jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
     if (checkInputManagerUnitialized(env)) {
         return;
     }
@@ -1022,9 +853,11 @@
         return;
     }
 
+    sp<InputWindowHandle> inputWindowHandle =
+            android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
 
     status_t status = gNativeInputManager->registerInputChannel(
-            env, inputChannel, inputChannelObj, monitor);
+            env, inputChannel, inputWindowHandle, monitor);
     if (status) {
         jniThrowRuntimeException(env, "Failed to register input channel.  "
                 "Check logs for details.");
@@ -1242,7 +1075,8 @@
             (void*) android_server_InputManager_nativeGetSwitchState },
     { "nativeHasKeys", "(II[I[Z)Z",
             (void*) android_server_InputManager_nativeHasKeys },
-    { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;Z)V",
+    { "nativeRegisterInputChannel",
+            "(Landroid/view/InputChannel;Lcom/android/server/InputWindowHandle;Z)V",
             (void*) android_server_InputManager_nativeRegisterInputChannel },
     { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
             (void*) android_server_InputManager_nativeUnregisterInputChannel },
@@ -1295,21 +1129,22 @@
             "notifyLidSwitchChanged", "(JZ)V");
 
     GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, gCallbacksClassInfo.clazz,
-            "notifyInputChannelBroken", "(Landroid/view/InputChannel;)V");
+            "notifyInputChannelBroken", "(Lcom/android/server/InputWindowHandle;)V");
 
     GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz,
-            "notifyANR", "(Ljava/lang/Object;Landroid/view/InputChannel;)J");
+            "notifyANR",
+            "(Lcom/android/server/InputApplicationHandle;Lcom/android/server/InputWindowHandle;)J");
 
     GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz,
             "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
 
     GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz,
             "interceptKeyBeforeDispatching",
-            "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Z");
+            "(Lcom/android/server/InputWindowHandle;Landroid/view/KeyEvent;I)Z");
 
     GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, gCallbacksClassInfo.clazz,
             "dispatchUnhandledKey",
-            "(Landroid/view/InputChannel;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
+            "(Lcom/android/server/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
 
     GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz,
             "checkInjectEventsPermission", "(II)Z");
@@ -1326,98 +1161,11 @@
     GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz,
             "getMaxEventsPerSecond", "()I");
 
-    // InputWindow
+    GET_METHOD_ID(gCallbacksClassInfo.getPointerLayer, gCallbacksClassInfo.clazz,
+            "getPointerLayer", "()I");
 
-    FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
-
-    GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
-            "inputChannel", "Landroid/view/InputChannel;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.name, gInputWindowClassInfo.clazz,
-            "name", "Ljava/lang/String;");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
-            "layoutParamsFlags", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
-            "layoutParamsType", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
-            "dispatchingTimeoutNanos", "J");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
-            "frameLeft", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
-            "frameTop", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
-            "frameRight", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
-            "frameBottom", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
-            "visibleFrameLeft", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
-            "visibleFrameTop", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
-            "visibleFrameRight", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
-            "visibleFrameBottom", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
-            "touchableAreaLeft", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
-            "touchableAreaTop", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
-            "touchableAreaRight", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
-            "touchableAreaBottom", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
-            "visible", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, gInputWindowClassInfo.clazz,
-            "canReceiveKeys", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
-            "hasFocus", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
-            "hasWallpaper", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
-            "paused", "Z");
-
-    GET_FIELD_ID(gInputWindowClassInfo.layer, gInputWindowClassInfo.clazz,
-            "layer", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
-            "ownerPid", "I");
-
-    GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
-            "ownerUid", "I");
-
-    // InputApplication
-
-    FIND_CLASS(gInputApplicationClassInfo.clazz, "com/android/server/InputApplication");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.name, gInputApplicationClassInfo.clazz,
-            "name", "Ljava/lang/String;");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.dispatchingTimeoutNanos,
-            gInputApplicationClassInfo.clazz,
-            "dispatchingTimeoutNanos", "J");
-
-    GET_FIELD_ID(gInputApplicationClassInfo.token, gInputApplicationClassInfo.clazz,
-            "token", "Ljava/lang/Object;");
+    GET_METHOD_ID(gCallbacksClassInfo.getPointerIcon, gCallbacksClassInfo.clazz,
+            "getPointerIcon", "()Lcom/android/server/InputManager$PointerIcon;");
 
     // KeyEvent
 
@@ -1465,6 +1213,19 @@
     GET_FIELD_ID(gConfigurationClassInfo.navigation, gConfigurationClassInfo.clazz,
             "navigation", "I");
 
+    // PointerIcon
+
+    FIND_CLASS(gPointerIconClassInfo.clazz, "com/android/server/InputManager$PointerIcon");
+
+    GET_FIELD_ID(gPointerIconClassInfo.bitmap, gPointerIconClassInfo.clazz,
+            "bitmap", "Landroid/graphics/Bitmap;");
+
+    GET_FIELD_ID(gPointerIconClassInfo.hotSpotX, gPointerIconClassInfo.clazz,
+            "hotSpotX", "F");
+
+    GET_FIELD_ID(gPointerIconClassInfo.hotSpotY, gPointerIconClassInfo.clazz,
+            "hotSpotY", "F");
+
     return 0;
 }
 
diff --git a/services/jni/com_android_server_InputWindow.cpp b/services/jni/com_android_server_InputWindow.cpp
new file mode 100644
index 0000000..a4609a0
--- /dev/null
+++ b/services/jni/com_android_server_InputWindow.cpp
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputWindow"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <android_view_InputChannel.h>
+#include "com_android_server_InputWindow.h"
+#include "com_android_server_InputWindowHandle.h"
+
+namespace android {
+
+static struct {
+    jclass clazz;
+
+    jfieldID inputWindowHandle;
+    jfieldID inputChannel;
+    jfieldID name;
+    jfieldID layoutParamsFlags;
+    jfieldID layoutParamsType;
+    jfieldID dispatchingTimeoutNanos;
+    jfieldID frameLeft;
+    jfieldID frameTop;
+    jfieldID frameRight;
+    jfieldID frameBottom;
+    jfieldID visibleFrameLeft;
+    jfieldID visibleFrameTop;
+    jfieldID visibleFrameRight;
+    jfieldID visibleFrameBottom;
+    jfieldID touchableAreaLeft;
+    jfieldID touchableAreaTop;
+    jfieldID touchableAreaRight;
+    jfieldID touchableAreaBottom;
+    jfieldID visible;
+    jfieldID canReceiveKeys;
+    jfieldID hasFocus;
+    jfieldID hasWallpaper;
+    jfieldID paused;
+    jfieldID layer;
+    jfieldID ownerPid;
+    jfieldID ownerUid;
+} gInputWindowClassInfo;
+
+
+// --- Global functions ---
+
+void android_server_InputWindow_toNative(
+        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow) {
+    jobject inputWindowHandleObj = env->GetObjectField(inputWindowObj,
+            gInputWindowClassInfo.inputWindowHandle);
+    if (inputWindowHandleObj) {
+        outInputWindow->inputWindowHandle =
+                android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
+        env->DeleteLocalRef(inputWindowHandleObj);
+    } else {
+        outInputWindow->inputWindowHandle = NULL;
+    }
+
+    jobject inputChannelObj = env->GetObjectField(inputWindowObj,
+            gInputWindowClassInfo.inputChannel);
+    if (inputChannelObj) {
+        outInputWindow->inputChannel =
+                android_view_InputChannel_getInputChannel(env, inputChannelObj);
+        env->DeleteLocalRef(inputChannelObj);
+    } else {
+        outInputWindow->inputChannel = NULL;
+    }
+
+    jstring nameObj = jstring(env->GetObjectField(inputWindowObj,
+            gInputWindowClassInfo.name));
+    if (nameObj) {
+        const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
+        outInputWindow->name.setTo(nameStr);
+        env->ReleaseStringUTFChars(nameObj, nameStr);
+        env->DeleteLocalRef(nameObj);
+    } else {
+        LOGE("InputWindow.name should not be null.");
+        outInputWindow->name.setTo("unknown");
+    }
+
+    outInputWindow->layoutParamsFlags = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.layoutParamsFlags);
+    outInputWindow->layoutParamsType = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.layoutParamsType);
+    outInputWindow->dispatchingTimeout = env->GetLongField(inputWindowObj,
+            gInputWindowClassInfo.dispatchingTimeoutNanos);
+    outInputWindow->frameLeft = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.frameLeft);
+    outInputWindow->frameTop = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.frameTop);
+    outInputWindow->frameRight = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.frameRight);
+    outInputWindow->frameBottom = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.frameBottom);
+    outInputWindow->visibleFrameLeft = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.visibleFrameLeft);
+    outInputWindow->visibleFrameTop = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.visibleFrameTop);
+    outInputWindow->visibleFrameRight = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.visibleFrameRight);
+    outInputWindow->visibleFrameBottom = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.visibleFrameBottom);
+    outInputWindow->touchableAreaLeft = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.touchableAreaLeft);
+    outInputWindow->touchableAreaTop = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.touchableAreaTop);
+    outInputWindow->touchableAreaRight = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.touchableAreaRight);
+    outInputWindow->touchableAreaBottom = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.touchableAreaBottom);
+    outInputWindow->visible = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.visible);
+    outInputWindow->canReceiveKeys = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.canReceiveKeys);
+    outInputWindow->hasFocus = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.hasFocus);
+    outInputWindow->hasWallpaper = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.hasWallpaper);
+    outInputWindow->paused = env->GetBooleanField(inputWindowObj,
+            gInputWindowClassInfo.paused);
+    outInputWindow->layer = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.layer);
+    outInputWindow->ownerPid = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.ownerPid);
+    outInputWindow->ownerUid = env->GetIntField(inputWindowObj,
+            gInputWindowClassInfo.ownerUid);
+}
+
+
+// --- JNI ---
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputWindow(JNIEnv* env) {
+    FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
+
+    GET_FIELD_ID(gInputWindowClassInfo.inputWindowHandle, gInputWindowClassInfo.clazz,
+            "inputWindowHandle", "Lcom/android/server/InputWindowHandle;");
+
+    GET_FIELD_ID(gInputWindowClassInfo.inputChannel, gInputWindowClassInfo.clazz,
+            "inputChannel", "Landroid/view/InputChannel;");
+
+    GET_FIELD_ID(gInputWindowClassInfo.name, gInputWindowClassInfo.clazz,
+            "name", "Ljava/lang/String;");
+
+    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsFlags, gInputWindowClassInfo.clazz,
+            "layoutParamsFlags", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.layoutParamsType, gInputWindowClassInfo.clazz,
+            "layoutParamsType", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.dispatchingTimeoutNanos, gInputWindowClassInfo.clazz,
+            "dispatchingTimeoutNanos", "J");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameLeft, gInputWindowClassInfo.clazz,
+            "frameLeft", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameTop, gInputWindowClassInfo.clazz,
+            "frameTop", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameRight, gInputWindowClassInfo.clazz,
+            "frameRight", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
+            "frameBottom", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
+            "visibleFrameLeft", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
+            "visibleFrameTop", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
+            "visibleFrameRight", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
+            "visibleFrameBottom", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
+            "touchableAreaLeft", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
+            "touchableAreaTop", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
+            "touchableAreaRight", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
+            "touchableAreaBottom", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
+            "visible", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.canReceiveKeys, gInputWindowClassInfo.clazz,
+            "canReceiveKeys", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.hasFocus, gInputWindowClassInfo.clazz,
+            "hasFocus", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.hasWallpaper, gInputWindowClassInfo.clazz,
+            "hasWallpaper", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.paused, gInputWindowClassInfo.clazz,
+            "paused", "Z");
+
+    GET_FIELD_ID(gInputWindowClassInfo.layer, gInputWindowClassInfo.clazz,
+            "layer", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.ownerPid, gInputWindowClassInfo.clazz,
+            "ownerPid", "I");
+
+    GET_FIELD_ID(gInputWindowClassInfo.ownerUid, gInputWindowClassInfo.clazz,
+            "ownerUid", "I");
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindow.h b/services/jni/com_android_server_InputWindow.h
new file mode 100644
index 0000000..eaf7bde
--- /dev/null
+++ b/services/jni/com_android_server_InputWindow.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_WINDOW_H
+#define _ANDROID_SERVER_INPUT_WINDOW_H
+
+#include <input/InputWindow.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+extern void android_server_InputWindow_toNative(
+        JNIEnv* env, jobject inputWindowObj, InputWindow* outInputWindow);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_WINDOW_H
diff --git a/services/jni/com_android_server_InputWindowHandle.cpp b/services/jni/com_android_server_InputWindowHandle.cpp
new file mode 100644
index 0000000..4d66212
--- /dev/null
+++ b/services/jni/com_android_server_InputWindowHandle.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "InputWindowHandle"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/threads.h>
+
+#include "com_android_server_InputWindowHandle.h"
+#include "com_android_server_InputApplicationHandle.h"
+
+namespace android {
+
+static struct {
+    jclass clazz;
+
+    jfieldID ptr;
+    jfieldID inputApplicationHandle;
+} gInputWindowHandleClassInfo;
+
+static Mutex gHandleMutex;
+
+
+// --- NativeInputWindowHandle ---
+
+NativeInputWindowHandle::NativeInputWindowHandle(
+        const sp<InputApplicationHandle>& inputApplicationHandle, jweak objWeak) :
+        InputWindowHandle(inputApplicationHandle),
+        mObjWeak(objWeak) {
+}
+
+NativeInputWindowHandle::~NativeInputWindowHandle() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    env->DeleteWeakGlobalRef(mObjWeak);
+}
+
+jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) {
+    return env->NewLocalRef(mObjWeak);
+}
+
+
+// --- Global functions ---
+
+sp<NativeInputWindowHandle> android_server_InputWindowHandle_getHandle(
+        JNIEnv* env, jobject inputWindowHandleObj) {
+    if (!inputWindowHandleObj) {
+        return NULL;
+    }
+
+    AutoMutex _l(gHandleMutex);
+
+    int ptr = env->GetIntField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr);
+    NativeInputWindowHandle* handle;
+    if (ptr) {
+        handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
+    } else {
+        jobject inputApplicationHandleObj = env->GetObjectField(inputWindowHandleObj,
+                gInputWindowHandleClassInfo.inputApplicationHandle);
+        sp<InputApplicationHandle> inputApplicationHandle =
+                android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
+        env->DeleteLocalRef(inputApplicationHandleObj);
+
+        jweak objWeak = env->NewWeakGlobalRef(inputWindowHandleObj);
+        handle = new NativeInputWindowHandle(inputApplicationHandle, objWeak);
+        handle->incStrong(inputWindowHandleObj);
+        env->SetIntField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr,
+                reinterpret_cast<int>(handle));
+    }
+    return handle;
+}
+
+
+// --- JNI ---
+
+static void android_server_InputWindowHandle_nativeDispose(JNIEnv* env, jobject obj) {
+    AutoMutex _l(gHandleMutex);
+
+    int ptr = env->GetIntField(obj, gInputWindowHandleClassInfo.ptr);
+    if (ptr) {
+        env->SetIntField(obj, gInputWindowHandleClassInfo.ptr, 0);
+
+        NativeInputWindowHandle* handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
+        handle->decStrong(obj);
+    }
+}
+
+
+static JNINativeMethod gInputWindowHandleMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeDispose", "()V",
+            (void*) android_server_InputWindowHandle_nativeDispose },
+};
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_InputWindowHandle(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "com/android/server/InputWindowHandle",
+            gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods));
+    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    FIND_CLASS(gInputWindowHandleClassInfo.clazz, "com/android/server/InputWindowHandle");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, gInputWindowHandleClassInfo.clazz,
+            "ptr", "I");
+
+    GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle,
+            gInputWindowHandleClassInfo.clazz,
+            "inputApplicationHandle", "Lcom/android/server/InputApplicationHandle;");
+
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/com_android_server_InputWindowHandle.h b/services/jni/com_android_server_InputWindowHandle.h
new file mode 100644
index 0000000..43f2a6b
--- /dev/null
+++ b/services/jni/com_android_server_InputWindowHandle.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
+#define _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
+
+#include <input/InputWindow.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+namespace android {
+
+class NativeInputWindowHandle : public InputWindowHandle {
+public:
+    NativeInputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
+            jweak objWeak);
+    virtual ~NativeInputWindowHandle();
+
+    jobject getInputWindowHandleObjLocalRef(JNIEnv* env);
+
+private:
+    jweak mObjWeak;
+};
+
+
+extern sp<NativeInputWindowHandle> android_server_InputWindowHandle_getHandle(
+        JNIEnv* env, jobject inputWindowHandleObj);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
diff --git a/services/jni/com_android_server_UsbService.cpp b/services/jni/com_android_server_UsbService.cpp
deleted file mode 100644
index d8b2418..0000000
--- a/services/jni/com_android_server_UsbService.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "UsbService"
-#include "utils/Log.h"
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include "android_runtime/AndroidRuntime.h"
-#include "utils/Vector.h"
-
-#include <usbhost/usbhost.h>
-#include <linux/version.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
-#include <linux/usb/ch9.h>
-#else
-#include <linux/usb_ch9.h>
-#endif
-
-#include <stdio.h>
-
-namespace android
-{
-
-static jmethodID method_usbCameraAdded;
-static jmethodID method_usbCameraRemoved;
-
-Vector<int> mDeviceList;
-
-static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
-    if (env->ExceptionCheck()) {
-        LOGE("An exception was thrown by callback '%s'.", methodName);
-        LOGE_EX(env);
-        env->ExceptionClear();
-    }
-}
-
-static int usb_device_added(const char *devname, void* client_data) {
-    // check to see if it is a camera
-    struct usb_descriptor_header* desc;
-    struct usb_descriptor_iter iter;
-
-    struct usb_device *device = usb_device_open(devname);
-    if (!device) {
-        LOGE("usb_device_open failed\n");
-        return 0;
-    }
-
-    usb_descriptor_iter_init(device, &iter);
-
-    while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {
-        if (desc->bDescriptorType == USB_DT_INTERFACE) {
-            struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;
-
-            if (interface->bInterfaceClass == USB_CLASS_STILL_IMAGE &&
-                interface->bInterfaceSubClass == 1 && // Still Image Capture
-                interface->bInterfaceProtocol == 1)     // Picture Transfer Protocol (PIMA 15470)
-            {
-                LOGD("Found camera: \"%s\" \"%s\"\n", usb_device_get_manufacturer_name(device),
-                        usb_device_get_product_name(device));
-
-                // interface should be followed by three endpoints
-                struct usb_endpoint_descriptor *ep;
-                struct usb_endpoint_descriptor *ep_in_desc = NULL;
-                struct usb_endpoint_descriptor *ep_out_desc = NULL;
-                struct usb_endpoint_descriptor *ep_intr_desc = NULL;
-                for (int i = 0; i < 3; i++) {
-                    ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
-                    if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) {
-                        LOGE("endpoints not found\n");
-                        goto done;
-                    }
-                    if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
-                        if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-                            ep_in_desc = ep;
-                        else
-                            ep_out_desc = ep;
-                    } else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT &&
-                        ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
-                        ep_intr_desc = ep;
-                    }
-                }
-                if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) {
-                    LOGE("endpoints not found\n");
-                    goto done;
-                }
-
-                // if we got here, we found a camera
-                JNIEnv* env = AndroidRuntime::getJNIEnv();
-                jobject thiz = (jobject)client_data;
-
-                int id = usb_device_get_unique_id_from_name(devname);
-                mDeviceList.add(id);
-
-                env->CallVoidMethod(thiz, method_usbCameraAdded, id);
-                checkAndClearExceptionFromCallback(env, __FUNCTION__);
-            }
-        }
-    }
-done:
-    usb_device_close(device);
-    return 0;
-}
-
-static int usb_device_removed(const char *devname, void* client_data) {
-    int id = usb_device_get_unique_id_from_name(devname);
-
-    // see if it is a device we know about
-    for (int i = 0; i < mDeviceList.size(); i++) {
-        if (id  == mDeviceList[i]) {
-            mDeviceList.removeAt(i);
-
-            JNIEnv* env = AndroidRuntime::getJNIEnv();
-            jobject thiz = (jobject)client_data;
-
-            env->CallVoidMethod(thiz, method_usbCameraRemoved, id);
-            checkAndClearExceptionFromCallback(env, __FUNCTION__);
-            break;
-        }
-    }
-    return 0;
-}
-
-static void android_server_UsbService_monitorUsbHostBus(JNIEnv *env, jobject thiz)
-{
-    struct usb_host_context* context = usb_host_init();
-    if (!context) {
-        LOGE("usb_host_init failed");
-        return;
-    }
-    // this will never return so it is safe to pass thiz directly
-    usb_host_run(context, usb_device_added, usb_device_removed, NULL, (void *)thiz);
-}
-
-static JNINativeMethod method_table[] = {
-    { "monitorUsbHostBus", "()V", (void*)android_server_UsbService_monitorUsbHostBus }
-};
-
-int register_android_server_UsbService(JNIEnv *env)
-{
-    jclass clazz = env->FindClass("com/android/server/UsbService");
-    if (clazz == NULL) {
-        LOGE("Can't find com/android/server/UsbService");
-        return -1;
-    }
-    method_usbCameraAdded = env->GetMethodID(clazz, "usbCameraAdded", "(I)V");
-    if (method_usbCameraAdded == NULL) {
-        LOGE("Can't find usbCameraAdded");
-        return -1;
-    }
-    method_usbCameraRemoved = env->GetMethodID(clazz, "usbCameraRemoved", "(I)V");
-    if (method_usbCameraRemoved == NULL) {
-        LOGE("Can't find usbCameraRemoved");
-        return -1;
-    }
-
-    return jniRegisterNativeMethods(env, "com/android/server/UsbService",
-            method_table, NELEM(method_table));
-}
-
-};
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index 613683b..bdd6d80 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -6,10 +6,13 @@
 namespace android {
 int register_android_server_AlarmManagerService(JNIEnv* env);
 int register_android_server_BatteryService(JNIEnv* env);
+int register_android_server_InputApplication(JNIEnv* env);
+int register_android_server_InputApplicationHandle(JNIEnv* env);
+int register_android_server_InputWindow(JNIEnv* env);
+int register_android_server_InputWindowHandle(JNIEnv* env);
 int register_android_server_InputManager(JNIEnv* env);
 int register_android_server_LightsService(JNIEnv* env);
 int register_android_server_PowerManagerService(JNIEnv* env);
-int register_android_server_UsbService(JNIEnv* env);
 int register_android_server_VibratorService(JNIEnv* env);
 int register_android_server_SystemServer(JNIEnv* env);
 int register_android_server_location_GpsLocationProvider(JNIEnv* env);
@@ -29,11 +32,14 @@
     LOG_ASSERT(env, "Could not retrieve the env!");
 
     register_android_server_PowerManagerService(env);
+    register_android_server_InputApplication(env);
+    register_android_server_InputApplicationHandle(env);
+    register_android_server_InputWindow(env);
+    register_android_server_InputWindowHandle(env);
     register_android_server_InputManager(env);
     register_android_server_LightsService(env);
     register_android_server_AlarmManagerService(env);
     register_android_server_BatteryService(env);
-    register_android_server_UsbService(env);
     register_android_server_VibratorService(env);
     register_android_server_SystemServer(env);
     register_android_server_location_GpsLocationProvider(env);
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 8a021cb..0c1fcf9 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -503,12 +503,18 @@
 
 void LayerBase::setBufferCrop(const Rect& crop) {
     if (!crop.isEmpty()) {
-        mBufferCrop = crop;
+        if (mBufferCrop != crop) {
+            mBufferCrop = crop;
+            mFlinger->invalidateHwcGeometry();
+        }
     }
 }
 
 void LayerBase::setBufferTransform(uint32_t transform) {
-    mBufferTransform = transform;
+    if (mBufferTransform != transform) {
+        mBufferTransform = transform;
+        mFlinger->invalidateHwcGeometry();
+    }
 }
 
 void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7c4790f..154b822 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -144,6 +144,11 @@
     return bclient;
 }
 
+sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
+{
+    sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
+    return gba;
+}
 
 const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
 {
@@ -460,7 +465,7 @@
         handleTransactionLocked(transactionFlags, ditchedLayers);
         mLastTransactionTime = systemTime() - now;
         mDebugInTransaction = 0;
-        mHwWorkListDirty = true;
+        invalidateHwcGeometry();
         // here the transaction has been committed
     }
 
@@ -726,13 +731,18 @@
 
             mWormholeRegion = screenRegion.subtract(opaqueRegion);
             mVisibleRegionsDirty = false;
-            mHwWorkListDirty = true;
+            invalidateHwcGeometry();
         }
 
     unlockPageFlip(currentLayers);
     mDirtyRegion.andSelf(screenRegion);
 }
 
+void SurfaceFlinger::invalidateHwcGeometry()
+{
+    mHwWorkListDirty = true;
+}
+
 bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
 {
     bool recomputeVisibleRegions = false;
@@ -1099,8 +1109,12 @@
 
 status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
 {
-    // remove the layer from the main list (through a transaction).
+    // First add the layer to the purgatory list, which makes sure it won't
+    // go away, then remove it from the main list (through a transaction).
     ssize_t err = removeLayer_l(layerBase);
+    if (err >= 0) {
+        mLayerPurgatory.add(layerBase);
+    }
 
     layerBase->onRemoved();
 
@@ -1349,6 +1363,19 @@
              * to use the purgatory.
              */
             status_t err = flinger->removeLayer_l(l);
+            if (err == NAME_NOT_FOUND) {
+                // The surface wasn't in the current list, which means it was
+                // removed already, which means it is in the purgatory,
+                // and need to be removed from there.
+                // This needs to happen from the main thread since its dtor
+                // must run from there (b/c of OpenGL ES). Additionally, we
+                // can't really acquire our internal lock from
+                // destroySurface() -- see postMessage() below.
+                ssize_t idx = flinger->mLayerPurgatory.remove(l);
+                LOGE_IF(idx < 0,
+                        "layer=%p is not in the purgatory list", l.get());
+            }
+
             LOGE_IF(err<0 && err != NAME_NOT_FOUND,
                     "error removing layer=%p (%s)", l.get(), strerror(-err));
             return true;
@@ -1586,7 +1613,7 @@
             case 1008:  // toggle use of hw composer
                 n = data.readInt32();
                 mDebugDisableHWC = n ? 1 : 0;
-                mHwWorkListDirty = true;
+                invalidateHwcGeometry();
                 // fall-through...
             case 1004:{ // repaint everything
                 Mutex::Autolock _l(mStateLock);
@@ -2123,6 +2150,7 @@
 
         // invert everything, b/c glReadPixel() below will invert the FB
         glViewport(0, 0, sw, sh);
+        glScissor(0, 0, sw, sh);
         glMatrixMode(GL_PROJECTION);
         glPushMatrix();
         glLoadIdentity();
@@ -2132,6 +2160,7 @@
         // redraw the screen entirely...
         glClearColor(0,0,0,1);
         glClear(GL_COLOR_BUFFER_BIT);
+
         const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
         const size_t count = layers.size();
         for (size_t i=0 ; i<count ; ++i) {
@@ -2169,7 +2198,6 @@
                 result = NO_MEMORY;
             }
         }
-
         glEnable(GL_SCISSOR_TEST);
         glViewport(0, 0, hw_w, hw_h);
         glMatrixMode(GL_PROJECTION);
@@ -2445,6 +2473,39 @@
 
 // ---------------------------------------------------------------------------
 
+GraphicBufferAlloc::GraphicBufferAlloc() {}
+
+GraphicBufferAlloc::~GraphicBufferAlloc() {}
+
+sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
+        PixelFormat format, uint32_t usage) {
+    sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
+    status_t err = graphicBuffer->initCheck();
+    if (err != 0) {
+        LOGE("createGraphicBuffer: init check failed: %d", err);
+        return 0;
+    } else if (graphicBuffer->handle == 0) {
+        LOGE("createGraphicBuffer: unable to create GraphicBuffer");
+        return 0;
+    }
+    Mutex::Autolock _l(mLock);
+    mBuffers.add(graphicBuffer);
+    return graphicBuffer;
+}
+
+void GraphicBufferAlloc::freeAllGraphicBuffersExcept(int bufIdx) {
+    Mutex::Autolock _l(mLock);
+    if (0 <= bufIdx && bufIdx < mBuffers.size()) {
+        sp<GraphicBuffer> b(mBuffers[bufIdx]);
+        mBuffers.clear();
+        mBuffers.add(b);
+    } else {
+        mBuffers.clear();
+    }
+}
+
+// ---------------------------------------------------------------------------
+
 GraphicPlane::GraphicPlane()
     : mHw(0)
 {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ca7d27d..eabdc64 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -34,6 +34,7 @@
 #include <ui/PixelFormat.h>
 #include <surfaceflinger/ISurfaceComposer.h>
 #include <surfaceflinger/ISurfaceComposerClient.h>
+#include <surfaceflinger/IGraphicBufferAlloc.h>
 
 #include "Barrier.h"
 #include "Layer.h"
@@ -119,6 +120,21 @@
     sp<SurfaceFlinger> mFlinger;
 };
 
+class GraphicBufferAlloc : public BnGraphicBufferAlloc
+{
+public:
+    GraphicBufferAlloc();
+    virtual ~GraphicBufferAlloc();
+
+    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+        PixelFormat format, uint32_t usage);
+    virtual void freeAllGraphicBuffersExcept(int bufIdx);
+
+private:
+    Vector<sp<GraphicBuffer> > mBuffers;
+    Mutex mLock;
+};
+
 // ---------------------------------------------------------------------------
 
 class GraphicPlane
@@ -184,6 +200,7 @@
     // ISurfaceComposer interface
     virtual sp<ISurfaceComposerClient>  createConnection();
     virtual sp<ISurfaceComposerClient>  createClientConnection();
+    virtual sp<IGraphicBufferAlloc>     createGraphicBufferAlloc();
     virtual sp<IMemoryHeap>             getCblk() const;
     virtual void                        bootFinished();
     virtual void                        openGlobalTransaction();
@@ -208,6 +225,7 @@
     status_t removeLayer(const sp<LayerBase>& layer);
     status_t addLayer(const sp<LayerBase>& layer);
     status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
+    void invalidateHwcGeometry();
 
     sp<Layer> getLayer(const sp<ISurface>& sur) const;
 
@@ -357,6 +375,7 @@
     volatile    int32_t                 mTransactionFlags;
     volatile    int32_t                 mTransactionCount;
                 Condition               mTransactionCV;
+                SortedVector< sp<LayerBase> > mLayerPurgatory;
                 bool                    mResizeTransationPending;
 
                 // protected by mStateLock (but we could use another lock)
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
index c7da3d4..5e4c136 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -1327,11 +1327,15 @@
      *            the password for APN, or NULL
      * @param authType
      *            the PAP / CHAP auth type. Values is one of SETUP_DATA_AUTH_*
+     * @param protocol
+     *            one of the PDP_type values in TS 27.007 section 10.1.1.
+     *            For example, "IP", "IPV6", "IPV4V6", or "PPP".
      * @param result
      *            Callback message
      */
-    public void setupDataCall(String radioTechnology, String profile, String apn,
-            String user, String password, String authType, Message result);
+    public void setupDataCall(String radioTechnology, String profile,
+            String apn, String user, String password, String authType,
+            String protocol, Message result);
 
     /**
      * Deactivate packet data connection
diff --git a/telephony/java/com/android/internal/telephony/DataCallState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
index d0f3d24..df12153 100644
--- a/telephony/java/com/android/internal/telephony/DataCallState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -17,16 +17,43 @@
 
 package com.android.internal.telephony;
 
+/**
+ * This is RIL_Data_Call_Response_v5 from ril.h
+ * TODO: Rename to DataCallResponse.
+ */
 public class DataCallState {
-    public int cid;
-    public int active;
-    public String type;
-    public String apn;
-    public String address;
+    public int version = 0;
+    public int status = 0;
+    public int cid = 0;
+    public int active = 0;
+    public String type = "";
+    public String ifname = "";
+    public String [] addresses = new String[0];
+    public String [] dnses = new String[0];
 
     @Override
     public String toString() {
-        return "DataCallState: {" + " cid: " + cid + ", active: " + active + ", type: " + type
-                + ", apn: " + apn + ", address: " + address + " }";
+        StringBuffer sb = new StringBuffer();
+        sb.append("DataCallState: {")
+           .append("version=").append(version)
+           .append(" status=").append(status)
+           .append(" cid=").append(cid)
+           .append(" active=").append(active)
+           .append(" type=").append(type)
+           .append("' ifname='").append(ifname);
+        sb.append("' addresses=[");
+        for (String addr : addresses) {
+            sb.append(addr);
+            sb.append(",");
+        }
+        if (addresses.length > 0) sb.deleteCharAt(sb.length()-1);
+        sb.append("] dnses=[");
+        for (String addr : dnses) {
+            sb.append(addr);
+            sb.append(",");
+        }
+        if (dnses.length > 0) sb.deleteCharAt(sb.length()-1);
+        sb.append("]}");
+        return sb.toString();
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index c143424..31c89d0 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -27,13 +27,11 @@
 import android.os.Message;
 import android.os.SystemProperties;
 import android.text.TextUtils;
-import android.util.EventLog;
 
 import java.net.InetAddress;
-import java.net.InterfaceAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
+import java.net.Inet4Address;
 import java.net.UnknownHostException;
+import java.util.HashMap;
 
 /**
  * {@hide}
@@ -55,48 +53,6 @@
  * <code>AsyncResult.exception = new Exception()</code>.
  *
  * The other public methods are provided for debugging.
- *
- * Below is the state machine description for this class.
- *
- * DataConnection {
- *   + mDefaultState {
- *        EVENT_RESET { clearSettings, notifiyDisconnectCompleted, >mInactiveState }.
- *        EVENT_CONNECT {  notifyConnectCompleted(FailCause.UNKNOWN) }.
- *        EVENT_DISCONNECT { notifyDisconnectCompleted }.
- *
- *        // Ignored messages
- *        EVENT_SETUP_DATA_CONNECTION_DONE,
- *        EVENT_GET_LAST_FAIL_DONE,
- *        EVENT_DEACTIVATE_DONE.
- *     }
- *   ++ # mInactiveState
- *        e(doNotifications)
- *        x(clearNotifications) {
- *            EVENT_RESET { notifiyDisconnectCompleted }.
- *            EVENT_CONNECT {startConnecting, >mActivatingState }.
- *        }
- *   ++   mActivatingState {
- *            EVENT_DISCONNECT { %EVENT_DISCONNECT }.
- *            EVENT_SETUP_DATA_CONNECTION_DONE {
- *                  if (SUCCESS) { notifyConnectCompleted(FailCause.NONE), >mActiveState }.
- *                  if (ERR_BadCommand) {
- *                         notifyConnectCompleted(FailCause.UNKNOWN), >mInactiveState }.
- *                  if (ERR_BadDns) { tearDownData($DEACTIVATE_DONE), >mDisconnectingBadDnsState }.
- *                  if (ERR_Other) { getLastDataCallFailCause($EVENT_GET_LAST_FAIL_DONE) }.
- *                  if (ERR_Stale) {}.
- *            }
- *            EVENT_GET_LAST_FAIL_DONE { notifyConnectCompleted(result), >mInactive }.
- *        }
- *   ++   mActiveState {
- *            EVENT_DISCONNECT { tearDownData($EVENT_DEACTIVATE_DONE), >mDisconnecting }.
- *        }
- *   ++   mDisconnectingState {
- *            EVENT_DEACTIVATE_DONE { notifyDisconnectCompleted, >mInactiveState }.
- *        }
- *   ++   mDisconnectingBadDnsState {
- *            EVENT_DEACTIVATE_DONE { notifyConnectComplete(FailCause.UNKNOWN), >mInactiveState }.
- *        }
- *  }
  */
 public abstract class DataConnection extends HierarchicalStateMachine {
     protected static final boolean DBG = true;
@@ -108,24 +64,22 @@
      * Class returned by onSetupConnectionCompleted.
      */
     protected enum SetupResult {
+        SUCCESS,
         ERR_BadCommand,
-        ERR_BadDns,
-        ERR_Other,
+        ERR_UnacceptableParameter,
+        ERR_GetLastErrorFromRil,
         ERR_Stale,
-        SUCCESS;
+        ERR_RilError;
 
         public FailCause mFailCause;
 
+        SetupResult() {
+            mFailCause = FailCause.fromInt(0);
+        }
+
         @Override
         public String toString() {
-            switch (this) {
-                case ERR_BadCommand: return "Bad Command";
-                case ERR_BadDns: return "Bad DNS";
-                case ERR_Other: return "Other error";
-                case ERR_Stale: return "Stale command";
-                case SUCCESS: return "SUCCESS";
-                default: return "unknown";
-            }
+            return name() + "  SetupResult.mFailCause=" + mFailCause;
         }
     }
 
@@ -167,31 +121,66 @@
     }
 
     /**
-     * Returned as the reason for a connection failure.
+     * Returned as the reason for a connection failure as defined
+     * by RIL_DataCallFailCause in ril.h and some local errors.
      */
     public enum FailCause {
-        NONE,
-        OPERATOR_BARRED,
-        INSUFFICIENT_RESOURCES,
-        MISSING_UNKNOWN_APN,
-        UNKNOWN_PDP_ADDRESS,
-        USER_AUTHENTICATION,
-        ACTIVATION_REJECT_GGSN,
-        ACTIVATION_REJECT_UNSPECIFIED,
-        SERVICE_OPTION_NOT_SUPPORTED,
-        SERVICE_OPTION_NOT_SUBSCRIBED,
-        SERVICE_OPTION_OUT_OF_ORDER,
-        NSAPI_IN_USE,
-        PROTOCOL_ERRORS,
-        REGISTRATION_FAIL,
-        GPRS_REGISTRATION_FAIL,
-        UNKNOWN,
+        NONE(0),
 
-        RADIO_NOT_AVAILABLE;
+        // This series of errors as specified by the standards
+        // specified in ril.h
+        OPERATOR_BARRED(0x08),
+        INSUFFICIENT_RESOURCES(0x1A),
+        MISSING_UNKNOWN_APN(0x1B),
+        UNKNOWN_PDP_ADDRESS_TYPE(0x1C),
+        USER_AUTHENTICATION(0x1D),
+        ACTIVATION_REJECT_GGSN(0x1E),
+        ACTIVATION_REJECT_UNSPECIFIED(0x1F),
+        SERVICE_OPTION_NOT_SUPPORTED(0x20),
+        SERVICE_OPTION_NOT_SUBSCRIBED(0x21),
+        SERVICE_OPTION_OUT_OF_ORDER(0x22),
+        NSAPI_IN_USE(0x23),
+        ONLY_IPV4_ALLOWED(0x32),
+        ONLY_IPV6_ALLOWED(0x33),
+        ONLY_SINGLE_BEARER_ALLOWED(0x34),
+        PROTOCOL_ERRORS(0x6F),
+
+        // Local errors generated by Vendor RIL
+        // specified in ril.h
+        REGISTRATION_FAIL(-1),
+        GPRS_REGISTRATION_FAIL(-2),
+        SIGNAL_LOST(-3),
+        PREF_RADIO_TECH_CHANGED(-4),
+        RADIO_POWER_OFF(-5),
+        TETHERED_CALL_ACTIVE(-6),
+        ERROR_UNSPECIFIED(0xFFFF),
+
+        // Errors generated by the Framework
+        // specified here
+        UNKNOWN(0x10000),
+        RADIO_NOT_AVAILABLE(0x10001),
+        UNACCEPTABLE_NETWORK_PARAMETER(0x10002);
+
+        private final int mErrorCode;
+        private static final HashMap<Integer, FailCause> sErrorCodeToFailCauseMap;
+        static {
+            sErrorCodeToFailCauseMap = new HashMap<Integer, FailCause>();
+            for (FailCause fc : values()) {
+                sErrorCodeToFailCauseMap.put(fc.ordinal(), fc);
+            }
+        }
+
+        FailCause(int errorCode) {
+            mErrorCode = errorCode;
+        }
+
+        int getErrorCode() {
+            return mErrorCode;
+        }
 
         public boolean isPermanentFail() {
             return (this == OPERATOR_BARRED) || (this == MISSING_UNKNOWN_APN) ||
-                   (this == UNKNOWN_PDP_ADDRESS) || (this == USER_AUTHENTICATION) ||
+                   (this == UNKNOWN_PDP_ADDRESS_TYPE) || (this == USER_AUTHENTICATION) ||
                    (this == SERVICE_OPTION_NOT_SUPPORTED) ||
                    (this == SERVICE_OPTION_NOT_SUBSCRIBED) || (this == NSAPI_IN_USE) ||
                    (this == PROTOCOL_ERRORS);
@@ -199,52 +188,21 @@
 
         public boolean isEventLoggable() {
             return (this == OPERATOR_BARRED) || (this == INSUFFICIENT_RESOURCES) ||
-                    (this == UNKNOWN_PDP_ADDRESS) || (this == USER_AUTHENTICATION) ||
+                    (this == UNKNOWN_PDP_ADDRESS_TYPE) || (this == USER_AUTHENTICATION) ||
                     (this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) ||
                     (this == SERVICE_OPTION_NOT_SUBSCRIBED) ||
                     (this == SERVICE_OPTION_NOT_SUPPORTED) ||
                     (this == SERVICE_OPTION_OUT_OF_ORDER) || (this == NSAPI_IN_USE) ||
-                    (this == PROTOCOL_ERRORS);
+                    (this == PROTOCOL_ERRORS) ||
+                    (this == UNACCEPTABLE_NETWORK_PARAMETER);
         }
 
-        @Override
-        public String toString() {
-            switch (this) {
-            case NONE:
-                return "No Error";
-            case OPERATOR_BARRED:
-                return "Operator Barred";
-            case INSUFFICIENT_RESOURCES:
-                return "Insufficient Resources";
-            case MISSING_UNKNOWN_APN:
-                return "Missing / Unknown APN";
-            case UNKNOWN_PDP_ADDRESS:
-                return "Unknown PDP Address";
-            case USER_AUTHENTICATION:
-                return "Error User Authentication";
-            case ACTIVATION_REJECT_GGSN:
-                return "Activation Reject GGSN";
-            case ACTIVATION_REJECT_UNSPECIFIED:
-                return "Activation Reject unspecified";
-            case SERVICE_OPTION_NOT_SUPPORTED:
-                return "Data Not Supported";
-            case SERVICE_OPTION_NOT_SUBSCRIBED:
-                return "Data Not subscribed";
-            case SERVICE_OPTION_OUT_OF_ORDER:
-                return "Data Services Out of Order";
-            case NSAPI_IN_USE:
-                return "NSAPI in use";
-            case PROTOCOL_ERRORS:
-                return "Protocol Errors";
-            case REGISTRATION_FAIL:
-                return "Network Registration Failure";
-            case GPRS_REGISTRATION_FAIL:
-                return "Data Network Registration Failure";
-            case RADIO_NOT_AVAILABLE:
-                return "Radio Not Available";
-            default:
-                return "Unknown Data Error";
+        public static FailCause fromInt(int errorCode) {
+            FailCause fc = sErrorCodeToFailCauseMap.get(errorCode);
+            if (fc == null) {
+                fc = UNKNOWN;
             }
+            return fc;
         }
     }
 
@@ -274,12 +232,11 @@
     Object userData;
 
     //***** Abstract methods
+    @Override
     public abstract String toString();
 
     protected abstract void onConnect(ConnectionParams cp);
 
-    protected abstract FailCause getFailCauseFromRequest(int rilCause);
-
     protected abstract boolean isDnsOk(String[] domainNameServers);
 
     protected abstract void log(String s);
@@ -300,7 +257,7 @@
             addState(mActivatingState, mDefaultState);
             addState(mActiveState, mDefaultState);
             addState(mDisconnectingState, mDefaultState);
-            addState(mDisconnectingBadDnsState, mDefaultState);
+            addState(mDisconnectingErrorCreatingConnection, mDefaultState);
         setInitialState(mInactiveState);
         if (DBG) log("DataConnection constructor X");
     }
@@ -408,20 +365,26 @@
      * @return SetupResult.
      */
     private SetupResult onSetupConnectionCompleted(AsyncResult ar) {
-        SetupResult result;
-        String[] response = ((String[]) ar.result);
+        DataCallState response = (DataCallState) ar.result;
         ConnectionParams cp = (ConnectionParams) ar.userObj;
+        SetupResult result;
 
         if (ar.exception != null) {
-            if (DBG) log("DataConnection Init failed " + ar.exception);
+            if (DBG) {
+                log("onSetupConnectionCompleted failed, ar.exception=" + ar.exception +
+                    " response=" + response);
+            }
 
             if (ar.exception instanceof CommandException
                     && ((CommandException) (ar.exception)).getCommandError()
                     == CommandException.Error.RADIO_NOT_AVAILABLE) {
                 result = SetupResult.ERR_BadCommand;
                 result.mFailCause = FailCause.RADIO_NOT_AVAILABLE;
+            } else if ((response == null) || (response.version < 4)) {
+                result = SetupResult.ERR_GetLastErrorFromRil;
             } else {
-                result = SetupResult.ERR_Other;
+                result = SetupResult.ERR_RilError;
+                result.mFailCause = FailCause.fromInt(response.status);
             }
         } else if (cp.tag != mTag) {
             if (DBG) {
@@ -429,69 +392,93 @@
             }
             result = SetupResult.ERR_Stale;
         } else {
-//            log("onSetupConnectionCompleted received " + response.length + " response strings:");
-//            for (int i = 0; i < response.length; i++) {
-//                log("  response[" + i + "]='" + response[i] + "'");
-//            }
+            log("onSetupConnectionCompleted received DataCallState: " + response);
 
             // Start with clean network properties and if we have
             // a failure we'll clear again at the bottom of this code.
             LinkProperties linkProperties = new LinkProperties();
-            if (response.length >= 2) {
-                cid = Integer.parseInt(response[0]);
-                String interfaceName = response[1];
-                result = SetupResult.SUCCESS;
-
+            if (response.status == FailCause.NONE.getErrorCode()) {
                 try {
-                    String prefix = "net." + interfaceName + ".";
-
-                    NetworkInterface networkInterface = NetworkInterface.getByName(interfaceName);
-                    linkProperties.setInterfaceName(interfaceName);
-
-                    // TODO: Get gateway and dns via RIL interface not property?
-                    String gatewayAddress = SystemProperties.get(prefix + "gw");
-                    linkProperties.setGateway(InetAddress.getByName(gatewayAddress));
-
-                    for (InterfaceAddress addr : networkInterface.getInterfaceAddresses()) {
-                        linkProperties.addLinkAddress(new LinkAddress(addr));
+                    cid = response.cid;
+                    linkProperties.setInterfaceName(response.ifname);
+                    for (String addr : response.addresses) {
+                        LinkAddress la;
+                        if (!InetAddress.isNumeric(addr)) {
+                            EventLogTags.writeBadIpAddress(addr);
+                            throw new UnknownHostException("Non-numeric ip addr=" + addr);
+                        }
+                        InetAddress ia = InetAddress.getByName(addr);
+                        if (ia instanceof Inet4Address) {
+                            la = new LinkAddress(ia, 32);
+                        } else {
+                            la = new LinkAddress(ia, 128);
+                        }
+                        linkProperties.addLinkAddress(la);
                     }
-                    // TODO: Get gateway and dns via RIL interface not property?
-                    String dnsServers[] = new String[2];
-                    dnsServers[0] = SystemProperties.get(prefix + "dns1");
-                    dnsServers[1] = SystemProperties.get(prefix + "dns2");
-                    if (isDnsOk(dnsServers)) {
-                        linkProperties.addDns(InetAddress.getByName(dnsServers[0]));
-                        linkProperties.addDns(InetAddress.getByName(dnsServers[1]));
+
+                    if (response.dnses.length != 0) {
+                        for (String addr : response.dnses) {
+                            if (!InetAddress.isNumeric(addr)) {
+                                EventLogTags.writePdpBadDnsAddress("dns=" + addr); 
+                                throw new UnknownHostException("Non-numeric dns addr=" + addr);
+                            }
+                            InetAddress ia = InetAddress.getByName(addr);
+                            linkProperties.addDns(ia);
+                        }
+                        result = SetupResult.SUCCESS;
                     } else {
-                        result = SetupResult.ERR_BadDns;
+                        String prefix = "net." + response.ifname + ".";
+
+                        String dnsServers[] = new String[2];
+                        dnsServers[0] = SystemProperties.get(prefix + "dns1");
+                        dnsServers[1] = SystemProperties.get(prefix + "dns2");
+                        if (isDnsOk(dnsServers)) {
+                            for (String dnsAddr : dnsServers) {
+                                if (!InetAddress.isNumeric(dnsAddr)) {
+                                    EventLogTags.writePdpBadDnsAddress("dnsAddr=" + dnsAddr);
+                                    throw new UnknownHostException("Non-numeric dns addr="
+                                                + dnsAddr);
+                                }
+                                InetAddress ia = InetAddress.getByName(dnsAddr);
+                                linkProperties.addDns(ia);
+                            }
+                            result = SetupResult.SUCCESS;
+                        } else {
+                            StringBuilder sb = new StringBuilder();
+                            for (String dnsAddr : dnsServers) {
+                                sb.append(dnsAddr);
+                                sb.append(" ");
+                            }
+                            EventLogTags.writePdpBadDnsAddress("Unacceptable dns addresses=" + sb);
+                            throw new UnknownHostException("Unacceptable dns addresses=" + sb);
+                        }
                     }
-                } catch (UnknownHostException e1) {
-                    log("onSetupCompleted: UnknowHostException " + e1);
-                    e1.printStackTrace();
-                    result = SetupResult.ERR_Other;
-                } catch (SocketException e2) {
-                    log("onSetupCompleted: SocketException " + e2);
-                    e2.printStackTrace();
-                    result = SetupResult.ERR_Other;
+                } catch (UnknownHostException e) {
+                    log("onSetupCompleted: UnknownHostException " + e);
+                    e.printStackTrace();
+                    result = SetupResult.ERR_UnacceptableParameter;
                 }
             } else {
-                log("onSetupCompleted: error; expected number of responses >= 2 was " +
-                        response.length);
-                result = SetupResult.ERR_Other;
+                if (response.version < 4) {
+                    result = SetupResult.ERR_GetLastErrorFromRil;
+                } else {
+                    result = SetupResult.ERR_RilError;
+                }
             }
 
             // An error occurred so clear properties
             if (result != SetupResult.SUCCESS) {
-                log("onSetupCompleted with an error clearing LinkProperties");
+                log("onSetupConnectionCompleted with an error, clearing LinkProperties");
                 linkProperties.clear();
             }
             mLinkProperties = linkProperties;
         }
 
         if (DBG) {
-            log("DataConnection setup result='" + result + "' on cid=" + cid);
+            log("onSetupConnectionCompleted: DataConnection setup result='"
+                    + result + "' on cid=" + cid);
             if (result == SetupResult.SUCCESS) {
-                log("LinkProperties: " + mLinkProperties.toString());
+                log("onSetupConnectionCompleted: LinkProperties: " + mLinkProperties.toString());
             }
         }
         return result;
@@ -640,6 +627,7 @@
                     cp = (ConnectionParams) ar.userObj;
 
                     SetupResult result = onSetupConnectionCompleted(ar);
+                    if (DBG) log("DcActivatingState onSetupConnectionCompleted result=" + result);
                     switch (result) {
                         case SUCCESS:
                             // All is well
@@ -653,26 +641,21 @@
                             mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
                             transitionTo(mInactiveState);
                             break;
-                        case ERR_BadDns:
-                            // Connection succeeded but DNS info is bad so disconnect
-                            StringBuilder dnsAddressesSb = new StringBuilder();
-                            for (InetAddress addr : mLinkProperties.getDnses()) {
-                                if (dnsAddressesSb.length() != 0) dnsAddressesSb.append(" ");
-                                dnsAddressesSb.append(addr.toString());
-                            }
-                            if (dnsAddressesSb.length() == 0) {
-                                dnsAddressesSb.append("no-dns-addresses");
-                            }
-                            EventLog.writeEvent(EventLogTags.PDP_BAD_DNS_ADDRESS,
-                                    dnsAddressesSb.toString());
+                        case ERR_UnacceptableParameter:
+                            // The addresses given from the RIL are bad
                             tearDownData(cp);
-                            transitionTo(mDisconnectingBadDnsState);
+                            transitionTo(mDisconnectingErrorCreatingConnection);
                             break;
-                        case ERR_Other:
-                            // Request the failure cause and process in this state
+                        case ERR_GetLastErrorFromRil:
+                            // Request failed and this is an old RIL
                             phone.mCM.getLastDataCallFailCause(
                                     obtainMessage(EVENT_GET_LAST_FAIL_DONE, cp));
                             break;
+                        case ERR_RilError:
+                            // Request failed and mFailCause has the reason
+                            mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
+                            transitionTo(mInactiveState);
+                            break;
                         case ERR_Stale:
                             // Request is stale, ignore.
                             break;
@@ -691,7 +674,7 @@
                         if (DBG) log("DcActivatingState msg.what=EVENT_GET_LAST_FAIL_DONE");
                         if (ar.exception == null) {
                             int rilFailCause = ((int[]) (ar.result))[0];
-                            cause = getFailCauseFromRequest(rilFailCause);
+                            cause = FailCause.fromInt(rilFailCause);
                         }
                         // Transition to inactive but send notifications after
                         // we've entered the mInactive state.
@@ -808,10 +791,9 @@
     private DcDisconnectingState mDisconnectingState = new DcDisconnectingState();
 
     /**
-     * The state machine is disconnecting after a bad dns setup
-     * was found in mInactivatingState.
+     * The state machine is disconnecting after an creating a connection.
      */
-    private class DcDisconnectingBadDnsState extends HierarchicalState {
+    private class DcDisconnectionErrorCreatingConnection extends HierarchicalState {
         @Override protected boolean processMessage(Message msg) {
             boolean retVal;
 
@@ -820,27 +802,38 @@
                     AsyncResult ar = (AsyncResult) msg.obj;
                     ConnectionParams cp = (ConnectionParams) ar.userObj;
                     if (cp.tag == mTag) {
-                        if (DBG) log("DcDisconnectingBadDnsState msg.what=EVENT_DEACTIVATE_DONE");
+                        if (DBG) {
+                            log("DcDisconnectionErrorCreatingConnection" +
+                                " msg.what=EVENT_DEACTIVATE_DONE");
+                        }
+
                         // Transition to inactive but send notifications after
                         // we've entered the mInactive state.
-                        mInactiveState.setEnterNotificationParams(cp, FailCause.UNKNOWN);
+                        mInactiveState.setEnterNotificationParams(cp,
+                                FailCause.UNACCEPTABLE_NETWORK_PARAMETER);
                         transitionTo(mInactiveState);
                     } else {
-                        if (DBG) log("DcDisconnectingBadDnsState EVENT_DEACTIVE_DONE stale dp.tag="
-                                + cp.tag + ", mTag=" + mTag);
+                        if (DBG) {
+                            log("DcDisconnectionErrorCreatingConnection EVENT_DEACTIVATE_DONE" +
+                                    " stale dp.tag=" + cp.tag + ", mTag=" + mTag);
+                        }
                     }
                     retVal = true;
                     break;
 
                 default:
-                    if (DBG) log("DcDisconnectingBadDnsState not handled msg.what=" + msg.what);
+                    if (DBG) {
+                        log("DcDisconnectionErrorCreatingConnection not handled msg.what="
+                                + msg.what);
+                    }
                     retVal = false;
                     break;
             }
             return retVal;
         }
     }
-    private DcDisconnectingBadDnsState mDisconnectingBadDnsState = new DcDisconnectingBadDnsState();
+    private DcDisconnectionErrorCreatingConnection mDisconnectingErrorCreatingConnection =
+                new DcDisconnectionErrorCreatingConnection();
 
     // ******* public interface
 
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 737342f..2343dd8 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -358,7 +358,7 @@
         return new ArrayList<DataConnection>(mDataConnections.values());
     }
 
-    protected boolean isApnTypeActive(String type) {
+    public boolean isApnTypeActive(String type) {
         // TODO: support simultaneous with List instead
         return mActiveApn != null && mActiveApn.canHandleType(type);
     }
diff --git a/telephony/java/com/android/internal/telephony/EventLogTags.logtags b/telephony/java/com/android/internal/telephony/EventLogTags.logtags
index b06c27d..9be7b80 100644
--- a/telephony/java/com/android/internal/telephony/EventLogTags.logtags
+++ b/telephony/java/com/android/internal/telephony/EventLogTags.logtags
@@ -53,3 +53,6 @@
 
 # CDMA service state transition
 50116 cdma_service_state_change (oldState|1|5), (oldDataState|1|5), (newState|1|5), (newDataState|1|5)
+
+# Bad IP address
+50117 bad_ip_address (ip_address|3)
diff --git a/telephony/java/com/android/internal/telephony/OperatorInfo.aidl b/telephony/java/com/android/internal/telephony/OperatorInfo.aidl
new file mode 100644
index 0000000..3ded8dd
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/OperatorInfo.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+/**
+ * Used to indicate that the OperatorInfo object is parcelable to aidl.
+ * This is a simple effort to make OperatorInfo parcelable rather than
+ * trying to make the conventional containing object (AsyncResult),
+ * implement parcelable.  This functionality is needed for the
+ * NetworkQueryService to fix 1128695
+ */
+parcelable OperatorInfo;
diff --git a/telephony/java/com/android/internal/telephony/OperatorInfo.java b/telephony/java/com/android/internal/telephony/OperatorInfo.java
new file mode 100644
index 0000000..1999cb3
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/OperatorInfo.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * {@hide}
+ */
+public class OperatorInfo implements Parcelable {
+    public enum State {
+        UNKNOWN,
+        AVAILABLE,
+        CURRENT,
+        FORBIDDEN;
+    }
+
+    private String operatorAlphaLong;
+    private String operatorAlphaShort;
+    private String operatorNumeric;
+
+    private State state = State.UNKNOWN;
+
+
+    public String
+    getOperatorAlphaLong() {
+        return operatorAlphaLong;
+    }
+
+    public String
+    getOperatorAlphaShort() {
+        return operatorAlphaShort;
+    }
+
+    public String
+    getOperatorNumeric() {
+        return operatorNumeric;
+    }
+
+    public State
+    getState() {
+        return state;
+    }
+
+    OperatorInfo(String operatorAlphaLong,
+                String operatorAlphaShort,
+                String operatorNumeric,
+                State state) {
+
+        this.operatorAlphaLong = operatorAlphaLong;
+        this.operatorAlphaShort = operatorAlphaShort;
+        this.operatorNumeric = operatorNumeric;
+
+        this.state = state;
+    }
+
+
+    public OperatorInfo(String operatorAlphaLong,
+                String operatorAlphaShort,
+                String operatorNumeric,
+                String stateString) {
+        this (operatorAlphaLong, operatorAlphaShort,
+                operatorNumeric, rilStateToState(stateString));
+    }
+
+    /**
+     * See state strings defined in ril.h RIL_REQUEST_QUERY_AVAILABLE_NETWORKS
+     */
+    private static State rilStateToState(String s) {
+        if (s.equals("unknown")) {
+            return State.UNKNOWN;
+        } else if (s.equals("available")) {
+            return State.AVAILABLE;
+        } else if (s.equals("current")) {
+            return State.CURRENT;
+        } else if (s.equals("forbidden")) {
+            return State.FORBIDDEN;
+        } else {
+            throw new RuntimeException(
+                "RIL impl error: Invalid network state '" + s + "'");
+        }
+    }
+
+
+    public String toString() {
+        return "OperatorInfo " + operatorAlphaLong
+                + "/" + operatorAlphaShort
+                + "/" + operatorNumeric
+                + "/" + state;
+    }
+
+    /**
+     * Parcelable interface implemented below.
+     * This is a simple effort to make OperatorInfo parcelable rather than
+     * trying to make the conventional containing object (AsyncResult),
+     * implement parcelable.  This functionality is needed for the
+     * NetworkQueryService to fix 1128695.
+     */
+
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Implement the Parcelable interface.
+     * Method to serialize a OperatorInfo object.
+     */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(operatorAlphaLong);
+        dest.writeString(operatorAlphaShort);
+        dest.writeString(operatorNumeric);
+        dest.writeSerializable(state);
+    }
+
+    /**
+     * Implement the Parcelable interface
+     * Method to deserialize a OperatorInfo object, or an array thereof.
+     */
+    public static final Creator<OperatorInfo> CREATOR =
+        new Creator<OperatorInfo>() {
+            public OperatorInfo createFromParcel(Parcel in) {
+                OperatorInfo opInfo = new OperatorInfo(
+                        in.readString(), /*operatorAlphaLong*/
+                        in.readString(), /*operatorAlphaShort*/
+                        in.readString(), /*operatorNumeric*/
+                        (State) in.readSerializable()); /*state*/
+                return opInfo;
+            }
+
+            public OperatorInfo[] newArray(int size) {
+                return new OperatorInfo[size];
+            }
+        };
+}
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 25ad48d..e2896d9b 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -27,7 +27,6 @@
 import android.telephony.SignalStrength;
 
 import com.android.internal.telephony.DataConnection;
-import com.android.internal.telephony.gsm.NetworkInfo;
 import com.android.internal.telephony.test.SimulatedRadioControl;
 
 import java.util.List;
@@ -132,6 +131,7 @@
     static final String FEATURE_ENABLE_SUPL = "enableSUPL";
     static final String FEATURE_ENABLE_DUN = "enableDUN";
     static final String FEATURE_ENABLE_HIPRI = "enableHIPRI";
+    static final String FEATURE_ENABLE_DUN_ALWAYS = "enableDUNAlways";
 
     /**
      * Return codes for <code>enableApnType()</code>
@@ -1055,7 +1055,7 @@
      * one of the following members:.<p>
      *<ul>
      * <li><code>response.obj.result</code> will be a <code>List</code> of
-     * <code>com.android.internal.telephony.gsm.NetworkInfo</code> objects, or</li>
+     * <code>OperatorInfo</code> objects, or</li>
      * <li><code>response.obj.exception</code> will be set with an exception
      * on failure.</li>
      * </ul>
@@ -1069,8 +1069,7 @@
      * @param response The message to dispatch when the network selection
      * is complete.
      *
-     * @see #selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo,
-     * android.os.Message )
+     * @see #selectNetworkManually(OperatorInfo, android.os.Message )
      */
     void setNetworkSelectionModeAutomatic(Message response);
 
@@ -1082,7 +1081,7 @@
      *
      * @see #setNetworkSelectionModeAutomatic(Message)
      */
-    void selectNetworkManually(NetworkInfo network,
+    void selectNetworkManually(OperatorInfo network,
                             Message response);
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index 219efbb..15b23bb 100644
--- a/telephony/java/com/android/internal/telephony/PhoneProxy.java
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -32,7 +32,6 @@
 
 import com.android.internal.telephony.cdma.CDMAPhone;
 import com.android.internal.telephony.gsm.GSMPhone;
-import com.android.internal.telephony.gsm.NetworkInfo;
 import com.android.internal.telephony.test.SimulatedRadioControl;
 
 import java.util.List;
@@ -550,7 +549,7 @@
         mActivePhone.setNetworkSelectionModeAutomatic(response);
     }
 
-    public void selectNetworkManually(NetworkInfo network, Message response) {
+    public void selectNetworkManually(OperatorInfo network, Message response) {
         mActivePhone.selectNetworkManually(network, response);
     }
 
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index c97ba6e..21c88f1 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -50,12 +50,12 @@
 import com.android.internal.telephony.CallForwardInfo;
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.DataCallState;
-import com.android.internal.telephony.gsm.NetworkInfo;
 import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
 import com.android.internal.telephony.gsm.SuppServiceNotification;
 import com.android.internal.telephony.IccCardApplication;
 import com.android.internal.telephony.IccCardStatus;
 import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.OperatorInfo;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.SmsResponse;
 import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
@@ -375,23 +375,26 @@
                 case EVENT_WAKE_LOCK_TIMEOUT:
                     // Haven't heard back from the last request.  Assume we're
                     // not getting a response and  release the wake lock.
-                    // TODO should we clean up mRequestList and mRequestPending
                     synchronized (mWakeLock) {
                         if (mWakeLock.isHeld()) {
-                            if (RILJ_LOGD) {
-                                synchronized (mRequestsList) {
-                                    int count = mRequestsList.size();
-                                    Log.d(LOG_TAG, "WAKE_LOCK_TIMEOUT " +
-                                        " mReqPending=" + mRequestMessagesPending +
-                                        " mRequestList=" + count);
-
-                                    for (int i = 0; i < count; i++) {
-                                        rr = mRequestsList.get(i);
-                                        Log.d(LOG_TAG, i + ": [" + rr.mSerial + "] " +
-                                            requestToString(rr.mRequest));
-
-                                    }
-                                }
+                            // The timer of WAKE_LOCK_TIMEOUT is reset with each
+                            // new send request. So when WAKE_LOCK_TIMEOUT occurs
+                            // all requests in mRequestList already waited at
+                            // least DEFAULT_WAKE_LOCK_TIMEOUT but no response.
+                            // Therefore all should be treated as lost requests.
+                            // Those lost requests return GENERIC_FAILURE and
+                            // request list is cleared.
+                            //
+                            // Note: mRequestMessagesPending shows how many
+                            //       requests are waiting to be sent (and before
+                            //       to be added in request list) since star the
+                            //       timer. It should be
+                            //       zero here since all request should already
+                            //       be put in request list while TIMEOUT occurs.
+                            clearRequestsList(GENERIC_FAILURE, true);
+                            if (mRequestMessagesPending != 0) {
+                                Log.e(LOG_TAG, "ERROR: mReqPending is NOT 0 at TIMEOUT, "
+                                    + "mReqPending = " + mRequestMessagesPending);
                             }
                             mWakeLock.release();
                         }
@@ -563,15 +566,7 @@
                 RILRequest.resetSerial();
 
                 // Clear request list on close
-                synchronized (mRequestsList) {
-                    for (int i = 0, sz = mRequestsList.size() ; i < sz ; i++) {
-                        RILRequest rr = mRequestsList.get(i);
-                        rr.onError(RADIO_NOT_AVAILABLE, null);
-                        rr.release();
-                    }
-
-                    mRequestsList.clear();
-                }
+                clearRequestsList(RADIO_NOT_AVAILABLE, false);
             }} catch (Throwable tr) {
                 Log.e(LOG_TAG,"Uncaught exception", tr);
             }
@@ -1269,22 +1264,10 @@
         return 1;
     }
 
-    /**
-     * The preferred new alternative to setupDefaultPDP that is
-     * CDMA-compatible.
-     *
-     */
     public void
     setupDataCall(String radioTechnology, String profile, String apn,
-            String user, String password, String authType, Message result) {
-        setupDataCallWithProtocol(radioTechnology, profile, apn, user, password,
-                              authType, "IP", result);
-    }
-
-    public void
-    setupDataCallWithProtocol(String radioTechnology, String profile,
-            String apn, String user, String password, String authType,
-            String protocolType, Message result) {
+            String user, String password, String authType, String protocol,
+            Message result) {
         RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);
 
@@ -1296,12 +1279,12 @@
         rr.mp.writeString(user);
         rr.mp.writeString(password);
         rr.mp.writeString(authType);
-        rr.mp.writeString(protocolType);
+        rr.mp.writeString(protocol);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> "
                 + requestToString(rr.mRequest) + " " + radioTechnology + " "
                 + profile + " " + apn + " " + user + " "
-                + password + " " + authType + " " + protocolType);
+                + password + " " + authType + " " + protocol);
 
         send(rr);
     }
@@ -2059,6 +2042,34 @@
         releaseWakeLockIfDone();
     }
 
+    /**
+     * Release each request in mReqeustsList then clear the list
+     * @param error is the RIL_Errno sent back
+     * @param loggable true means to print all requests in mRequestslist
+     */
+    private void clearRequestsList(int error, boolean loggable) {
+        RILRequest rr;
+        synchronized (mRequestsList) {
+            int count = mRequestsList.size();
+            if (RILJ_LOGD && loggable) {
+                Log.d(LOG_TAG, "WAKE_LOCK_TIMEOUT " +
+                        " mReqPending=" + mRequestMessagesPending +
+                        " mRequestList=" + count);
+            }
+
+            for (int i = 0; i < count ; i++) {
+                rr = mRequestsList.get(i);
+                if (RILJ_LOGD && loggable) {
+                    Log.d(LOG_TAG, i + ": [" + rr.mSerial + "] " +
+                            requestToString(rr.mRequest));
+                }
+                rr.onError(error, null);
+                rr.release();
+            }
+            mRequestsList.clear();
+        }
+    }
+
     private RILRequest findAndRemoveRequestFromList(int serial) {
         synchronized (mRequestsList) {
             for (int i = 0, s = mRequestsList.size() ; i < s ; i++) {
@@ -2128,7 +2139,7 @@
             case RIL_REQUEST_DTMF: ret =  responseVoid(p); break;
             case RIL_REQUEST_SEND_SMS: ret =  responseSMS(p); break;
             case RIL_REQUEST_SEND_SMS_EXPECT_MORE: ret =  responseSMS(p); break;
-            case RIL_REQUEST_SETUP_DATA_CALL: ret =  responseStrings(p); break;
+            case RIL_REQUEST_SETUP_DATA_CALL: ret =  responseSetupDataCall(p); break;
             case RIL_REQUEST_SIM_IO: ret =  responseICC_IO(p); break;
             case RIL_REQUEST_SEND_USSD: ret =  responseVoid(p); break;
             case RIL_REQUEST_CANCEL_USSD: ret =  responseVoid(p); break;
@@ -2149,7 +2160,7 @@
             case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: ret =  responseInts(p); break;
             case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: ret =  responseVoid(p); break;
             case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL: ret =  responseVoid(p); break;
-            case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS : ret =  responseNetworkInfos(p); break;
+            case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS : ret =  responseOperatorInfos(p); break;
             case RIL_REQUEST_DTMF_START: ret =  responseVoid(p); break;
             case RIL_REQUEST_DTMF_STOP: ret =  responseVoid(p); break;
             case RIL_REQUEST_BASEBAND_VERSION: ret =  responseString(p); break;
@@ -2886,37 +2897,95 @@
         return response;
     }
 
-    private Object
-    responseDataCallList(Parcel p) {
-        int num;
-        ArrayList<DataCallState> response;
+    private DataCallState getDataCallState(Parcel p, int version) {
+        DataCallState dataCall = new DataCallState();
 
-        num = p.readInt();
-        response = new ArrayList<DataCallState>(num);
-
-        for (int i = 0; i < num; i++) {
-            DataCallState dataCall = new DataCallState();
-
+        dataCall.version = version;
+        if (version < 5) {
             dataCall.cid = p.readInt();
             dataCall.active = p.readInt();
             dataCall.type = p.readString();
-            dataCall.apn = p.readString();
-            String address = p.readString();
-            if (address != null) {
-                address = address.split(" ")[0];
+            p.readString(); // Ignore apn
+            String addresses = p.readString();
+            if (addresses != null) {
+                dataCall.addresses = addresses.split(" ");
             }
-            dataCall.address = address;
+        } else {
+            dataCall.status = p.readInt();
+            dataCall.cid = p.readInt();
+            dataCall.active = p.readInt();
+            dataCall.type = p.readString();
+            dataCall.ifname = p.readString();
+            String addresses = p.readString();
+            if (addresses != null) {
+                dataCall.addresses = addresses.split(" ");
+            }
+            String dnses = p.readString();
+            if (addresses != null) {
+                dataCall.dnses = dnses.split(" ");
+            }
+        }
+        return dataCall;
+    }
 
-            response.add(dataCall);
+    private Object
+    responseDataCallList(Parcel p) {
+        ArrayList<DataCallState> response;
+
+        int ver = p.readInt();
+        int num = p.readInt();
+        Log.d(LOG_TAG, "responseDataCallList ver=" + ver + " num=" + num);
+
+        response = new ArrayList<DataCallState>(num);
+        for (int i = 0; i < num; i++) {
+            response.add(getDataCallState(p, ver));
         }
 
         return response;
     }
 
     private Object
-    responseNetworkInfos(Parcel p) {
+    responseSetupDataCall(Parcel p) {
+        int ver = p.readInt();
+        int num = p.readInt();
+        Log.d(LOG_TAG, "responseSetupDataCall ver=" + ver + " num=" + num);
+
+        DataCallState dataCall;
+
+        if (ver < 5) {
+            if (num != 3) {
+                throw new RuntimeException(
+                        "RIL_REQUEST_SETUP_DATA_CALL response expecting 3 strings got " + num);
+            }
+            dataCall = new DataCallState();
+            dataCall.cid = Integer.parseInt(p.readString());
+            dataCall.ifname = p.readString();
+            if (dataCall.ifname == null) {
+                throw new RuntimeException(
+                        "RIL_REQUEST_SETUP_DATA_CALL response ifname");
+            }
+            String addresses = p.readString();
+            if (addresses == null) {
+                throw new RuntimeException(
+                "RIL_REQUEST_SETUP_DATA_CALL response no addresses");
+            }
+            dataCall.addresses = addresses.split(" ");
+        } else {
+            if (num != 1) {
+                throw new RuntimeException(
+                        "RIL_REQUEST_SETUP_DATA_CALL response expecting 1 RIL_Data_Call_response_v5"
+                        + " got " + num);
+            }
+            dataCall = getDataCallState(p, ver);
+        }
+
+        return dataCall;
+    }
+
+    private Object
+    responseOperatorInfos(Parcel p) {
         String strings[] = (String [])responseStrings(p);
-        ArrayList<NetworkInfo> ret;
+        ArrayList<OperatorInfo> ret;
 
         if (strings.length % 4 != 0) {
             throw new RuntimeException(
@@ -2924,11 +2993,11 @@
                 + strings.length + " strings, expected multible of 4");
         }
 
-        ret = new ArrayList<NetworkInfo>(strings.length / 4);
+        ret = new ArrayList<OperatorInfo>(strings.length / 4);
 
         for (int i = 0 ; i < strings.length ; i += 4) {
             ret.add (
-                new NetworkInfo(
+                new OperatorInfo(
                     strings[i+0],
                     strings[i+1],
                     strings[i+2],
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 305e15f..9b21de8 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -91,11 +91,16 @@
     /* Setup a packet data connection. See ril.h RIL_REQUEST_SETUP_DATA_CALL */
     int SETUP_DATA_TECH_CDMA      = 0;
     int SETUP_DATA_TECH_GSM       = 1;
+
     int SETUP_DATA_AUTH_NONE      = 0;
     int SETUP_DATA_AUTH_PAP       = 1;
     int SETUP_DATA_AUTH_CHAP      = 2;
     int SETUP_DATA_AUTH_PAP_CHAP  = 3;
 
+    String SETUP_DATA_PROTOCOL_IP     = "IP";
+    String SETUP_DATA_PROTOCOL_IPV6   = "IPV6";
+    String SETUP_DATA_PROTOCOL_IPV4V6 = "IPV4V6";
+
     /* Deactivate data call reasons */
     int DEACTIVATE_REASON_NONE = 0;
     int DEACTIVATE_REASON_RADIO_OFF = 1;
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index e7cfe75..99123af 100644
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -37,6 +37,7 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.StatFs;
+import android.os.SystemProperties;
 import android.provider.Telephony;
 import android.provider.Telephony.Sms.Intents;
 import android.provider.Settings;
@@ -156,8 +157,10 @@
     protected boolean mStorageAvailable = true;
     protected boolean mReportMemoryStatusPending = false;
 
-    /* Flag indicating whether the current device allows sms service */
+    /* Flags indicating whether the current device allows sms service */
     protected boolean mSmsCapable = true;
+    protected boolean mSmsReceiveDisabled;
+    protected boolean mSmsSendDisabled;
 
     protected static int getNextConcatenatedRef() {
         sConcatenatedRef += 1;
@@ -255,6 +258,13 @@
 
         mSmsCapable = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_sms_capable);
+        mSmsReceiveDisabled = !SystemProperties.getBoolean(
+                                TelephonyProperties.PROPERTY_SMS_RECEIVE, mSmsCapable);
+        mSmsSendDisabled = !SystemProperties.getBoolean(
+                                TelephonyProperties.PROPERTY_SMS_SEND, mSmsCapable);
+        Log.d(TAG, "SMSDispatcher: ctor mSmsCapable=" + mSmsCapable
+                + " mSmsReceiveDisabled=" + mSmsReceiveDisabled
+                + " mSmsSendDisabled=" + mSmsSendDisabled);
     }
 
     public void dispose() {
@@ -783,13 +793,13 @@
      */
     protected void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
             PendingIntent deliveryIntent) {
-        if (!mSmsCapable) {
+        if (mSmsSendDisabled) {
             if (sentIntent != null) {
                 try {
                     sentIntent.send(RESULT_ERROR_NO_SERVICE);
                 } catch (CanceledException ex) {}
             }
-            Log.d(TAG, "Device does not support sms service.");
+            Log.d(TAG, "Device does not support sending sms.");
             return;
         }
 
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 136d5b1..e6189be 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -147,4 +147,16 @@
      * when there is a radio technology change.
      */
     static final String PROPERTY_RESET_ON_RADIO_TECH_CHANGE = "persist.radio.reset_on_switch";
+
+    /**
+     * Set to false to disable SMS receiving, default is
+     * the value of config_sms_capable
+     */
+    static final String PROPERTY_SMS_RECEIVE = "telephony.sms.receive";
+
+    /**
+     * Set to false to disable SMS sending, default is
+     * the value of config_sms_capable
+     */
+    static final String PROPERTY_SMS_SEND = "telephony.sms.send";
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 1e77589..3131ebe 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -56,6 +56,7 @@
 import com.android.internal.telephony.IccPhoneBookInterfaceManager;
 import com.android.internal.telephony.IccSmsInterfaceManager;
 import com.android.internal.telephony.MmiCode;
+import com.android.internal.telephony.OperatorInfo;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.PhoneNotifier;
@@ -483,7 +484,7 @@
     }
 
     public void
-    selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo network,
+    selectNetworkManually(OperatorInfo network,
             Message response) {
         Log.e(LOG_TAG, "selectNetworkManually: not possible in CDMA");
     }
@@ -610,7 +611,8 @@
             // If we're out of service, open TCP sockets may still work
             // but no data will flow
             ret = DataState.DISCONNECTED;
-        } else if (mDataConnection.isApnTypeEnabled(apnType) == false) {
+        } else if (mDataConnection.isApnTypeEnabled(apnType) == false ||
+                mDataConnection.isApnTypeActive(apnType) == false) {
             ret = DataState.DISCONNECTED;
         } else {
             switch (mDataConnection.getState()) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
index c645da5c..1a0dbc2 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -20,6 +20,7 @@
 import android.util.Log;
 
 import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnection.FailCause;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.RetryManager;
@@ -31,13 +32,6 @@
 
     private static final String LOG_TAG = "CDMA";
 
-    /** Fail cause of last Data Call activate from RIL_LastDataCallActivateFailCause */
-    private final static int PS_NET_DOWN_REASON_OPERATOR_DETERMINED_BARRING         = 8;
-    private final static int PS_NET_DOWN_REASON_AUTH_FAILED                         = 29;
-    private final static int PS_NET_DOWN_REASON_OPTION_NOT_SUPPORTED                = 32;
-    private final static int PS_NET_DOWN_REASON_OPTION_UNSUBSCRIBED                 = 33;
-
-
     // ***** Constructor
     private CdmaDataConnection(CDMAPhone phone, String name, RetryManager rm) {
         super(phone, name, rm);
@@ -89,9 +83,12 @@
         // msg.obj will be returned in AsyncResult.userObj;
         Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
         msg.obj = cp;
-        phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_CDMA),
-                Integer.toString(dataProfile), null, null,
-                null, Integer.toString(RILConstants.SETUP_DATA_AUTH_PAP_CHAP), msg);
+        phone.mCM.setupDataCall(
+                Integer.toString(RILConstants.SETUP_DATA_TECH_CDMA),
+                Integer.toString(dataProfile),
+                null, null, null,
+                Integer.toString(RILConstants.SETUP_DATA_AUTH_PAP_CHAP),
+                RILConstants.SETUP_DATA_PROTOCOL_IP, msg);
     }
 
     @Override
@@ -101,29 +98,6 @@
     }
 
     @Override
-    protected FailCause getFailCauseFromRequest(int rilCause) {
-        FailCause cause;
-
-        switch (rilCause) {
-            case PS_NET_DOWN_REASON_OPERATOR_DETERMINED_BARRING:
-                cause = FailCause.OPERATOR_BARRED;
-                break;
-            case PS_NET_DOWN_REASON_AUTH_FAILED:
-                cause = FailCause.USER_AUTHENTICATION;
-                break;
-            case PS_NET_DOWN_REASON_OPTION_NOT_SUPPORTED:
-                cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED;
-                break;
-            case PS_NET_DOWN_REASON_OPTION_UNSUBSCRIBED:
-                cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED;
-                break;
-            default:
-                cause = FailCause.UNKNOWN;
-        }
-        return cause;
-    }
-
-    @Override
     protected boolean isDnsOk(String[] domainNameServers) {
         if ((NULL_IP.equals(domainNameServers[0])
                 && NULL_IP.equals(domainNameServers[1])
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 01234b0..6bd2d09 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -107,10 +107,10 @@
             return Activity.RESULT_OK;
         }
 
-        if (!mSmsCapable) {
-            // Device doesn't support SMS service,
+        if (mSmsReceiveDisabled) {
+            // Device doesn't support receiving SMS,
             Log.d(TAG, "Received short message on device which doesn't support "
-                    + "SMS service. Ignored.");
+                    + "receiving SMS. Ignored.");
             return Intents.RESULT_SMS_HANDLED;
         }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index de15408..2c5aa3c 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -443,18 +443,21 @@
                     mMin = cdmaSubscription[3];
                     mPrlVersion = cdmaSubscription[4];
                     Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION MDN=" + mMdn);
-                    //Notify apps subscription info is ready
+
+                    mIsMinInfoReady = true;
+
+                    int otaspMode = getOtasp();
+                    int oldOtaspMode = mCurrentOtaspMode;
+                    mCurrentOtaspMode = otaspMode;
+
+                    // Notify apps subscription info is ready
                     if (cdmaForSubscriptionInfoReadyRegistrants != null) {
+                        Log.d(LOG_TAG, "call cdmaForSubscriptionInfoReady.notifyRegistrants()");
                         cdmaForSubscriptionInfoReadyRegistrants.notifyRegistrants();
                     }
-                    if (!mIsMinInfoReady) {
-                        mIsMinInfoReady = true;
-                    }
-                    int otaspMode = getOtasp();
-                    if (mCurrentOtaspMode != otaspMode) {
+                    if (oldOtaspMode != mCurrentOtaspMode) {
                         Log.d(LOG_TAG, "call phone.notifyOtaspChanged old otaspMode=" +
-                                mCurrentOtaspMode + " new otaspMode=" + otaspMode);
-                        mCurrentOtaspMode = otaspMode;
+                                oldOtaspMode + " new otaspMode=" + mCurrentOtaspMode);
                         phone.notifyOtaspChanged(mCurrentOtaspMode);
                     }
                     phone.getIccCard().broadcastIccStateChangedIntent(IccCard.INTENT_VALUE_ICC_IMSI,
@@ -605,7 +608,11 @@
         // mOperatorAlphaLong contains the ERI text
         String plmn = ss.getOperatorAlphaLong();
         if (!TextUtils.equals(plmn, curPlmn)) {
-            boolean showPlmn = !TextUtils.isEmpty(plmn);
+            // Allow A blank plmn, "" to set showPlmn to true. Previously, we
+            // would set showPlmn to true only if plmn was not empty, i.e. was not
+            // null and not blank. But this would cause us to incorrectly display
+            // "No Service". Now showPlmn is set to true for any non null string.
+            boolean showPlmn = plmn != null;
             Log.d(LOG_TAG,
                     String.format("updateSpnDisplay: changed sending intent" +
                             " showPlmn='%b' plmn='%s'", showPlmn, plmn));
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index 628f11a..c17197e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -62,6 +62,7 @@
 import com.android.internal.telephony.IccPhoneBookInterfaceManager;
 import com.android.internal.telephony.IccSmsInterfaceManager;
 import com.android.internal.telephony.MmiCode;
+import com.android.internal.telephony.OperatorInfo;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.PhoneNotifier;
@@ -300,7 +301,8 @@
             // If we're out of service, open TCP sockets may still work
             // but no data will flow
             ret = DataState.DISCONNECTED;
-        } else if (mDataConnection.isApnTypeEnabled(apnType) == false) {
+        } else if (mDataConnection.isApnTypeEnabled(apnType) == false ||
+                mDataConnection.isApnTypeActive(apnType) == false) {
             ret = DataState.DISCONNECTED;
         } else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */
             switch (mDataConnection.getState()) {
@@ -1024,19 +1026,19 @@
     }
 
     public void
-    selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo network,
+    selectNetworkManually(OperatorInfo network,
             Message response) {
         // wrap the response message in our own message along with
         // the operator's id.
         NetworkSelectMessage nsm = new NetworkSelectMessage();
         nsm.message = response;
-        nsm.operatorNumeric = network.operatorNumeric;
-        nsm.operatorAlphaLong = network.operatorAlphaLong;
+        nsm.operatorNumeric = network.getOperatorNumeric();
+        nsm.operatorAlphaLong = network.getOperatorAlphaLong();
 
         // get the message
         Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
 
-        mCM.setNetworkSelectionModeManual(network.operatorNumeric, msg);
+        mCM.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg);
     }
 
     public void
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
index dfba8d6..1d60bda 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -33,24 +33,6 @@
 
     private static final String LOG_TAG = "GSM";
 
-    /** Fail cause of last PDP activate, from RIL_LastPDPActivateFailCause */
-    private static final int PDP_FAIL_OPERATOR_BARRED = 0x08;
-    private static final int PDP_FAIL_INSUFFICIENT_RESOURCES = 0x1A;
-    private static final int PDP_FAIL_MISSING_UKNOWN_APN = 0x1B;
-    private static final int PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE = 0x1C;
-    private static final int PDP_FAIL_USER_AUTHENTICATION = 0x1D;
-    private static final int PDP_FAIL_ACTIVATION_REJECT_GGSN = 0x1E;
-    private static final int PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED = 0x1F;
-    private static final int PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED = 0x20;
-    private static final int PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED = 0x21;
-    private static final int PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER = 0x22;
-    private static final int PDP_FAIL_NSAPI_IN_USE      = 0x23;
-    private static final int PDP_FAIL_PROTOCOL_ERRORS   = 0x6F;
-    private static final int PDP_FAIL_ERROR_UNSPECIFIED = 0xffff;
-
-    private static final int PDP_FAIL_REGISTRATION_FAIL = -1;
-    private static final int PDP_FAIL_GPRS_REGISTRATION_FAIL = -2;
-
     //***** Instance Variables
     private ApnSetting apn;
 
@@ -110,9 +92,12 @@
             authType = (apn.user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP :
                 RILConstants.SETUP_DATA_AUTH_NONE;
         }
-        phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_GSM),
-                Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), apn.apn, apn.user,
-                apn.password, Integer.toString(authType), msg);
+        phone.mCM.setupDataCall(
+                Integer.toString(RILConstants.SETUP_DATA_TECH_GSM),
+                Integer.toString(RILConstants.DATA_PROFILE_DEFAULT),
+                apn.apn, apn.user, apn.password,
+                Integer.toString(authType),
+                RILConstants.SETUP_DATA_PROTOCOL_IP, msg);
     }
 
     @Override
@@ -129,62 +114,6 @@
     }
 
     @Override
-    protected FailCause getFailCauseFromRequest(int rilCause) {
-        FailCause cause;
-
-        switch (rilCause) {
-            case PDP_FAIL_OPERATOR_BARRED:
-                cause = FailCause.OPERATOR_BARRED;
-                break;
-            case PDP_FAIL_INSUFFICIENT_RESOURCES:
-                cause = FailCause.INSUFFICIENT_RESOURCES;
-                break;
-            case PDP_FAIL_MISSING_UKNOWN_APN:
-                cause = FailCause.MISSING_UNKNOWN_APN;
-                break;
-            case PDP_FAIL_UNKNOWN_PDP_ADDRESS_TYPE:
-                cause = FailCause.UNKNOWN_PDP_ADDRESS;
-                break;
-            case PDP_FAIL_USER_AUTHENTICATION:
-                cause = FailCause.USER_AUTHENTICATION;
-                break;
-            case PDP_FAIL_ACTIVATION_REJECT_GGSN:
-                cause = FailCause.ACTIVATION_REJECT_GGSN;
-                break;
-            case PDP_FAIL_ACTIVATION_REJECT_UNSPECIFIED:
-                cause = FailCause.ACTIVATION_REJECT_UNSPECIFIED;
-                break;
-            case PDP_FAIL_SERVICE_OPTION_OUT_OF_ORDER:
-                cause = FailCause.SERVICE_OPTION_OUT_OF_ORDER;
-                break;
-            case PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED:
-                cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED;
-                break;
-            case PDP_FAIL_SERVICE_OPTION_NOT_SUBSCRIBED:
-                cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED;
-                break;
-            case PDP_FAIL_NSAPI_IN_USE:
-                cause = FailCause.NSAPI_IN_USE;
-                break;
-            case PDP_FAIL_PROTOCOL_ERRORS:
-                cause = FailCause.PROTOCOL_ERRORS;
-                break;
-            case PDP_FAIL_ERROR_UNSPECIFIED:
-                cause = FailCause.UNKNOWN;
-                break;
-            case PDP_FAIL_REGISTRATION_FAIL:
-                cause = FailCause.REGISTRATION_FAIL;
-                break;
-            case PDP_FAIL_GPRS_REGISTRATION_FAIL:
-                cause = FailCause.GPRS_REGISTRATION_FAIL;
-                break;
-            default:
-                cause = FailCause.UNKNOWN;
-        }
-        return cause;
-    }
-
-    @Override
     protected boolean isDnsOk(String[] domainNameServers) {
         if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1])
                 && !((GSMPhone) phone).isDnsCheckDisabled()) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index 497c552..bbe579d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -110,7 +110,7 @@
             return Intents.RESULT_SMS_HANDLED;
         }
 
-        if (!mSmsCapable) {
+        if (mSmsReceiveDisabled) {
             // Device doesn't support SMS service,
             Log.d(TAG, "Received short message on device which doesn't support "
                     + "SMS service. Ignored.");
diff --git a/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.aidl b/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.aidl
deleted file mode 100644
index d88d0b7..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-/**
- * Used to indicate that the NetworkInfo object is parcelable to aidl.
- * This is a simple effort to make NetworkInfo parcelable rather than
- * trying to make the conventional containing object (AsyncResult),
- * implement parcelable.  This functionality is needed for the
- * NetworkQueryService to fix 1128695
- */
-parcelable NetworkInfo;
diff --git a/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.java b/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.java
deleted file mode 100644
index 04fd13e..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.gsm;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * {@hide}
- */
-public class NetworkInfo implements Parcelable {
-    public enum State {
-        UNKNOWN,
-        AVAILABLE,
-        CURRENT,
-        FORBIDDEN;
-    }
-
-    String operatorAlphaLong;
-    String operatorAlphaShort;
-    String operatorNumeric;
-
-    State state = State.UNKNOWN;
-
-
-    public String
-    getOperatorAlphaLong() {
-        return operatorAlphaLong;
-    }
-
-    public String
-    getOperatorAlphaShort() {
-        return operatorAlphaShort;
-    }
-
-    public String
-    getOperatorNumeric() {
-        return operatorNumeric;
-    }
-
-    public State
-    getState() {
-        return state;
-    }
-
-    NetworkInfo(String operatorAlphaLong,
-                String operatorAlphaShort,
-                String operatorNumeric,
-                State state) {
-
-        this.operatorAlphaLong = operatorAlphaLong;
-        this.operatorAlphaShort = operatorAlphaShort;
-        this.operatorNumeric = operatorNumeric;
-
-        this.state = state;
-    }
-
-
-    public NetworkInfo(String operatorAlphaLong,
-                String operatorAlphaShort,
-                String operatorNumeric,
-                String stateString) {
-        this (operatorAlphaLong, operatorAlphaShort,
-                operatorNumeric, rilStateToState(stateString));
-    }
-
-    /**
-     * See state strings defined in ril.h RIL_REQUEST_QUERY_AVAILABLE_NETWORKS
-     */
-    private static State rilStateToState(String s) {
-        if (s.equals("unknown")) {
-            return State.UNKNOWN;
-        } else if (s.equals("available")) {
-            return State.AVAILABLE;
-        } else if (s.equals("current")) {
-            return State.CURRENT;
-        } else if (s.equals("forbidden")) {
-            return State.FORBIDDEN;
-        } else {
-            throw new RuntimeException(
-                "RIL impl error: Invalid network state '" + s + "'");
-        }
-    }
-
-
-    public String toString() {
-        return "NetworkInfo " + operatorAlphaLong
-                + "/" + operatorAlphaShort
-                + "/" + operatorNumeric
-                + "/" + state;
-    }
-
-    /**
-     * Parcelable interface implemented below.
-     * This is a simple effort to make NetworkInfo parcelable rather than
-     * trying to make the conventional containing object (AsyncResult),
-     * implement parcelable.  This functionality is needed for the
-     * NetworkQueryService to fix 1128695.
-     */
-
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * Implement the Parcelable interface.
-     * Method to serialize a NetworkInfo object.
-     */
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(operatorAlphaLong);
-        dest.writeString(operatorAlphaShort);
-        dest.writeString(operatorNumeric);
-        dest.writeSerializable(state);
-    }
-
-    /**
-     * Implement the Parcelable interface
-     * Method to deserialize a NetworkInfo object, or an array thereof.
-     */
-    public static final Creator<NetworkInfo> CREATOR =
-        new Creator<NetworkInfo>() {
-            public NetworkInfo createFromParcel(Parcel in) {
-                NetworkInfo netInfo = new NetworkInfo(
-                        in.readString(), /*operatorAlphaLong*/
-                        in.readString(), /*operatorAlphaShort*/
-                        in.readString(), /*operatorNumeric*/
-                        (State) in.readSerializable()); /*state*/
-                return netInfo;
-            }
-
-            public NetworkInfo[] newArray(int size) {
-                return new NetworkInfo[size];
-            }
-        };
-}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
index 2e729fe..1939f95 100644
--- a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
@@ -186,7 +186,7 @@
 
     public void setupDataCall(String radioTechnology, String profile,
             String apn, String user, String password, String authType,
-            Message result) {
+            String protcol, Message result) {
     }
 
     public void deactivateDataCall(int cid, int reason, Message result) {
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 461f01d..f9bc0e9 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -17,6 +17,7 @@
 package com.android.internal.telephony.sip;
 
 import android.content.Context;
+import android.media.AudioManager;
 import android.net.rtp.AudioGroup;
 import android.net.sip.SipAudioCall;
 import android.net.sip.SipErrorCode;
@@ -133,7 +134,7 @@
                     (ringingCall.getState() == Call.State.WAITING)) {
                 if (DEBUG) Log.d(LOG_TAG, "acceptCall");
                 // Always unmute when answering a new call
-                setMute(false);
+                ringingCall.setMute(false);
                 ringingCall.acceptCall();
             } else {
                 throw new CallStateException("phone not ringing");
@@ -173,7 +174,7 @@
             throw new CallStateException("cannot dial in current state");
         }
 
-        setMute(false);
+        foregroundCall.setMute(false);
         try {
             Connection c = foregroundCall.dial(dialString);
             return c;
@@ -291,16 +292,13 @@
 
     @Override
     public void setEchoSuppressionEnabled(boolean enabled) {
+        // TODO: Remove the enabled argument. We should check the speakerphone
+        // state with AudioManager instead of keeping a state here so the
+        // method with a state argument is redundant. Also rename the method
+        // to something like onSpeaerphoneStateChanged(). Echo suppression may
+        // not be available on every device.
         synchronized (SipPhone.class) {
-            AudioGroup audioGroup = foregroundCall.getAudioGroup();
-            if (audioGroup == null) return;
-            int mode = audioGroup.getMode();
-            audioGroup.setMode(enabled
-                    ? AudioGroup.MODE_ECHO_SUPPRESSION
-                    : AudioGroup.MODE_NORMAL);
-            if (DEBUG) Log.d(LOG_TAG, String.format(
-                    "audioGroup mode change: %d --> %d", mode,
-                    audioGroup.getMode()));
+            foregroundCall.setAudioGroupMode();
         }
     }
 
@@ -453,13 +451,33 @@
             ((SipConnection) connections.get(0)).acceptCall();
         }
 
+        private boolean isSpeakerOn() {
+            return ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE))
+                    .isSpeakerphoneOn();
+        }
+
+        void setAudioGroupMode() {
+            AudioGroup audioGroup = getAudioGroup();
+            if (audioGroup == null) return;
+            int mode = audioGroup.getMode();
+            if (state == State.HOLDING) {
+                audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
+            } else if (getMute()) {
+                audioGroup.setMode(AudioGroup.MODE_MUTED);
+            } else if (isSpeakerOn()) {
+                audioGroup.setMode(AudioGroup.MODE_ECHO_SUPPRESSION);
+            } else {
+                audioGroup.setMode(AudioGroup.MODE_NORMAL);
+            }
+            if (DEBUG) Log.d(LOG_TAG, String.format(
+                    "audioGroup mode change: %d --> %d", mode,
+                    audioGroup.getMode()));
+        }
+
         void hold() throws CallStateException {
             setState(State.HOLDING);
-            AudioGroup audioGroup = getAudioGroup();
-            if (audioGroup != null) {
-                audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
-            }
             for (Connection c : connections) ((SipConnection) c).hold();
+            setAudioGroupMode();
         }
 
         void unhold() throws CallStateException {
@@ -468,19 +486,19 @@
             for (Connection c : connections) {
                 ((SipConnection) c).unhold(audioGroup);
             }
+            setAudioGroupMode();
         }
 
         void setMute(boolean muted) {
-            AudioGroup audioGroup = getAudioGroup();
-            if (audioGroup == null) return;
-            audioGroup.setMode(
-                    muted ? AudioGroup.MODE_MUTED : AudioGroup.MODE_NORMAL);
+            for (Connection c : connections) {
+                ((SipConnection) c).setMute(muted);
+            }
         }
 
         boolean getMute() {
-            AudioGroup audioGroup = getAudioGroup();
-            if (audioGroup == null) return false;
-            return (audioGroup.getMode() == AudioGroup.MODE_MUTED);
+            return connections.isEmpty()
+                    ? false
+                    : ((SipConnection) connections.get(0)).getMute();
         }
 
         void merge(SipCall that) throws CallStateException {
@@ -739,6 +757,17 @@
             }
         }
 
+        void setMute(boolean muted) {
+            if ((mSipAudioCall != null) && (muted != mSipAudioCall.isMuted())) {
+                mSipAudioCall.toggleMute();
+            }
+        }
+
+        boolean getMute() {
+            return (mSipAudioCall == null) ? false
+                                           : mSipAudioCall.isMuted();
+        }
+
         @Override
         protected void setState(Call.State state) {
             if (state == mState) return;
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
index db9e35a..9dfc015 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
@@ -38,6 +38,7 @@
 import com.android.internal.telephony.IccPhoneBookInterfaceManager;
 import com.android.internal.telephony.IccSmsInterfaceManager;
 import com.android.internal.telephony.MmiCode;
+import com.android.internal.telephony.OperatorInfo;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.PhoneNotifier;
@@ -347,7 +348,7 @@
     }
 
     public void selectNetworkManually(
-            com.android.internal.telephony.gsm.NetworkInfo network,
+            OperatorInfo network,
             Message response) {
     }
 
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
index c2f88e5..37867b2 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -954,8 +954,9 @@
         unimplemented(response);
     }
 
-    public void setupDataCall(String radioTechnology, String profile, String apn, String user,
-            String password, String authType, Message result) {
+    public void setupDataCall(String radioTechnology, String profile,
+            String apn, String user, String password, String authType,
+            String protocol, Message result) {
         unimplemented(result);
     }
 
diff --git a/test-runner/src/android/test/ActivityTestCase.java b/test-runner/src/android/test/ActivityTestCase.java
index 18bfccc..c7b1d70 100644
--- a/test-runner/src/android/test/ActivityTestCase.java
+++ b/test-runner/src/android/test/ActivityTestCase.java
@@ -19,10 +19,11 @@
 import android.app.Activity;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 
 /**
  * This is common code used to support Activity test cases.  For more useful classes, please see
- * {@link android.test.ActivityUnitTestCase} and 
+ * {@link android.test.ActivityUnitTestCase} and
  * {@link android.test.ActivityInstrumentationTestCase}.
  */
 public abstract class ActivityTestCase extends InstrumentationTestCase {
@@ -38,7 +39,7 @@
     protected Activity getActivity() {
         return mActivity;
     }
-    
+
     /**
      * Set the activity under test.
      * @param testActivity The activity under test
@@ -46,15 +47,15 @@
     protected void setActivity(Activity testActivity) {
         mActivity = testActivity;
     }
-    
+
     /**
      * This function is called by various TestCase implementations, at tearDown() time, in order
      * to scrub out any class variables.  This protects against memory leaks in the case where a
      * test case creates a non-static inner class (thus referencing the test case) and gives it to
      * someone else to hold onto.
-     * 
+     *
      * @param testCaseClass The class of the derived TestCase implementation.
-     * 
+     *
      * @throws IllegalAccessException
      */
     protected void scrubClass(final Class<?> testCaseClass)
@@ -62,7 +63,8 @@
         final Field[] fields = getClass().getDeclaredFields();
         for (Field field : fields) {
             final Class<?> fieldClass = field.getDeclaringClass();
-            if (testCaseClass.isAssignableFrom(fieldClass) && !field.getType().isPrimitive()) {
+            if (testCaseClass.isAssignableFrom(fieldClass) && !field.getType().isPrimitive()
+                    && (field.getModifiers() & Modifier.FINAL) == 0) {
                 try {
                     field.setAccessible(true);
                     field.set(this, null);
@@ -77,6 +79,6 @@
         }
     }
 
-    
+
 
 }
diff --git a/test-runner/src/android/test/InstrumentationTestRunner.java b/test-runner/src/android/test/InstrumentationTestRunner.java
index 5ce3efc..c3d09ff 100644
--- a/test-runner/src/android/test/InstrumentationTestRunner.java
+++ b/test-runner/src/android/test/InstrumentationTestRunner.java
@@ -16,8 +16,6 @@
 
 package android.test;
 
-import static android.test.suitebuilder.TestPredicates.REJECT_PERFORMANCE;
-
 import com.android.internal.util.Predicate;
 import com.android.internal.util.Predicates;
 
@@ -172,8 +170,6 @@
     /** @hide */
     public static final String ARGUMENT_TEST_SIZE_PREDICATE = "size";
     /** @hide */
-    public static final String ARGUMENT_INCLUDE_PERF = "perf";
-    /** @hide */
     public static final String ARGUMENT_DELAY_MSEC = "delay_msec";
 
     private static final String SMALL_SUITE = "small";
@@ -305,7 +301,6 @@
         Predicate<TestMethod> testSizePredicate = null;
         Predicate<TestMethod> testAnnotationPredicate = null;
         Predicate<TestMethod> testNotAnnotationPredicate = null;
-        boolean includePerformance = false;
         String testClassesArg = null;
         boolean logOnly = false;
 
@@ -323,7 +318,6 @@
             testNotAnnotationPredicate = getNotAnnotationPredicate(
                     arguments.getString(ARGUMENT_NOT_ANNOTATION));
 
-            includePerformance = getBooleanArgument(arguments, ARGUMENT_INCLUDE_PERF);
             logOnly = getBooleanArgument(arguments, ARGUMENT_LOG_ONLY);
             mCoverage = getBooleanArgument(arguments, "coverage");
             mCoverageFilePath = arguments.getString("coverageFile");
@@ -348,9 +342,6 @@
         if (testNotAnnotationPredicate != null) {
             testSuiteBuilder.addRequirements(testNotAnnotationPredicate);
         }
-        if (!includePerformance) {
-            testSuiteBuilder.addRequirements(REJECT_PERFORMANCE);
-        }
 
         if (testClassesArg == null) {
             if (mPackageOfTests != null) {
diff --git a/test-runner/src/android/test/LoaderTestCase.java b/test-runner/src/android/test/LoaderTestCase.java
index 8be6590..c8564c2 100644
--- a/test-runner/src/android/test/LoaderTestCase.java
+++ b/test-runner/src/android/test/LoaderTestCase.java
@@ -64,7 +64,7 @@
                 // Shut the loader down
                 completedLoader.unregisterListener(this);
                 completedLoader.stopLoading();
-                completedLoader.destroy();
+                completedLoader.reset();
 
                 // Store the result, unblocking the test thread
                 queue.add(data);
diff --git a/test-runner/src/android/test/PerformanceTestBase.java b/test-runner/src/android/test/PerformanceTestBase.java
deleted file mode 100644
index 4a0a589..0000000
--- a/test-runner/src/android/test/PerformanceTestBase.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test;
-
-import junit.framework.TestCase;
-
-/**
- * {@hide} Not needed for SDK.
- */
-public class PerformanceTestBase extends TestCase implements PerformanceTestCase {
-
-    public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-        return 0;
-    }
-
-    public boolean isPerformanceOnly() {
-        return true;
-    }
-}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 615870b..2e4199e 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -496,8 +496,17 @@
         throw new UnsupportedOperationException();
     }
 
-    @Override
     public void setPackageObbPath(String packageName, String path) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public void setPackageObbPaths(String packageName, String[] paths) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String[] getPackageObbPaths(String packageName) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/test-runner/src/android/test/suitebuilder/TestPredicates.java b/test-runner/src/android/test/suitebuilder/TestPredicates.java
index d814e0b..47aca55 100644
--- a/test-runner/src/android/test/suitebuilder/TestPredicates.java
+++ b/test-runner/src/android/test/suitebuilder/TestPredicates.java
@@ -17,7 +17,6 @@
 package android.test.suitebuilder;
 
 import android.test.InstrumentationTestCase;
-import android.test.PerformanceTestBase;
 import android.test.suitebuilder.annotation.HasAnnotation;
 import android.test.suitebuilder.annotation.Suppress;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -43,7 +42,5 @@
     public static final Predicate<TestMethod> SELECT_LARGE = new HasAnnotation(LargeTest.class);
     public static final Predicate<TestMethod> REJECT_SUPPRESSED =
             Predicates.not(new HasAnnotation(Suppress.class));
-    public static final Predicate<TestMethod> REJECT_PERFORMANCE =
-            Predicates.not(new AssignableFrom(PerformanceTestBase.class));
 
 }
diff --git a/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java b/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java
index 428905e..28f7216 100644
--- a/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java
+++ b/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java
@@ -24,7 +24,6 @@
 import com.google.android.collect.Lists;
 import static android.test.suitebuilder.TestGrouping.SORT_BY_FULLY_QUALIFIED_NAME;
 import static android.test.suitebuilder.TestPredicates.REJECT_SUPPRESSED;
-import static android.test.suitebuilder.TestPredicates.REJECT_PERFORMANCE;
 
 import junit.framework.Test;
 import junit.framework.TestCase;
@@ -71,9 +70,9 @@
         this.testCases = Lists.newArrayList();
         addRequirements(REJECT_SUPPRESSED);
     }
-    
+
     /** @hide pending API Council approval */
-    public TestSuiteBuilder addTestClassByName(String testClassName, String testMethodName, 
+    public TestSuiteBuilder addTestClassByName(String testClassName, String testMethodName,
             Context context) {
 
         AndroidTestRunner atr = new AndroidTestRunner();
@@ -83,7 +82,7 @@
         this.testCases.addAll(atr.getTestCases());
         return this;
     }
-    
+
     /** @hide pending API Council approval */
     public TestSuiteBuilder addTestSuite(TestSuite testSuite) {
         for (TestCase testCase : (List<TestCase>) TestCaseUtil.getTests(testSuite, true)) {
@@ -242,7 +241,7 @@
 
     /**
      * @return the test package that represents the packages that were included for our test suite.
-     * 
+     *
      * {@hide} Not needed for 1.0 SDK.
      */
     protected TestGrouping getTestGrouping() {
@@ -262,7 +261,7 @@
         addSuiteIfNecessary(testMethod.getEnclosingClassname());
         suiteForCurrentClass.addTest(testMethod.createTest());
     }
-    
+
     private void addTest(Test test) {
         addSuiteIfNecessary(test.getClass().getName());
         suiteForCurrentClass.addTest(test);
diff --git a/test-runner/src/android/test/suitebuilder/UnitTestSuiteBuilder.java b/test-runner/src/android/test/suitebuilder/UnitTestSuiteBuilder.java
index 8cf4c86..a746b35 100644
--- a/test-runner/src/android/test/suitebuilder/UnitTestSuiteBuilder.java
+++ b/test-runner/src/android/test/suitebuilder/UnitTestSuiteBuilder.java
@@ -18,7 +18,7 @@
 
 /**
  * A suite builder that finds unit tests.
- * 
+ *
  * {@hide} Not needed for 1.0 SDK.
  */
 public class UnitTestSuiteBuilder extends TestSuiteBuilder {
@@ -31,6 +31,5 @@
     public UnitTestSuiteBuilder(String name, ClassLoader classLoader) {
         super(name, classLoader);
         addRequirements(TestPredicates.REJECT_INSTRUMENTATION);
-        addRequirements(TestPredicates.REJECT_PERFORMANCE);
     }
 }
diff --git a/tests/CoreTests/android/core/AndroidPerformanceTests.java b/tests/CoreTests/android/core/AndroidPerformanceTests.java
deleted file mode 100644
index e604d59..0000000
--- a/tests/CoreTests/android/core/AndroidPerformanceTests.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import android.test.TestListActivity;
-
-public class AndroidPerformanceTests extends TestListActivity {
-    @Override
-    public String getTestSuite() {
-        return "com.android.unit_tests.AndroidPerformanceTests$Suite";
-    }
-
-    public static class Suite {
-        public static String[] children() {
-            return new String[] {
-                JavaPerformanceTests.class.getName(),
-                PerformanceTests.class.getName(),
-            };
-        }
-    }
-}
diff --git a/tests/CoreTests/android/core/ArrayListPerformanceTest.java b/tests/CoreTests/android/core/ArrayListPerformanceTest.java
deleted file mode 100644
index 6130e83..0000000
--- a/tests/CoreTests/android/core/ArrayListPerformanceTest.java
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import java.util.ArrayList;
-import android.test.PerformanceTestBase;
-
-public class ArrayListPerformanceTest extends PerformanceTestBase {
-
-    private ArrayList<Integer> mList;
-
-    @Override
-    @SuppressWarnings("unchecked")
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        mList = new ArrayList();
-        mList.add(0);
-        mList.add(1);
-        mList.add(2);
-        mList.add(3);
-        mList.add(4);
-        mList.add(5);
-        mList.add(6);
-        mList.add(7);
-        mList.add(8);
-        mList.add(9);
-    }
-
-    public void testArrayListAdd() {
-        int i = 0;
-        for (; i < 10; i++) {
-            mList.add(i);
-            mList.add(i);
-            mList.add(i);
-            mList.add(i);
-            mList.add(i);
-            mList.add(i);
-            mList.add(i);
-            mList.add(i);
-            mList.add(i);
-            mList.add(i);
-        }
-    }
-
-    public void testArrayListAdd1() {
-        int i = 0;
-        for (; i < 10; i++) {
-            mList.add(7, i);
-            mList.add(7, i);
-            mList.add(7, i);
-            mList.add(7, i);
-            mList.add(7, i);
-            mList.add(7, i);
-            mList.add(7, i);
-            mList.add(7, i);
-            mList.add(7, i);
-            mList.add(7, i);
-        }
-    }
-
-    public void testArrayListToArray() {
-        Object rArray;
-        int i = 0;
-        for (; i < 100; i++) {
-            rArray = mList.toArray();
-            rArray = mList.toArray();
-            rArray = mList.toArray();
-            rArray = mList.toArray();
-            rArray = mList.toArray();
-            rArray = mList.toArray();
-            rArray = mList.toArray();
-            rArray = mList.toArray();
-            rArray = mList.toArray();
-            rArray = mList.toArray();
-        }
-    }
-
-    public void testArrayListSize() {
-        int i = 0, len;
-        for (; i < 100; i++) {
-            len = mList.size();
-            len = mList.size();
-            len = mList.size();
-            len = mList.size();
-            len = mList.size();
-            len = mList.size();
-            len = mList.size();
-            len = mList.size();
-            len = mList.size();
-            len = mList.size();
-        }
-    }
-
-    public void testArrayListGet() {
-        int i = 0, value;
-        int len = mList.size();
-        for (; i < len; i++) {
-            value = mList.get(i);
-            value = mList.get(i);
-            value = mList.get(i);
-            value = mList.get(i);
-            value = mList.get(i);
-            value = mList.get(i);
-            value = mList.get(i);
-            value = mList.get(i);
-            value = mList.get(i);
-            value = mList.get(i);
-        }
-    }
-
-    public void testArrayListContains() {
-        boolean flag;
-        int i = 0;
-
-        for (; i < 100; i++) {
-            flag = mList.contains(i);
-            flag = mList.contains(i);
-            flag = mList.contains(i);
-            flag = mList.contains(i);
-            flag = mList.contains(i);
-            flag = mList.contains(i);
-            flag = mList.contains(i);
-            flag = mList.contains(i);
-            flag = mList.contains(i);
-            flag = mList.contains(i);
-
-        }
-    }
-
-    public void testArrayListToArray1() {
-        Integer[] rArray = new Integer[10];
-
-        Integer[] mArray;
-        int i = 0;
-        for (; i < 100; i++) {
-            mArray = mList.toArray(rArray);
-            mArray = mList.toArray(rArray);
-            mArray = mList.toArray(rArray);
-            mArray = mList.toArray(rArray);
-            mArray = mList.toArray(rArray);
-            mArray = mList.toArray(rArray);
-            mArray = mList.toArray(rArray);
-            mArray = mList.toArray(rArray);
-            mArray = mList.toArray(rArray);
-            mArray = mList.toArray(rArray);
-        }
-    }
-
-    public void testArrayListSet() {
-        int i = 0;
-        for (; i < 10; i++) {
-            mList.set(5, 0);
-            mList.set(5, 0);
-            mList.set(5, 0);
-            mList.set(5, 0);
-            mList.set(5, 0);
-            mList.set(5, 0);
-            mList.set(5, 0);
-            mList.set(5, 0);
-            mList.set(5, 0);
-            mList.set(5, 0);
-        }
-    }
-
-    public void testArrayListIndexOf() {
-        int i = 0, index;
-
-        for (; i < 100; i++) {
-            index = mList.indexOf(0);
-            index = mList.indexOf(0);
-            index = mList.indexOf(0);
-            index = mList.indexOf(0);
-            index = mList.indexOf(0);
-            index = mList.indexOf(0);
-            index = mList.indexOf(0);
-            index = mList.indexOf(0);
-            index = mList.indexOf(0);
-            index = mList.indexOf(0);
-        }
-    }
-
-    public void testArrayListLastIndexOf() {
-        int i = 0, index;
-
-        for (; i < 100; i++) {
-            index = mList.lastIndexOf(0);
-            index = mList.lastIndexOf(0);
-            index = mList.lastIndexOf(0);
-            index = mList.lastIndexOf(0);
-            index = mList.lastIndexOf(0);
-            index = mList.lastIndexOf(0);
-            index = mList.lastIndexOf(0);
-            index = mList.lastIndexOf(0);
-            index = mList.lastIndexOf(0);
-            index = mList.lastIndexOf(0);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public void testArrayListRemove() {
-        ArrayList<Integer> aList;
-        aList = new ArrayList();
-        for (int j = 0; j < 10000; j++) {
-            aList.add(0);
-        }
-
-        int i = 0, index;
-
-        for (; i < 10; i++) {
-            index = aList.remove(0);
-            index = aList.remove(0);
-            index = aList.remove(0);
-            index = aList.remove(0);
-            index = aList.remove(0);
-            index = aList.remove(0);
-            index = aList.remove(0);
-            index = aList.remove(0);
-            index = aList.remove(0);
-            index = aList.remove(0);
-
-
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public void testArrayListAddAll() {
-        ArrayList<Integer> aList = new ArrayList();
-
-        int i = 0;
-        boolean b;
-        for (; i < 10; i++) {
-            b = aList.addAll(mList);
-            b = aList.addAll(mList);
-            b = aList.addAll(mList);
-            b = aList.addAll(mList);
-            b = aList.addAll(mList);
-            b = aList.addAll(mList);
-            b = aList.addAll(mList);
-            b = aList.addAll(mList);
-            b = aList.addAll(mList);
-            b = aList.addAll(mList);
-
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public void testArrayListRemove1() {
-        ArrayList<String> aList;
-        String s;
-
-        aList = new ArrayList();
-        for (int j = 0; j < 100; j++) {
-            aList.add("a");
-            aList.add("b");
-        }
-        s = new String("a");
-
-        int i = 0;
-        boolean b;
-        for (; i < 10; i++) {
-            b = aList.remove(s);
-            b = aList.remove(s);
-            b = aList.remove(s);
-            b = aList.remove(s);
-            b = aList.remove(s);
-            b = aList.remove(s);
-            b = aList.remove(s);
-            b = aList.remove(s);
-            b = aList.remove(s);
-            b = aList.remove(s);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public void testArrayListAddAll1() {
-        ArrayList<Integer> aList = new ArrayList();
-
-        int i = 0;
-        boolean b;
-
-        for (; i < 10; i++) {
-            b = aList.addAll(0, mList);
-            b = aList.addAll(0, mList);
-            b = aList.addAll(0, mList);
-            b = aList.addAll(0, mList);
-            b = aList.addAll(0, mList);
-            b = aList.addAll(0, mList);
-            b = aList.addAll(0, mList);
-            b = aList.addAll(0, mList);
-            b = aList.addAll(0, mList);
-            b = aList.addAll(0, mList);
-        }
-    }
-
-    public void testArrayListClone() {
-        Object rObj;
-        int i = 0;
-
-        for (; i < 100; i++) {
-            rObj = mList.clone();
-            rObj = mList.clone();
-            rObj = mList.clone();
-            rObj = mList.clone();
-            rObj = mList.clone();
-            rObj = mList.clone();
-            rObj = mList.clone();
-            rObj = mList.clone();
-            rObj = mList.clone();
-            rObj = mList.clone();
-        }
-    }
-}
diff --git a/tests/CoreTests/android/core/HashMapPerfTest.java b/tests/CoreTests/android/core/HashMapPerfTest.java
deleted file mode 100644
index 8475222..0000000
--- a/tests/CoreTests/android/core/HashMapPerfTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import android.os.SystemClock;
-import android.test.suitebuilder.annotation.LargeTest;
-import junit.framework.TestCase;
-
-import java.util.HashMap;
-import java.util.Random;
-
-/**
- * Tests basic functionality of HashMaps and prints the time needed to System.out
- */
-public class HashMapPerfTest extends TestCase {
-
-    private static final Random sRandom = new Random(1);
-
-    class StringThing {
-
-        String mId;
-
-        public StringThing() {
-            int len = sRandom.nextInt(20) + 1;
-            char[] chars = new char[len];
-            chars[0] = 't';
-            for (int i = 1; i < len; i++) {
-                chars[i] = (char) ('q' + sRandom.nextInt(4));
-            }
-            mId = new String(chars, 0, len);
-        }
-
-        public String getId() {
-            return mId;
-        }
-    }
-
-    private static final int NUM_ELTS = 1000;
-    private static final int ITERS = 100;
-
-    String[] keyCopies = new String[NUM_ELTS];
-
-    private static final boolean lookupByOriginals = false;
-
-    @LargeTest
-    public void testHashMapPerformance() throws Exception {
-        StringThing[] st = new StringThing[NUM_ELTS];
-        for (int i = 0; i < NUM_ELTS; i++) {
-            st[i] = new StringThing();
-            keyCopies[i] = st[i].getId();
-        }
-
-        // android.os.Debug.startMethodTracing();
-        long start = SystemClock.uptimeMillis();
-        for (int i = 0; i < ITERS; i++) {
-            HashMap<String, StringThing> map = new HashMap<String, StringThing>();
-            for (int j = 0; j < NUM_ELTS; j++) {
-                StringThing s = st[i];
-                map.put(s.getId(), s);
-            }
-            for (int j = 0; j < NUM_ELTS; j++) {
-                if (lookupByOriginals) {
-                    StringThing s = st[i];
-                    map.get(s.getId());
-                } else {
-                    map.get(keyCopies[j]);
-                }
-            }
-        }
-        long finish = SystemClock.uptimeMillis();
-        // android.os.Debug.stopMethodTracing();
-
-        // This should be an assertion instead
-        
-//        System.out.println("time (" + NUM_ELTS +
-//                ", elts, " + ITERS +
-//                " iters) = " + (finish - start));
-    }
-}
diff --git a/tests/CoreTests/android/core/HashMapPerformanceTest.java b/tests/CoreTests/android/core/HashMapPerformanceTest.java
deleted file mode 100644
index 82727bb..0000000
--- a/tests/CoreTests/android/core/HashMapPerformanceTest.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Set;
-
-import android.test.PerformanceTestBase;
-import android.test.PerformanceTestCase;
-
-public class HashMapPerformanceTest extends PerformanceTestBase {
-    public static final int ITERATIONS = 1000;
-    public HashMap mMap;
-    public String[] mKeys;
-
-    @Override
-    @SuppressWarnings("unchecked")
-    protected void setUp() throws Exception {
-        super.setUp();
-        mMap = new HashMap();
-        mKeys = new String[ITERATIONS];
-
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            mKeys[i] = Integer.toString(i, 16);
-            mMap.put(mKeys[i], i);
-        }
-    }
-
-    @Override
-    public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-        intermediates.setInternalIterations(ITERATIONS);
-        return 0;
-    }
-
-    public void testHashMapGet() {
-        int num;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            num = (Integer) mMap.get(mKeys[i]);
-            num = (Integer) mMap.get(mKeys[i]);
-            num = (Integer) mMap.get(mKeys[i]);
-            num = (Integer) mMap.get(mKeys[i]);
-            num = (Integer) mMap.get(mKeys[i]);
-            num = (Integer) mMap.get(mKeys[i]);
-            num = (Integer) mMap.get(mKeys[i]);
-            num = (Integer) mMap.get(mKeys[i]);
-            num = (Integer) mMap.get(mKeys[i]);
-            num = (Integer) mMap.get(mKeys[i]);
-        }
-    }
-
-    public void testHashMapKeySet() {
-        Set keyset;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            keyset = mMap.keySet();
-            keyset = mMap.keySet();
-            keyset = mMap.keySet();
-            keyset = mMap.keySet();
-            keyset = mMap.keySet();
-            keyset = mMap.keySet();
-            keyset = mMap.keySet();
-            keyset = mMap.keySet();
-            keyset = mMap.keySet();
-            keyset = mMap.keySet();
-        }
-    }
-
-    public void testHashMapEntrySet() {
-        Set keyset;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            keyset = mMap.entrySet();
-            keyset = mMap.entrySet();
-            keyset = mMap.entrySet();
-            keyset = mMap.entrySet();
-            keyset = mMap.entrySet();
-            keyset = mMap.entrySet();
-            keyset = mMap.entrySet();
-            keyset = mMap.entrySet();
-            keyset = mMap.entrySet();
-            keyset = mMap.entrySet();
-
-
-        }
-    }
-
-    public void testHashMapValues() {
-        Collection c;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            c = mMap.values();
-            c = mMap.values();
-            c = mMap.values();
-            c = mMap.values();
-            c = mMap.values();
-            c = mMap.values();
-            c = mMap.values();
-            c = mMap.values();
-            c = mMap.values();
-            c = mMap.values();
-
-
-        }
-    }
-
-    public void testHashMapSize() {
-        int len;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            len = mMap.size();
-            len = mMap.size();
-            len = mMap.size();
-            len = mMap.size();
-            len = mMap.size();
-            len = mMap.size();
-            len = mMap.size();
-            len = mMap.size();
-            len = mMap.size();
-            len = mMap.size();
-
-
-        }
-    }
-
-    public void testHashMapContainsValue() {
-        boolean flag;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = mMap.containsValue(i);
-            flag = mMap.containsValue(i);
-            flag = mMap.containsValue(i);
-            flag = mMap.containsValue(i);
-            flag = mMap.containsValue(i);
-            flag = mMap.containsValue(i);
-            flag = mMap.containsValue(i);
-            flag = mMap.containsValue(i);
-            flag = mMap.containsValue(i);
-            flag = mMap.containsValue(i);
-
-
-        }
-    }
-
-    public void testHashMapRemove() {
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            mMap.remove(mKeys[i]);
-            mMap.remove(mKeys[i]);
-            mMap.remove(mKeys[i]);
-            mMap.remove(mKeys[i]);
-            mMap.remove(mKeys[i]);
-            mMap.remove(mKeys[i]);
-            mMap.remove(mKeys[i]);
-            mMap.remove(mKeys[i]);
-            mMap.remove(mKeys[i]);
-            mMap.remove(mKeys[i]);
-        }
-    }
-
-
-    public void testHashMapClone() {
-        HashMap cMap;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            cMap = (HashMap) mMap.clone();
-            cMap = (HashMap) mMap.clone();
-            cMap = (HashMap) mMap.clone();
-            cMap = (HashMap) mMap.clone();
-            cMap = (HashMap) mMap.clone();
-            cMap = (HashMap) mMap.clone();
-            cMap = (HashMap) mMap.clone();
-            cMap = (HashMap) mMap.clone();
-            cMap = (HashMap) mMap.clone();
-            cMap = (HashMap) mMap.clone();
-        }
-    }
-}
diff --git a/tests/CoreTests/android/core/HashSetTest.java b/tests/CoreTests/android/core/HashSetTest.java
deleted file mode 100644
index 09a711f..0000000
--- a/tests/CoreTests/android/core/HashSetTest.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import android.test.PerformanceTestBase;
-import android.test.PerformanceTestCase;
-
-import java.util.HashSet;
-import java.util.Iterator;
-
-/**
- * Implements basic performance test functionality for HashSets
- */
-
-public class HashSetTest extends PerformanceTestBase {
-    public static final int ITERATIONS = 1000;
-    public static HashSet<Integer> sSet;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        sSet = new HashSet<Integer>();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            sSet.add(i);
-        }
-    }
-
-    @Override
-    public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-        intermediates.setInternalIterations(ITERATIONS);
-        return 0;
-    }
-
-    /**
-     * 
-     * Tests performance for the HashSet method Add(Object arg 0)
-     * 
-     */
-
-    @SuppressWarnings("unchecked")
-    public void testHashSetAdd() {
-        HashSet set = new HashSet();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-        }
-
-    }
-
-    /**
-     * 
-     * Tests performance of HashSet method contains(Object arg 0)
-     * 
-     */
-
-    public void testHashSetContains() {
-        Integer index = new Integer(500);
-        boolean flag;
-        HashSet set = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-        }
-    }
-
-    /**
-     * 
-     * Tests performance of HashSet method size()
-     * 
-     */
-
-    public void testHashSetSize() {
-        int num;
-        HashSet set = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            num = set.size();
-            num = set.size();
-            num = set.size();
-            num = set.size();
-            num = set.size();
-            num = set.size();
-            num = set.size();
-            num = set.size();
-            num = set.size();
-        }
-    }
-
-    /**
-     * 
-     * Tests performance of the HashSet method -iterator()
-     * 
-     */
-
-    public void testHashSetIterator() {
-        Iterator iterator;
-        HashSet set = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-        }
-    }
-
-    /**
-     * 
-     * Tests performance for the HashSet method Remove(Object arg 0)
-     * 
-     */
-
-    @SuppressWarnings("unchecked")
-    public void testHashSetRemove() {
-        HashSet set = new HashSet(sSet);
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-        }
-    }
-
-    /**
-     * 
-     * Tests performance for the HashSet method isEmpty(Object arg 0)
-     * 
-     */
-
-    public void testHashSetIsEmpty() {
-        HashSet set = sSet;
-        boolean flag;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = set.isEmpty();
-            flag = set.isEmpty();
-            flag = set.isEmpty();
-            flag = set.isEmpty();
-            flag = set.isEmpty();
-            flag = set.isEmpty();
-            flag = set.isEmpty();
-            flag = set.isEmpty();
-            flag = set.isEmpty();
-            flag = set.isEmpty();
-        }
-    }
-
-    /**
-     * 
-     * Tests performance for the HashSet method clone()
-     * 
-     */
-
-    public void testHashSetClone() {
-        HashSet hSet = sSet;
-        Object set;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            set = hSet.clone();
-            set = hSet.clone();
-            set = hSet.clone();
-            set = hSet.clone();
-            set = hSet.clone();
-            set = hSet.clone();
-            set = hSet.clone();
-            set = hSet.clone();
-            set = hSet.clone();
-            set = hSet.clone();
-        }
-    }
-}
diff --git a/tests/CoreTests/android/core/HashtableTest.java b/tests/CoreTests/android/core/HashtableTest.java
deleted file mode 100644
index 6160f57..0000000
--- a/tests/CoreTests/android/core/HashtableTest.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import android.test.PerformanceTestBase;
-import android.test.PerformanceTestCase;
-
-import java.util.Hashtable;
-import java.util.Set;
-import java.util.Enumeration;
-
-/**
- * Implements basic performance test functionality for java.util.Hashtable
- */
-
-public class HashtableTest extends PerformanceTestBase {
-    public static final int ITERATIONS = 1000;
-    public Hashtable<String, Integer> sTable;
-    public String[] sKeys;
-
-    @Override
-    @SuppressWarnings("unchecked")
-    protected void setUp() throws Exception {
-        super.setUp();
-        sTable = new Hashtable();
-        sKeys = new String[ITERATIONS];
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            sKeys[i] = Integer.toString(i, 16);
-            sTable.put(sKeys[i], i);
-        }
-    }
-
-    @Override
-    public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-        intermediates.setInternalIterations(ITERATIONS);
-        return 0;
-    }
-
-    @SuppressWarnings("unchecked")
-    public void testHashtablePut() {
-        Hashtable hTable = new Hashtable();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            hTable.put(i, i);
-            hTable.put(i, i);
-            hTable.put(i, i);
-            hTable.put(i, i);
-            hTable.put(i, i);
-            hTable.put(i, i);
-            hTable.put(i, i);
-            hTable.put(i, i);
-            hTable.put(i, i);
-            hTable.put(i, i);
-        }
-    }
-
-    public void testHashtableGet() {
-        int value;
-        String[] keys = sKeys;
-        Hashtable<String, Integer> hTable = sTable;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            value = hTable.get(keys[i]);
-            value = hTable.get(keys[i]);
-            value = hTable.get(keys[i]);
-            value = hTable.get(keys[i]);
-            value = hTable.get(keys[i]);
-            value = hTable.get(keys[i]);
-            value = hTable.get(keys[i]);
-            value = hTable.get(keys[i]);
-            value = hTable.get(keys[i]);
-            value = hTable.get(keys[i]);
-        }
-    }
-
-    public void testHashtablekeyset() {
-        Set keyset;
-        Hashtable<String, Integer> hTable = sTable;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            keyset = hTable.keySet();
-            keyset = hTable.keySet();
-            keyset = hTable.keySet();
-            keyset = hTable.keySet();
-            keyset = hTable.keySet();
-            keyset = hTable.keySet();
-            keyset = hTable.keySet();
-            keyset = hTable.keySet();
-            keyset = hTable.keySet();
-            keyset = hTable.keySet();
-        }
-    }
-
-    /**
-     * 
-     */
-
-    public void testHashtableEntrySet() {
-        Set keyset;
-        Hashtable<String, Integer> hTable = sTable;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            keyset = hTable.entrySet();
-            keyset = hTable.entrySet();
-            keyset = hTable.entrySet();
-            keyset = hTable.entrySet();
-            keyset = hTable.entrySet();
-            keyset = hTable.entrySet();
-            keyset = hTable.entrySet();
-            keyset = hTable.entrySet();
-            keyset = hTable.entrySet();
-            keyset = hTable.entrySet();
-        }
-    }
-
-    public void testHashtableSize() {
-        int len;
-        Hashtable<String, Integer> hTable = sTable;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            len = hTable.size();
-            len = hTable.size();
-            len = hTable.size();
-            len = hTable.size();
-            len = hTable.size();
-            len = hTable.size();
-            len = hTable.size();
-            len = hTable.size();
-            len = hTable.size();
-            len = hTable.size();
-        }
-    }
-
-    public void testHashtableContainsValue() {
-        boolean flag;
-        Hashtable<String, Integer> hTable = sTable;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = hTable.containsValue(i);
-            flag = hTable.containsValue(i);
-            flag = hTable.containsValue(i);
-            flag = hTable.containsValue(i);
-            flag = hTable.containsValue(i);
-            flag = hTable.containsValue(i);
-            flag = hTable.containsValue(i);
-            flag = hTable.containsValue(i);
-            flag = hTable.containsValue(i);
-            flag = hTable.containsValue(i);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public void testHashtableRemove() {
-        Hashtable<String, Integer> hTable = new Hashtable(sTable);
-        String[] keys = sKeys;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            hTable.remove(keys[i]);
-            hTable.remove(keys[i]);
-            hTable.remove(keys[i]);
-            hTable.remove(keys[i]);
-            hTable.remove(keys[i]);
-            hTable.remove(keys[i]);
-            hTable.remove(keys[i]);
-            hTable.remove(keys[i]);
-            hTable.remove(keys[i]);
-            hTable.remove(keys[i]);
-        }
-    }
-
-    public void testHashtableContains() {
-        Hashtable<String, Integer> hTable = sTable;
-        boolean flag;
-
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = hTable.contains(i);
-            flag = hTable.contains(i);
-            flag = hTable.contains(i);
-            flag = hTable.contains(i);
-            flag = hTable.contains(i);
-            flag = hTable.contains(i);
-            flag = hTable.contains(i);
-            flag = hTable.contains(i);
-            flag = hTable.contains(i);
-            flag = hTable.contains(i);
-        }
-    }
-
-    public void testHashtableContainsKey() {
-        Hashtable<String, Integer> hTable = sTable;
-        boolean flag;
-
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = hTable.containsKey(i);
-            flag = hTable.containsKey(i);
-            flag = hTable.containsKey(i);
-            flag = hTable.containsKey(i);
-            flag = hTable.containsKey(i);
-            flag = hTable.containsKey(i);
-            flag = hTable.containsKey(i);
-            flag = hTable.containsKey(i);
-            flag = hTable.containsKey(i);
-            flag = hTable.containsKey(i);
-        }
-    }
-
-    public void testHashtableIsEmpty() {
-        Hashtable<String, Integer> hTable = sTable;
-        boolean flag;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = hTable.isEmpty();
-            flag = hTable.isEmpty();
-            flag = hTable.isEmpty();
-            flag = hTable.isEmpty();
-            flag = hTable.isEmpty();
-            flag = hTable.isEmpty();
-            flag = hTable.isEmpty();
-            flag = hTable.isEmpty();
-            flag = hTable.isEmpty();
-            flag = hTable.isEmpty();
-        }
-    }
-
-    public void testHashtableKeys() {
-        Hashtable<String, Integer> hTable = sTable;
-        Enumeration<String> keys;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            keys = hTable.keys();
-            keys = hTable.keys();
-            keys = hTable.keys();
-            keys = hTable.keys();
-            keys = hTable.keys();
-            keys = hTable.keys();
-            keys = hTable.keys();
-            keys = hTable.keys();
-            keys = hTable.keys();
-            keys = hTable.keys();
-        }
-    }
-
-    public void testHashtableElements() {
-        Hashtable<String, Integer> hTable = sTable;
-        Enumeration<Integer> elements;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            elements = hTable.elements();
-            elements = hTable.elements();
-            elements = hTable.elements();
-            elements = hTable.elements();
-            elements = hTable.elements();
-            elements = hTable.elements();
-            elements = hTable.elements();
-            elements = hTable.elements();
-            elements = hTable.elements();
-            elements = hTable.elements();
-        }
-    }
-
-    public void testHashtableHashCode() {
-        int index;
-        Hashtable<String, Integer> hTable = sTable;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            index = hTable.hashCode();
-            index = hTable.hashCode();
-            index = hTable.hashCode();
-            index = hTable.hashCode();
-            index = hTable.hashCode();
-            index = hTable.hashCode();
-            index = hTable.hashCode();
-            index = hTable.hashCode();
-            index = hTable.hashCode();
-            index = hTable.hashCode();
-        }
-    }
-
-    public void testHashtableEquals() {
-        boolean flag;
-        Hashtable<String, Integer> hTable = sTable;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = hTable.equals(hTable);
-            flag = hTable.equals(hTable);
-            flag = hTable.equals(hTable);
-            flag = hTable.equals(hTable);
-            flag = hTable.equals(hTable);
-            flag = hTable.equals(hTable);
-            flag = hTable.equals(hTable);
-            flag = hTable.equals(hTable);
-            flag = hTable.equals(hTable);
-            flag = hTable.equals(hTable);
-        }
-    }
-
-    public void testHashtableToString() {
-        String str;
-        Hashtable<String, Integer> hTable = sTable;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            str = hTable.toString();
-            str = hTable.toString();
-            str = hTable.toString();
-            str = hTable.toString();
-            str = hTable.toString();
-            str = hTable.toString();
-            str = hTable.toString();
-            str = hTable.toString();
-            str = hTable.toString();
-            str = hTable.toString();
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public void testHashtablePutAll() {
-        Hashtable<String, Integer> hTable = new Hashtable();
-        Hashtable<String, Integer> hTable1 = sTable;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            hTable.putAll(hTable1);
-            hTable.putAll(hTable1);
-            hTable.putAll(hTable1);
-            hTable.putAll(hTable1);
-            hTable.putAll(hTable1);
-            hTable.putAll(hTable1);
-            hTable.putAll(hTable1);
-            hTable.putAll(hTable1);
-            hTable.putAll(hTable1);
-            hTable.putAll(hTable1);
-        }
-    }
-
-    /**
-     * 
-     * clone() returns a Hashtable .. It should return Object as per the
-     * specification.
-     * 
-     */
-
-    public void testHashtableClone() {
-        Hashtable hashTable;
-        Hashtable<String, Integer> hTable = sTable;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            hashTable = (Hashtable) hTable.clone();
-            hashTable = (Hashtable) hTable.clone();
-            hashTable = (Hashtable) hTable.clone();
-            hashTable = (Hashtable) hTable.clone();
-            hashTable = (Hashtable) hTable.clone();
-            hashTable = (Hashtable) hTable.clone();
-            hashTable = (Hashtable) hTable.clone();
-            hashTable = (Hashtable) hTable.clone();
-            hashTable = (Hashtable) hTable.clone();
-            hashTable = (Hashtable) hTable.clone();
-        }
-    }
-}
diff --git a/tests/CoreTests/android/core/HeapTest.java b/tests/CoreTests/android/core/HeapTest.java
index 6116f5e..400d041 100644
--- a/tests/CoreTests/android/core/HeapTest.java
+++ b/tests/CoreTests/android/core/HeapTest.java
@@ -46,73 +46,6 @@
         return new WeakReference<Object>(new Object());
     }
 
-    /**
-     * Allocates the specified number of bytes. This is done in a separate method
-     * to ensure that the Object's address isn't sitting in a stale local register.
-     */
-    private void allocateMemory(int size) {
-        byte[] b = new byte[size];
-    }
-
-    @MediumTest
-    public void testMinimumHeapSize() throws Exception {
-        VMRuntime r = VMRuntime.getRuntime();
-        final boolean RUN_FLAKY = false;
-
-        long origSize = r.getMinimumHeapSize();
-        if (RUN_FLAKY) {
-            /* Check that the default value is zero.  This will break if anyone
-             * in this process sets the minimum heap size to a positive value
-             * before calling this test.
-             */
-            assertTrue(origSize == 0);
-        }
-
-        long size = 4 * 1024 * 1024;
-        long oldSize = r.setMinimumHeapSize(size);
-        assertTrue(oldSize == origSize);
-
-        long newSize = r.getMinimumHeapSize();
-        /* This will fail if the maximum heap size (-Xmx) is smaller than 4MB.
-         */
-        assertTrue(newSize == size);
-
-        /* Make sure that getting the size doesn't change anything.
-         */
-        newSize = r.getMinimumHeapSize();
-        assertTrue(newSize == size);
-
-        /* This test is flaky; if the heap is already large and fragmented,
-         * it can fail.  It can also fail if another thread causes a GC
-         * at the wrong time.
-         */
-        if (RUN_FLAKY) {
-            /* Increase the minimum size, allocate a big object, and make sure that
-             * a GC didn't happen.
-             */
-            WeakReference ref = newRef();
-            assertNotNull(ref.get());
-
-            r.setMinimumHeapSize(8 * 1024 * 1024);
-            allocateMemory(4 * 1024 * 1024);
-
-            /* If a GC happened, this reference will be null.
-             */
-            assertNotNull(ref.get());
-        }
-
-        /* Restore the original setting.
-         */
-        r.setMinimumHeapSize(origSize);
-        newSize = r.getMinimumHeapSize();
-        assertTrue(newSize == origSize);
-
-        /* Clean up any large stuff we've allocated,
-         * and re-establish the normal utilization ratio.
-         */
-        Runtime.getRuntime().gc();
-    }
-
     private static void makeRefs(Object objects[], SoftReference<Object> refs[]) {
         for (int i = 0; i < objects.length; i++) {
             objects[i] = (Object) new byte[8 * 1024];
@@ -540,94 +473,4 @@
             objSize = (objSize * 4) / 5;
         }
     }
-
-    // TODO: flaky test
-    //@SmallTest
-    public void testExternalOomeLarge() {
-        /* Just shy of the typical max heap size so that it will actually
-         * try to allocate it instead of short-circuiting.
-         */
-        final int HUGE_SIZE = (16 * 1024 * 1024 - 32);
-
-        assertFalse(VMRuntime.getRuntime().trackExternalAllocation(HUGE_SIZE));
-    }
-
-    /**
-     * "Allocates" external memory in progressively smaller chunks until there's
-     * only roughly 16 bytes left.
-     *
-     * @return the number of bytes allocated
-     */
-    private long allocateMaxExternal() {
-        final VMRuntime runtime = VMRuntime.getRuntime();
-        final int SIXTEEN_MB = (16 * 1024 * 1024);
-        final int MIN_SIZE = 16;
-        long totalAllocated = 0;
-        boolean success;
-
-        success = false;
-        try {
-            /* "Allocate" progressively smaller chunks to "fill up" the entire heap.
-             */
-            int objSize = 1 * 1024 * 1024;
-            while (objSize >= MIN_SIZE) {
-                boolean sawFailure = false;
-                for (int i = 0; i < SIXTEEN_MB / objSize; i++) {
-                    if (runtime.trackExternalAllocation(objSize)) {
-                        totalAllocated += objSize;
-                    } else {
-                        sawFailure = true;
-                        break;
-                    }
-                }
-
-                if (!sawFailure) {
-                    throw new RuntimeException("Test failed: " +
-                            "no failure while filling heap");
-                }
-
-                objSize = (objSize * 4) / 5;
-            }
-            success = true;
-        } finally {
-            if (!success) {
-                runtime.trackExternalFree(totalAllocated);
-                totalAllocated = 0;
-            }
-        }
-        return totalAllocated;
-    }
-
-    public void xxtest00ExternalOomeSmall() {
-        VMRuntime.getRuntime().trackExternalFree(allocateMaxExternal());
-    }
-
-    /**
-     * Allocates as much external memory as possible, then allocates from the heap
-     * until an OOME is caught.
-     *
-     * It's nice to run this test while the real heap is small, hence the '00' in its
-     * name to force it to run before testOomeSmall().
-     */
-    public void xxtest00CombinedOomeSmall() {
-        long totalAllocated = 0;
-        boolean sawEx = false;
-        try {
-            totalAllocated = allocateMaxExternal();
-            LinkedList<Object> list = new LinkedList<Object>();
-            try {
-                while (true) {
-                    list.add((Object)new byte[8192]);
-                }
-                /*NOTREACHED*/
-            } catch (OutOfMemoryError oom) {
-                sawEx = true;
-            }
-        } finally {
-            VMRuntime.getRuntime().trackExternalFree(totalAllocated);
-        }
-        assertTrue(sawEx);
-    }
-
-    //TODO: test external alloc debugging/inspection
 }
diff --git a/tests/CoreTests/android/core/JavaPerformanceTests.java b/tests/CoreTests/android/core/JavaPerformanceTests.java
deleted file mode 100644
index 95075ea..0000000
--- a/tests/CoreTests/android/core/JavaPerformanceTests.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-/**
- * 
- */
-public class JavaPerformanceTests {
-
-    public static String[] children() {
-        return new String[] {
-                HashMapPerformanceTest.class.getName(),
-                ArrayListPerformanceTest.class.getName(),
-                TreeMapPerformanceTest.class.getName(),
-                TreeSetTest.class.getName(),
-                HashSetTest.class.getName(),
-                HashtableTest.class.getName(),
-                VectorTest.class.getName(),
-                LinkedListTest.class.getName(),
-                MathPerformanceTest.class.getName(),
-        };
-    }
-}
diff --git a/tests/CoreTests/android/core/LinkedListTest.java b/tests/CoreTests/android/core/LinkedListTest.java
deleted file mode 100644
index 8b237fd..0000000
--- a/tests/CoreTests/android/core/LinkedListTest.java
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import android.test.PerformanceTestBase;
-import android.test.PerformanceTestCase;
-import java.util.LinkedList;
-import java.util.ListIterator;
-
-/**
- * This class contains performance tests for methods in java.util.LinkedList
- * 
- */
-@SuppressWarnings("unchecked")
-public class LinkedListTest extends PerformanceTestBase {
-    public static final int ITERATIONS = 1000;
-    LinkedList<Integer> mLinkedList;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mLinkedList = new LinkedList();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            mLinkedList.add(i);
-        }
-    }
-
-    @Override
-    public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-        intermediates.setInternalIterations(ITERATIONS);
-        return 0;
-    }
-
-    public void testLinkedListAdd() {
-        LinkedList<Integer> list = new LinkedList();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            list.add(i);
-            list.add(i);
-            list.add(i);
-            list.add(i);
-            list.add(i);
-            list.add(i);
-            list.add(i);
-            list.add(i);
-            list.add(i);
-            list.add(i);
-        }
-    }
-
-    public void testLinkedListAdd1() {
-        LinkedList<Integer> list = new LinkedList();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            list.add(0, i);
-            list.add(0, i);
-            list.add(0, i);
-            list.add(0, i);
-            list.add(0, i);
-            list.add(0, i);
-            list.add(0, i);
-            list.add(0, i);
-            list.add(0, i);
-            list.add(0, i);
-        }
-    }
-
-    public void testLinkedListToArray() {
-        Object array;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            array = list.toArray();
-            array = list.toArray();
-            array = list.toArray();
-            array = list.toArray();
-            array = list.toArray();
-            array = list.toArray();
-            array = list.toArray();
-            array = list.toArray();
-            array = list.toArray();
-            array = list.toArray();
-        }
-    }
-
-    public void testLinkedListSize() {
-        LinkedList<Integer> list = mLinkedList;
-        int len;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            len = list.size();
-            len = list.size();
-            len = list.size();
-            len = list.size();
-            len = list.size();
-            len = list.size();
-            len = list.size();
-            len = list.size();
-            len = list.size();
-            len = list.size();
-        }
-    }
-
-    public void testLinkedListGet() {
-        int element;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            element = list.get(i);
-            element = list.get(i);
-            element = list.get(i);
-            element = list.get(i);
-            element = list.get(i);
-            element = list.get(i);
-            element = list.get(i);
-            element = list.get(i);
-            element = list.get(i);
-            element = list.get(i);
-        }
-    }
-
-    public void testLinkedListContains() {
-        boolean flag;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = list.contains(i);
-            flag = list.contains(i);
-            flag = list.contains(i);
-            flag = list.contains(i);
-            flag = list.contains(i);
-            flag = list.contains(i);
-            flag = list.contains(i);
-            flag = list.contains(i);
-            flag = list.contains(i);
-            flag = list.contains(i);
-        }
-    }
-
-    public void testLinkedListToArray1() {
-        Integer[] rArray = new Integer[100];
-        Integer[] array;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            array = list.toArray(rArray);
-            array = list.toArray(rArray);
-            array = list.toArray(rArray);
-            array = list.toArray(rArray);
-            array = list.toArray(rArray);
-            array = list.toArray(rArray);
-            array = list.toArray(rArray);
-            array = list.toArray(rArray);
-            array = list.toArray(rArray);
-            array = list.toArray(rArray);
-        }
-    }
-
-    public void testLinkedListSet() {
-        LinkedList<Integer> list = mLinkedList;
-        int value1 = 500, value2 = 0;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            list.set(value1, value2);
-            list.set(value1, value2);
-            list.set(value1, value2);
-            list.set(value1, value2);
-            list.set(value1, value2);
-            list.set(value1, value2);
-            list.set(value1, value2);
-            list.set(value1, value2);
-            list.set(value1, value2);
-            list.set(value1, value2);
-        }
-    }
-
-    public void testLinkedListIndexOf() {
-        int index;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            index = list.indexOf(0);
-            index = list.indexOf(0);
-            index = list.indexOf(0);
-            index = list.indexOf(0);
-            index = list.indexOf(0);
-            index = list.indexOf(0);
-            index = list.indexOf(0);
-            index = list.indexOf(0);
-            index = list.indexOf(0);
-            index = list.indexOf(0);
-
-        }
-    }
-
-    public void testLinkedListLastIndexOf() {
-        int index;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            index = list.lastIndexOf(0);
-            index = list.lastIndexOf(0);
-            index = list.lastIndexOf(0);
-            index = list.lastIndexOf(0);
-            index = list.lastIndexOf(0);
-            index = list.lastIndexOf(0);
-            index = list.lastIndexOf(0);
-            index = list.lastIndexOf(0);
-            index = list.lastIndexOf(0);
-            index = list.lastIndexOf(0);
-        }
-    }
-
-    public void testLinkedListRemove() {
-        int index;
-        LinkedList<Integer> list = new LinkedList(mLinkedList);
-        for (int i = 10; i > 0; i--) {
-            index = list.remove();
-            index = list.remove();
-            index = list.remove();
-            index = list.remove();
-            index = list.remove();
-            index = list.remove();
-            index = list.remove();
-            index = list.remove();
-            index = list.remove();
-            index = list.remove();
-        }
-    }
-
-    public void testLinkedListRemove1() {
-        int index;
-        LinkedList<Integer> list = new LinkedList(mLinkedList);
-        for (int i = 10; i > 0; i--) {
-            index = list.remove(0);
-            index = list.remove(0);
-            index = list.remove(0);
-            index = list.remove(0);
-            index = list.remove(0);
-            index = list.remove(0);
-            index = list.remove(0);
-            index = list.remove(0);
-            index = list.remove(0);
-            index = list.remove(0);
-        }
-    }
-
-    public void testLinkedListRemoveFirst() {
-        int index;
-        LinkedList<Integer> list = new LinkedList(mLinkedList);
-        for (int i = 10; i > 0; i--) {
-            index = list.removeFirst();
-            index = list.removeFirst();
-            index = list.removeFirst();
-            index = list.removeFirst();
-            index = list.removeFirst();
-            index = list.removeFirst();
-            index = list.removeFirst();
-            index = list.removeFirst();
-            index = list.removeFirst();
-            index = list.removeFirst();
-        }
-    }
-
-    public void testLinkedListRemoveLast() {
-        int index;
-        LinkedList<Integer> list = new LinkedList(mLinkedList);
-        for (int i = 10; i > 0; i--) {
-            index = list.removeLast();
-            index = list.removeLast();
-            index = list.removeLast();
-            index = list.removeLast();
-            index = list.removeLast();
-            index = list.removeLast();
-            index = list.removeLast();
-            index = list.removeLast();
-            index = list.removeLast();
-            index = list.removeLast();
-        }
-    }
-
-    public void testLinkedListAddAll() {
-        LinkedList<Integer> mList = mLinkedList;
-        boolean flag;
-        LinkedList<Integer> list = new LinkedList();
-        for (int i = 10; i > 0; i--) {
-            flag = list.addAll(mList);
-            flag = list.addAll(mList);
-            flag = list.addAll(mList);
-            flag = list.addAll(mList);
-            flag = list.addAll(mList);
-            flag = list.addAll(mList);
-            flag = list.addAll(mList);
-            flag = list.addAll(mList);
-            flag = list.addAll(mList);
-            flag = list.addAll(mList);
-        }
-    }
-
-    public void testLinkedListRemove2() {
-        LinkedList<String> list;
-        String s = new String("a");
-        list = new LinkedList();
-        for (int j = 1000; j > 0; j--) {
-            list.add("a");
-            list.add("b");
-        }
-        boolean flag;
-        for (int i = 10; i > 0; i--) {
-            flag = list.remove(s);
-            flag = list.remove(s);
-            flag = list.remove(s);
-            flag = list.remove(s);
-            flag = list.remove(s);
-            flag = list.remove(s);
-            flag = list.remove(s);
-            flag = list.remove(s);
-            flag = list.remove(s);
-            flag = list.remove(s);
-        }
-    }
-
-    public void testLinkedListAddAll1() {
-        LinkedList<Integer> mList = new LinkedList();
-        int pos = 0;
-        boolean flag;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = 0; i < 10; i++) {
-            flag = mList.addAll(pos, list);
-            flag = mList.addAll(pos, list);
-            flag = mList.addAll(pos, list);
-            flag = mList.addAll(pos, list);
-            flag = mList.addAll(pos, list);
-            flag = mList.addAll(pos, list);
-            flag = mList.addAll(pos, list);
-            flag = mList.addAll(pos, list);
-            flag = mList.addAll(pos, list);
-            flag = mList.addAll(pos, list);
-        }
-    }
-
-    public void testLinkedListClone() {
-        Object rObj;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = 100; i > 0; i--) {
-            rObj = list.clone();
-            rObj = list.clone();
-            rObj = list.clone();
-            rObj = list.clone();
-            rObj = list.clone();
-            rObj = list.clone();
-            rObj = list.clone();
-            rObj = list.clone();
-            rObj = list.clone();
-            rObj = list.clone();
-        }
-    }
-
-    public void testLinkedListHashcode() {
-        int element;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            element = list.hashCode();
-            element = list.hashCode();
-            element = list.hashCode();
-            element = list.hashCode();
-            element = list.hashCode();
-            element = list.hashCode();
-            element = list.hashCode();
-            element = list.hashCode();
-            element = list.hashCode();
-            element = list.hashCode();
-        }
-    }
-
-    public void testLinkedListElement() {
-        int element;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            element = list.element();
-            element = list.element();
-            element = list.element();
-            element = list.element();
-            element = list.element();
-            element = list.element();
-            element = list.element();
-            element = list.element();
-            element = list.element();
-            element = list.element();
-        }
-    }
-
-    public void testLinkedListToString() {
-        String str;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            str = list.toString();
-            str = list.toString();
-            str = list.toString();
-            str = list.toString();
-            str = list.toString();
-            str = list.toString();
-            str = list.toString();
-            str = list.toString();
-            str = list.toString();
-            str = list.toString();
-        }
-    }
-
-    public void testLinkedListIsEmpty() {
-        boolean flag;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = list.isEmpty();
-            flag = list.isEmpty();
-            flag = list.isEmpty();
-            flag = list.isEmpty();
-            flag = list.isEmpty();
-            flag = list.isEmpty();
-            flag = list.isEmpty();
-            flag = list.isEmpty();
-            flag = list.isEmpty();
-            flag = list.isEmpty();
-        }
-    }
-
-    public void testLinkedListOffer() {
-        LinkedList<Integer> list = new LinkedList();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            list.offer(i);
-            list.offer(i);
-            list.offer(i);
-            list.offer(i);
-            list.offer(i);
-            list.offer(i);
-            list.offer(i);
-            list.offer(i);
-            list.offer(i);
-            list.offer(i);
-        }
-    }
-
-    public void testLinkedListPeek() {
-        int element;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            element = list.peek();
-            element = list.peek();
-            element = list.peek();
-            element = list.peek();
-            element = list.peek();
-            element = list.peek();
-            element = list.peek();
-            element = list.peek();
-            element = list.peek();
-            element = list.peek();
-        }
-    }
-
-    public void testLinkedListPoll() {
-        int element;
-        LinkedList<Integer> list = new LinkedList(mLinkedList);
-        for (int i = 10; i > 0; i--) {
-            element = list.poll();
-            element = list.poll();
-            element = list.poll();
-            element = list.poll();
-            element = list.poll();
-            element = list.poll();
-            element = list.poll();
-            element = list.poll();
-            element = list.poll();
-            element = list.poll();
-        }
-    }
-
-    public void testLinkedListAddLast() {
-        LinkedList<Integer> list = new LinkedList();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            list.addLast(i);
-            list.addLast(i);
-            list.addLast(i);
-            list.addLast(i);
-            list.addLast(i);
-            list.addLast(i);
-            list.addLast(i);
-            list.addLast(i);
-            list.addLast(i);
-            list.addLast(i);
-        }
-    }
-
-    public void testLinkedListAddFirst() {
-        LinkedList<Integer> list = new LinkedList();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            list.addFirst(i);
-            list.addFirst(i);
-            list.addFirst(i);
-            list.addFirst(i);
-            list.addFirst(i);
-            list.addFirst(i);
-            list.addFirst(i);
-            list.addFirst(i);
-            list.addFirst(i);
-            list.addFirst(i);
-        }
-    }
-
-    public void testLinkedListIterator() {
-        ListIterator iterator;
-        LinkedList<Integer> list = mLinkedList;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            iterator = list.listIterator();
-            iterator = list.listIterator();
-            iterator = list.listIterator();
-            iterator = list.listIterator();
-            iterator = list.listIterator();
-            iterator = list.listIterator();
-            iterator = list.listIterator();
-            iterator = list.listIterator();
-            iterator = list.listIterator();
-            iterator = list.listIterator();
-        }
-    }
-}
diff --git a/tests/CoreTests/android/core/MathPerformanceTest.java b/tests/CoreTests/android/core/MathPerformanceTest.java
deleted file mode 100644
index b1eb500..0000000
--- a/tests/CoreTests/android/core/MathPerformanceTest.java
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import android.test.PerformanceTestBase;
-import android.test.PerformanceTestCase;
-
-/**
- * 
- * Implements basic performance test functionality for java.lang.Math
- * 
- */
-
-public class MathPerformanceTest extends PerformanceTestBase {
-    public static final int ITERATIONS = 1000;
-    public static final double sDouble1 = -2450.50;
-    public static final double sDouble2 = -500;
-    public static final float sFloat = 300.50f;
-    public static final int sInt = 90;
-
-    @Override
-    public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-        intermediates.setInternalIterations(ITERATIONS);
-        return 0;
-    }
-
-    public void testDoubleAbs() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.abs(sDouble1);
-            result = Math.abs(sDouble1);
-            result = Math.abs(sDouble1);
-            result = Math.abs(sDouble1);
-            result = Math.abs(sDouble1);
-            result = Math.abs(sDouble1);
-            result = Math.abs(sDouble1);
-            result = Math.abs(sDouble1);
-            result = Math.abs(sDouble1);
-            result = Math.abs(sDouble1);
-        }
-    }
-
-    public void testFloatAbs() {
-        float result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.abs(sFloat);
-            result = Math.abs(sFloat);
-            result = Math.abs(sFloat);
-            result = Math.abs(sFloat);
-            result = Math.abs(sFloat);
-            result = Math.abs(sFloat);
-            result = Math.abs(sFloat);
-            result = Math.abs(sFloat);
-            result = Math.abs(sFloat);
-            result = Math.abs(sFloat);
-        }
-    }
-
-    public void testMathSin() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.sin(sDouble1);
-            result = Math.sin(sDouble1);
-            result = Math.sin(sDouble1);
-            result = Math.sin(sDouble1);
-            result = Math.sin(sDouble1);
-            result = Math.sin(sDouble1);
-            result = Math.sin(sDouble1);
-            result = Math.sin(sDouble1);
-            result = Math.sin(sDouble1);
-            result = Math.sin(sDouble1);
-        }
-    }
-
-    public void testMathCos() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.cos(sDouble1);
-            result = Math.cos(sDouble1);
-            result = Math.cos(sDouble1);
-            result = Math.cos(sDouble1);
-            result = Math.cos(sDouble1);
-            result = Math.cos(sDouble1);
-            result = Math.cos(sDouble1);
-            result = Math.cos(sDouble1);
-            result = Math.cos(sDouble1);
-            result = Math.cos(sDouble1);
-        }
-    }
-
-    public void testMathTan() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.tan(sDouble1);
-            result = Math.tan(sDouble1);
-            result = Math.tan(sDouble1);
-            result = Math.tan(sDouble1);
-            result = Math.tan(sDouble1);
-            result = Math.tan(sDouble1);
-            result = Math.tan(sDouble1);
-            result = Math.tan(sDouble1);
-            result = Math.tan(sDouble1);
-            result = Math.tan(sDouble1);
-        }
-    }
-
-    public void testMathASin() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.asin(sDouble1);
-            result = Math.asin(sDouble1);
-            result = Math.asin(sDouble1);
-            result = Math.asin(sDouble1);
-            result = Math.asin(sDouble1);
-            result = Math.asin(sDouble1);
-            result = Math.asin(sDouble1);
-            result = Math.asin(sDouble1);
-            result = Math.asin(sDouble1);
-            result = Math.asin(sDouble1);
-        }
-    }
-
-    public void testMathACos() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.acos(sDouble1);
-            result = Math.acos(sDouble1);
-            result = Math.acos(sDouble1);
-            result = Math.acos(sDouble1);
-            result = Math.acos(sDouble1);
-            result = Math.acos(sDouble1);
-            result = Math.acos(sDouble1);
-            result = Math.acos(sDouble1);
-            result = Math.acos(sDouble1);
-            result = Math.acos(sDouble1);
-        }
-    }
-
-    public void testMathATan() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.atan(sDouble1);
-            result = Math.atan(sDouble1);
-            result = Math.atan(sDouble1);
-            result = Math.atan(sDouble1);
-            result = Math.atan(sDouble1);
-            result = Math.atan(sDouble1);
-            result = Math.atan(sDouble1);
-            result = Math.atan(sDouble1);
-            result = Math.atan(sDouble1);
-            result = Math.atan(sDouble1);
-        }
-    }
-
-    public void testMathLog() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.log(sDouble1);
-            result = Math.log(sDouble1);
-            result = Math.log(sDouble1);
-            result = Math.log(sDouble1);
-            result = Math.log(sDouble1);
-            result = Math.log(sDouble1);
-            result = Math.log(sDouble1);
-            result = Math.log(sDouble1);
-            result = Math.log(sDouble1);
-            result = Math.log(sDouble1);
-        }
-    }
-
-    public void testMathSqrt() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.sqrt(sDouble1);
-            result = Math.sqrt(sDouble1);
-            result = Math.sqrt(sDouble1);
-            result = Math.sqrt(sDouble1);
-            result = Math.sqrt(sDouble1);
-            result = Math.sqrt(sDouble1);
-            result = Math.sqrt(sDouble1);
-            result = Math.sqrt(sDouble1);
-            result = Math.sqrt(sDouble1);
-            result = Math.sqrt(sDouble1);
-        }
-    }
-
-    public void testMathCeil() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.ceil(sDouble1);
-            result = Math.ceil(sDouble1);
-            result = Math.ceil(sDouble1);
-            result = Math.ceil(sDouble1);
-            result = Math.ceil(sDouble1);
-            result = Math.ceil(sDouble1);
-            result = Math.ceil(sDouble1);
-            result = Math.ceil(sDouble1);
-            result = Math.ceil(sDouble1);
-            result = Math.ceil(sDouble1);
-        }
-    }
-
-    public void testMathRound() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.round(sDouble1);
-            result = Math.round(sDouble1);
-            result = Math.round(sDouble1);
-            result = Math.round(sDouble1);
-            result = Math.round(sDouble1);
-            result = Math.round(sDouble1);
-            result = Math.round(sDouble1);
-            result = Math.round(sDouble1);
-            result = Math.round(sDouble1);
-            result = Math.round(sDouble1);
-        }
-    }
-
-    public void testMathFloor() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.floor(sDouble1);
-            result = Math.floor(sDouble1);
-            result = Math.floor(sDouble1);
-            result = Math.floor(sDouble1);
-            result = Math.floor(sDouble1);
-            result = Math.floor(sDouble1);
-            result = Math.floor(sDouble1);
-            result = Math.floor(sDouble1);
-            result = Math.floor(sDouble1);
-            result = Math.floor(sDouble1);
-        }
-    }
-
-    public void testMathExp() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.exp(sDouble1);
-            result = Math.exp(sDouble1);
-            result = Math.exp(sDouble1);
-            result = Math.exp(sDouble1);
-            result = Math.exp(sDouble1);
-            result = Math.exp(sDouble1);
-            result = Math.exp(sDouble1);
-            result = Math.exp(sDouble1);
-            result = Math.exp(sDouble1);
-            result = Math.exp(sDouble1);
-        }
-    }
-
-    /**
-     * 
-     */
-
-    public void testMathPow() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.pow(sDouble1, sDouble2);
-            result = Math.pow(sDouble1, sDouble2);
-            result = Math.pow(sDouble1, sDouble2);
-            result = Math.pow(sDouble1, sDouble2);
-            result = Math.pow(sDouble1, sDouble2);
-            result = Math.pow(sDouble1, sDouble2);
-            result = Math.pow(sDouble1, sDouble2);
-            result = Math.pow(sDouble1, sDouble2);
-            result = Math.pow(sDouble1, sDouble2);
-            result = Math.pow(sDouble1, sDouble2);
-        }
-    }
-
-    public void testMathMax() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.max(sDouble1, sDouble2);
-            result = Math.max(sDouble1, sDouble2);
-            result = Math.max(sDouble1, sDouble2);
-            result = Math.max(sDouble1, sDouble2);
-            result = Math.max(sDouble1, sDouble2);
-            result = Math.max(sDouble1, sDouble2);
-            result = Math.max(sDouble1, sDouble2);
-            result = Math.max(sDouble1, sDouble2);
-            result = Math.max(sDouble1, sDouble2);
-            result = Math.max(sDouble1, sDouble2);
-        }
-    }
-
-    public void testMathMin() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.min(sDouble1, sDouble2);
-            result = Math.min(sDouble1, sDouble2);
-            result = Math.min(sDouble1, sDouble2);
-            result = Math.min(sDouble1, sDouble2);
-            result = Math.min(sDouble1, sDouble2);
-            result = Math.min(sDouble1, sDouble2);
-            result = Math.min(sDouble1, sDouble2);
-            result = Math.min(sDouble1, sDouble2);
-            result = Math.min(sDouble1, sDouble2);
-            result = Math.min(sDouble1, sDouble2);
-        }
-    }
-
-    public void testMathRandom() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.random();
-            result = Math.random();
-            result = Math.random();
-            result = Math.random();
-            result = Math.random();
-            result = Math.random();
-            result = Math.random();
-            result = Math.random();
-            result = Math.random();
-            result = Math.random();
-        }
-    }
-
-    public void testMathIEEERemainder() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.IEEEremainder(sDouble1, sDouble2);
-            result = Math.IEEEremainder(sDouble1, sDouble2);
-            result = Math.IEEEremainder(sDouble1, sDouble2);
-            result = Math.IEEEremainder(sDouble1, sDouble2);
-            result = Math.IEEEremainder(sDouble1, sDouble2);
-            result = Math.IEEEremainder(sDouble1, sDouble2);
-            result = Math.IEEEremainder(sDouble1, sDouble2);
-            result = Math.IEEEremainder(sDouble1, sDouble2);
-            result = Math.IEEEremainder(sDouble1, sDouble2);
-            result = Math.IEEEremainder(sDouble1, sDouble2);
-        }
-    }
-
-    public void testMathToDegrees() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.toDegrees(sDouble1);
-            result = Math.toDegrees(sDouble1);
-            result = Math.toDegrees(sDouble1);
-            result = Math.toDegrees(sDouble1);
-            result = Math.toDegrees(sDouble1);
-            result = Math.toDegrees(sDouble1);
-            result = Math.toDegrees(sDouble1);
-            result = Math.toDegrees(sDouble1);
-            result = Math.toDegrees(sDouble1);
-            result = Math.toDegrees(sDouble1);
-        }
-    }
-
-    public void testMathToRadians() {
-        double result;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            result = Math.toRadians(sDouble1);
-            result = Math.toRadians(sDouble1);
-            result = Math.toRadians(sDouble1);
-            result = Math.toRadians(sDouble1);
-            result = Math.toRadians(sDouble1);
-            result = Math.toRadians(sDouble1);
-            result = Math.toRadians(sDouble1);
-            result = Math.toRadians(sDouble1);
-            result = Math.toRadians(sDouble1);
-            result = Math.toRadians(sDouble1);
-        }
-    }
-}
diff --git a/tests/CoreTests/android/core/PerformanceTests.java b/tests/CoreTests/android/core/PerformanceTests.java
deleted file mode 100644
index faf46e6..0000000
--- a/tests/CoreTests/android/core/PerformanceTests.java
+++ /dev/null
@@ -1,1224 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import org.apache.harmony.dalvik.NativeTestTarget;
-
-import android.test.PerformanceTestBase;
-import android.test.PerformanceTestCase;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import junit.framework.Assert;
-
-public class PerformanceTests {
-    public static String[] children() {
-        return new String[] {
-                //StringEquals2.class.getName(),
-                //StringEquals10.class.getName(),
-                //StringEquals20.class.getName(),
-                //StringEquals200.class.getName(),
-                //StringEquals200U.class.getName(),
-                //StringCompareTo10.class.getName(),
-                //StringCompareTo200.class.getName(),
-                StringLength.class.getName(),
-                StringCrawl.class.getName(),
-                Ackermann.class.getName(),
-                AddTest.class.getName(),
-//                AddMemberVariableTest.class.getName(),
-                ArrayListIterator.class.getName(),
-                BoundsCheckTest.class.getName(),
-//                EmptyClassBaseTest.class.getName(),
-                EmptyJniStaticMethod0.class.getName(),
-                EmptyJniStaticMethod6.class.getName(),
-                EmptyJniStaticMethod6L.class.getName(),
-                FibonacciFast.class.getName(),
-                FibonacciSlow.class.getName(),
-//                LoopTests.class.getName(),
-//                HashMapTest.class.getName(),
-//                InterfaceTests.class.getName(),
-                LocalVariableAccess.class.getName(),
-                MemeberVariableAccess.class.getName(),
-                NestedLoop.class.getName(),
-//                StringConcatenationTests.class.getName(),
-//                ArrayListBase.class.getName(),
-                SynchronizedGetAndSetInt.class.getName(),
-
-                /* this will not work on JamVM -- lacks atomic ops */
-                AtomicGetAndSetInt.class.getName(),
-        };
-    }
-
-    public static class SizeTest {
-        private int mSize;
-
-        public SizeTest(int size) {
-            mSize = size;
-        }
-
-        public int size() {
-            return mSize;
-        }
-    }
-
-    public static class LocalVariableAccess extends PerformanceTestBase {
-        private static final int ITERATIONS = 100000;
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 20);
-            return 0;
-        }
-
-        public void testRun() {
-            boolean variable = false;
-            boolean local = true;
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                local = variable;
-                local = variable;
-                local = variable;
-                local = variable;
-                local = variable; // 5
-                local = variable;
-                local = variable;
-                local = variable;
-                local = variable;
-                local = variable; // 10
-                local = variable;
-                local = variable;
-                local = variable;
-                local = variable;
-                local = variable; // 15
-                local = variable;
-                local = variable;
-                local = variable;
-                local = variable;
-                local = variable; // 20
-            }
-        }
-    }
-
-    /* This test is intentionally misspelled. Please do not rename it. Thanks! */
-    public static class MemeberVariableAccess extends PerformanceTestBase {
-        private static final int ITERATIONS = 100000;
-
-        public volatile boolean mMember = false;
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 20);
-            return 0;
-        }
-
-        public void testRun() {
-            boolean local = true;
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                local = mMember;
-                local = mMember;
-                local = mMember;
-                local = mMember;
-                local = mMember; // 5
-                local = mMember;
-                local = mMember;
-                local = mMember;
-                local = mMember;
-                local = mMember; // 10
-                local = mMember;
-                local = mMember;
-                local = mMember;
-                local = mMember;
-                local = mMember; // 15
-                local = mMember;
-                local = mMember;
-                local = mMember;
-                local = mMember;
-                local = mMember; // 20
-            }
-        }
-    }
-
-    public static class ArrayListIterator extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-        private ArrayList mList;
-        private String[] mKeys;
-        private Iterator mIterator;
-
-        public void setUp() throws Exception {
-            super.setUp();
-            mList = new ArrayList();
-            mKeys = new String[ITERATIONS];
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                mKeys[i] = Integer.toString(i, 16);
-                mList.add(mKeys[i]);
-            }
-        }
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS);
-            return 0;
-        }
-
-        public void testRun() {
-            mIterator = mList.iterator();
-            while (mIterator.hasNext()) {
-                mIterator.next();
-            }
-        }
-    }
-
-    public static class Ackermann extends PerformanceTestBase {
-        public static final int ITERATIONS = 100;
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS);
-            return 0;
-        }
-
-        public void testRun() {
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                ackermann(3, 13);
-            }
-        }
-
-        private int ackermann(int m, int n) {
-            if (m == 0)
-                return n + 1;
-            if (n == 0)
-                return ackermann(m - 1, 1);
-            return ackermann(m, n - 1);
-        }
-    }
-
-    public static class FibonacciSlow extends PerformanceTestBase {
-        public void setUp() throws Exception {
-            super.setUp();
-            Assert.assertEquals(0, fibonacci(0));
-            Assert.assertEquals(1, fibonacci(1));
-            Assert.assertEquals(1, fibonacci(2));
-            Assert.assertEquals(2, fibonacci(3));
-            Assert.assertEquals(6765, fibonacci(20));
-        }
-
-        public void tearDown() {
-        }
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            return 0;
-        }
-
-        public void testRun() {
-            fibonacci(20);
-        }
-
-        private long fibonacci(long n) {
-            if (n == 0)
-                return 0;
-            if (n == 1)
-                return 1;
-            return fibonacci(n - 2) + fibonacci(n - 1);
-        }
-    }
-
-    public static class FibonacciFast extends PerformanceTestBase {
-        public void setUp() throws Exception {
-            super.setUp();
-            Assert.assertEquals(0, fibonacci(0));
-            Assert.assertEquals(1, fibonacci(1));
-            Assert.assertEquals(1, fibonacci(2));
-            Assert.assertEquals(2, fibonacci(3));
-            Assert.assertEquals(6765, fibonacci(20));
-        }
-
-        public void tearDown() {
-        }
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            return 0;
-        }
-
-        public void testRun() {
-            fibonacci(5000);
-        }
-
-        private long fibonacci(long n) {
-            if (n == 0)
-                return 0;
-            if (n == 1)
-                return 1;
-
-            int x = 0;
-            int y = 1;
-            for (int i = 0; i < n - 1; i++) {
-                y = y + x;
-                x = y - x;
-            }
-
-            return y;
-        }
-    }
-
-    public static class HashMapTest extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-        private HashMap mMap;
-        private String[] mKeys;
-
-        public void setUp() throws Exception {
-            super.setUp();
-            mMap = new HashMap();
-            mKeys = new String[ITERATIONS];
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                mKeys[i] = Integer.toString(i, 16);
-                mMap.put(mKeys[i], i);
-            }
-        }
-
-        public void tearDown() {
-        }
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS);
-            return 0;
-        }
-
-        public void testHashMapContainsKey() {
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                mMap.containsKey(mKeys[i]);
-            }
-        }
-
-        public void testHashMapIterator() {
-            Iterator iterator;
-
-            iterator = mMap.entrySet().iterator();
-            while (iterator.hasNext()) {
-                iterator.next();
-            }
-        }
-
-        public void testHashMapPut() {
-            HashMap map = new HashMap();
-            String[] keys = mKeys;
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                map.put(keys[i], i);
-            }
-        }
-    }
-
-    interface IA {
-        void funcA0();
-        void funcA1();
-        void funcA2();
-        void funcA3();
-    }
-    interface IAB extends IA {
-        void funcAB0();
-        void funcAB1();
-        void funcAB2();
-        void funcAB3();
-    }
-    interface IABC extends IAB {
-        void funcABC0();
-        void funcABC1();
-        void funcABC2();
-        void funcABC3();
-    }
-    interface IB {
-        void funcB0();
-        void funcB1();
-        void funcB2();
-        void funcB3();
-    }
-    interface IC {
-        void funcC0();
-        void funcC1();
-        void funcC2();
-        void funcC3();
-    }
-
-    static class Alphabet implements Cloneable, IB, IABC, IC, Runnable {
-        public void funcA0() {
-        }
-        public void funcA1() {
-        }
-        public void funcA2() {
-        }
-        public void funcA3() {
-        }
-        public void funcAB0() {
-        }
-        public void funcAB1() {
-        }
-        public void funcAB2() {
-        }
-        public void funcAB3() {
-        }
-        public void funcABC0() {
-        }
-        public void funcABC1() {
-        }
-        public void funcABC2() {
-        }
-        public void funcABC3() {
-        }
-        public void funcB0() {
-        }
-        public void funcB1() {
-        }
-        public void funcB2() {
-        }
-        public void funcB3() {
-        }
-        public void funcC0() {
-        }
-        public void funcC1() {
-        }
-        public void funcC2() {
-        }
-        public void funcC3() {
-        }
-        public void run() {
-        }
-    };
-
-    public static class InterfaceTests extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 10);
-            return 0;
-        }
-
-        /* call method directly */
-        public void testInterfaceCalls0() {
-            Alphabet alpha = new Alphabet();
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                alpha.funcABC1();
-                alpha.funcABC1();
-                alpha.funcABC1();
-                alpha.funcABC1();
-                alpha.funcABC1();
-                alpha.funcABC1();
-                alpha.funcABC1();
-                alpha.funcABC1();
-                alpha.funcABC1();
-                alpha.funcABC1();
-            }
-        }
-
-       /* call method through interface reference */
-        public void testInterfaceCalls1() {
-            Alphabet alpha = new Alphabet();
-            IABC iabc = alpha;
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                iabc.funcABC1();
-                iabc.funcABC1();
-                iabc.funcABC1();
-                iabc.funcABC1();
-                iabc.funcABC1();
-                iabc.funcABC1();
-                iabc.funcABC1();
-                iabc.funcABC1();
-                iabc.funcABC1();
-                iabc.funcABC1();
-            }
-        }
-
-        public void testInstanceOfTrivial() {
-            Alphabet alpha = new Alphabet();
-            IABC iabc = alpha;
-            boolean val;
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                val = iabc instanceof Alphabet;
-                val = iabc instanceof Alphabet;
-                val = iabc instanceof Alphabet;
-                val = iabc instanceof Alphabet;
-                val = iabc instanceof Alphabet;
-                val = iabc instanceof Alphabet;
-                val = iabc instanceof Alphabet;
-                val = iabc instanceof Alphabet;
-                val = iabc instanceof Alphabet;
-                val = iabc instanceof Alphabet;
-            }
-        }
-
-        public void testInstanceOfInterface() {
-            Alphabet alpha = new Alphabet();
-            IABC iabc = alpha;
-            boolean val;
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                val = iabc instanceof IA;
-                val = iabc instanceof IA;
-                val = iabc instanceof IA;
-                val = iabc instanceof IA;
-                val = iabc instanceof IA;
-                val = iabc instanceof IA;
-                val = iabc instanceof IA;
-                val = iabc instanceof IA;
-                val = iabc instanceof IA;
-                val = iabc instanceof IA;
-            }
-        }
-
-        public void testInstanceOfNot() {
-            Alphabet alpha = new Alphabet();
-            IABC iabc = alpha;
-            boolean val;
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                val = iabc instanceof EmptyInterface;
-                val = iabc instanceof EmptyInterface;
-                val = iabc instanceof EmptyInterface;
-                val = iabc instanceof EmptyInterface;
-                val = iabc instanceof EmptyInterface;
-                val = iabc instanceof EmptyInterface;
-                val = iabc instanceof EmptyInterface;
-                val = iabc instanceof EmptyInterface;
-                val = iabc instanceof EmptyInterface;
-                val = iabc instanceof EmptyInterface;
-            }
-        }
-    }
-
-    public static class NestedLoop extends PerformanceTestBase {
-        private static final int ITERATIONS = 10;
-        private static final int LOOPS = 5;
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * LOOPS);
-            return 0;
-        }
-
-        public void testRun() {
-            int x = 0;
-            for (int a = 0; a < ITERATIONS; a++) {
-                for (int b = 0; b < ITERATIONS; b++) {
-                    for (int c = 0; c < ITERATIONS; c++) {
-                        for (int d = 0; d < ITERATIONS; d++) {
-                            for (int e = 0; e < ITERATIONS; e++) {
-                                x++;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    public static class StringConcatenationTests extends PerformanceTestBase {
-        private static final int ITERATIONS = 1000;
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS);
-            return 0;
-        }
-
-        public void testStringConcatenation1() {
-            StringBuffer buffer = new StringBuffer();
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                buffer.append("Hello World!\n");
-            }
-            buffer = null;
-        }
-
-        public void testStringConcatenation2() {
-            String string = "";
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                string += "Hello World!\n";
-            }
-            string = null;
-        }
-    }
-
-    public static class StringLength extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-        private static final String TEST_STRING = "This is the string we use for testing..."; // 40 chars
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 10);
-            return 0;
-        }
-
-        public void testRun() {
-            String testStr = TEST_STRING;
-            int length;
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                length = testStr.length();
-                length = testStr.length();
-                length = testStr.length();
-                length = testStr.length();
-                length = testStr.length();
-                length = testStr.length();
-                length = testStr.length();
-                length = testStr.length();
-                length = testStr.length();
-                length = testStr.length();
-            }
-        }
-    }
-
-    public static class EmptyJniStaticMethod0 extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 10);
-            return 0;
-        }
-
-        public void testRun() {
-            int a, b, c, d, e, f;
-
-            a = b = c = d = e = f = 0;
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-            }
-        }
-    }
-    public static class EmptyJniStaticMethod6 extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 10);
-            return 0;
-        }
-
-        public void testRun() {
-            int a, b, c, d, e, f;
-
-            a = b = c = d = e = f = 0;
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-            }
-        }
-    }
-    public static class EmptyJniStaticMethod6L extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 10);
-            return 0;
-        }
-
-        public void testRun() {
-            String a = null;
-            String[] b = null;
-            int[][] c = null;
-            Object d = null;
-            Object[] e = null;
-            Object[][][][] f = null;
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6L(a, b, c, d, e, f);
-            }
-        }
-    }
-
-    public static class StringCrawl extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-        private static final String TEST_STRING = "This is the string we use for testing..."; // 40 chars
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * TEST_STRING.length());
-            return 0;
-        }
-
-        public void testRun() {
-            String testStr = TEST_STRING;
-            char ch;
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                /* this is the wrong way to walk through a string */
-                for (int j = 0; j < testStr.length(); j++) {
-                    ch = testStr.charAt(j);
-                }
-            }
-        }
-    }
-
-    public static class AddTest extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 20);
-            return 0;
-        }
-
-        public void testRun() {
-            int j = 0;
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-            }
-        }
-    }
-
-    public static class AddMemberVariableTest extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-        private int j;
-
-        public void setUp() throws Exception {
-           super.setUp();
-           j = 0;
-        }
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 10);
-            return 0;
-        }
-
-        public void testAddMemberVariableTest() {
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-                j++;
-            }
-        }
-
-        public void testAddMemberVariableInMethodTest() {
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                add();
-                add();
-                add();
-                add();
-                add();
-                add();
-                add();
-                add();
-                add();
-                add();
-            }
-        }
-
-        public void add() {
-            j++;
-        }
-    }
-
-    private interface EmptyInterface {
-        public void emptyVirtual();
-
-    }
-
-    private static class EmptyClass implements EmptyInterface {
-        public void emptyVirtual() {
-        }
-
-        public static void emptyStatic() {
-        }
-    }
-
-    public static class EmptyClassBaseTest extends PerformanceTestBase {
-        protected EmptyInterface mEmptyInterface;
-        protected EmptyClass mEmptyClass;
-
-        public void setUp() throws Exception {
-            super.setUp();
-            mEmptyClass = new EmptyClass();
-            mEmptyInterface = mEmptyClass;
-        }
-        private static final int ITERATIONS = 10000;
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 10);
-            return 0;
-        }
-
-        public void testEmptyVirtualMethod() {
-            //EmptyClass emtpyClass = mEmptyClass;
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                mEmptyClass.emptyVirtual();
-                mEmptyClass.emptyVirtual();
-                mEmptyClass.emptyVirtual();
-                mEmptyClass.emptyVirtual();
-                mEmptyClass.emptyVirtual();
-                mEmptyClass.emptyVirtual();
-                mEmptyClass.emptyVirtual();
-                mEmptyClass.emptyVirtual();
-                mEmptyClass.emptyVirtual();
-                mEmptyClass.emptyVirtual();
-            }
-        }
-
-        public void testEmptyVirtualMethodTestInLocal() {
-            EmptyClass empty = mEmptyClass;
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                empty.emptyVirtual();
-                empty.emptyVirtual();
-                empty.emptyVirtual();
-                empty.emptyVirtual();
-                empty.emptyVirtual();
-                empty.emptyVirtual();
-                empty.emptyVirtual();
-                empty.emptyVirtual();
-                empty.emptyVirtual();
-                empty.emptyVirtual();
-            }
-        }
-
-    public void testEmptyStaticMethod () {
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                EmptyClass.emptyStatic();
-                EmptyClass.emptyStatic();
-                EmptyClass.emptyStatic();
-                EmptyClass.emptyStatic();
-                EmptyClass.emptyStatic();
-                EmptyClass.emptyStatic();
-                EmptyClass.emptyStatic();
-                EmptyClass.emptyStatic();
-                EmptyClass.emptyStatic();
-                EmptyClass.emptyStatic();
-            }
-        }
-
-    public void testEmptyJniStaticMethod0() {
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-                NativeTestTarget.emptyJniStaticMethod0();
-            }
-        }
-
-    public void testEmptyJniStaticMethod6() {
-            int a, b, c, d, e, f;
-
-            a = b = c = d = e = f = 0;
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-                NativeTestTarget.emptyJniStaticMethod6(a, b, c, d, e, f);
-            }
-        }
-
-    public void testEmptyInternalStaticMethod() {
-            /*
-             * The method called is a VM-internal method with no extra
-             * wrapping.
-             */
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                NativeTestTarget.emptyInternalStaticMethod();
-                NativeTestTarget.emptyInternalStaticMethod();
-                NativeTestTarget.emptyInternalStaticMethod();
-                NativeTestTarget.emptyInternalStaticMethod();
-                NativeTestTarget.emptyInternalStaticMethod();
-                NativeTestTarget.emptyInternalStaticMethod();
-                NativeTestTarget.emptyInternalStaticMethod();
-                NativeTestTarget.emptyInternalStaticMethod();
-                NativeTestTarget.emptyInternalStaticMethod();
-                NativeTestTarget.emptyInternalStaticMethod();
-            }
-        }
-
-    public void testEmptyInlineStaticMethod() {
-            /*
-             * The method called is a VM-internal method that gets
-             * specially "inlined" in a bytecode transformation.
-             */
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                NativeTestTarget.emptyInlineMethod();
-                NativeTestTarget.emptyInlineMethod();
-                NativeTestTarget.emptyInlineMethod();
-                NativeTestTarget.emptyInlineMethod();
-                NativeTestTarget.emptyInlineMethod();
-                NativeTestTarget.emptyInlineMethod();
-                NativeTestTarget.emptyInlineMethod();
-                NativeTestTarget.emptyInlineMethod();
-                NativeTestTarget.emptyInlineMethod();
-                NativeTestTarget.emptyInlineMethod();
-            }
-        }
-
-    public void testEmptyInterfaceMethodTest() {
-            EmptyInterface emptyInterface = mEmptyInterface;
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                emptyInterface.emptyVirtual();
-                emptyInterface.emptyVirtual();
-                emptyInterface.emptyVirtual();
-                emptyInterface.emptyVirtual();
-                emptyInterface.emptyVirtual();
-                emptyInterface.emptyVirtual();
-                emptyInterface.emptyVirtual();
-                emptyInterface.emptyVirtual();
-                emptyInterface.emptyVirtual();
-                emptyInterface.emptyVirtual();
-            }
-        }
-    }
-
-    public static class LoopTests extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-        private SizeTest mSizeTest = new SizeTest(ITERATIONS);
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS);
-            return 0;
-        }
-
-        public void testForLoopTest() {
-            int i = 0;
-            for (; i < 10000; i++) {
-            }
-        }
-
-        public void testWhileLoopTest() {
-            int i = 0;
-
-            while (i < 10000) {
-                i++;
-            }
-        }
-
-        public void testForLoopSizeCalledInside() {
-            for (int i = 0; i < mSizeTest.size(); i++) {
-            }
-        }
-
-        public void testForLoopSizeCalledOutside() {
-            final int size = mSizeTest.size();
-            for (int i = 0; i < size; i++) {
-            }
-        }
-    }
-
-    public static class BoundsCheckTest extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 10);
-            return 0;
-        }
-
-        public void testRun() {
-            int[] data = new int[1];
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                data[0] = i;
-                data[0] = i;
-                data[0] = i;
-                data[0] = i;
-                data[0] = i;
-                data[0] = i;
-                data[0] = i;
-                data[0] = i;
-                data[0] = i;
-                data[0] = i;
-            }
-        }
-    }
-
-    public static class ArrayListBase extends PerformanceTestBase {
-        public void setUp() throws Exception {
-            super.setUp();
-            mList = new ArrayList();
-            mList.add(0);
-            mList.add(1);
-            mList.add(2);
-            mList.add(3);
-            mList.add(4);
-            mList.add(5);
-            mList.add(6);
-            mList.add(7);
-            mList.add(8);
-            mList.add(9);
-        }
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(100);
-            return 0;
-        }
-
-        ArrayList<Integer> mList;
-
-        public void testForArrayList() {
-            int i = 0;
-            int res = 0;
-            for (; i < 100; i++) {
-                for (int j = 0; j < mList.size(); j++) {
-                    res += mList.get(j);
-                }
-            }
-        }
-
-        public void testForLocalArrayList() {
-            int i = 0;
-            int res = 0;
-            for (; i < 100; i++) {
-                final List<Integer> list = mList;
-                final int N = list.size();
-                for (int j = 0; j < N; j++) {
-                    res += list.get(j);
-                }
-            }
-        }
-
-        public void testForEachArrayList() {
-            int i = 0;
-            int res = 0;
-            for (; i < 100; i++) {
-                for (Integer v : mList) {
-                    res += v;
-                }
-            }
-        }
-    }
-
-    public static class SynchronizedGetAndSetInt extends PerformanceTestBase {
-        private static final int ITERATIONS = 100000;
-
-        public int mMember = 0;
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS);
-            return 0;
-        }
-
-        public void testRun() {
-            int result = 0;
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                synchronized (this) {
-                    result = mMember;
-                    mMember = i;
-                }
-            }
-        }
-    }
-
-    public static class AtomicGetAndSetInt extends PerformanceTestBase {
-        private static final int ITERATIONS = 100000;
-
-        public AtomicInteger mMember = new AtomicInteger(0);
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS);
-            return 0;
-        }
-
-        public void testRun() {
-            int result = 0;
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                result = mMember.getAndSet(i);
-            }
-        }
-    }
-
-    public static abstract class StringEquals extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-
-        protected String mString1, mString2;
-        public void setUp() throws Exception {
-          super.setUp();
-        }
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 10);
-            return 0;
-        }
-
-        public void testRun() {
-            String string1 = mString1;
-            String string2 = mString2;
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                string1.equals(string2);
-                string1.equals(string2);
-                string1.equals(string2);
-                string1.equals(string2);
-                string1.equals(string2);
-                string1.equals(string2);
-                string1.equals(string2);
-                string1.equals(string2);
-                string1.equals(string2);
-                string1.equals(string2);
-            }
-        }
-    }
-
-    public static class StringEquals2 extends StringEquals {
-        public void setUp() throws Exception {
-            mString1 = "01";
-            mString2 = "0x";
-        }
-    }
-    public static class StringEquals10 extends StringEquals {
-        public void setUp() throws Exception {
-            mString1 = "0123456789";
-            mString2 = "012345678x";
-        }
-    }
-    public static class StringEquals20 extends StringEquals {
-        public void setUp() throws Exception {
-            mString1 = "01234567890123456789";
-            mString2 = "0123456789012345678x";
-        }
-    }
-
-    public static class StringEquals200 extends StringEquals {
-        public void setUp() throws Exception {
-            mString1 = "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789";
-            mString2 = "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "012345678901234567890123456789012345678x";
-        }
-    }
-    public static class StringEquals200U extends StringEquals {
-        /* make one of the strings non-word aligned (bad memcmp case) */
-        public void setUp() throws Exception {
-            String tmpStr;
-            mString1 = "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789";
-            tmpStr = "z0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "012345678901234567890123456789012345678x";
-            mString2 = tmpStr.substring(1);
-        }
-    }
-
-    public static abstract class StringCompareTo extends PerformanceTestBase {
-        private static final int ITERATIONS = 10000;
-
-        protected String mString1, mString2;
-
-        public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-            intermediates.setInternalIterations(ITERATIONS * 10);
-            return 0;
-        }
-
-        public void testRun() {
-            String string1 = mString1;
-            String string2 = mString2;
-
-            for (int i = ITERATIONS - 1; i >= 0; i--) {
-                string1.compareTo(string2);
-                string1.compareTo(string2);
-                string1.compareTo(string2);
-                string1.compareTo(string2);
-                string1.compareTo(string2);
-                string1.compareTo(string2);
-                string1.compareTo(string2);
-                string1.compareTo(string2);
-                string1.compareTo(string2);
-                string1.compareTo(string2);
-            }
-        }
-    }
-    public static class StringCompareTo10 extends StringCompareTo {
-        public void setUp() throws Exception {
-            mString1 = "0123456789";
-            mString2 = "012345678x";
-        }
-    }
-    public static class StringCompareTo200 extends StringCompareTo {
-        public void setUp() throws Exception {
-            mString1 = "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789";
-            mString2 = "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "0123456789012345678901234567890123456789"
-                    + "012345678901234567890123456789012345678x";
-        }
-    }
-}
-
diff --git a/tests/CoreTests/android/core/TreeMapPerformanceTest.java b/tests/CoreTests/android/core/TreeMapPerformanceTest.java
deleted file mode 100644
index 3a210f4..0000000
--- a/tests/CoreTests/android/core/TreeMapPerformanceTest.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import android.test.PerformanceTestBase;
-import android.test.PerformanceTestCase;
-
-import java.util.Collection;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-/**
- * Implements basic performance test functionality for java.util.TreeMap
- */
-
-public class TreeMapPerformanceTest extends PerformanceTestBase {
-    public static final int ITERATIONS = 1000;
-    public static TreeMap<String, Integer> sMap;
-    public static String[] sKeys;
-
-    @Override
-    @SuppressWarnings("unchecked")
-    protected void setUp() throws Exception {
-        super.setUp();
-        sMap = new TreeMap();
-        sKeys = new String[ITERATIONS];
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            sKeys[i] = Integer.toString(i, 16);
-            sMap.put(sKeys[i], i);
-        }
-    }
-
-    @Override
-    public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-        intermediates.setInternalIterations(ITERATIONS);
-        return 0;
-    }
-
-    @SuppressWarnings("unchecked")
-    public void testTreeMapPut() {
-        TreeMap map = new TreeMap();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            map.put(i, i);
-            map.put(i, i);
-            map.put(i, i);
-            map.put(i, i);
-            map.put(i, i);
-            map.put(i, i);
-            map.put(i, i);
-            map.put(i, i);
-            map.put(i, i);
-            map.put(i, i);
-        }
-    }
-
-    public void testTreeMapGet() {
-        int value;
-        TreeMap<String, Integer> map = sMap;
-        String[] keys = sKeys;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            value = map.get(keys[i]);
-            value = map.get(keys[i]);
-            value = map.get(keys[i]);
-            value = map.get(keys[i]);
-            value = map.get(keys[i]);
-            value = map.get(keys[i]);
-            value = map.get(keys[i]);
-            value = map.get(keys[i]);
-            value = map.get(keys[i]);
-            value = map.get(keys[i]);
-        }
-    }
-
-    public void testTreeMapFirstKey() {
-        String key;
-        TreeMap<String, Integer> map = sMap;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            key = map.firstKey();
-            key = map.firstKey();
-            key = map.firstKey();
-            key = map.firstKey();
-            key = map.firstKey();
-            key = map.firstKey();
-            key = map.firstKey();
-            key = map.firstKey();
-            key = map.firstKey();
-            key = map.firstKey();
-        }
-    }
-
-    public void testTreeMapKeySet() {
-        Set keyset;
-        TreeMap<String, Integer> map = sMap;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            keyset = map.keySet();
-            keyset = map.keySet();
-            keyset = map.keySet();
-            keyset = map.keySet();
-            keyset = map.keySet();
-            keyset = map.keySet();
-            keyset = map.keySet();
-            keyset = map.keySet();
-            keyset = map.keySet();
-            keyset = map.keySet();
-        }
-    }
-
-    public void testTreeMapEntrySet() {
-        Set keyset;
-        TreeMap<String, Integer> map = sMap;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            keyset = map.entrySet();
-            keyset = map.entrySet();
-            keyset = map.entrySet();
-            keyset = map.entrySet();
-            keyset = map.entrySet();
-            keyset = map.entrySet();
-            keyset = map.entrySet();
-            keyset = map.entrySet();
-            keyset = map.entrySet();
-            keyset = map.entrySet();
-        }
-    }
-
-    public void testTreeMapValues() {
-        Collection collection;
-        TreeMap<String, Integer> map = sMap;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            collection = map.values();
-            collection = map.values();
-            collection = map.values();
-            collection = map.values();
-            collection = map.values();
-            collection = map.values();
-            collection = map.values();
-            collection = map.values();
-            collection = map.values();
-            collection = map.values();
-        }
-    }
-
-    public void testTreeMapSize() {
-        int len;
-        TreeMap<String, Integer> map = sMap;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            len = map.size();
-            len = map.size();
-            len = map.size();
-            len = map.size();
-            len = map.size();
-            len = map.size();
-            len = map.size();
-            len = map.size();
-            len = map.size();
-            len = map.size();
-        }
-    }
-
-    public void testTreeMapContainsKey() {
-        boolean flag;
-        String key = sKeys[525];
-        TreeMap<String, Integer> map = sMap;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = map.containsKey(key);
-            flag = map.containsKey(key);
-            flag = map.containsKey(key);
-            flag = map.containsKey(key);
-            flag = map.containsKey(key);
-            flag = map.containsKey(key);
-            flag = map.containsKey(key);
-            flag = map.containsKey(key);
-            flag = map.containsKey(key);
-            flag = map.containsKey(key);
-        }
-    }
-
-    public void testTreeMapContainsValue() {
-        boolean flag;
-        TreeMap<String, Integer> map = sMap;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = map.containsValue(i);
-            flag = map.containsValue(i);
-            flag = map.containsValue(i);
-            flag = map.containsValue(i);
-            flag = map.containsValue(i);
-            flag = map.containsValue(i);
-            flag = map.containsValue(i);
-            flag = map.containsValue(i);
-            flag = map.containsValue(i);
-            flag = map.containsValue(i);
-        }
-    }
-
-    public void testTreeMapHeadMap() {
-        SortedMap map;
-        String str = sKeys[100];
-        TreeMap<String, Integer> tMap = sMap;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            map = tMap.headMap(str);
-            map = tMap.headMap(str);
-            map = tMap.headMap(str);
-            map = tMap.headMap(str);
-            map = tMap.headMap(str);
-            map = tMap.headMap(str);
-            map = tMap.headMap(str);
-            map = tMap.headMap(str);
-            map = tMap.headMap(str);
-            map = tMap.headMap(str);
-        }
-    }
-
-    public void testTreeMapSubMap() {
-        String str1 = sKeys[400];
-        String str2 = sKeys[500];
-        SortedMap map;
-        TreeMap<String, Integer> tMap = sMap;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            map = tMap.subMap(str1, str2);
-            map = tMap.subMap(str1, str2);
-            map = tMap.subMap(str1, str2);
-            map = tMap.subMap(str1, str2);
-            map = tMap.subMap(str1, str2);
-            map = tMap.subMap(str1, str2);
-            map = tMap.subMap(str1, str2);
-            map = tMap.subMap(str1, str2);
-            map = tMap.subMap(str1, str2);
-            map = tMap.subMap(str1, str2);
-        }
-    }
-
-    public void testTreeMapTailMap() {
-        String str = sKeys[900];
-        TreeMap<String, Integer> tMap = sMap;
-        SortedMap map;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            map = tMap.tailMap(str);
-            map = tMap.tailMap(str);
-            map = tMap.tailMap(str);
-            map = tMap.tailMap(str);
-            map = tMap.tailMap(str);
-            map = tMap.tailMap(str);
-            map = tMap.tailMap(str);
-            map = tMap.tailMap(str);
-            map = tMap.tailMap(str);
-            map = tMap.tailMap(str);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public void testTreeMapRemove() {
-        TreeMap<String, Integer> tMap = new TreeMap(sMap);
-        String[] keys = sKeys;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            tMap.remove(keys[i]);
-            tMap.remove(keys[i]);
-            tMap.remove(keys[i]);
-            tMap.remove(keys[i]);
-            tMap.remove(keys[i]);
-            tMap.remove(keys[i]);
-            tMap.remove(keys[i]);
-            tMap.remove(keys[i]);
-            tMap.remove(keys[i]);
-            tMap.remove(keys[i]);
-        }
-    }
-}
diff --git a/tests/CoreTests/android/core/TreeSetTest.java b/tests/CoreTests/android/core/TreeSetTest.java
deleted file mode 100644
index a6a3309..0000000
--- a/tests/CoreTests/android/core/TreeSetTest.java
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import android.test.PerformanceTestBase;
-import android.test.PerformanceTestCase;
-
-import java.util.TreeSet;
-import java.util.SortedSet;
-import java.util.Iterator;
-import java.util.Comparator;
-
-/**
- * Implements basic performance test functionality for java.util.TreeSet
- */
-
-public class TreeSetTest extends PerformanceTestBase {
-    public static final int ITERATIONS = 1000;
-    public static TreeSet<Integer> sSet;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        sSet = new TreeSet<Integer>();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            sSet.add(i);
-        }
-    }
-
-    @Override
-    public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-        intermediates.setInternalIterations(ITERATIONS);
-        return 0;
-    }
-
-    /**
-     * 
-     * Tests performance for the java.util.TreeSet method Add(Object arg 0)
-     * 
-     */
-
-    @SuppressWarnings("unchecked")
-    public void testTreeSetAdd() {
-        TreeSet<Integer> set = new TreeSet();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-            set.add(i);
-        }
-    }
-
-    /**
-     * 
-     * Tests performance for the java.util.TreeSet method - first()
-     * 
-     */
-
-    public void testTreeSetFirst() {
-        int value;
-        TreeSet<Integer> set = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            value = set.first();
-            value = set.first();
-            value = set.first();
-            value = set.first();
-            value = set.first();
-            value = set.first();
-            value = set.first();
-            value = set.first();
-            value = set.first();
-        }
-    }
-
-    /**
-     * 
-     * Tests performance for the java.util.TreeSet method - last()
-     * 
-     */
-
-    public void testTreeSetLast() {
-        int value;
-        TreeSet<Integer> set = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            value = set.last();
-            value = set.last();
-            value = set.last();
-            value = set.last();
-            value = set.last();
-            value = set.last();
-            value = set.last();
-            value = set.last();
-            value = set.last();
-        }
-    }
-
-    /**
-     * 
-     * Tests performance of the java.util.TreeSet method- contains(Object arg0)
-     * 
-     */
-
-    public void testTreeSetContains() {
-        Integer index = new Integer(500);
-        boolean flag;
-        TreeSet<Integer> set = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-            flag = set.contains(index);
-        }
-    }
-
-    /**
-     * 
-     * Tests performance for the java.util.TreeSet method - size()
-     * 
-     */
-
-    public void testTreeSetSize() {
-        int value;
-        TreeSet<Integer> set = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            value = set.size();
-            value = set.size();
-            value = set.size();
-            value = set.size();
-            value = set.size();
-            value = set.size();
-            value = set.size();
-            value = set.size();
-            value = set.size();
-        }
-    }
-
-    /**
-     * 
-     * Tests performance for the java.util.TreeSet method - iterator()
-     * 
-     */
-
-    public void testTreeSetIterator() {
-        Iterator iterator;
-        TreeSet<Integer> set = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-            iterator = set.iterator();
-        }
-    }
-
-    /**
-     * 
-     * Tests performance for the java.util.TreeSet method - comparator()
-     * 
-     */
-
-    public void testTreeSetComparator() {
-        Comparator comparator;
-        TreeSet<Integer> set = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            comparator = set.comparator();
-            comparator = set.comparator();
-            comparator = set.comparator();
-            comparator = set.comparator();
-            comparator = set.comparator();
-            comparator = set.comparator();
-            comparator = set.comparator();
-            comparator = set.comparator();
-            comparator = set.comparator();
-        }
-    }
-
-    /**
-     * 
-     * Tests performance for the java.util.TreeSet method - clone()
-     * 
-     */
-
-    public void testTreeSetClone() {
-        Object obj;
-        TreeSet<Integer> set = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            obj = set.clone();
-            obj = set.clone();
-            obj = set.clone();
-            obj = set.clone();
-            obj = set.clone();
-            obj = set.clone();
-            obj = set.clone();
-            obj = set.clone();
-            obj = set.clone();
-            obj = set.clone();
-        }
-    }
-
-    /**
-     * 
-     * Tests performance of the java.util.TreeSet method - remove(Object arg0)
-     * 
-     */
-
-    @SuppressWarnings("unchecked")
-    public void testTreeSetRemove() {
-        TreeSet<Integer> set = new TreeSet(sSet);
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-            set.remove(i);
-        }
-    }
-
-    /**
-     * 
-     * Tests performance of the java.util.TreeSet method- headSet(Integer arg0)
-     * 
-     */
-
-    public void testTreeSetHeadSet() {
-        Integer value = new Integer(100);
-        SortedSet set;
-        TreeSet<Integer> tSet = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            set = tSet.headSet(value);
-            set = tSet.headSet(value);
-            set = tSet.headSet(value);
-            set = tSet.headSet(value);
-            set = tSet.headSet(value);
-            set = tSet.headSet(value);
-            set = tSet.headSet(value);
-            set = tSet.headSet(value);
-            set = tSet.headSet(value);
-            set = tSet.headSet(value);
-        }
-    }
-
-    /**
-     * 
-     * Tests performance of subSet(Integer arg0, Integer arg1) - TreeSet
-     * 
-     */
-
-    public void testTreeSetSubSet() {
-        Integer value = new Integer(400);
-        Integer nInt = new Integer(500);
-        SortedSet set;
-        TreeSet<Integer> tSet = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            set = tSet.subSet(value, nInt);
-            set = tSet.subSet(value, nInt);
-            set = tSet.subSet(value, nInt);
-            set = tSet.subSet(value, nInt);
-            set = tSet.subSet(value, nInt);
-            set = tSet.subSet(value, nInt);
-            set = tSet.subSet(value, nInt);
-            set = tSet.subSet(value, nInt);
-            set = tSet.subSet(value, nInt);
-            set = tSet.subSet(value, nInt);
-
-        }
-
-    }
-
-    /**
-     * 
-     * Tests performance of tailSet(Integer arg0) - TreeSet
-     * 
-     */
-
-    public void testTreeSetTailSet() {
-        Integer value = new Integer(900);
-        SortedSet set;
-        TreeSet<Integer> tSet = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            set = tSet.tailSet(value);
-            set = tSet.tailSet(value);
-            set = tSet.tailSet(value);
-            set = tSet.tailSet(value);
-            set = tSet.tailSet(value);
-            set = tSet.tailSet(value);
-            set = tSet.tailSet(value);
-            set = tSet.tailSet(value);
-            set = tSet.tailSet(value);
-            set = tSet.tailSet(value);
-        }
-    }
-
-    /**
-     * 
-     * Tests performance for the java.util.TreeSet method - isEmpty()
-     * 
-     */
-
-    public void testTreeSetIsEmpty() {
-        boolean flag;
-        TreeSet<Integer> tSet = sSet;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = tSet.isEmpty();
-            flag = tSet.isEmpty();
-            flag = tSet.isEmpty();
-            flag = tSet.isEmpty();
-            flag = tSet.isEmpty();
-            flag = tSet.isEmpty();
-            flag = tSet.isEmpty();
-            flag = tSet.isEmpty();
-            flag = tSet.isEmpty();
-            flag = tSet.isEmpty();
-        }
-    }
-}
diff --git a/tests/CoreTests/android/core/VectorTest.java b/tests/CoreTests/android/core/VectorTest.java
deleted file mode 100644
index b4c84fd..0000000
--- a/tests/CoreTests/android/core/VectorTest.java
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import android.test.PerformanceTestBase;
-import android.test.PerformanceTestCase;
-
-import java.util.Vector;
-import java.util.Enumeration;
-
-/**
- * Basic Performance Tests for java.util.Vector
- */
-
-@SuppressWarnings("unchecked")
-public class VectorTest extends PerformanceTestBase {
-    public static final int ITERATIONS = 1000;
-    private Vector<Integer> mVector;
-    private Vector<String> mStrVector;
-    private String mTestString = "Hello Android";
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mVector = new Vector();
-        mStrVector = new Vector();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            assertTrue(mVector.add(i));
-            assertTrue(mStrVector.add(Integer.toString(i)));
-        }
-    }
-
-    @Override
-    public int startPerformance(PerformanceTestCase.Intermediates intermediates) {
-        intermediates.setInternalIterations(ITERATIONS);
-        return 0;
-    }
-
-    public void testVectorAdd() {
-        Vector<Integer> vector = new Vector();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            vector.add(i);
-            vector.add(i);
-            vector.add(i);
-            vector.add(i);
-            vector.add(i);
-            vector.add(i);
-            vector.add(i);
-            vector.add(i);
-            vector.add(i);
-            vector.add(i);
-        }
-    }
-
-    public void testVectorAdd1() {
-        Vector<Integer> vector = new Vector();
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            vector.add(0, i);
-            vector.add(0, i);
-            vector.add(0, i);
-            vector.add(0, i);
-            vector.add(0, i);
-            vector.add(0, i);
-            vector.add(0, i);
-            vector.add(0, i);
-            vector.add(0, i);
-            vector.add(0, i);
-        }
-    }
-
-    public void testVectorToArray() {
-        Object array;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            array = vector.toArray();
-            array = vector.toArray();
-            array = vector.toArray();
-            array = vector.toArray();
-            array = vector.toArray();
-            array = vector.toArray();
-            array = vector.toArray();
-            array = vector.toArray();
-            array = vector.toArray();
-            array = vector.toArray();
-        }
-    }
-
-    /**
-     * 
-     */
-    public void testVectorSize() {
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            int mLen;
-            mLen = vector.size();
-            mLen = vector.size();
-            mLen = vector.size();
-            mLen = vector.size();
-            mLen = vector.size();
-            mLen = vector.size();
-            mLen = vector.size();
-            mLen = vector.size();
-            mLen = vector.size();
-            mLen = vector.size();
-        }
-    }
-
-    public void testVectorGet() {
-        int element;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            element = vector.get(i);
-            element = vector.get(i);
-            element = vector.get(i);
-            element = vector.get(i);
-            element = vector.get(i);
-            element = vector.get(i);
-            element = vector.get(i);
-            element = vector.get(i);
-            element = vector.get(i);
-            element = vector.get(i);
-        }
-
-    }
-
-    public void testVectorContains() {
-        boolean flag;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            flag = vector.contains(i);
-            flag = vector.contains(i);
-            flag = vector.contains(i);
-            flag = vector.contains(i);
-            flag = vector.contains(i);
-            flag = vector.contains(i);
-            flag = vector.contains(i);
-            flag = vector.contains(i);
-            flag = vector.contains(i);
-            flag = vector.contains(i);
-        }
-    }
-
-    public void testVectorToArray1() {
-        Integer[] rArray = new Integer[100];
-        Integer[] array;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            array = vector.toArray(rArray);
-            array = vector.toArray(rArray);
-            array = vector.toArray(rArray);
-            array = vector.toArray(rArray);
-            array = vector.toArray(rArray);
-            array = vector.toArray(rArray);
-            array = vector.toArray(rArray);
-            array = vector.toArray(rArray);
-            array = vector.toArray(rArray);
-            array = vector.toArray(rArray);
-        }
-    }
-
-    public void testVectorSet() {
-        Vector<Integer> vector = mVector;
-        int pos = 5, value = 0;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            vector.set(pos, value);
-            vector.set(pos, value);
-            vector.set(pos, value);
-            vector.set(pos, value);
-            vector.set(pos, value);
-            vector.set(pos, value);
-            vector.set(pos, value);
-            vector.set(pos, value);
-            vector.set(pos, value);
-            vector.set(pos, value);
-        }
-    }
-
-    public void testVectorIndexOf() {
-        int index, value = 0;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            index = vector.indexOf(value);
-            index = vector.indexOf(value);
-            index = vector.indexOf(value);
-            index = vector.indexOf(value);
-            index = vector.indexOf(value);
-            index = vector.indexOf(value);
-            index = vector.indexOf(value);
-            index = vector.indexOf(value);
-            index = vector.indexOf(value);
-            index = vector.indexOf(value);
-        }
-    }
-
-    public void testVectorLastIndexOf() {
-        int index, value = 0;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i >= 0; i--) {
-            index = vector.lastIndexOf(value);
-            index = vector.lastIndexOf(value);
-            index = vector.lastIndexOf(value);
-            index = vector.lastIndexOf(value);
-            index = vector.lastIndexOf(value);
-            index = vector.lastIndexOf(value);
-            index = vector.lastIndexOf(value);
-            index = vector.lastIndexOf(value);
-            index = vector.lastIndexOf(value);
-            index = vector.lastIndexOf(value);
-        }
-    }
-
-    public void testVectorRemove() {
-        int index, value = 0;
-        Vector<Integer> vector = new Vector(mVector);
-        for (int i = 10; i > 0; i--) {
-            index = vector.remove(value);
-            index = vector.remove(value);
-            index = vector.remove(value);
-            index = vector.remove(value);
-            index = vector.remove(value);
-            index = vector.remove(value);
-            index = vector.remove(value);
-            index = vector.remove(value);
-            index = vector.remove(value);
-            index = vector.remove(value);
-        }
-    }
-
-    public void testVectorRemoveElement() {
-        Vector<Integer> vector = new Vector(mVector);
-        for (int i = 10; i > 0; i--) {
-            vector.removeElement(i);
-            vector.removeElement(i);
-            vector.removeElement(i);
-            vector.removeElement(i);
-            vector.removeElement(i);
-            vector.removeElement(i);
-            vector.removeElement(i);
-            vector.removeElement(i);
-            vector.removeElement(i);
-            vector.removeElement(i);
-        }
-    }
-
-    public void VectorRemoveElementAt() {
-        Vector<Integer> vector = new Vector(mVector);
-        for (int i = 10; i > 0; i--) {
-            vector.removeElementAt(i);
-            vector.removeElementAt(i);
-            vector.removeElementAt(i);
-            vector.removeElementAt(i);
-            vector.removeElementAt(i);
-            vector.removeElementAt(i);
-            vector.removeElementAt(i);
-            vector.removeElementAt(i);
-            vector.removeElementAt(i);
-            vector.removeElementAt(i);
-        }
-    }
-
-    public void VectorAddAll() {
-        Vector<Integer> vector = new Vector(), vector1 = mVector;
-
-        boolean flag;
-        for (int i = 10; i > 0; i--) {
-            flag = vector.addAll(vector1);
-            flag = vector.addAll(vector1);
-            flag = vector.addAll(vector1);
-            flag = vector.addAll(vector1);
-            flag = vector.addAll(vector1);
-            flag = vector.addAll(vector1);
-            flag = vector.addAll(vector1);
-            flag = vector.addAll(vector1);
-            flag = vector.addAll(vector1);
-            flag = vector.addAll(vector1);
-        }
-    }
-
-    public void VectorRemove1() {
-        Vector<String> vector = mStrVector;
-        for (int j = 1000; j > 0; j--) {
-            vector.add("a");
-            vector.add("b");
-        }
-        String s = new String("a");
-        boolean flag;
-        for (int i = 10; i > 0; i--) {
-            flag = vector.remove(s);
-            flag = vector.remove(s);
-            flag = vector.remove(s);
-            flag = vector.remove(s);
-            flag = vector.remove(s);
-            flag = vector.remove(s);
-            flag = vector.remove(s);
-            flag = vector.remove(s);
-            flag = vector.remove(s);
-            flag = vector.remove(s);
-        }
-    }
-
-    public void testVectorAddAll1() {
-        Vector<Integer> mEmptyVector = new Vector();
-        boolean flag;
-        int pos = 0;
-        Vector<Integer> vector1 = mVector;
-        Vector<Integer> vector = mEmptyVector;
-        for (int i = 10; i > 0; i--) {
-            flag = vector.addAll(pos, vector1);
-            flag = vector.addAll(pos, vector1);
-            flag = vector.addAll(pos, vector1);
-            flag = vector.addAll(pos, vector1);
-            flag = vector.addAll(pos, vector1);
-            flag = vector.addAll(pos, vector1);
-            flag = vector.addAll(pos, vector1);
-            flag = vector.addAll(pos, vector1);
-            flag = vector.addAll(pos, vector1);
-            flag = vector.addAll(pos, vector1);
-        }
-    }
-
-    public void testVectorClone() {
-        Object obj;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            obj = vector.clone();
-            obj = vector.clone();
-            obj = vector.clone();
-            obj = vector.clone();
-            obj = vector.clone();
-            obj = vector.clone();
-            obj = vector.clone();
-            obj = vector.clone();
-            obj = vector.clone();
-            obj = vector.clone();
-        }
-    }
-
-    public void testVectorCapacity() {
-        int capacity;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            capacity = vector.capacity();
-            capacity = vector.capacity();
-            capacity = vector.capacity();
-            capacity = vector.capacity();
-            capacity = vector.capacity();
-            capacity = vector.capacity();
-            capacity = vector.capacity();
-            capacity = vector.capacity();
-            capacity = vector.capacity();
-            capacity = vector.capacity();
-        }
-    }
-
-    public void testVectorHashcode() {
-        int element;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            element = vector.hashCode();
-            element = vector.hashCode();
-            element = vector.hashCode();
-            element = vector.hashCode();
-            element = vector.hashCode();
-            element = vector.hashCode();
-            element = vector.hashCode();
-            element = vector.hashCode();
-            element = vector.hashCode();
-            element = vector.hashCode();
-        }
-    }
-
-    public void testVectorElements() {
-        Enumeration<Integer> elements;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            elements = vector.elements();
-            elements = vector.elements();
-            elements = vector.elements();
-            elements = vector.elements();
-            elements = vector.elements();
-            elements = vector.elements();
-            elements = vector.elements();
-            elements = vector.elements();
-            elements = vector.elements();
-            elements = vector.elements();
-        }
-    }
-
-    public void testVectorToString() {
-        String str;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            str = vector.toString();
-            str = vector.toString();
-            str = vector.toString();
-            str = vector.toString();
-            str = vector.toString();
-            str = vector.toString();
-            str = vector.toString();
-            str = vector.toString();
-            str = vector.toString();
-            str = vector.toString();
-        }
-    }
-
-    public void testVectorElementAt() {
-        int element;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            element = vector.elementAt(50);
-            element = vector.elementAt(50);
-            element = vector.elementAt(50);
-            element = vector.elementAt(50);
-            element = vector.elementAt(50);
-            element = vector.elementAt(50);
-            element = vector.elementAt(50);
-            element = vector.elementAt(50);
-            element = vector.elementAt(50);
-            element = vector.elementAt(50);
-        }
-    }
-
-    public void testVectorAddElement() {
-        int element;
-        Vector<String> vector = mStrVector;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            vector.addElement(mTestString);
-            vector.addElement(mTestString);
-            vector.addElement(mTestString);
-            vector.addElement(mTestString);
-            vector.addElement(mTestString);
-            vector.addElement(mTestString);
-            vector.addElement(mTestString);
-            vector.addElement(mTestString);
-            vector.addElement(mTestString);
-            vector.addElement(mTestString);
-        }
-    }
-
-    public void testVectorFirstElement() {
-        int element;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            element = vector.firstElement();
-            element = vector.firstElement();
-            element = vector.firstElement();
-            element = vector.firstElement();
-            element = vector.firstElement();
-            element = vector.firstElement();
-            element = vector.firstElement();
-            element = vector.firstElement();
-            element = vector.firstElement();
-            element = vector.firstElement();
-        }
-    }
-
-    public void testVectorLastElement() {
-        int element;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            element = vector.lastElement();
-            element = vector.lastElement();
-            element = vector.lastElement();
-            element = vector.lastElement();
-            element = vector.lastElement();
-            element = vector.lastElement();
-            element = vector.lastElement();
-            element = vector.lastElement();
-            element = vector.lastElement();
-            element = vector.lastElement();
-        }
-    }
-
-    public void testVectorSetElementAt() {
-        Vector<Integer> vector = mVector;
-        int value1 = 500, value2 = 50;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            vector.setElementAt(value1, value2);
-            vector.setElementAt(value1, value2);
-            vector.setElementAt(value1, value2);
-            vector.setElementAt(value1, value2);
-            vector.setElementAt(value1, value2);
-            vector.setElementAt(value1, value2);
-            vector.setElementAt(value1, value2);
-            vector.setElementAt(value1, value2);
-            vector.setElementAt(value1, value2);
-            vector.setElementAt(value1, value2);
-        }
-    }
-
-    public void testVectorIsEmpty() {
-        boolean flag;
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            flag = vector.isEmpty();
-            flag = vector.isEmpty();
-            flag = vector.isEmpty();
-            flag = vector.isEmpty();
-            flag = vector.isEmpty();
-            flag = vector.isEmpty();
-            flag = vector.isEmpty();
-            flag = vector.isEmpty();
-            flag = vector.isEmpty();
-            flag = vector.isEmpty();
-        }
-    }
-
-    public void testVectorCopyInto() {
-        Integer[] rArray = new Integer[ITERATIONS];
-        Vector<Integer> vector = mVector;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            vector.copyInto(rArray);
-            vector.copyInto(rArray);
-            vector.copyInto(rArray);
-            vector.copyInto(rArray);
-            vector.copyInto(rArray);
-            vector.copyInto(rArray);
-            vector.copyInto(rArray);
-            vector.copyInto(rArray);
-            vector.copyInto(rArray);
-            vector.copyInto(rArray);
-        }
-    }
-
-    public void testVectorInsertElementAt() {
-        Vector<String> vector = mStrVector;
-        String string = mTestString;
-        for (int i = ITERATIONS - 1; i > 0; i--) {
-            vector.insertElementAt(string, i);
-            vector.insertElementAt(string, i);
-            vector.insertElementAt(string, i);
-            vector.insertElementAt(string, i);
-            vector.insertElementAt(string, i);
-            vector.insertElementAt(string, i);
-            vector.insertElementAt(string, i);
-            vector.insertElementAt(string, i);
-            vector.insertElementAt(string, i);
-            vector.insertElementAt(string, i);
-        }
-    }
-}
diff --git a/tests/DumpRenderTree/assets/run_layout_tests.py b/tests/DumpRenderTree/assets/run_layout_tests.py
index ceac5d2..21c02ec 100755
--- a/tests/DumpRenderTree/assets/run_layout_tests.py
+++ b/tests/DumpRenderTree/assets/run_layout_tests.py
@@ -4,8 +4,8 @@
 
   First, you need to get an SD card or sdcard image that has layout tests on it.
   Layout tests are in following directory:
-    /sdcard/android/layout_tests
-  For example, /sdcard/android/layout_tests/fast
+    /sdcard/webkit/layout_tests
+  For example, /sdcard/webkit/layout_tests/fast
 
   Usage:
     Run all tests under fast/ directory:
@@ -22,7 +22,7 @@
   use --refresh-test-list option *once* to re-generate test list on the card.
 
   Some other options are:
-    --rebaseline generates expected layout tests results under /sdcard/android/expected_result/
+    --rebaseline generates expected layout tests results under /sdcard/webkit/expected_result/
     --time-out-ms (default is 8000 millis) for each test
     --adb-options="-e" passes option string to adb
     --results-directory=..., (default is ./layout-test-results) directory name under which results are stored.
@@ -57,8 +57,8 @@
     output: adb_cmd string
   """
 
-  # pull /sdcard/android/running_test.txt, if the content is "#DONE", it's done
-  shell_cmd_str = adb_cmd + " shell cat /sdcard/android/running_test.txt"
+  # pull /sdcard/webkit/running_test.txt, if the content is "#DONE", it's done
+  shell_cmd_str = adb_cmd + " shell cat /sdcard/webkit/running_test.txt"
   adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
   return adb_output.strip() == "#DONE"
 
@@ -207,7 +207,7 @@
     # Get the running_test.txt
     logging.error("DumpRenderTree crashed, output:\n" + adb_output)
 
-    shell_cmd_str = adb_cmd + " shell cat /sdcard/android/running_test.txt"
+    shell_cmd_str = adb_cmd + " shell cat /sdcard/webkit/running_test.txt"
     crashed_test = ""
     while not crashed_test:
       (crashed_test, err) = subprocess.Popen(
diff --git a/tests/DumpRenderTree/assets/run_page_cycler.py b/tests/DumpRenderTree/assets/run_page_cycler.py
index 8b8fb38..692f32e 100755
--- a/tests/DumpRenderTree/assets/run_page_cycler.py
+++ b/tests/DumpRenderTree/assets/run_page_cycler.py
@@ -6,7 +6,7 @@
 
   Usage:
     Run a single page cycler test:
-      run_page_cycler.py "file:///sdcard/android/page_cycler/moz/start.html?auto=1\&iterations=10"
+      run_page_cycler.py "file:///sdcard/webkit/page_cycler/moz/start.html\?auto=1\&iterations=10"
 """
 
 import logging
@@ -32,7 +32,7 @@
 
   # Include all tests if none are specified.
   if not args:
-    print "need a URL, e.g. file:///sdcard/android/page_cycler/moz/start.html"
+    print "need a URL, e.g. file:///sdcard/webkit/page_cycler/moz/start.html\?auto=1\&iterations=10"
     sys.exit(1)
   else:
     path = ' '.join(args);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 56beada..b2d2a98 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -92,6 +92,7 @@
         ignoreResultList.add("fast/encoding/percent-escaping.html"); // fails in Java HTTP stack, see http://b/issue?id=3046984
         ignoreResultList.add("http/tests/appcache/empty-manifest.html"); // flaky
         ignoreResultList.add("http/tests/appcache/fallback.html"); // http://b/issue?id=2713004
+        ignoreResultList.add("http/tests/appcache/foreign-fallback.html"); // Flaky, may be due to DRT, see http://b/3285647
         ignoreResultList.add("http/tests/appcache/foreign-iframe-main.html"); // flaky - skips states
         ignoreResultList.add("http/tests/appcache/manifest-with-empty-file.html"); // flaky
         ignoreResultList.add("http/tests/appcache/origin-quota.html"); // needs clearAllApplicationCaches(), see http://b/issue?id=2944196
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java
index 73d7363..4a47a0e 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java
@@ -181,7 +181,7 @@
     }
 
     protected void setupPath() {
-        mPath = Environment.getExternalStorageDirectory() + "/android/layout_tests";
+        mPath = Environment.getExternalStorageDirectory() + "/webkit/layout_tests";
         mBaseLength = mPath.length();
     }
 
@@ -189,7 +189,7 @@
     protected int mBaseLength;
     protected String mFocusFile;
     protected int mFocusIndex;
-    
+
     private final static int OPEN_DIRECTORY = 0;
     private final static int RUN_TESTS = 1;
 
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
index 5d34e25..b7d2c26 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
@@ -35,15 +35,15 @@
     private static final String LOGTAG = "FsUtils";
     static final String EXTERNAL_DIR = Environment.getExternalStorageDirectory().toString();
     static final String HTTP_TESTS_PREFIX =
-        EXTERNAL_DIR + "/android/layout_tests/http/tests/";
+        EXTERNAL_DIR + "/webkit/layout_tests/http/tests/";
     static final String HTTPS_TESTS_PREFIX =
-        EXTERNAL_DIR + "/android/layout_tests/http/tests/ssl/";
+        EXTERNAL_DIR + "/webkit/layout_tests/http/tests/ssl/";
     static final String HTTP_LOCAL_TESTS_PREFIX =
-        EXTERNAL_DIR + "/android/layout_tests/http/tests/local/";
+        EXTERNAL_DIR + "/webkit/layout_tests/http/tests/local/";
     static final String HTTP_MEDIA_TESTS_PREFIX =
-        EXTERNAL_DIR + "/android/layout_tests/http/tests/media/";
+        EXTERNAL_DIR + "/webkit/layout_tests/http/tests/media/";
     static final String HTTP_WML_TESTS_PREFIX =
-        EXTERNAL_DIR + "/android/layout_tests/http/tests/wml/";
+        EXTERNAL_DIR + "/webkit/layout_tests/http/tests/wml/";
 
     private FsUtils() {
         //no creation of instances
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
index 8aa3c69..050b779 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -129,11 +129,11 @@
     static final int DEFAULT_TIMEOUT_IN_MILLIS = 5000;
 
     static final String EXTERNAL_DIR = Environment.getExternalStorageDirectory().toString();
-    static final String LAYOUT_TESTS_ROOT = EXTERNAL_DIR + "/android/layout_tests/";
-    static final String LAYOUT_TESTS_RESULT_DIR = EXTERNAL_DIR + "/android/layout_tests_results/";
-    static final String ANDROID_EXPECTED_RESULT_DIR = EXTERNAL_DIR + "/android/expected_results/";
-    static final String LAYOUT_TESTS_LIST_FILE = EXTERNAL_DIR + "/android/layout_tests_list.txt";
-    static final String TEST_STATUS_FILE = EXTERNAL_DIR + "/android/running_test.txt";
+    static final String LAYOUT_TESTS_ROOT = EXTERNAL_DIR + "/webkit/layout_tests/";
+    static final String LAYOUT_TESTS_RESULT_DIR = EXTERNAL_DIR + "/webkit/layout_tests_results/";
+    static final String ANDROID_EXPECTED_RESULT_DIR = EXTERNAL_DIR + "/webkit/expected_results/";
+    static final String LAYOUT_TESTS_LIST_FILE = EXTERNAL_DIR + "/webkit/layout_tests_list.txt";
+    static final String TEST_STATUS_FILE = EXTERNAL_DIR + "/webkit/running_test.txt";
     static final String LAYOUT_TESTS_RESULTS_REFERENCE_FILES[] = {
           "results/layout_tests_passed.txt",
           "results/layout_tests_failed.txt",
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
index 4982c46..e5a46b9 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
@@ -93,11 +93,8 @@
         final VMRuntime runtime = VMRuntime.getRuntime();
 
         runtime.gcSoftReferences();
-        runtime.runFinalizationSync();
         runtime.gcSoftReferences();
-        runtime.runFinalizationSync();
         runtime.gcSoftReferences();
-        runtime.runFinalizationSync();
         Runtime.getRuntime().runFinalization();
         Runtime.getRuntime().gc();
         Runtime.getRuntime().gc();
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 643dbf5..a3466e2 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -75,6 +75,7 @@
         public void handleMessage(Message msg) {
             if (msg.what == MSG_TIMEOUT) {
                 mTimedOut = true;
+                mWebView.stopLoading();
                 if (mCallback != null)
                     mCallback.timedOut(mWebView.getUrl());
                 if (!mRequestedWebKitData) {
@@ -86,10 +87,12 @@
                 }
                 return;
             } else if (msg.what == MSG_WEBKIT_DATA) {
+                mHandler.removeMessages(MSG_DUMP_TIMEOUT);
                 TestShellActivity.this.dump(mTimedOut, (String)msg.obj);
                 return;
+            } else if (msg.what == MSG_DUMP_TIMEOUT) {
+                throw new RuntimeException("WebView dump timeout, is it pegged?");
             }
-
             super.handleMessage(msg);
         }
     }
@@ -106,10 +109,12 @@
             case DUMP_AS_TEXT:
                 callback.arg1 = mDumpTopFrameAsText ? 1 : 0;
                 callback.arg2 = mDumpChildFramesAsText ? 1 : 0;
+                setDumpTimeout(DUMP_TIMEOUT_MS);
                 mWebView.documentAsText(callback);
                 break;
             case EXT_REPR:
                 mWebView.externalRepresentation(callback);
+                setDumpTimeout(DUMP_TIMEOUT_MS);
                 break;
             default:
                 finished();
@@ -117,6 +122,11 @@
         }
     }
 
+    private void setDumpTimeout(long timeout) {
+        Message msg = mHandler.obtainMessage(MSG_DUMP_TIMEOUT);
+        mHandler.sendMessageDelayed(msg, timeout);
+    }
+
     public void clearCache() {
       mWebView.freeMemory();
     }
@@ -933,9 +943,11 @@
     private boolean mDumpWebKitData = false;
 
     static final String TIMEOUT_STR = "**Test timeout";
+    static final long DUMP_TIMEOUT_MS = 20000; //20s timeout for dumping webview content
 
     static final int MSG_TIMEOUT = 0;
     static final int MSG_WEBKIT_DATA = 1;
+    static final int MSG_DUMP_TIMEOUT = 2;
 
     static final String LOGTAG="TestShell";
 
diff --git a/tests/DumpRenderTree2/assets/run_layout_tests.py b/tests/DumpRenderTree2/assets/run_layout_tests.py
index 0dfd229..3b8c09a 100755
--- a/tests/DumpRenderTree2/assets/run_layout_tests.py
+++ b/tests/DumpRenderTree2/assets/run_layout_tests.py
@@ -42,6 +42,7 @@
   cmd += "-w com.android.dumprendertree2/com.android.dumprendertree2.scriptsupport.ScriptTestRunner"
 
   logging.info("Running the tests...")
+  logging.debug("Command = %s" % cmd)
   (stdoutdata, stderrdata) = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
   if re.search("^INSTRUMENTATION_STATUS_CODE: -1", stdoutdata, re.MULTILINE) != None:
     logging.info("Failed to run the tests. Is DumpRenderTree2 installed on the device?")
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/FileFilter.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/FileFilter.java
index 6c33a21..5360e3d 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/FileFilter.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/FileFilter.java
@@ -68,8 +68,8 @@
     public void loadTestExpectations() {
         URL url = null;
         try {
-            url = new URL(ForwarderManager.getHostSchemePort(false) + "LayoutTests/" +
-                    TEST_EXPECTATIONS_TXT_PATH);
+            url = new URL(ForwarderManager.getHostSchemePort(false) +
+                    "LayoutTests/" + TEST_EXPECTATIONS_TXT_PATH);
         } catch (MalformedURLException e) {
             assert false;
         }
@@ -78,9 +78,14 @@
             InputStream inputStream = null;
             BufferedReader bufferedReader = null;
             try {
-                bufferedReader = new BufferedReader(new StringReader(new String(
-                        FsUtils.readDataFromUrl(url))));
-
+                byte[] httpAnswer = FsUtils.readDataFromUrl(url);
+                if (httpAnswer == null) {
+                    Log.w(LOG_TAG, "loadTestExpectations(): File not found: " +
+                            TEST_EXPECTATIONS_TXT_PATH);
+                    return;
+                }
+                bufferedReader = new BufferedReader(new StringReader(
+                        new String(httpAnswer)));
                 String line;
                 String entry;
                 String[] parts;
@@ -113,7 +118,8 @@
                     path = trimTrailingSlashIfPresent(parts[0]);
 
                     /** Split on whitespace */
-                    tokens = new HashSet<String>(Arrays.asList(parts[1].split("\\s", 0)));
+                    tokens = new HashSet<String>(Arrays.asList(
+                            parts[1].split("\\s", 0)));
 
                     /** Chose the right collections to add to */
                     if (tokens.contains(TOKEN_CRASH)) {
@@ -138,8 +144,6 @@
                     bufferedReader.close();
                 }
             }
-        } catch (FileNotFoundException e) {
-            Log.w(LOG_TAG, "reloadConfiguration(): File not found: " + e.getMessage());
         } catch (IOException e) {
             Log.e(LOG_TAG, "url=" + url, e);
         }
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index c60613c..e73afa0 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -18,13 +18,31 @@
     package="com.android.test.hwui">
 
     <uses-permission android:name="android.permission.INTERNET" />
-    <uses-sdk android:minSdkVersion="Froyo" />
+    <uses-sdk android:minSdkVersion="Honeycomb" />
     
     <application
         android:label="HwUi"
         android:hardwareAccelerated="true">
 
         <activity
+                android:name="ViewLayersActivity"
+                android:label="_ViewLayers">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+        <activity
+                android:name="ViewLayersActivity2"
+                android:label="_ViewLayers2">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+        <activity
                 android:name="AlphaLayersActivity"
                 android:label="_αLayers">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/res/layout/_advanced_blend.xml b/tests/HwAccelerationTest/res/layout/_advanced_blend.xml
new file mode 100644
index 0000000..5b6fd3c
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/_advanced_blend.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.test.hwui.AdvancedBlendActivity.ShadersView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent" />
diff --git a/tests/HwAccelerationTest/res/layout/_advanced_gradient.xml b/tests/HwAccelerationTest/res/layout/_advanced_gradient.xml
new file mode 100644
index 0000000..5e32ed2
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/_advanced_gradient.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.test.hwui.AdvancedGradientsActivity.GradientsView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent" />
diff --git a/tests/HwAccelerationTest/res/layout/_layers.xml b/tests/HwAccelerationTest/res/layout/_layers.xml
new file mode 100644
index 0000000..25c76ac
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/_layers.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.test.hwui.LayersActivity.LayersView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent" />
+
diff --git a/tests/HwAccelerationTest/res/layout/_lines.xml b/tests/HwAccelerationTest/res/layout/_lines.xml
new file mode 100644
index 0000000..c24dc25
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/_lines.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.test.hwui.LinesActivity.LinesView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent" />
+
diff --git a/tests/HwAccelerationTest/res/layout/_newlayers.xml b/tests/HwAccelerationTest/res/layout/_newlayers.xml
new file mode 100644
index 0000000..5c37e37
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/_newlayers.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.test.hwui.NewLayersActivity.LayersView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent" />
+
diff --git a/tests/HwAccelerationTest/res/layout/_paths.xml b/tests/HwAccelerationTest/res/layout/_paths.xml
new file mode 100644
index 0000000..34baf84
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/_paths.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.test.hwui.PathsActivity.PathsView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent" />
diff --git a/tests/HwAccelerationTest/res/layout/_shaders.xml b/tests/HwAccelerationTest/res/layout/_shaders.xml
new file mode 100644
index 0000000..070ac12
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/_shaders.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.test.hwui.ShadersActivity.ShadersView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent" />
+
diff --git a/tests/HwAccelerationTest/res/layout/advanced_blend.xml b/tests/HwAccelerationTest/res/layout/advanced_blend.xml
deleted file mode 100644
index 6efdd73..0000000
--- a/tests/HwAccelerationTest/res/layout/advanced_blend.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<com.android.test.hwui.AdvancedBlendActivity.ShadersView
-  xmlns:android="http://schemas.android.com/apk/res/android"
-  android:layout_width="fill_parent"
-  android:layout_height="fill_parent">
-</com.android.test.hwui.AdvancedBlendActivity.ShadersView>
diff --git a/tests/HwAccelerationTest/res/layout/advanced_gradient.xml b/tests/HwAccelerationTest/res/layout/advanced_gradient.xml
deleted file mode 100644
index dd937f9..0000000
--- a/tests/HwAccelerationTest/res/layout/advanced_gradient.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<com.android.test.hwui.AdvancedGradientsActivity.GradientsView
-  xmlns:android="http://schemas.android.com/apk/res/android"
-  android:layout_width="fill_parent"
-  android:layout_height="fill_parent">
-</com.android.test.hwui.AdvancedGradientsActivity.GradientsView>
diff --git a/tests/HwAccelerationTest/res/layout/view_layers.xml b/tests/HwAccelerationTest/res/layout/view_layers.xml
new file mode 100644
index 0000000..e0cdc78
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/view_layers.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ListView
+        android:id="@+id/list1"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
+
+    <ListView
+        android:id="@+id/list2"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
+
+    <ListView
+        android:id="@+id/list3"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
+
+</LinearLayout>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/LayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/LayersActivity.java
index b705117..9d5cd28 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/LayersActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/LayersActivity.java
@@ -33,11 +33,11 @@
         setContentView(new LayersView(this));
     }
 
-    static class LayersView extends View {
+    public static class LayersView extends View {
         private Paint mLayerPaint;
         private final Paint mRectPaint;
 
-        LayersView(Context c) {
+        public LayersView(Context c) {
             super(c);
 
             mLayerPaint = new Paint();
@@ -47,11 +47,11 @@
         @Override
         protected void onDraw(Canvas canvas) {
             super.onDraw(canvas);
-            
+
             canvas.translate(140.0f, 100.0f);
 
             //canvas.drawRGB(255, 255, 255);
-            
+
             int count = canvas.saveLayer(0.0f, 0.0f, 200.0f, 100.0f, mLayerPaint,
                     Canvas.ALL_SAVE_FLAG);
 
@@ -59,9 +59,9 @@
             canvas.drawRect(0.0f, 0.0f, 200.0f, 100.0f, mRectPaint);
 
             canvas.restoreToCount(count);
-            
+
             canvas.translate(0.0f, 125.0f);
-            
+
             count = canvas.saveLayer(0.0f, 0.0f, 200.0f, 100.0f, mLayerPaint,
                     Canvas.ALL_SAVE_FLAG);
 
@@ -75,8 +75,8 @@
 
             mRectPaint.setColor(0xff0000ff);
             mRectPaint.setAlpha(255);
-            canvas.drawRect(0.0f, 0.0f, 100.0f, 50.0f, mRectPaint);            
-            
+            canvas.drawRect(0.0f, 0.0f, 100.0f, 50.0f, mRectPaint);
+
             mLayerPaint.setAlpha(127);
             mLayerPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
             count = canvas.saveLayer(50.0f, 25.0f, 150.0f, 75.0f, mLayerPaint,
@@ -86,13 +86,13 @@
             canvas.drawRect(50.0f, 25.0f, 150.0f, 75.0f, mRectPaint);
 
             canvas.restoreToCount(count);
-            
+
             canvas.translate(0.0f, 125.0f);
 
             mRectPaint.setColor(0xff0000ff);
             mRectPaint.setAlpha(255);
-            canvas.drawRect(0.0f, 0.0f, 100.0f, 50.0f, mRectPaint);            
-            
+            canvas.drawRect(0.0f, 0.0f, 100.0f, 50.0f, mRectPaint);
+
             mLayerPaint.setColor(0xffff0000);
             mLayerPaint.setAlpha(127);
             mLayerPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
@@ -103,7 +103,7 @@
             canvas.drawRect(50.0f, 25.0f, 150.0f, 75.0f, mRectPaint);
 
             canvas.restoreToCount(count);
-            
+
             mLayerPaint = new Paint();
         }
     }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
index 6afbb01..8ca842e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java
@@ -23,6 +23,7 @@
 import android.graphics.BitmapShader;
 import android.graphics.Canvas;
 import android.graphics.Paint;
+import android.graphics.drawable.ColorDrawable;
 import android.os.Bundle;
 import android.view.View;
 
@@ -31,11 +32,13 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        getWindow().setBackgroundDrawable(new ColorDrawable(0xffffffff));
         final LinesView view = new LinesView(this);
+        //view.setAlpha(0.80f);
         setContentView(view);
     }
 
-    static class LinesView extends View {
+    public static class LinesView extends View {
         private static final boolean LINE_AA = false;
 
         private final Bitmap mBitmap1;
@@ -47,7 +50,7 @@
         private final Paint mAlphaPaint;
         private final Paint mHairLinePaint;
 
-        LinesView(Context c) {
+        public LinesView(Context c) {
             super(c);
 
             mBitmap1 = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1);
@@ -71,7 +74,7 @@
             mAlphaPaint.setAntiAlias(LINE_AA);
             mAlphaPaint.setColor(0x7fff0050);
             mAlphaPaint.setStrokeWidth(10.0f);
-            
+
             mHairLinePaint = new Paint();
             mHairLinePaint.setAntiAlias(LINE_AA);
             mHairLinePaint.setColor(0xff0000ff);
@@ -91,19 +94,17 @@
         protected void onDraw(Canvas canvas) {
             super.onDraw(canvas);
 
-            canvas.drawARGB(255, 255, 255, 255);
-
             canvas.save();
             canvas.translate(100.0f, 20.0f);
 
             canvas.drawLine(0.0f, 0.0f, 40.0f, 400.0f, mSmallPaint);
             canvas.drawLine(5.0f, 0.0f, 95.0f, 400.0f, mMediumPaint);
             canvas.drawLine(22.0f, 0.0f, 162.0f, 400.0f, mLargePaint);
-            
+
             mLargePaint.setShader(mShader);
             canvas.drawLine(42.0f, 0.0f, 222.0f, 400.0f, mLargePaint);
             mLargePaint.setShader(null);
-            
+
             canvas.drawLines(mPoints, mAlphaPaint);
 
             mSmallPaint.setAntiAlias(false);
@@ -111,14 +112,14 @@
             mSmallPaint.setAntiAlias(LINE_AA);
             canvas.drawLine(0.0f, 0.0f, 0.0f, 400.0f, mSmallPaint);
             canvas.drawLine(0.0f, 400.0f, 400.0f, 400.0f, mSmallPaint);
-            
+
             canvas.translate(120.0f, 0.0f);
-            mAlphaPaint.setShader(mShader);            
+            mAlphaPaint.setShader(mShader);
             canvas.drawLines(mPoints, mAlphaPaint);
             mAlphaPaint.setShader(null);
 
             canvas.restore();
-            
+
             canvas.scale(10.0f, 10.0f);
             canvas.drawLine(50.0f, 40.0f, 10.0f, 40.0f, mSmallPaint);
             canvas.drawLine(10.0f, 50.0f, 50.0f, 50.0f, mSmallPaint);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/NewLayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/NewLayersActivity.java
index d9a2893..2509d367 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/NewLayersActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/NewLayersActivity.java
@@ -31,11 +31,11 @@
         setContentView(new LayersView(this));
     }
 
-    static class LayersView extends View {
+    public static class LayersView extends View {
         private Paint mLayerPaint;
         private final Paint mRectPaint;
 
-        LayersView(Context c) {
+        public LayersView(Context c) {
             super(c);
 
             mLayerPaint = new Paint();
@@ -57,7 +57,7 @@
 
             canvas.translate(0.0f, 200.0f);
             drawStuff(canvas, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
-            
+
             canvas.restore();
         }
 
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PathsActivity.java
index 8d9bf37..5ddcd20 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/PathsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PathsActivity.java
@@ -37,7 +37,7 @@
         setContentView(view);
     }
 
-    static class PathsView extends View {
+    public static class PathsView extends View {
         private final Bitmap mBitmap1;
         private final Paint mSmallPaint;
         private final Paint mMediumPaint;
@@ -50,7 +50,7 @@
         private final float mOffset;
         private final Paint mLinePaint;
 
-        PathsView(Context c) {
+        public PathsView(Context c) {
             super(c);
 
             mBitmap1 = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1);
@@ -60,7 +60,7 @@
             mSmallPaint.setColor(0xffff0000);
             mSmallPaint.setStrokeWidth(1.0f);
             mSmallPaint.setStyle(Paint.Style.STROKE);
-            
+
             mLinePaint = new Paint();
             mLinePaint.setAntiAlias(true);
             mLinePaint.setColor(0xffff00ff);
@@ -69,7 +69,7 @@
 
             mMediumPaint = new Paint();
             mMediumPaint.setAntiAlias(true);
-            mMediumPaint.setColor(0xff0000ff);
+            mMediumPaint.setColor(0xe00000ff);
             mMediumPaint.setStrokeWidth(10.0f);
             mMediumPaint.setStyle(Paint.Style.STROKE);
 
@@ -112,7 +112,7 @@
             canvas.save();
             canvas.translate(200.0f, 60.0f);
             canvas.drawPath(mPath, mSmallPaint);
-            
+
             canvas.translate(350.0f, 0.0f);
             canvas.drawPath(mPath, mMediumPaint);
 
@@ -121,12 +121,12 @@
             canvas.drawPath(mPath, mLargePaint);
             mLargePaint.setShader(null);
             canvas.restore();
-            
+
             canvas.save();
             canvas.translate(200.0f, 360.0f);
             canvas.drawPath(mPath, mSmallPaint);
             canvas.drawRect(mPathBounds, mBoundsPaint);
-            
+
             canvas.translate(350.0f, 0.0f);
             canvas.drawBitmap(mBitmap, mPathBounds.left - mOffset * 1.5f,
                     mPathBounds.top - mOffset * 1.5f, null);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ShadersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ShadersActivity.java
index 02eaa7c..1d18f61 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ShadersActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ShadersActivity.java
@@ -39,7 +39,7 @@
         setContentView(new ShadersView(this));
     }
 
-    static class ShadersView extends View {
+    public static class ShadersView extends View {
         private BitmapShader mRepeatShader;
         private BitmapShader mTranslatedShader;
         private BitmapShader mScaledShader;
@@ -52,8 +52,11 @@
         private LinearGradient mDiagGradient;
         private LinearGradient mVertGradient;
         private Bitmap mTexture;
+        private Matrix mMtx1;
+        private Matrix mMtx2;
+        private Matrix mMtx3;
 
-        ShadersView(Context c) {
+        public ShadersView(Context c) {
             super(c);
 
             mTexture = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1);
@@ -67,28 +70,28 @@
 
             mTranslatedShader = new BitmapShader(mTexture, Shader.TileMode.REPEAT,
                     Shader.TileMode.REPEAT);
-            Matrix m1 = new Matrix();
-            m1.setTranslate(mTexWidth / 2.0f, mTexHeight / 2.0f);
-            m1.postRotate(45, 0, 0);
-            mTranslatedShader.setLocalMatrix(m1);
-            
+            mMtx1 = new Matrix();
+            mMtx1.setTranslate(mTexWidth / 2.0f, mTexHeight / 2.0f);
+            mMtx1.postRotate(45, 0, 0);
+            mTranslatedShader.setLocalMatrix(mMtx1);
+
             mScaledShader = new BitmapShader(mTexture, Shader.TileMode.MIRROR,
                     Shader.TileMode.MIRROR);
-            Matrix m2 = new Matrix();
-            m2.setScale(0.5f, 0.5f);
-            mScaledShader.setLocalMatrix(m2);
+            mMtx2 = new Matrix();
+            mMtx2.setScale(0.5f, 0.5f);
+            mScaledShader.setLocalMatrix(mMtx2);
 
             mHorGradient = new LinearGradient(0.0f, 0.0f, 1.0f, 0.0f,
                     Color.RED, Color.GREEN, Shader.TileMode.CLAMP);
-            Matrix m3 = new Matrix();
-            m3.setScale(mDrawHeight, 1.0f);
-            m3.postRotate(-90.0f);
-            m3.postTranslate(0.0f, mDrawHeight);
-            mHorGradient.setLocalMatrix(m3);
-            
+            mMtx3 = new Matrix();
+            mMtx3.setScale(mDrawHeight, 1.0f);
+            mMtx3.postRotate(-90.0f);
+            mMtx3.postTranslate(0.0f, mDrawHeight);
+            mHorGradient.setLocalMatrix(mMtx3);
+
             mDiagGradient = new LinearGradient(0.0f, 0.0f, mDrawWidth / 1.5f, mDrawHeight,
                     Color.BLUE, Color.MAGENTA, Shader.TileMode.CLAMP);
-            
+
             mVertGradient = new LinearGradient(0.0f, 0.0f, 0.0f, mDrawHeight / 2.0f,
                     Color.YELLOW, Color.MAGENTA, Shader.TileMode.MIRROR);
 
@@ -107,7 +110,7 @@
 
             mPaint.setShader(mRepeatShader);
             canvas.drawRect(0.0f, 0.0f, mDrawWidth, mDrawHeight, mPaint);
-            
+
             canvas.translate(0.0f, 40.0f + mDrawHeight);
             mPaint.setShader(mTranslatedShader);
             canvas.drawRect(0.0f, 0.0f, mDrawWidth, mDrawHeight, mPaint);
@@ -124,7 +127,7 @@
 
             mPaint.setShader(mHorGradient);
             canvas.drawRect(0.0f, 0.0f, mDrawWidth, mDrawHeight, mPaint);
-            
+
             canvas.translate(0.0f, 40.0f + mDrawHeight);
             mPaint.setShader(mDiagGradient);
             canvas.drawRect(0.0f, 0.0f, mDrawWidth, mDrawHeight, mPaint);
@@ -132,7 +135,7 @@
             canvas.translate(0.0f, 40.0f + mDrawHeight);
             mPaint.setShader(mVertGradient);
             canvas.drawRect(0.0f, 0.0f, mDrawWidth, mDrawHeight, mPaint);
-            
+
             canvas.restore();
         }
     }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
index eb0df51..1b79cb6 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
@@ -82,6 +82,14 @@
             mLargePaint.setAlpha(100);
             canvas.drawText("Hello OpenGL renderer!", 100, 500, mLargePaint);
             mLargePaint.setAlpha(255);
+            mLargePaint.setShadowLayer(3.0f, 3.0f, 3.0f, 0xd000ff00);
+            mLargePaint.setColor(0x00ffff00);
+            canvas.drawText("Hello OpenGL renderer!", 100, 600, mLargePaint);
+            mLargePaint.setShadowLayer(3.0f, 3.0f, 3.0f, 0x80000000);
+            mLargePaint.setColor(0x4dffffff);
+            canvas.drawText("Hello OpenGL renderer!", 100, 650, mLargePaint);
+            mLargePaint.setAlpha(255);
+            mLargePaint.setColor(0xff000000);
             mLargePaint.clearShadowLayer();
             
             canvas.drawText("Hello OpenGL renderer!", 500, 40, mStrikePaint);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
new file mode 100644
index 0000000..359447d
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class ViewLayersActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        setContentView(R.layout.view_layers);
+
+        setupList(R.id.list1);
+        setupList(R.id.list2);
+        setupList(R.id.list3);
+
+        getWindow().getDecorView().postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                final View leftList = findViewById(R.id.list1);
+                final View middleList = findViewById(R.id.list2);
+                final View rightList = findViewById(R.id.list3);
+
+                final ObjectAnimator moveRight = ObjectAnimator.ofFloat(leftList,
+                        "x", 0, rightList.getLeft());
+                moveRight.setDuration(1500);
+                moveRight.setRepeatCount(ObjectAnimator.INFINITE);
+                moveRight.setRepeatMode(ObjectAnimator.REVERSE);
+
+                final ObjectAnimator moveLeft = ObjectAnimator.ofFloat(rightList,
+                        "x", rightList.getLeft(), 0);
+                moveLeft.setDuration(1500);
+                moveLeft.setRepeatCount(ObjectAnimator.INFINITE);
+                moveLeft.setRepeatMode(ObjectAnimator.REVERSE);
+
+                final ObjectAnimator rotate = ObjectAnimator.ofFloat(middleList,
+                        "rotationY", 0, 360);
+                rotate.setDuration(3000);
+                rotate.setRepeatCount(ObjectAnimator.INFINITE);
+                rotate.setRepeatMode(ObjectAnimator.REVERSE);
+
+                Paint p = new Paint();
+                p.setColorFilter(new PorterDuffColorFilter(0xffff0000, PorterDuff.Mode.MULTIPLY));
+                
+                Paint p2 = new Paint();
+                p2.setAlpha(127);
+
+                Paint p3 = new Paint();
+                p3.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
+                
+                leftList.setLayerType(View.LAYER_TYPE_SOFTWARE, p);
+                leftList.setAlpha(0.5f);
+                middleList.setLayerType(View.LAYER_TYPE_HARDWARE, p3);
+                middleList.setAlpha(0.5f);
+                rightList.setLayerType(View.LAYER_TYPE_SOFTWARE, p2);
+
+                moveRight.start();
+                moveLeft.start();
+                rotate.start();
+            }
+        }, 2000);
+    }
+
+    private void setupList(int listId) {
+        final ListView list = (ListView) findViewById(listId);
+        list.setAdapter(new SimpleListAdapter(this));
+    }
+
+    private static class SimpleListAdapter extends ArrayAdapter<String> {
+        public SimpleListAdapter(Context context) {
+            super(context, android.R.layout.simple_list_item_1, DATA_LIST);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            TextView v = (TextView) super.getView(position, convertView, parent);
+            final Resources r = getContext().getResources();
+            final DisplayMetrics metrics = r.getDisplayMetrics();
+            v.setCompoundDrawablePadding((int) (6 * metrics.density + 0.5f));
+            v.setCompoundDrawablesWithIntrinsicBounds(r.getDrawable(R.drawable.icon),
+                    null, null, null);
+            return v;
+        }
+    }
+
+    private static final String[] DATA_LIST = {
+            "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
+            "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
+            "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
+            "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
+            "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
+            "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
+            "British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria",
+            "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
+            "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
+            "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
+            "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
+            "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
+            "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
+            "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
+            "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
+            "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
+            "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
+            "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
+            "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
+            "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
+            "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
+            "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
+            "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
+            "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
+            "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
+            "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
+            "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
+            "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
+            "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
+            "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
+            "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
+            "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
+            "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
+            "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
+            "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
+            "Ukraine", "United Arab Emirates", "United Kingdom",
+            "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
+            "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
+            "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
+    };
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java
new file mode 100644
index 0000000..a0b1d78
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity2.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class ViewLayersActivity2 extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        setContentView(R.layout.view_layers);
+
+        setupList(R.id.list1);
+        setupList(R.id.list2);
+        setupList(R.id.list3);
+    }
+
+    private void setupList(int listId) {
+        final ListView list = (ListView) findViewById(listId);
+        list.setAdapter(new SimpleListAdapter(this));
+        list.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+    }
+
+    private static class SimpleListAdapter extends ArrayAdapter<String> {
+        public SimpleListAdapter(Context context) {
+            super(context, android.R.layout.simple_list_item_1, DATA_LIST);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            TextView v = (TextView) super.getView(position, convertView, parent);
+            final Resources r = getContext().getResources();
+            final DisplayMetrics metrics = r.getDisplayMetrics();
+            v.setCompoundDrawablePadding((int) (6 * metrics.density + 0.5f));
+            v.setCompoundDrawablesWithIntrinsicBounds(r.getDrawable(R.drawable.icon),
+                    null, null, null);
+            return v;
+        }
+    }
+
+    private static final String[] DATA_LIST = {
+            "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
+            "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
+            "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
+            "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium",
+            "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia",
+            "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
+            "British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria",
+            "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde",
+            "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
+            "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
+            "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic",
+            "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
+            "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea",
+            "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland",
+            "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia",
+            "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar",
+            "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau",
+            "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary",
+            "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica",
+            "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos",
+            "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
+            "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands",
+            "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
+            "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia",
+            "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand",
+            "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas",
+            "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru",
+            "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar",
+            "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena",
+            "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon",
+            "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal",
+            "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
+            "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea",
+            "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden",
+            "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas",
+            "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey",
+            "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda",
+            "Ukraine", "United Arab Emirates", "United Kingdom",
+            "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan",
+            "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara",
+            "Yemen", "Yugoslavia", "Zambia", "Zimbabwe"
+    };
+}
diff --git a/tests/StatusBar/AndroidManifest.xml b/tests/StatusBar/AndroidManifest.xml
index ddb756b..81442bf 100644
--- a/tests/StatusBar/AndroidManifest.xml
+++ b/tests/StatusBar/AndroidManifest.xml
@@ -5,6 +5,7 @@
     <uses-permission android:name="android.permission.STATUS_BAR" />
     <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
     <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
 
     <application>
         <activity android:name="StatusBarTest" android:label="_StatusBar">
diff --git a/tests/StatusBar/res/drawable-mdpi/pineapple2.png b/tests/StatusBar/res/drawable-mdpi/pineapple2.png
new file mode 100644
index 0000000..ddc1038
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/pineapple2.png
Binary files differ
diff --git a/tests/StatusBar/res/layout/notification_builder_test.xml b/tests/StatusBar/res/layout/notification_builder_test.xml
index 58c4fbb..3c37a73 100644
--- a/tests/StatusBar/res/layout/notification_builder_test.xml
+++ b/tests/StatusBar/res/layout/notification_builder_test.xml
@@ -238,7 +238,7 @@
                         />
                 <RadioButton
                         android:id="@+id/when_midnight"
-                        style="@style/FieldContents.Disabled"
+                        style="@style/FieldContents"
                         android:text="midnight"
                         />
                 <RadioButton
@@ -322,7 +322,7 @@
                 <RadioButton
                         android:id="@+id/title_short"
                         style="@style/FieldContents"
-                        android:text="cwshort"
+                        android:text="short"
                         android:tag="Title"
                         />
                 <RadioButton
@@ -604,6 +604,11 @@
                         style="@style/FieldContents"
                         android:text="pineapple"
                         />
+                <RadioButton
+                        android:id="@+id/large_icon_pineapple2"
+                        style="@style/FieldContents"
+                        android:text="pineapple2"
+                        />
             </RadioGroup>
             
 
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
index e9a3513c..5a2ebac 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
@@ -16,6 +16,8 @@
 
 package com.android.statusbartest;
 
+import java.util.GregorianCalendar;
+
 import android.app.Activity;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -190,8 +192,14 @@
 
         // when
         switch (getRadioChecked(R.id.group_when)) {
-            case R.id.when_midnight:
+            case R.id.when_midnight: {
+                GregorianCalendar c = new GregorianCalendar();
+                c.set(GregorianCalendar.HOUR_OF_DAY, 0);
+                c.set(GregorianCalendar.MINUTE, 0);
+                c.set(GregorianCalendar.SECOND, 0);
+                b.setWhen(c.getTimeInMillis());
                 break;
+            }
             case R.id.when_now:
                 b.setWhen(System.currentTimeMillis());
                 break;
@@ -276,6 +284,9 @@
             case R.id.large_icon_pineapple:
                 b.setLargeIcon(loadBitmap(R.drawable.pineapple));
                 break;
+            case R.id.large_icon_pineapple2:
+                b.setLargeIcon(loadBitmap(R.drawable.pineapple2));
+                break;
         }
 
         // sound TODO
diff --git a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
index 92d5bee..31a1cf5a 100644
--- a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
@@ -26,6 +26,8 @@
 import android.os.IPowerManager;
 import android.widget.ListView;
 import android.content.Intent;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.StatusBarManager;
@@ -66,6 +68,24 @@
         return mTests;
     }
     private Test[] mTests = new Test[] {
+        new Test("Enable settings widget") {
+            public void run() {
+                PackageManager pm = getPackageManager();
+                pm.setComponentEnabledSetting(new ComponentName("com.android.settings",
+                            "com.android.settings.widget.SettingsAppWidgetProvider"),
+                        PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
+
+            }
+        },
+        new Test("Disable settings widget") {
+            public void run() {
+                PackageManager pm = getPackageManager();
+                pm.setComponentEnabledSetting(new ComponentName("com.android.settings",
+                            "com.android.settings.widget.SettingsAppWidgetProvider"),
+                        PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
+
+            }
+        },
         new Test("Enable proximity") {
             public void run() {
                 mProx.acquire();
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index 44c7d72..563f28c 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -178,6 +178,11 @@
                 mStatusBarManager.disable(StatusBarManager.DISABLE_CLOCK);
             }
         },
+        new Test("Disable System Info") {
+            public void run() {
+                mStatusBarManager.disable(StatusBarManager.DISABLE_SYSTEM_INFO);
+            }
+        },
         new Test("Disable everything in 3 sec") {
             public void run() {
                 mHandler.postDelayed(new Runnable() {
diff --git a/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetHostActivity.java b/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetHostActivity.java
index bb0fa60..2c8c5ba 100644
--- a/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetHostActivity.java
+++ b/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetHostActivity.java
@@ -46,14 +46,22 @@
     AppWidgetContainerView mAppWidgetContainer;
 
     public AppWidgetHostActivity() {
-        mAppWidgetManager = AppWidgetManager.getInstance(this);
     }
 
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
+        mAppWidgetManager = AppWidgetManager.getInstance(this);
+
         setContentView(R.layout.appwidget_host);
 
+        mHost = new AppWidgetHost(this, HOST_ID) {
+                protected AppWidgetHostView onCreateView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) {
+                    return new MyAppWidgetView(appWidgetId);
+                }
+            };
+
+
         findViewById(R.id.add_appwidget).setOnClickListener(mOnClickListener);
         mAppWidgetContainer = (AppWidgetContainerView)findViewById(R.id.appwidget_container);
 
@@ -188,11 +196,7 @@
         }
     }
 
-    AppWidgetHost mHost = new AppWidgetHost(this, HOST_ID) {
-        protected AppWidgetHostView onCreateView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) {
-            return new MyAppWidgetView(appWidgetId);
-        }
-    };
+    AppWidgetHost mHost;
 }
 
 
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 4614d6f..7f84df6 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -148,7 +148,8 @@
 
 bool isValidResourceType(const String8& type)
 {
-    return type == "anim" || type == "drawable" || type == "layout"
+    return type == "anim" || type == "animator" || type == "interpolator"
+        || type == "drawable" || type == "layout"
         || type == "values" || type == "xml" || type == "raw"
         || type == "color" || type == "menu" || type == "mipmap";
 }
@@ -798,6 +799,8 @@
     sp<ResourceTypeSet> drawables;
     sp<ResourceTypeSet> layouts;
     sp<ResourceTypeSet> anims;
+    sp<ResourceTypeSet> animators;
+    sp<ResourceTypeSet> interpolators;
     sp<ResourceTypeSet> xmls;
     sp<ResourceTypeSet> raws;
     sp<ResourceTypeSet> colors;
@@ -807,6 +810,8 @@
     ASSIGN_IT(drawable);
     ASSIGN_IT(layout);
     ASSIGN_IT(anim);
+    ASSIGN_IT(animator);
+    ASSIGN_IT(interpolator);
     ASSIGN_IT(xml);
     ASSIGN_IT(raw);
     ASSIGN_IT(color);
@@ -827,6 +832,8 @@
     if (!applyFileOverlay(bundle, assets, &drawables, "drawable") ||
             !applyFileOverlay(bundle, assets, &layouts, "layout") ||
             !applyFileOverlay(bundle, assets, &anims, "anim") ||
+            !applyFileOverlay(bundle, assets, &animators, "animator") ||
+            !applyFileOverlay(bundle, assets, &interpolators, "interpolator") ||
             !applyFileOverlay(bundle, assets, &xmls, "xml") ||
             !applyFileOverlay(bundle, assets, &raws, "raw") ||
             !applyFileOverlay(bundle, assets, &colors, "color") ||
@@ -879,6 +886,20 @@
         }
     }
 
+    if (animators != NULL) {
+        err = makeFileResources(bundle, assets, &table, animators, "animator");
+        if (err != NO_ERROR) {
+            hasErrors = true;
+        }
+    }
+
+    if (interpolators != NULL) {
+        err = makeFileResources(bundle, assets, &table, interpolators, "interpolator");
+        if (err != NO_ERROR) {
+            hasErrors = true;
+        }
+    }
+
     if (xmls != NULL) {
         err = makeFileResources(bundle, assets, &table, xmls, "xml");
         if (err != NO_ERROR) {
@@ -986,6 +1007,36 @@
         err = NO_ERROR;
     }
 
+    if (animators != NULL) {
+        ResourceDirIterator it(animators, String8("animator"));
+        while ((err=it.next()) == NO_ERROR) {
+            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+            if (err != NO_ERROR) {
+                hasErrors = true;
+            }
+        }
+
+        if (err < NO_ERROR) {
+            hasErrors = true;
+        }
+        err = NO_ERROR;
+    }
+
+    if (interpolators != NULL) {
+        ResourceDirIterator it(interpolators, String8("interpolator"));
+        while ((err=it.next()) == NO_ERROR) {
+            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+            if (err != NO_ERROR) {
+                hasErrors = true;
+            }
+        }
+
+        if (err < NO_ERROR) {
+            hasErrors = true;
+        }
+        err = NO_ERROR;
+    }
+
     if (xmls != NULL) {
         ResourceDirIterator it(xmls, String8("xml"));
         while ((err=it.next()) == NO_ERROR) {
diff --git a/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java b/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java
index b46d95c..60ad645 100644
--- a/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java
@@ -16,7 +16,7 @@
 
 package android.app;
 
-import com.android.layoutlib.api.IProjectCallback;
+import com.android.ide.common.rendering.api.IProjectCallback;
 
 import android.content.Context;
 import android.os.Bundle;
diff --git a/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java
new file mode 100644
index 0000000..190eb37
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+import java.awt.Composite;
+
+/**
+ * Delegate implementing the native methods of android.graphics.AvoidXfermode
+ *
+ * Through the layoutlib_create tool, the original native methods of AvoidXfermode have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original AvoidXfermode class.
+ *
+ * Because this extends {@link Xfermode_Delegate}, there's no need to use a
+ * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by
+ * {@link Xfermode_Delegate}.
+ *
+ */
+public class AvoidXfermode_Delegate extends Xfermode_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public Composite getComposite(int alpha) {
+        // FIXME
+        return null;
+    }
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Avoid Xfermodes are not supported in Layout Preview mode.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeCreate(int opColor, int tolerance, int nativeMode) {
+        AvoidXfermode_Delegate newDelegate = new AvoidXfermode_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
index 626f878..db3cf44 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
@@ -16,7 +16,8 @@
 
 package android.graphics;
 
-import com.android.layoutlib.api.ResourceDensity;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.ResourceDensity;
 import com.android.layoutlib.bridge.Bridge;
 
 import android.content.res.AssetManager;
@@ -351,7 +352,8 @@
                 If the exception happened on open, bm will be null.
                 If it happened on close, bm is still valid.
             */
-            Bridge.getLog().error(null, e);
+            Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
+                    String.format("Error decoding bitmap of id 0x%x", id), e, null /*data*/);
         } finally {
             try {
                 if (is != null) is.close();
@@ -450,9 +452,9 @@
         Bitmap  bm;
 
         if (is instanceof AssetManager.AssetInputStream) {
-            Bridge.getLog().error(null,
+            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
new file mode 100644
index 0000000..73c5a1a
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+import android.graphics.Shader.TileMode;
+
+/**
+ * Delegate implementing the native methods of android.graphics.BitmapShader
+ *
+ * Through the layoutlib_create tool, the original native methods of BitmapShader have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original BitmapShader class.
+ *
+ * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager},
+ * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}.
+ *
+ * @see Shader_Delegate
+ *
+ */
+public class BitmapShader_Delegate extends Shader_Delegate {
+
+    // ---- delegate data ----
+    private java.awt.Paint mJavaPaint;
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public java.awt.Paint getJavaPaint() {
+        return mJavaPaint;
+    }
+
+    @Override
+    public boolean isSupported() {
+        return true;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        // no message since isSupported returns true;
+        return null;
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeCreate(int native_bitmap, int shaderTileModeX,
+            int shaderTileModeY) {
+        Bitmap_Delegate bitmap = Bitmap_Delegate.getDelegate(native_bitmap);
+        if (bitmap == null) {
+            return 0;
+        }
+
+        BitmapShader_Delegate newDelegate = new BitmapShader_Delegate(
+                bitmap.getImage(),
+                Shader_Delegate.getTileMode(shaderTileModeX),
+                Shader_Delegate.getTileMode(shaderTileModeY));
+        return sManager.addDelegate(newDelegate);
+    }
+
+    /*package*/ static int nativePostCreate(int native_shader, int native_bitmap,
+            int shaderTileModeX, int shaderTileModeY) {
+        // pass, not needed.
+        return 0;
+    }
+
+    // ---- Private delegate/helper methods ----
+
+    private BitmapShader_Delegate(java.awt.image.BufferedImage image,
+            TileMode tileModeX, TileMode tileModeY) {
+        mJavaPaint = new BitmapShaderPaint(image, tileModeX, tileModeY);
+    }
+
+    private class BitmapShaderPaint implements java.awt.Paint {
+        private final java.awt.image.BufferedImage mImage;
+        private final TileMode mTileModeX;
+        private final TileMode mTileModeY;
+
+        BitmapShaderPaint(java.awt.image.BufferedImage image,
+                TileMode tileModeX, TileMode tileModeY) {
+            mImage = image;
+            mTileModeX = tileModeX;
+            mTileModeY = tileModeY;
+        }
+
+        public java.awt.PaintContext createContext(
+                java.awt.image.ColorModel      colorModel,
+                java.awt.Rectangle             deviceBounds,
+                java.awt.geom.Rectangle2D      userBounds,
+                java.awt.geom.AffineTransform  xform,
+                java.awt.RenderingHints        hints) {
+
+            java.awt.geom.AffineTransform canvasMatrix;
+            try {
+                canvasMatrix = xform.createInverse();
+            } catch (java.awt.geom.NoninvertibleTransformException e) {
+                Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
+                        "Unable to inverse matrix in BitmapShader", e, null /*data*/);
+                canvasMatrix = new java.awt.geom.AffineTransform();
+            }
+
+            java.awt.geom.AffineTransform localMatrix = getLocalMatrix();
+            try {
+                localMatrix = localMatrix.createInverse();
+            } catch (java.awt.geom.NoninvertibleTransformException e) {
+                Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
+                        "Unable to inverse matrix in BitmapShader", e, null /*data*/);
+                localMatrix = new java.awt.geom.AffineTransform();
+            }
+
+            return new BitmapShaderContext(canvasMatrix, localMatrix, colorModel);
+        }
+
+        private class BitmapShaderContext implements java.awt.PaintContext {
+
+            private final java.awt.geom.AffineTransform mCanvasMatrix;
+            private final java.awt.geom.AffineTransform mLocalMatrix;
+            private final java.awt.image.ColorModel mColorModel;
+
+            public BitmapShaderContext(
+                    java.awt.geom.AffineTransform canvasMatrix,
+                    java.awt.geom.AffineTransform localMatrix,
+                    java.awt.image.ColorModel colorModel) {
+                mCanvasMatrix = canvasMatrix;
+                mLocalMatrix = localMatrix;
+                mColorModel = colorModel;
+            }
+
+            public void dispose() {
+            }
+
+            public java.awt.image.ColorModel getColorModel() {
+                return mColorModel;
+            }
+
+            public java.awt.image.Raster getRaster(int x, int y, int w, int h) {
+                java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(w, h,
+                        java.awt.image.BufferedImage.TYPE_INT_ARGB);
+
+                int[] data = new int[w*h];
+
+                int index = 0;
+                float[] pt1 = new float[2];
+                float[] pt2 = new float[2];
+                for (int iy = 0 ; iy < h ; iy++) {
+                    for (int ix = 0 ; ix < w ; ix++) {
+                        // handle the canvas transform
+                        pt1[0] = x + ix;
+                        pt1[1] = y + iy;
+                        mCanvasMatrix.transform(pt1, 0, pt2, 0, 1);
+
+                        // handle the local matrix.
+                        pt1[0] = pt2[0];
+                        pt1[1] = pt2[1];
+                        mLocalMatrix.transform(pt1, 0, pt2, 0, 1);
+
+                        data[index++] = getColor(pt2[0], pt2[1]);
+                    }
+                }
+
+                image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/);
+
+                return image.getRaster();
+            }
+        }
+
+        /**
+         * Returns a color for an arbitrary point.
+         */
+        private int getColor(float fx, float fy) {
+            int x = getCoordinate(Math.round(fx), mImage.getWidth(), mTileModeX);
+            int y = getCoordinate(Math.round(fy), mImage.getHeight(), mTileModeY);
+
+            return mImage.getRGB(x, y);
+        }
+
+        private int getCoordinate(int i, int size, TileMode mode) {
+            if (i < 0) {
+                switch (mode) {
+                    case CLAMP:
+                        i = 0;
+                        break;
+                    case REPEAT:
+                        i = size - 1 - (-i % size);
+                        break;
+                    case MIRROR:
+                        // this is the same as the positive side, just make the value positive
+                        // first.
+                        i = -i;
+                        int count = i / size;
+                        i = i % size;
+
+                        if ((count % 2) == 1) {
+                            i = size - 1 - i;
+                        }
+                        break;
+                }
+            } else if (i >= size) {
+                switch (mode) {
+                    case CLAMP:
+                        i = size - 1;
+                        break;
+                    case REPEAT:
+                        i = i % size;
+                        break;
+                    case MIRROR:
+                        int count = i / size;
+                        i = i % size;
+
+                        if ((count % 2) == 1) {
+                            i = size - 1 - i;
+                        }
+                        break;
+                }
+            }
+
+            return i;
+        }
+
+
+        public int getTransparency() {
+            return java.awt.Paint.TRANSLUCENT;
+        }
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index fe201c1..108d183 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -16,7 +16,9 @@
 
 package android.graphics;
 
-import com.android.layoutlib.api.ResourceDensity;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.ResourceDensity;
+import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Bitmap.Config;
@@ -29,6 +31,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.Buffer;
+import java.util.Arrays;
 
 import javax.imageio.ImageIO;
 
@@ -45,7 +48,7 @@
  * @see DelegateManager
  *
  */
-public class Bitmap_Delegate {
+public final class Bitmap_Delegate {
 
     // ---- delegate manager ----
     private static final DelegateManager<Bitmap_Delegate> sManager =
@@ -54,8 +57,11 @@
     // ---- delegate helper data ----
 
     // ---- delegate data ----
+    private final Config mConfig;
     private BufferedImage mImage;
     private boolean mHasAlpha = true;
+    private int mGenerationId = 0;
+
 
     // ---- Public Helper methods ----
 
@@ -86,7 +92,7 @@
     public static Bitmap createBitmap(File input, boolean isMutable, ResourceDensity density)
             throws IOException {
         // create a delegate with the content of the file.
-        Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input));
+        Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
 
         return createBitmap(delegate, isMutable, density.getDpi());
     }
@@ -104,7 +110,7 @@
     public static Bitmap createBitmap(InputStream input, boolean isMutable, ResourceDensity density)
             throws IOException {
         // create a delegate with the content of the stream.
-        Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input));
+        Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
 
         return createBitmap(delegate, isMutable, density.getDpi());
     }
@@ -122,7 +128,7 @@
     public static Bitmap createBitmap(BufferedImage image, boolean isMutable,
             ResourceDensity density) throws IOException {
         // create a delegate with the given image.
-        Bitmap_Delegate delegate = new Bitmap_Delegate(image);
+        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
 
         return createBitmap(delegate, isMutable, density.getDpi());
     }
@@ -134,7 +140,6 @@
         // get the delegate from the native int.
         Bitmap_Delegate delegate = sManager.getDelegate(bitmap.mNativeBitmap);
         if (delegate == null) {
-            assert false;
             return null;
         }
 
@@ -163,6 +168,31 @@
         return mImage;
     }
 
+    /**
+     * Returns the Android bitmap config. Note that this not the config of the underlying
+     * Java2D bitmap.
+     */
+    public Config getConfig() {
+        return mConfig;
+    }
+
+    /**
+     * Returns the hasAlpha rendering hint
+     * @return true if the bitmap alpha should be used at render time
+     */
+    public boolean hasAlpha() {
+        return mHasAlpha && mConfig != Config.RGB_565;
+    }
+
+    /**
+     * Update the generationId.
+     *
+     * @see Bitmap#getGenerationId()
+     */
+    public void change() {
+        mGenerationId++;
+    }
+
     // ---- native methods ----
 
     /*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width,
@@ -172,17 +202,41 @@
         // create the image
         BufferedImage image = new BufferedImage(width, height, imageType);
 
-        // FIXME fill the bitmap!
+        if (colors != null) {
+            image.setRGB(0, 0, width, height, colors, offset, stride);
+        }
 
         // create a delegate with the content of the stream.
-        Bitmap_Delegate delegate = new Bitmap_Delegate(image);
+        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.sConfigs[nativeConfig]);
 
         return createBitmap(delegate, mutable, Bitmap.getDefaultDensity());
     }
 
     /*package*/ static Bitmap nativeCopy(int srcBitmap, int nativeConfig, boolean isMutable) {
-        // FIXME implement native delegate
-        throw new UnsupportedOperationException("Native delegate needed for Bitmap");
+        Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(srcBitmap);
+        if (srcBmpDelegate == null) {
+            return null;
+        }
+
+        BufferedImage srcImage = srcBmpDelegate.getImage();
+
+        int width = srcImage.getWidth();
+        int height = srcImage.getHeight();
+
+        int imageType = getBufferedImageType(nativeConfig);
+
+        // create the image
+        BufferedImage image = new BufferedImage(width, height, imageType);
+
+        // copy the source image into the image.
+        int[] argb = new int[width * height];
+        srcImage.getRGB(0, 0, width, height, argb, 0, width);
+        image.setRGB(0, 0, width, height, argb, 0, width);
+
+        // create a delegate with the content of the stream.
+        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.sConfigs[nativeConfig]);
+
+        return createBitmap(delegate, isMutable, Bitmap.getDefaultDensity());
     }
 
     /*package*/ static void nativeDestructor(int nativeBitmap) {
@@ -195,15 +249,15 @@
 
     /*package*/ static boolean nativeCompress(int nativeBitmap, int format, int quality,
             OutputStream stream, byte[] tempStorage) {
-        // FIXME implement native delegate
-        throw new UnsupportedOperationException("Native delegate needed for Bitmap");
+        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
+                "Bitmap.compress() is not supported", null /*data*/);
+        return true;
     }
 
     /*package*/ static void nativeErase(int nativeBitmap, int color) {
         // get the delegate from the native int.
         Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -211,10 +265,7 @@
 
         Graphics2D g = image.createGraphics();
         try {
-            if (delegate.mHasAlpha == false) {
-                color |= color & 0xFF000000;
-            }
-            g.setColor(new java.awt.Color(color));
+            g.setColor(new java.awt.Color(color, true));
 
             g.fillRect(0, 0, image.getWidth(), image.getHeight());
         } finally {
@@ -226,7 +277,6 @@
         // get the delegate from the native int.
         Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -237,7 +287,6 @@
         // get the delegate from the native int.
         Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -248,7 +297,6 @@
         // get the delegate from the native int.
         Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -256,14 +304,19 @@
     }
 
     /*package*/ static int nativeConfig(int nativeBitmap) {
-        return Config.ARGB_8888.nativeInt;
+        // get the delegate from the native int.
+        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
+        if (delegate == null) {
+            return 0;
+        }
+
+        return delegate.mConfig.nativeInt;
     }
 
     /*package*/ static boolean nativeHasAlpha(int nativeBitmap) {
         // get the delegate from the native int.
         Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
         if (delegate == null) {
-            assert false;
             return true;
         }
 
@@ -274,7 +327,6 @@
         // get the delegate from the native int.
         Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -283,20 +335,32 @@
 
     /*package*/ static void nativeGetPixels(int nativeBitmap, int[] pixels, int offset,
             int stride, int x, int y, int width, int height) {
-        // FIXME implement native delegate
-        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeGetPixels");
+        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
+        if (delegate == null) {
+            return;
+        }
+
+        delegate.getImage().getRGB(x, y, width, height, pixels, offset, stride);
     }
 
 
     /*package*/ static void nativeSetPixel(int nativeBitmap, int x, int y, int color) {
-        // FIXME implement native delegate
-        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSetPixel");
+        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
+        if (delegate == null) {
+            return;
+        }
+
+        delegate.getImage().setRGB(x, y, color);
     }
 
     /*package*/ static void nativeSetPixels(int nativeBitmap, int[] colors, int offset,
             int stride, int x, int y, int width, int height) {
-        // FIXME implement native delegate
-        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSetPixels");
+        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
+        if (delegate == null) {
+            return;
+        }
+
+        delegate.getImage().setRGB(x, y, width, height, colors, offset, stride);
     }
 
     /*package*/ static void nativeCopyPixelsToBuffer(int nativeBitmap, Buffer dst) {
@@ -310,38 +374,68 @@
     }
 
     /*package*/ static int nativeGenerationId(int nativeBitmap) {
-        // FIXME implement native delegate
-        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeGenerationId");
+        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
+        if (delegate == null) {
+            return 0;
+        }
+
+        return delegate.mGenerationId;
     }
 
     /*package*/ static Bitmap nativeCreateFromParcel(Parcel p) {
-        // FIXME implement native delegate
-        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeCreateFromParcel");
+        // 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.",
+                null /*data*/);
+        return null;
     }
 
     /*package*/ static boolean nativeWriteToParcel(int nativeBitmap, boolean isMutable,
             int density, Parcel p) {
-        // FIXME implement native delegate
-        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeWriteToParcel");
+        // 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.",
+                null /*data*/);
+        return false;
     }
 
     /*package*/ static Bitmap nativeExtractAlpha(int nativeBitmap, int nativePaint,
             int[] offsetXY) {
-        // FIXME implement native delegate
-        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeExtractAlpha");
+        Bitmap_Delegate bitmap = sManager.getDelegate(nativeBitmap);
+        if (bitmap == null) {
+            return null;
+        }
+
+        // get the paint which can be null if nativePaint is 0.
+        Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint);
+
+        if (paint != null && paint.getMaskFilter() != null) {
+            Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
+                    "MaskFilter not supported in Bitmap.extractAlpha",
+                    null, null /*data*/);
+        }
+
+        int alpha = paint != null ? paint.getAlpha() : 0xFF;
+        BufferedImage image = createCopy(bitmap.getImage(), BufferedImage.TYPE_INT_ARGB, alpha);
+
+        // create the delegate. The actual Bitmap config is only an alpha channel
+        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ALPHA_8);
+
+        // the density doesn't matter, it's set by the Java method.
+        return createBitmap(delegate, false /*isMutable*/,
+                ResourceDensity.DEFAULT_DENSITY /*density*/);
     }
 
-
     /*package*/ static void nativePrepareToDraw(int nativeBitmap) {
-        // FIXME implement native delegate
-        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativePrepareToDraw");
+        // nothing to be done here.
     }
 
     /*package*/ static void nativeSetHasAlpha(int nativeBitmap, boolean hasAlpha) {
         // get the delegate from the native int.
         Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -349,14 +443,53 @@
     }
 
     /*package*/ static boolean nativeSameAs(int nb0, int nb1) {
-        // FIXME implement native delegate
-        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSameAs");
+        Bitmap_Delegate delegate1 = sManager.getDelegate(nb0);
+        if (delegate1 == null) {
+            return false;
+        }
+
+        Bitmap_Delegate delegate2 = sManager.getDelegate(nb1);
+        if (delegate2 == null) {
+            return false;
+        }
+
+        BufferedImage image1 = delegate1.getImage();
+        BufferedImage image2 = delegate2.getImage();
+        if (delegate1.mConfig != delegate2.mConfig ||
+                image1.getWidth() != image2.getWidth() ||
+                image1.getHeight() != image2.getHeight()) {
+            return false;
+        }
+
+        // get the internal data
+        int w = image1.getWidth();
+        int h = image2.getHeight();
+        int[] argb1 = new int[w*h];
+        int[] argb2 = new int[w*h];
+
+        image1.getRGB(0, 0, w, h, argb1, 0, w);
+        image2.getRGB(0, 0, w, h, argb2, 0, w);
+
+        // compares
+        if (delegate1.mConfig == Config.ALPHA_8) {
+            // in this case we have to manually compare the alpha channel as the rest is garbage.
+            final int length = w*h;
+            for (int i = 0 ; i < length ; i++) {
+                if ((argb1[i] & 0xFF000000) != (argb2[i] & 0xFF000000)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        return Arrays.equals(argb1, argb2);
     }
 
     // ---- Private delegate/helper methods ----
 
-    private Bitmap_Delegate(BufferedImage image) {
+    private Bitmap_Delegate(BufferedImage image, Config config) {
         mImage = image;
+        mConfig = config;
     }
 
     private static Bitmap createBitmap(Bitmap_Delegate delegate, boolean isMutable, int density) {
@@ -366,4 +499,37 @@
         // and create/return a new Bitmap with it
         return new Bitmap(nativeInt, null /* buffer */, isMutable, null /*ninePatchChunk*/, density);
     }
+
+    /**
+     * Creates and returns a copy of a given BufferedImage.
+     * <p/>
+     * if alpha is different than 255, then it is applied to the alpha channel of each pixel.
+     *
+     * @param image the image to copy
+     * @param imageType the type of the new image
+     * @param alpha an optional alpha modifier
+     * @return a new BufferedImage
+     */
+    /*package*/ static BufferedImage createCopy(BufferedImage image, int imageType, int alpha) {
+        int w = image.getWidth();
+        int h = image.getHeight();
+
+        BufferedImage result = new BufferedImage(w, h, imageType);
+
+        int[] argb = new int[w * h];
+        image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
+
+        if (alpha != 255) {
+            final int length = argb.length;
+            for (int i = 0 ; i < length; i++) {
+                int a = (argb[i] >>> 24 * alpha) / 255;
+                argb[i] = (a << 24) | (argb[i] & 0x00FFFFFF);
+            }
+        }
+
+        result.setRGB(0, 0, w, h, argb, 0, w);
+
+        return result;
+    }
+
 }
diff --git a/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java
new file mode 100644
index 0000000..34824b4
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.graphics.BlurMaskFilter
+ *
+ * Through the layoutlib_create tool, the original native methods of BlurMaskFilter have
+ * been replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original BlurMaskFilter class.
+ *
+ * Because this extends {@link MaskFilter_Delegate}, there's no need to use a
+ * {@link DelegateManager}, as all the Shader classes will be added to the manager
+ * owned by {@link MaskFilter_Delegate}.
+ *
+ * @see MaskFilter_Delegate
+ *
+ */
+public class BlurMaskFilter_Delegate extends MaskFilter_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Blur Mask Filters are not supported.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeConstructor(float radius, int style) {
+        BlurMaskFilter_Delegate newDelegate = new BlurMaskFilter_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index c75e1b6..5a6902c 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -16,19 +16,21 @@
 
 package android.graphics;
 
+import com.android.ide.common.rendering.api.LayoutLog;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.layoutlib.bridge.impl.GcSnapshot;
 
+import android.graphics.Bitmap.Config;
 import android.graphics.Paint_Delegate.FontInfo;
 import android.text.TextUtils;
 
-import java.awt.AlphaComposite;
-import java.awt.BasicStroke;
 import java.awt.Color;
+import java.awt.Composite;
 import java.awt.Graphics2D;
 import java.awt.Rectangle;
 import java.awt.RenderingHints;
+import java.awt.Shape;
 import java.awt.geom.AffineTransform;
 import java.awt.image.BufferedImage;
 import java.util.List;
@@ -47,7 +49,7 @@
  * @see DelegateManager
  *
  */
-public class Canvas_Delegate {
+public final class Canvas_Delegate {
 
     // ---- delegate manager ----
     private static final DelegateManager<Canvas_Delegate> sManager =
@@ -55,9 +57,13 @@
 
     // ---- delegate helper data ----
 
+    private final static boolean[] sBoolOut = new boolean[1];
+
     // ---- delegate data ----
-    private BufferedImage mBufferedImage;
-    private GcSnapshot mSnapshot = new GcSnapshot();
+    private Bitmap_Delegate mBitmap;
+    private GcSnapshot mSnapshot;
+
+    private int mDrawFilter = 0;
 
     // ---- Public Helper methods ----
 
@@ -78,82 +84,90 @@
     /**
      * Returns the current {@link Graphics2D} used to draw.
      */
-    public GcSnapshot getGcSnapshot() {
+    public GcSnapshot getSnapshot() {
         return mSnapshot;
     }
 
+    /**
+     * Returns the {@link DrawFilter} delegate or null if none have been set.
+     *
+     * @return the delegate or null.
+     */
+    public DrawFilter_Delegate getDrawFilter() {
+        return DrawFilter_Delegate.getDelegate(mDrawFilter);
+    }
+
     // ---- native methods ----
 
     /*package*/ static boolean isOpaque(Canvas thisCanvas) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate from the native int.
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
+        if (canvasDelegate == null) {
+            return false;
+        }
+
+        return canvasDelegate.mBitmap.getConfig() == Config.RGB_565;
     }
 
     /*package*/ static int getWidth(Canvas thisCanvas) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return 0;
         }
 
-        return canvasDelegate.mBufferedImage.getWidth();
+        return canvasDelegate.mBitmap.getImage().getWidth();
     }
 
     /*package*/ static int getHeight(Canvas thisCanvas) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return 0;
         }
 
-        return canvasDelegate.mBufferedImage.getHeight();
+        return canvasDelegate.mBitmap.getImage().getHeight();
     }
 
     /*package*/ static void translate(Canvas thisCanvas, float dx, float dy) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return;
         }
 
-        canvasDelegate.getGcSnapshot().translate(dx, dy);
+        canvasDelegate.getSnapshot().translate(dx, dy);
     }
 
     /*package*/ static void rotate(Canvas thisCanvas, float degrees) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return;
         }
 
-        canvasDelegate.getGcSnapshot().rotate(Math.toRadians(degrees));
+        canvasDelegate.getSnapshot().rotate(Math.toRadians(degrees));
     }
 
     /*package*/ static void scale(Canvas thisCanvas, float sx, float sy) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return;
         }
 
-        canvasDelegate.getGcSnapshot().scale(sx, sy);
+        canvasDelegate.getSnapshot().scale(sx, sy);
     }
 
     /*package*/ static void skew(Canvas thisCanvas, float kx, float ky) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return;
         }
 
         // get the current top graphics2D object.
-        GcSnapshot g = canvasDelegate.getGcSnapshot();
+        GcSnapshot g = canvasDelegate.getSnapshot();
 
         // get its current matrix
         AffineTransform currentTx = g.getTransform();
@@ -182,7 +196,6 @@
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return false;
         }
 
@@ -203,7 +216,6 @@
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return 0;
         }
 
@@ -214,7 +226,6 @@
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return;
         }
 
@@ -225,18 +236,16 @@
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return 0;
         }
 
-        return canvasDelegate.getGcSnapshot().size();
+        return canvasDelegate.getSnapshot().size();
     }
 
     /*package*/ static void restoreToCount(Canvas thisCanvas, int saveCount) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return;
         }
 
@@ -254,38 +263,22 @@
         throw new UnsupportedOperationException();
     }
 
-    /*package*/ static void drawLines(Canvas thisCanvas, float[] pts, int offset, int count,
+    /*package*/ static void drawLines(Canvas thisCanvas,
+            final float[] pts, final int offset, final int count,
             Paint paint) {
-        // get the delegate from the native int.
-        Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
-        if (canvasDelegate == null) {
-            assert false;
-            return;
-        }
-
-        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint.mNativePaint);
-        if (paintDelegate == null) {
-            assert false;
-            return;
-        }
-
-        // get a Graphics2D object configured with the drawing parameters.
-        Graphics2D g = canvasDelegate.createCustomGraphics(paintDelegate);
-
-        try {
-            for (int i = 0 ; i < count ; i += 4) {
-                g.drawLine((int)pts[i + offset], (int)pts[i + offset + 1],
-                        (int)pts[i + offset + 2], (int)pts[i + offset + 3]);
-            }
-        } finally {
-            // dispose Graphics2D object
-            g.dispose();
-        }
+        draw(thisCanvas.mNativeCanvas, paint.mNativePaint, false /*compositeOnly*/,
+                false /*forceSrcMode*/, new GcSnapshot.Drawable() {
+                    public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                        for (int i = 0 ; i < count ; i += 4) {
+                            graphics.drawLine((int)pts[i + offset], (int)pts[i + offset + 1],
+                                    (int)pts[i + offset + 2], (int)pts[i + offset + 3]);
+                        }
+                    }
+                });
     }
 
     /*package*/ static void freeCaches() {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // nothing to be done here.
     }
 
     /*package*/ static int initRaster(int nativeBitmapOrZero) {
@@ -294,7 +287,7 @@
             Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmapOrZero);
 
             // create a new Canvas_Delegate with the given bitmap and return its new native int.
-            Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate.getImage());
+            Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate);
 
             return sManager.addDelegate(newDelegate);
         } else {
@@ -309,45 +302,74 @@
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return;
         }
 
         // get the delegate from the native int.
         Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
         if (bitmapDelegate == null) {
-            assert false;
             return;
         }
 
-        canvasDelegate.setBitmap(bitmapDelegate.getImage());
+        canvasDelegate.setBitmap(bitmapDelegate);
     }
 
     /*package*/ static int native_saveLayer(int nativeCanvas, RectF bounds,
                                                int paint, int layerFlags) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate from the native int.
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
+        if (canvasDelegate == null) {
+            return 0;
+        }
+
+        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
+        if (paintDelegate == null) {
+            return 0;
+        }
+
+        return canvasDelegate.saveLayer(bounds, paintDelegate, layerFlags);
     }
 
     /*package*/ static int native_saveLayer(int nativeCanvas, float l,
                                                float t, float r, float b,
                                                int paint, int layerFlags) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate from the native int.
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
+        if (canvasDelegate == null) {
+            return 0;
+        }
+
+        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
+        if (paintDelegate == null) {
+            return 0;
+        }
+
+        return canvasDelegate.saveLayer(new RectF(l, t, r, b),
+                paintDelegate, layerFlags);
     }
 
     /*package*/ static int native_saveLayerAlpha(int nativeCanvas,
                                                     RectF bounds, int alpha,
                                                     int layerFlags) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate from the native int.
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
+        if (canvasDelegate == null) {
+            return 0;
+        }
+
+        return canvasDelegate.saveLayerAlpha(bounds, alpha, layerFlags);
     }
 
     /*package*/ static int native_saveLayerAlpha(int nativeCanvas, float l,
                                                     float t, float r, float b,
                                                     int alpha, int layerFlags) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate from the native int.
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
+        if (canvasDelegate == null) {
+            return 0;
+        }
+
+        return canvasDelegate.saveLayerAlpha(new RectF(l, t, r, b), alpha, layerFlags);
     }
 
 
@@ -355,18 +377,16 @@
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return;
         }
 
         Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
         if (matrixDelegate == null) {
-            assert false;
             return;
         }
 
         // get the current top graphics2D object.
-        GcSnapshot snapshot = canvasDelegate.getGcSnapshot();
+        GcSnapshot snapshot = canvasDelegate.getSnapshot();
 
         // get its current matrix
         AffineTransform currentTx = snapshot.getTransform();
@@ -384,16 +404,16 @@
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
         if (canvasDelegate == null) {
-            assert false;
+            return;
         }
 
         Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
         if (matrixDelegate == null) {
-            assert false;
+            return;
         }
 
         // get the current top graphics2D object.
-        GcSnapshot snapshot = canvasDelegate.getGcSnapshot();
+        GcSnapshot snapshot = canvasDelegate.getSnapshot();
 
         // get the AffineTransform of the given matrix
         AffineTransform matrixTx = matrixDelegate.getAffineTransform();
@@ -403,9 +423,9 @@
 
         if (matrixDelegate.hasPerspective()) {
             assert false;
-            Bridge.getLog().warning(null,
+            Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE,
                     "android.graphics.Canvas#setMatrix(android.graphics.Matrix) only " +
-                    "supports affine transformations in the Layout Preview.");
+                    "supports affine transformations.", null, null /*data*/);
         }
     }
 
@@ -417,7 +437,7 @@
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
         if (canvasDelegate == null) {
-            assert false;
+            return false;
         }
 
         return canvasDelegate.clipRect(left, top, right, bottom, regionOp);
@@ -426,21 +446,56 @@
     /*package*/ static boolean native_clipPath(int nativeCanvas,
                                                   int nativePath,
                                                   int regionOp) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
+        if (canvasDelegate == null) {
+            return true;
+        }
+
+        Path_Delegate pathDelegate = Path_Delegate.getDelegate(nativePath);
+        if (pathDelegate == null) {
+            return true;
+        }
+
+        return canvasDelegate.mSnapshot.clip(pathDelegate.getJavaShape(), regionOp);
     }
 
     /*package*/ static boolean native_clipRegion(int nativeCanvas,
                                                     int nativeRegion,
                                                     int regionOp) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
+        if (canvasDelegate == null) {
+            return true;
+        }
+
+        Region_Delegate region = Region_Delegate.getDelegate(nativeRegion);
+        if (region == null) {
+            return true;
+        }
+
+        return canvasDelegate.mSnapshot.clip(region.getJavaArea(), regionOp);
     }
 
     /*package*/ static void nativeSetDrawFilter(int nativeCanvas,
                                                    int nativeFilter) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
+        if (canvasDelegate == null) {
+            return;
+        }
+
+        canvasDelegate.mDrawFilter = nativeFilter;
+
+        // get the delegate only because we don't support them at all for the moment, so
+        // we can display the message now.
+
+        DrawFilter_Delegate filterDelegate = DrawFilter_Delegate.getDelegate(nativeFilter);
+        if (canvasDelegate == null) {
+            return;
+        }
+
+        if (filterDelegate.isSupported() == false) {
+            Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER,
+                    filterDelegate.getSupportMessage(), null, null /*data*/);
+        }
     }
 
     /*package*/ static boolean native_getClipBounds(int nativeCanvas,
@@ -448,24 +503,35 @@
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return false;
         }
 
-        Rectangle rect = canvasDelegate.getGcSnapshot().getClip().getBounds();
-        if (rect != null) {
+        Rectangle rect = canvasDelegate.getSnapshot().getClip().getBounds();
+        if (rect != null && rect.isEmpty() == false) {
             bounds.left = rect.x;
             bounds.top = rect.y;
             bounds.right = rect.x + rect.width;
             bounds.bottom = rect.y + rect.height;
             return true;
         }
+
         return false;
     }
 
     /*package*/ static void native_getCTM(int canvas, int matrix) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate from the native int.
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
+        if (canvasDelegate == null) {
+            return;
+        }
+
+        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
+        if (matrixDelegate == null) {
+            return;
+        }
+
+        AffineTransform transform = canvasDelegate.getSnapshot().getTransform();
+        matrixDelegate.set(Matrix_Delegate.makeValues(transform));
     }
 
     /*package*/ static boolean native_quickReject(int nativeCanvas,
@@ -505,31 +571,33 @@
         native_drawColor(nativeCanvas, color, PorterDuff.Mode.SRC_OVER.nativeInt);
     }
 
-    /*package*/ static void native_drawColor(int nativeCanvas, int color, int mode) {
+    /*package*/ static void native_drawColor(int nativeCanvas, final int color, final int mode) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return;
         }
 
-        // get a new graphics context.
-        Graphics2D graphics = (Graphics2D)canvasDelegate.getGcSnapshot().create();
-        try {
-            // reset its transform just in case
-            graphics.setTransform(new AffineTransform());
+        final int w = canvasDelegate.mBitmap.getImage().getWidth();
+        final int h = canvasDelegate.mBitmap.getImage().getHeight();
+        draw(nativeCanvas, new GcSnapshot.Drawable() {
 
-            // set the color
-            graphics.setColor(new Color(color, true /*alpha*/));
+            public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                // reset its transform just in case
+                graphics.setTransform(new AffineTransform());
 
-            setModeInGraphics(graphics, mode);
+                // set the color
+                graphics.setColor(new Color(color, true /*alpha*/));
 
-            graphics.fillRect(0, 0, canvasDelegate.mBufferedImage.getWidth(),
-                    canvasDelegate.mBufferedImage.getHeight());
-        } finally {
-            // dispose Graphics2D object
-            graphics.dispose();
-        }
+                Composite composite = PorterDuffXfermode_Delegate.getComposite(
+                        PorterDuffXfermode_Delegate.getPorterDuffMode(mode), 0xFF);
+                if (composite != null) {
+                    graphics.setComposite(composite);
+                }
+
+                graphics.fillRect(0, 0, w, h);
+            }
+        });
     }
 
     /*package*/ static void native_drawPaint(int nativeCanvas, int paint) {
@@ -537,32 +605,16 @@
         throw new UnsupportedOperationException();
     }
 
-    /*package*/ static void native_drawLine(int nativeCanvas, float startX,
-                                               float startY, float stopX,
-                                               float stopY, int paint) {
-        // get the delegate from the native int.
-        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
-        if (canvasDelegate == null) {
-            assert false;
-            return;
-        }
+    /*package*/ static void native_drawLine(int nativeCanvas,
+            final float startX, final float startY, final float stopX, final float stopY,
+            int paint) {
 
-        // get the delegate from the native int.
-        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
-        if (paintDelegate == null) {
-            assert false;
-            return;
-        }
-
-        // get a Graphics2D object configured with the drawing parameters.
-        Graphics2D g = canvasDelegate.createCustomGraphics(paintDelegate);
-
-        try {
-            g.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY);
-        } finally {
-            // dispose Graphics2D object
-            g.dispose();
-        }
+        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
+                new GcSnapshot.Drawable() {
+                    public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                        graphics.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY);
+                    }
+        });
     }
 
     /*package*/ static void native_drawRect(int nativeCanvas, RectF rect,
@@ -570,82 +622,51 @@
         native_drawRect(nativeCanvas, rect.left, rect.top, rect.right, rect.bottom, paint);
     }
 
-    /*package*/ static void native_drawRect(int nativeCanvas, float left,
-                                               float top, float right,
-                                               float bottom, int paint) {
-        // get the delegate from the native int.
-        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
-        if (canvasDelegate == null) {
-            assert false;
-            return;
-        }
+    /*package*/ static void native_drawRect(int nativeCanvas,
+            final float left, final float top, final float right, final float bottom, int paint) {
 
-        // get the delegate from the native int.
-        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
-        if (paintDelegate == null) {
-            assert false;
-            return;
-        }
+        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
+                new GcSnapshot.Drawable() {
+                    public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                        int style = paint.getStyle();
 
-        if (right > left && bottom > top) {
-            // get a Graphics2D object configured with the drawing parameters.
-            Graphics2D g = canvasDelegate.createCustomGraphics(paintDelegate);
+                        // draw
+                        if (style == Paint.Style.FILL.nativeInt ||
+                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
+                            graphics.fillRect((int)left, (int)top,
+                                    (int)(right-left), (int)(bottom-top));
+                        }
 
-            try {
-                int style = paintDelegate.getStyle();
-
-                // draw
-                if (style == Paint.Style.FILL.nativeInt ||
-                        style == Paint.Style.FILL_AND_STROKE.nativeInt) {
-                    g.fillRect((int)left, (int)top, (int)(right-left), (int)(bottom-top));
-                }
-
-                if (style == Paint.Style.STROKE.nativeInt ||
-                        style == Paint.Style.FILL_AND_STROKE.nativeInt) {
-                    g.drawRect((int)left, (int)top, (int)(right-left), (int)(bottom-top));
-                }
-            } finally {
-                // dispose Graphics2D object
-                g.dispose();
-            }
-        }
+                        if (style == Paint.Style.STROKE.nativeInt ||
+                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
+                            graphics.drawRect((int)left, (int)top,
+                                    (int)(right-left), (int)(bottom-top));
+                        }
+                    }
+        });
     }
 
-    /*package*/ static void native_drawOval(int nativeCanvas, RectF oval,
-                                               int paint) {
-        // get the delegate from the native int.
-        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
-        if (canvasDelegate == null) {
-            assert false;
-            return;
-        }
-
-        // get the delegate from the native int.
-        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
-        if (paintDelegate == null) {
-            assert false;
-            return;
-        }
-
+    /*package*/ static void native_drawOval(int nativeCanvas, final RectF oval, int paint) {
         if (oval.right > oval.left && oval.bottom > oval.top) {
-            // get a Graphics2D object configured with the drawing parameters.
-            Graphics2D g = canvasDelegate.createCustomGraphics(paintDelegate);
+            draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
+                    new GcSnapshot.Drawable() {
+                        public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                            int style = paint.getStyle();
 
-            int style = paintDelegate.getStyle();
+                            // draw
+                            if (style == Paint.Style.FILL.nativeInt ||
+                                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
+                                graphics.fillOval((int)oval.left, (int)oval.top,
+                                        (int)oval.width(), (int)oval.height());
+                            }
 
-            // draw
-            if (style == Paint.Style.FILL.nativeInt ||
-                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
-                g.fillOval((int)oval.left, (int)oval.top, (int)oval.width(), (int)oval.height());
-            }
-
-            if (style == Paint.Style.STROKE.nativeInt ||
-                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
-                g.drawOval((int)oval.left, (int)oval.top, (int)oval.width(), (int)oval.height());
-            }
-
-            // dispose Graphics2D object
-            g.dispose();
+                            if (style == Paint.Style.STROKE.nativeInt ||
+                                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
+                                graphics.drawOval((int)oval.left, (int)oval.top,
+                                        (int)oval.width(), (int)oval.height());
+                            }
+                        }
+            });
         }
     }
 
@@ -665,52 +686,57 @@
     }
 
     /*package*/ static void native_drawRoundRect(int nativeCanvas,
-                                                    RectF rect, float rx,
-                                                    float ry, int paint) {
-        // get the delegate from the native int.
-        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
-        if (canvasDelegate == null) {
-            assert false;
-            return;
-        }
+            final RectF rect, final float rx, final float ry, int paint) {
 
-        // get the delegate from the native int.
-        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
-        if (paintDelegate == null) {
-            assert false;
-            return;
-        }
+        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
+                new GcSnapshot.Drawable() {
+                    public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                        int style = paint.getStyle();
 
-        if (rect.right > rect.left && rect.bottom > rect.top) {
-            // get a Graphics2D object configured with the drawing parameters.
-            Graphics2D g = canvasDelegate.createCustomGraphics(paintDelegate);
+                        // draw
+                        if (style == Paint.Style.FILL.nativeInt ||
+                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
+                            graphics.fillRoundRect(
+                                    (int)rect.left, (int)rect.top,
+                                    (int)rect.width(), (int)rect.height(),
+                                    (int)rx, (int)ry);
+                        }
 
-            int style = paintDelegate.getStyle();
-
-            // draw
-            if (style == Paint.Style.FILL.nativeInt ||
-                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
-                g.fillRoundRect(
-                        (int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(),
-                        (int)rx, (int)ry);
-            }
-
-            if (style == Paint.Style.STROKE.nativeInt ||
-                    style == Paint.Style.FILL_AND_STROKE.nativeInt) {
-                g.drawRoundRect(
-                        (int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(),
-                        (int)rx, (int)ry);
-            }
-
-            // dispose Graphics2D object
-            g.dispose();
-        }
+                        if (style == Paint.Style.STROKE.nativeInt ||
+                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
+                            graphics.drawRoundRect(
+                                    (int)rect.left, (int)rect.top,
+                                    (int)rect.width(), (int)rect.height(),
+                                    (int)rx, (int)ry);
+                        }
+                    }
+        });
     }
 
     /*package*/ static void native_drawPath(int nativeCanvas, int path,
                                                int paint) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
+                new GcSnapshot.Drawable() {
+                    public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                        Shape shape = pathDelegate.getJavaShape();
+                        int style = paint.getStyle();
+
+                        if (style == Paint.Style.FILL.nativeInt ||
+                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
+                            graphics.fill(shape);
+                        }
+
+                        if (style == Paint.Style.STROKE.nativeInt ||
+                                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
+                            graphics.draw(shape);
+                        }
+                    }
+        });
     }
 
     /*package*/ static void native_drawBitmap(Canvas thisCanvas, int nativeCanvas, int bitmap,
@@ -719,8 +745,19 @@
                                                  int canvasDensity,
                                                  int screenDensity,
                                                  int bitmapDensity) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate from the native int.
+        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
+        if (bitmapDelegate == null) {
+            return;
+        }
+
+        BufferedImage image = bitmapDelegate.getImage();
+        float right = left + image.getWidth();
+        float bottom = top + image.getHeight();
+
+        drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
+                0, 0, image.getWidth(), image.getHeight(),
+                (int)left, (int)top, (int)right, (int)bottom);
     }
 
     /*package*/ static void native_drawBitmap(Canvas thisCanvas, int nativeCanvas, int bitmap,
@@ -731,18 +768,17 @@
         // get the delegate from the native int.
         Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
         if (bitmapDelegate == null) {
-            assert false;
             return;
         }
 
         BufferedImage image = bitmapDelegate.getImage();
 
         if (src == null) {
-            drawBitmap(nativeCanvas, image, nativePaintOrZero,
+            drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
                     0, 0, image.getWidth(), image.getHeight(),
                     (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom);
         } else {
-            drawBitmap(nativeCanvas, image, nativePaintOrZero,
+            drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
                     src.left, src.top, src.width(), src.height(),
                     (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom);
         }
@@ -756,36 +792,83 @@
         // get the delegate from the native int.
         Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
         if (bitmapDelegate == null) {
-            assert false;
             return;
         }
 
         BufferedImage image = bitmapDelegate.getImage();
 
         if (src == null) {
-            drawBitmap(nativeCanvas, image, nativePaintOrZero,
+            drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
                     0, 0, image.getWidth(), image.getHeight(),
                     dst.left, dst.top, dst.right, dst.bottom);
         } else {
-            drawBitmap(nativeCanvas, image, nativePaintOrZero,
+            drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
                     src.left, src.top, src.width(), src.height(),
                     dst.left, dst.top, dst.right, dst.bottom);
         }
     }
 
     /*package*/ static void native_drawBitmap(int nativeCanvas, int[] colors,
-                                                int offset, int stride, float x,
-                                                 float y, int width, int height,
+                                                int offset, int stride, final float x,
+                                                 final float y, int width, int height,
                                                  boolean hasAlpha,
                                                  int nativePaintOrZero) {
-        // FIXME
-        throw new UnsupportedOperationException();
+
+        // create a temp BufferedImage containing the content.
+        final BufferedImage image = new BufferedImage(width, height,
+                hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
+        image.setRGB(0, 0, width, height, colors, offset, stride);
+
+        draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, false /*forceSrcMode*/,
+                new GcSnapshot.Drawable() {
+                    public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                        if (paint != null && paint.isFilterBitmap()) {
+                            graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+                                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+                        }
+
+                        graphics.drawImage(image, (int) x, (int) y, null);
+                    }
+        });
     }
 
     /*package*/ static void nativeDrawBitmapMatrix(int nCanvas, int nBitmap,
                                                       int nMatrix, int nPaint) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate from the native int.
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
+        if (canvasDelegate == null) {
+            return;
+        }
+
+        // get the delegate from the native int, which can be null
+        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
+
+        // get the delegate from the native int.
+        Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nBitmap);
+        if (bitmapDelegate == null) {
+            return;
+        }
+
+        final BufferedImage image = getImageToDraw(bitmapDelegate, paintDelegate, sBoolOut);
+
+        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
+        if (matrixDelegate == null) {
+            return;
+        }
+
+        final AffineTransform mtx = matrixDelegate.getAffineTransform();
+
+        canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() {
+                public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                    if (paint != null && paint.isFilterBitmap()) {
+                        graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+                                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+                    }
+
+                    //FIXME add support for canvas, screen and bitmap densities.
+                    graphics.drawImage(image, mtx, null);
+                }
+        }, paintDelegate, true /*compositeOnly*/, false /*forceSrcMode*/);
     }
 
     /*package*/ static void nativeDrawBitmapMesh(int nCanvas, int nBitmap,
@@ -804,116 +887,103 @@
         throw new UnsupportedOperationException();
     }
 
-    /*package*/ static void native_drawText(int nativeCanvas, char[] text,
-                                               int index, int count, float x,
-                                               float y, int flags, int paint) {
-        // WARNING: the logic in this method is similar to Paint.measureText.
-        // Any change to this method should be reflected in Paint.measureText
-
-        // get the delegate from the native int.
-        Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
-        if (canvasDelegate == null) {
-            assert false;
-            return;
-        }
-
-        // get the delegate from the native int.
-        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
-        if (paintDelegate == null) {
-            assert false;
-            return;
-        }
-
-        Graphics2D g = (Graphics2D) canvasDelegate.createCustomGraphics(paintDelegate);
-        try {
-            // Paint.TextAlign indicates how the text is positioned relative to X.
-            // LEFT is the default and there's nothing to do.
-            if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) {
-                float m = paintDelegate.measureText(text, index, count);
-                if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) {
-                    x -= m / 2;
-                } else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
-                    x -= m;
-                }
-            }
-
-            List<FontInfo> fonts = paintDelegate.getFonts();
-
-            if (fonts.size() > 0) {
-                FontInfo mainFont = fonts.get(0);
-                int i = index;
-                int lastIndex = index + count;
-                while (i < lastIndex) {
-                    // always start with the main font.
-                    int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex);
-                    if (upTo == -1) {
-                        // draw all the rest and exit.
-                        g.setFont(mainFont.mFont);
-                        g.drawChars(text, i, lastIndex - i, (int)x, (int)y);
-                        return;
-                    } else if (upTo > 0) {
-                        // draw what's possible
-                        g.setFont(mainFont.mFont);
-                        g.drawChars(text, i, upTo - i, (int)x, (int)y);
-
-                        // compute the width that was drawn to increase x
-                        x += mainFont.mMetrics.charsWidth(text, i, upTo - i);
-
-                        // move index to the first non displayed char.
-                        i = upTo;
-
-                        // don't call continue at this point. Since it is certain the main font
-                        // cannot display the font a index upTo (now ==i), we move on to the
-                        // fallback fonts directly.
+    /*package*/ static void native_drawText(int nativeCanvas,
+            final char[] text, final int index, final int count,
+            final float startX, final float startY, int flags, int paint) {
+        draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
+                new GcSnapshot.Drawable() {
+            public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                // WARNING: the logic in this method is similar to Paint.measureText.
+                // Any change to this method should be reflected in Paint.measureText
+                // Paint.TextAlign indicates how the text is positioned relative to X.
+                // LEFT is the default and there's nothing to do.
+                float x = startX;
+                float y = startY;
+                if (paint.getTextAlign() != Paint.Align.LEFT.nativeInt) {
+                    float m = paint.measureText(text, index, count);
+                    if (paint.getTextAlign() == Paint.Align.CENTER.nativeInt) {
+                        x -= m / 2;
+                    } else if (paint.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
+                        x -= m;
                     }
+                }
 
-                    // no char supported, attempt to read the next char(s) with the
-                    // fallback font. In this case we only test the first character
-                    // and then go back to test with the main font.
-                    // Special test for 2-char characters.
-                    boolean foundFont = false;
-                    for (int f = 1 ; f < fonts.size() ; f++) {
-                        FontInfo fontInfo = fonts.get(f);
+                List<FontInfo> fonts = paint.getFonts();
 
-                        // need to check that the font can display the character. We test
-                        // differently if the char is a high surrogate.
-                        int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
-                        upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount);
+                if (fonts.size() > 0) {
+                    FontInfo mainFont = fonts.get(0);
+                    int i = index;
+                    int lastIndex = index + count;
+                    while (i < lastIndex) {
+                        // always start with the main font.
+                        int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex);
                         if (upTo == -1) {
-                            // draw that char
-                            g.setFont(fontInfo.mFont);
-                            g.drawChars(text, i, charCount, (int)x, (int)y);
+                            // draw all the rest and exit.
+                            graphics.setFont(mainFont.mFont);
+                            graphics.drawChars(text, i, lastIndex - i, (int)x, (int)y);
+                            return;
+                        } else if (upTo > 0) {
+                            // draw what's possible
+                            graphics.setFont(mainFont.mFont);
+                            graphics.drawChars(text, i, upTo - i, (int)x, (int)y);
 
-                            // update x
-                            x += fontInfo.mMetrics.charsWidth(text, i, charCount);
+                            // compute the width that was drawn to increase x
+                            x += mainFont.mMetrics.charsWidth(text, i, upTo - i);
 
-                            // update the index in the text, and move on
+                            // move index to the first non displayed char.
+                            i = upTo;
+
+                            // don't call continue at this point. Since it is certain the main font
+                            // cannot display the font a index upTo (now ==i), we move on to the
+                            // fallback fonts directly.
+                        }
+
+                        // no char supported, attempt to read the next char(s) with the
+                        // fallback font. In this case we only test the first character
+                        // and then go back to test with the main font.
+                        // Special test for 2-char characters.
+                        boolean foundFont = false;
+                        for (int f = 1 ; f < fonts.size() ; f++) {
+                            FontInfo fontInfo = fonts.get(f);
+
+                            // need to check that the font can display the character. We test
+                            // differently if the char is a high surrogate.
+                            int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
+                            upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount);
+                            if (upTo == -1) {
+                                // draw that char
+                                graphics.setFont(fontInfo.mFont);
+                                graphics.drawChars(text, i, charCount, (int)x, (int)y);
+
+                                // update x
+                                x += fontInfo.mMetrics.charsWidth(text, i, charCount);
+
+                                // update the index in the text, and move on
+                                i += charCount;
+                                foundFont = true;
+                                break;
+
+                            }
+                        }
+
+                        // in case no font can display the char, display it with the main font.
+                        // (it'll put a square probably)
+                        if (foundFont == false) {
+                            int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
+
+                            graphics.setFont(mainFont.mFont);
+                            graphics.drawChars(text, i, charCount, (int)x, (int)y);
+
+                            // measure it to advance x
+                            x += mainFont.mMetrics.charsWidth(text, i, charCount);
+
+                            // and move to the next chars.
                             i += charCount;
-                            foundFont = true;
-                            break;
-
                         }
                     }
-
-                    // in case no font can display the char, display it with the main font.
-                    // (it'll put a square probably)
-                    if (foundFont == false) {
-                        int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
-
-                        g.setFont(mainFont.mFont);
-                        g.drawChars(text, i, charCount, (int)x, (int)y);
-
-                        // measure it to advance x
-                        x += mainFont.mMetrics.charsWidth(text, i, charCount);
-
-                        // and move to the next chars.
-                        i += charCount;
-                    }
                 }
             }
-        } finally {
-            g.dispose();
-        }
+        });
     }
 
     /*package*/ static void native_drawText(int nativeCanvas, String text,
@@ -939,7 +1009,7 @@
     /*package*/ static void native_drawTextRun(int nativeCanvas, char[] text,
             int start, int count, int contextStart, int contextCount,
             float x, float y, int flags, int paint) {
-        native_drawText(nativeCanvas, text, 0, count, x, y, flags, paint);
+        native_drawText(nativeCanvas, text, start, count, x, y, flags, paint);
     }
 
     /*package*/ static void native_drawPosText(int nativeCanvas,
@@ -986,7 +1056,6 @@
         // get the delegate from the native int so that it can be disposed.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return;
         }
 
@@ -998,11 +1067,47 @@
 
     // ---- Private delegate/helper methods ----
 
-    private Canvas_Delegate(BufferedImage image) {
-        setBitmap(image);
+    /**
+     * Executes a {@link GcSnapshot.Drawable} with a given canvas and paint.
+     * <p>Note that the drawable may actually be executed several times if there are
+     * layers involved (see {@link #saveLayer(RectF, int, int)}.
+     */
+    private static void draw(int nCanvas, int nPaint, boolean compositeOnly, boolean forceSrcMode,
+            GcSnapshot.Drawable drawable) {
+        // get the delegate from the native int.
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
+        if (canvasDelegate == null) {
+            return;
+        }
+
+        // get the paint which can be null if nPaint is 0;
+        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
+
+        canvasDelegate.getSnapshot().draw(drawable, paintDelegate, compositeOnly, forceSrcMode);
+    }
+
+    /**
+     * Executes a {@link GcSnapshot.Drawable} with a given canvas. No paint object will be provided
+     * to {@link GcSnapshot.Drawable#draw(Graphics2D, Paint_Delegate)}.
+     * <p>Note that the drawable may actually be executed several times if there are
+     * layers involved (see {@link #saveLayer(RectF, int, int)}.
+     */
+    private static void draw(int nCanvas, GcSnapshot.Drawable drawable) {
+        // get the delegate from the native int.
+        Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
+        if (canvasDelegate == null) {
+            return;
+        }
+
+        canvasDelegate.mSnapshot.draw(drawable);
+    }
+
+    private Canvas_Delegate(Bitmap_Delegate bitmap) {
+        mSnapshot = GcSnapshot.createDefaultSnapshot(mBitmap = bitmap);
     }
 
     private Canvas_Delegate() {
+        mSnapshot = GcSnapshot.createDefaultSnapshot(null /*image*/);
     }
 
     /**
@@ -1016,8 +1121,23 @@
         // get the current save count
         int count = mSnapshot.size();
 
-        // create a new snapshot and add it to the stack
-        mSnapshot = new GcSnapshot(mSnapshot, saveFlags);
+        mSnapshot = mSnapshot.save(saveFlags);
+
+        // return the old save count
+        return count;
+    }
+
+    private int saveLayerAlpha(RectF rect, int alpha, int saveFlags) {
+        Paint_Delegate paint = new Paint_Delegate();
+        paint.setAlpha(alpha);
+        return saveLayer(rect, paint, saveFlags);
+    }
+
+    private int saveLayer(RectF rect, Paint_Delegate paint, int saveFlags) {
+        // get the current save count
+        int count = mSnapshot.size();
+
+        mSnapshot = mSnapshot.saveLayer(rect, paint, saveFlags);
 
         // return the old save count
         return count;
@@ -1043,204 +1163,103 @@
         return mSnapshot.clipRect(left, top, right, bottom, regionOp);
     }
 
-    private void setBitmap(BufferedImage image) {
-        mBufferedImage = image;
+    private void setBitmap(Bitmap_Delegate bitmap) {
+        mBitmap = bitmap;
         assert mSnapshot.size() == 1;
-        mSnapshot.setGraphics2D(mBufferedImage.createGraphics());
+        mSnapshot.setBitmap(mBitmap);
     }
 
-    /**
-     * Creates a new {@link Graphics2D} based on the {@link Paint} parameters.
-     * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used.
-     */
-    /*package*/ Graphics2D createCustomGraphics(Paint_Delegate paint) {
-        // make new one
-        Graphics2D g = getGcSnapshot().create();
-
-        // configure it
-
-        if (paint.isAntiAliased()) {
-            g.setRenderingHint(
-                    RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-            g.setRenderingHint(
-                    RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
-        }
-
-        boolean useColorPaint = true;
-
-        // get the shader first, as it'll replace the color if it can be used it.
-        Shader_Delegate shaderDelegate = Shader_Delegate.getDelegate(paint.getShader());
-        if (shaderDelegate != null) {
-            java.awt.Paint shaderPaint = shaderDelegate.getJavaPaint();
-            assert shaderPaint != null;
-            if (shaderPaint != null) {
-                g.setPaint(shaderPaint);
-                useColorPaint = false;
-            } else {
-                Bridge.getLog().warning(null,
-                        String.format(
-                            "Shader '%1$s' is not supported in the Layout Preview.",
-                            shaderDelegate.getClass().getCanonicalName()));
-            }
-        }
-
-        if (useColorPaint) {
-            g.setColor(new Color(paint.getColor(), true /*hasAlpha*/));
-        }
-
-        int style = paint.getStyle();
-        if (style == Paint.Style.STROKE.nativeInt ||
-                style == Paint.Style.FILL_AND_STROKE.nativeInt) {
-
-            PathEffect_Delegate effectDelegate = PathEffect_Delegate.getDelegate(
-                    paint.getPathEffect());
-
-            if (effectDelegate instanceof DashPathEffect_Delegate) {
-                DashPathEffect_Delegate dpe = (DashPathEffect_Delegate)effectDelegate;
-                g.setStroke(new BasicStroke(
-                        paint.getStrokeWidth(),
-                        paint.getJavaCap(),
-                        paint.getJavaJoin(),
-                        paint.getStrokeMiter(),
-                        dpe.getIntervals(),
-                        dpe.getPhase()));
-            } else {
-                g.setStroke(new BasicStroke(
-                        paint.getStrokeWidth(),
-                        paint.getJavaCap(),
-                        paint.getJavaJoin(),
-                        paint.getStrokeMiter()));
-            }
-        }
-
-        Xfermode_Delegate xfermodeDelegate = Xfermode_Delegate.getDelegate(paint.getXfermode());
-        if (xfermodeDelegate instanceof PorterDuffXfermode_Delegate) {
-            int mode = ((PorterDuffXfermode_Delegate)xfermodeDelegate).getMode();
-
-            setModeInGraphics(g, mode);
-        } else {
-            // default mode is src_over
-            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
-
-            // if xfermode wasn't null, then it's something we don't support. log it.
-            if (xfermodeDelegate != null) {
-                assert false;
-                Bridge.getLog().warning(null,
-                        String.format(
-                            "Xfermode '%1$s' is not supported in the Layout Preview.",
-                            xfermodeDelegate.getClass().getCanonicalName()));
-            }
-        }
-
-        return g;
-    }
-
-    private static void setModeInGraphics(Graphics2D g, int mode) {
-        for (PorterDuff.Mode m : PorterDuff.Mode.values()) {
-            if (m.nativeInt == mode) {
-                setModeInGraphics(g, m);
-                return;
-            }
-        }
-    }
-
-    private static void setModeInGraphics(Graphics2D g, PorterDuff.Mode mode) {
-        switch (mode) {
-            case CLEAR:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 1.0f /*alpha*/));
-                break;
-            case DARKEN:
-                break;
-            case DST:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST, 1.0f /*alpha*/));
-                break;
-            case DST_ATOP:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, 1.0f /*alpha*/));
-                break;
-            case DST_IN:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN, 1.0f /*alpha*/));
-                break;
-            case DST_OUT:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT, 1.0f /*alpha*/));
-                break;
-            case DST_OVER:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, 1.0f /*alpha*/));
-                break;
-            case LIGHTEN:
-                break;
-            case MULTIPLY:
-                break;
-            case SCREEN:
-                break;
-            case SRC:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 1.0f /*alpha*/));
-                break;
-            case SRC_ATOP:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0f /*alpha*/));
-                break;
-            case SRC_IN:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, 1.0f /*alpha*/));
-                break;
-            case SRC_OUT:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT, 1.0f /*alpha*/));
-                break;
-            case SRC_OVER:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f /*alpha*/));
-                break;
-            case XOR:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.XOR, 1.0f /*alpha*/));
-                break;
-        }
-    }
-
-
     private static void drawBitmap(
             int nativeCanvas,
-            BufferedImage image,
+            Bitmap_Delegate bitmap,
             int nativePaintOrZero,
-            int sleft, int stop, int sright, int sbottom,
-            int dleft, int dtop, int dright, int dbottom) {
+            final int sleft, final int stop, final int sright, final int sbottom,
+            final int dleft, final int dtop, final int dright, final int dbottom) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
         if (canvasDelegate == null) {
-            assert false;
             return;
         }
 
-        // get the delegate from the native int.
-        Paint_Delegate paintDelegate = null;
-        if (nativePaintOrZero > 0) {
-            paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
-            if (paintDelegate == null) {
-                assert false;
-                return;
-            }
-        }
+        // get the paint, which could be null if the int is 0
+        Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
 
-        drawBitmap(canvasDelegate, image, paintDelegate,
-                sleft, stop, sright, sbottom,
-                dleft, dtop, dright, dbottom);
+        final BufferedImage image = getImageToDraw(bitmap, paintDelegate, sBoolOut);
+
+        draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, sBoolOut[0],
+                new GcSnapshot.Drawable() {
+                    public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                        if (paint != null && paint.isFilterBitmap()) {
+                            graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+                                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+                        }
+
+                        //FIXME add support for canvas, screen and bitmap densities.
+                        graphics.drawImage(image, dleft, dtop, dright, dbottom,
+                                sleft, stop, sright, sbottom, null);
+                    }
+        });
     }
 
-    private static void drawBitmap(
-            Canvas_Delegate canvasDelegate,
-            BufferedImage image,
-            Paint_Delegate paintDelegate,
-            int sleft, int stop, int sright, int sbottom,
-            int dleft, int dtop, int dright, int dbottom) {
 
-        Graphics2D g = canvasDelegate.getGcSnapshot().create();
-        try {
-            if (paintDelegate != null && paintDelegate.isFilterBitmap()) {
-                g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
-                        RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+    /**
+     * Returns a BufferedImage ready for drawing, based on the bitmap and paint delegate.
+     * The image returns, through a 1-size boolean array, whether the drawing code should
+     * use a SRC composite no matter what the paint says.
+     *
+     * @param bitmap the bitmap
+     * @param paint the paint that will be used to draw
+     * @param forceSrcMode whether the composite will have to be SRC
+     * @return the image to draw
+     */
+    private static BufferedImage getImageToDraw(Bitmap_Delegate bitmap, Paint_Delegate paint,
+            boolean[] forceSrcMode) {
+        BufferedImage image = bitmap.getImage();
+        forceSrcMode[0] = false;
+
+        // if the bitmap config is alpha_8, then we erase all color value from it
+        // before drawing it.
+        if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) {
+            fixAlpha8Bitmap(image);
+        } else if (bitmap.hasAlpha() == false) {
+            // hasAlpha is merely a rendering hint. There can in fact be alpha values
+            // in the bitmap but it should be ignored at drawing time.
+            // There is two ways to do this:
+            // - override the composite to be SRC. This can only be used if the composite
+            //   was going to be SRC or SRC_OVER in the first place
+            // - Create a different bitmap to draw in which all the alpha channel values is set
+            //   to 0xFF.
+            if (paint != null) {
+                Xfermode_Delegate xfermodeDelegate = paint.getXfermode();
+                if (xfermodeDelegate instanceof PorterDuffXfermode_Delegate) {
+                    PorterDuff.Mode mode =
+                        ((PorterDuffXfermode_Delegate)xfermodeDelegate).getMode();
+
+                    forceSrcMode[0] = mode == PorterDuff.Mode.SRC_OVER ||
+                            mode == PorterDuff.Mode.SRC;
+                }
             }
 
-            g.drawImage(image, dleft, dtop, dright, dbottom,
-                    sleft, stop, sright, sbottom, null);
-        } finally {
-            g.dispose();
+            // if we can't force SRC mode, then create a temp bitmap of TYPE_RGB
+            if (forceSrcMode[0] == false) {
+                image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF);
+            }
         }
+
+        return image;
+    }
+
+    private static void fixAlpha8Bitmap(final BufferedImage image) {
+        int w = image.getWidth();
+        int h = image.getHeight();
+        int[] argb = new int[w * h];
+        image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
+
+        final int length = argb.length;
+        for (int i = 0 ; i < length; i++) {
+            argb[i] &= 0xFF000000;
+        }
+        image.setRGB(0, 0, w, h, argb, 0, w);
     }
 }
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
new file mode 100644
index 0000000..3df170f
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.graphics.ColorFilter
+ *
+ * Through the layoutlib_create tool, the original native methods of ColorFilter have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original ColorFilter class.
+ *
+ * This also serve as a base class for all ColorFilter delegate classes.
+ *
+ * @see DelegateManager
+ *
+ */
+public abstract class ColorFilter_Delegate {
+
+    // ---- delegate manager ----
+    protected static final DelegateManager<ColorFilter_Delegate> sManager =
+            new DelegateManager<ColorFilter_Delegate>();
+
+    // ---- delegate helper data ----
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    public static ColorFilter_Delegate getDelegate(int nativeShader) {
+        return sManager.getDelegate(nativeShader);
+    }
+
+    public abstract boolean isSupported();
+    public abstract String getSupportMessage();
+
+    // ---- native methods ----
+
+    /*package*/ static void finalizer(int native_instance, int nativeColorFilter) {
+        sManager.removeDelegate(native_instance);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java
new file mode 100644
index 0000000..42843279
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.graphics.ColorMatrixColorFilter
+ *
+ * Through the layoutlib_create tool, the original native methods of ColorMatrixColorFilter have
+ * been replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original ColorMatrixColorFilter class.
+ *
+ * Because this extends {@link ColorFilter_Delegate}, there's no need to use a
+ * {@link DelegateManager}, as all the Shader classes will be added to the manager
+ * owned by {@link ColorFilter_Delegate}.
+ *
+ * @see ColorFilter_Delegate
+ *
+ */
+public class ColorMatrixColorFilter_Delegate extends ColorFilter_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "ColorMatrix Color Filters are not supported.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeColorMatrixFilter(float[] array) {
+        ColorMatrixColorFilter_Delegate newDelegate = new ColorMatrixColorFilter_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    /*package*/ static int nColorMatrixFilter(int nativeFilter, float[] array) {
+        // pass
+        return 0;
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java
new file mode 100644
index 0000000..39cbbc6
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+import java.awt.Stroke;
+
+/**
+ * Delegate implementing the native methods of android.graphics.ComposePathEffect
+ *
+ * Through the layoutlib_create tool, the original native methods of ComposePathEffect have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original ComposePathEffect class.
+ *
+ * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager},
+ * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}.
+ *
+ * @see PathEffect_Delegate
+ *
+ */
+public class ComposePathEffect_Delegate extends PathEffect_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public Stroke getStroke(Paint_Delegate paint) {
+        // FIXME
+        return null;
+    }
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Compose Path Effects are not supported in Layout Preview mode.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeCreate(int outerpe, int innerpe) {
+        ComposePathEffect_Delegate newDelegate = new ComposePathEffect_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java
new file mode 100644
index 0000000..b4baa6f
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+import java.awt.Paint;
+
+/**
+ * Delegate implementing the native methods of android.graphics.ComposeShader
+ *
+ * Through the layoutlib_create tool, the original native methods of ComposeShader have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original ComposeShader class.
+ *
+ * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager},
+ * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}.
+ *
+ * @see Shader_Delegate
+ *
+ */
+public class ComposeShader_Delegate extends Shader_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public Paint getJavaPaint() {
+        // FIXME
+        return null;
+    }
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Compose Shaders are not supported in Layout Preview mode.";
+    }
+
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeCreate1(int native_shaderA, int native_shaderB,
+            int native_mode) {
+        // FIXME not supported yet.
+        ComposeShader_Delegate newDelegate = new ComposeShader_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    /*package*/ static int nativeCreate2(int native_shaderA, int native_shaderB,
+            int porterDuffMode) {
+        // FIXME not supported yet.
+        ComposeShader_Delegate newDelegate = new ComposeShader_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    /*package*/ static int nativePostCreate1(int native_shader, int native_skiaShaderA,
+            int native_skiaShaderB, int native_mode) {
+        // pass, not needed.
+        return 0;
+    }
+
+    /*package*/ static int nativePostCreate2(int native_shader, int native_skiaShaderA,
+            int native_skiaShaderB, int porterDuffMode) {
+        // pass, not needed.
+        return 0;
+    }
+
+
+    // ---- Private delegate/helper methods ----
+
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java
new file mode 100644
index 0000000..0307cfb
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+import java.awt.Stroke;
+
+/**
+ * Delegate implementing the native methods of android.graphics.CornerPathEffect
+ *
+ * Through the layoutlib_create tool, the original native methods of CornerPathEffect have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original CornerPathEffect class.
+ *
+ * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager},
+ * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}.
+ *
+ * @see PathEffect_Delegate
+ *
+ */
+public class CornerPathEffect_Delegate extends PathEffect_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public Stroke getStroke(Paint_Delegate paint) {
+        // FIXME
+        return null;
+    }
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Corner Path Effects are not supported in Layout Preview mode.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeCreate(float radius) {
+        CornerPathEffect_Delegate newDelegate = new CornerPathEffect_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
index 7ee72d8..5a704a7 100644
--- a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
@@ -18,6 +18,9 @@
 
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
+import java.awt.BasicStroke;
+import java.awt.Stroke;
+
 /**
  * Delegate implementing the native methods of android.graphics.DashPathEffect
  *
@@ -32,8 +35,10 @@
  * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by
  * {@link PathEffect_Delegate}.
  *
+ * @see PathEffect_Delegate
+ *
  */
-public class DashPathEffect_Delegate extends PathEffect_Delegate {
+public final class DashPathEffect_Delegate extends PathEffect_Delegate {
 
     // ---- delegate data ----
 
@@ -42,12 +47,26 @@
 
     // ---- Public Helper methods ----
 
-    public float[] getIntervals() {
-        return mIntervals;
+    @Override
+    public Stroke getStroke(Paint_Delegate paint) {
+        return new BasicStroke(
+                paint.getStrokeWidth(),
+                paint.getJavaCap(),
+                paint.getJavaJoin(),
+                paint.getJavaStrokeMiter(),
+                mIntervals,
+                mPhase);
     }
 
-    public float getPhase() {
-        return mPhase;
+    @Override
+    public boolean isSupported() {
+        return true;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        // no message since isSupported returns true;
+        return null;
     }
 
     // ---- native methods ----
diff --git a/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java
new file mode 100644
index 0000000..04d7170
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+import java.awt.Stroke;
+
+/**
+ * Delegate implementing the native methods of android.graphics.DiscretePathEffect
+ *
+ * Through the layoutlib_create tool, the original native methods of DiscretePathEffect have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original DiscretePathEffect class.
+ *
+ * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager},
+ * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}.
+ *
+ * @see PathEffect_Delegate
+ *
+ */
+public class DiscretePathEffect_Delegate extends PathEffect_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public Stroke getStroke(Paint_Delegate paint) {
+        // FIXME
+        return null;
+    }
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Discrete Path Effects are not supported in Layout Preview mode.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeCreate(float length, float deviation) {
+        DiscretePathEffect_Delegate newDelegate = new DiscretePathEffect_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java
new file mode 100644
index 0000000..ddf20b6
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.graphics.DrawFilter
+ *
+ * Through the layoutlib_create tool, the original native methods of DrawFilter have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original DrawFilter class.
+ *
+ * This also serve as a base class for all DrawFilter delegate classes.
+ *
+ * @see DelegateManager
+ *
+ */
+public abstract class DrawFilter_Delegate {
+
+    // ---- delegate manager ----
+    protected static final DelegateManager<DrawFilter_Delegate> sManager =
+            new DelegateManager<DrawFilter_Delegate>();
+
+    // ---- delegate helper data ----
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    public static DrawFilter_Delegate getDelegate(int nativeDrawFilter) {
+        return sManager.getDelegate(nativeDrawFilter);
+    }
+
+    public abstract boolean isSupported();
+    public abstract String getSupportMessage();
+
+    // ---- native methods ----
+
+    /*package*/ static void nativeDestructor(int nativeDrawFilter) {
+        sManager.removeDelegate(nativeDrawFilter);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java
new file mode 100644
index 0000000..82f1da3
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.graphics.EmbossMaskFilter
+ *
+ * Through the layoutlib_create tool, the original native methods of EmbossMaskFilter have
+ * been replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original EmbossMaskFilter class.
+ *
+ * Because this extends {@link MaskFilter_Delegate}, there's no need to use a
+ * {@link DelegateManager}, as all the Shader classes will be added to the manager
+ * owned by {@link MaskFilter_Delegate}.
+ *
+ * @see MaskFilter_Delegate
+ *
+ */
+public class EmbossMaskFilter_Delegate extends MaskFilter_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Emboss Mask Filters are not supported.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeConstructor(float[] direction, float ambient,
+            float specular, float blurRadius) {
+        EmbossMaskFilter_Delegate newDelegate = new EmbossMaskFilter_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java
index bc4ccd2..7a0c2f7 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java
@@ -26,6 +26,18 @@
     protected final int[] mColors;
     protected final float[] mPositions;
 
+    @Override
+    public boolean isSupported() {
+        // all gradient shaders are supported.
+        return true;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        // all gradient shaders are supported, no need for a gradient support
+        return null;
+    }
+
     /**
      * Creates the base shader and do some basic test on the parameters.
      *
diff --git a/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java
new file mode 100644
index 0000000..132004f9
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/LayerRasterizer_Delegate.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.graphics.LayerRasterizer
+ *
+ * Through the layoutlib_create tool, the original native methods of LayerRasterizer have
+ * been replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original LayerRasterizer class.
+ *
+ * Because this extends {@link Rasterizer_Delegate}, there's no need to use a
+ * {@link DelegateManager}, as all the Shader classes will be added to the manager
+ * owned by {@link Rasterizer_Delegate}.
+ *
+ * @see Rasterizer_Delegate
+ *
+ */
+public class LayerRasterizer_Delegate extends Rasterizer_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Layer Rasterizers are not supported.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeConstructor() {
+        LayerRasterizer_Delegate newDelegate = new LayerRasterizer_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    /*package*/ static void nativeAddLayer(int native_layer, int native_paint, float dx, float dy) {
+
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java
new file mode 100644
index 0000000..ba2cfad
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.graphics.LightingColorFilter
+ *
+ * Through the layoutlib_create tool, the original native methods of LightingColorFilter have
+ * been replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original LightingColorFilter class.
+ *
+ * Because this extends {@link ColorFilter_Delegate}, there's no need to use a
+ * {@link DelegateManager}, as all the Shader classes will be added to the manager
+ * owned by {@link ColorFilter_Delegate}.
+ *
+ * @see ColorFilter_Delegate
+ *
+ */
+public class LightingColorFilter_Delegate extends ColorFilter_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Lighting Color Filters are not supported.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int native_CreateLightingFilter(int mul, int add) {
+        LightingColorFilter_Delegate newDelegate = new LightingColorFilter_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    /*package*/ static int nCreateLightingFilter(int nativeFilter, int mul, int add) {
+        // pass
+        return 0;
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
index 862b4544..9525dcf 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
@@ -16,15 +16,12 @@
 
 package android.graphics;
 
+import com.android.ide.common.rendering.api.LayoutLog;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Shader.TileMode;
 
-import java.awt.Paint;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-
 /**
  * Delegate implementing the native methods of android.graphics.LinearGradient
  *
@@ -41,7 +38,7 @@
  * @see Shader_Delegate
  *
  */
-public class LinearGradient_Delegate extends Gradient_Delegate {
+public final class LinearGradient_Delegate extends Gradient_Delegate {
 
     // ---- delegate data ----
     private java.awt.Paint mJavaPaint;
@@ -49,7 +46,7 @@
     // ---- Public Helper methods ----
 
     @Override
-    public Paint getJavaPaint() {
+    public java.awt.Paint getJavaPaint() {
         return mJavaPaint;
     }
 
@@ -58,17 +55,8 @@
     /*package*/ static int nativeCreate1(LinearGradient thisGradient,
             float x0, float y0, float x1, float y1,
             int colors[], float positions[], int tileMode) {
-        // figure out the tile
-        TileMode tile = null;
-        for (TileMode tm : TileMode.values()) {
-            if (tm.nativeInt == tileMode) {
-                tile = tm;
-                break;
-            }
-        }
-
         LinearGradient_Delegate newDelegate = new LinearGradient_Delegate(x0, y0, x1, y1,
-                colors, positions, tile);
+                colors, positions, Shader_Delegate.getTileMode(tileMode));
         return sManager.addDelegate(newDelegate);
     }
     /*package*/ static int nativeCreate2(LinearGradient thisGradient,
@@ -144,20 +132,22 @@
                 java.awt.RenderingHints        hints) {
             precomputeGradientColors();
 
-            AffineTransform canvasMatrix;
+            java.awt.geom.AffineTransform canvasMatrix;
             try {
                 canvasMatrix = xform.createInverse();
-            } catch (NoninvertibleTransformException e) {
-                Bridge.getLog().error(null, "Unable to inverse matrix in LinearGradient", e);
-                canvasMatrix = new AffineTransform();
+            } catch (java.awt.geom.NoninvertibleTransformException e) {
+                Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
+                        "Unable to inverse matrix in LinearGradient", e, null /*data*/);
+                canvasMatrix = new java.awt.geom.AffineTransform();
             }
 
-            AffineTransform localMatrix = getLocalMatrix();
+            java.awt.geom.AffineTransform localMatrix = getLocalMatrix();
             try {
                 localMatrix = localMatrix.createInverse();
-            } catch (NoninvertibleTransformException e) {
-                Bridge.getLog().error(null, "Unable to inverse matrix in LinearGradient", e);
-                localMatrix = new AffineTransform();
+            } catch (java.awt.geom.NoninvertibleTransformException e) {
+                Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
+                        "Unable to inverse matrix in LinearGradient", e, null /*data*/);
+                localMatrix = new java.awt.geom.AffineTransform();
             }
 
             return new LinearGradientPaintContext(canvasMatrix, localMatrix, colorModel);
@@ -165,12 +155,14 @@
 
         private class LinearGradientPaintContext implements java.awt.PaintContext {
 
-            private final AffineTransform mCanvasMatrix;
-            private final AffineTransform mLocalMatrix;
+            private final java.awt.geom.AffineTransform mCanvasMatrix;
+            private final java.awt.geom.AffineTransform mLocalMatrix;
             private final java.awt.image.ColorModel mColorModel;
 
-            public LinearGradientPaintContext(AffineTransform canvasMatrix,
-                    AffineTransform localMatrix, java.awt.image.ColorModel colorModel) {
+            private LinearGradientPaintContext(
+                    java.awt.geom.AffineTransform canvasMatrix,
+                    java.awt.geom.AffineTransform localMatrix,
+                    java.awt.image.ColorModel colorModel) {
                 mCanvasMatrix = canvasMatrix;
                 mLocalMatrix = localMatrix;
                 mColorModel = colorModel;
@@ -218,10 +210,17 @@
          * Returns a color for an arbitrary point.
          */
         private int getColor(float x, float y) {
-            // find the x position on the gradient vector.
-            float _x = (mDx*mDy*(y-mY0) + mDy*mDy*mX0 + mDx*mDx*x) / mDSize2;
-            // from it get the position relative to the vector
-            float pos = (float) ((_x - mX0) / mDx);
+            float pos;
+            if (mDx == 0) {
+                pos = (y - mY0) / mDy;
+            } else if (mDy == 0) {
+                pos = (x - mX0) / mDx;
+            } else {
+                // find the x position on the gradient vector.
+                float _x = (mDx*mDy*(y-mY0) + mDy*mDy*mX0 + mDx*mDx*x) / mDSize2;
+                // from it get the position relative to the vector
+                pos = (_x - mX0) / mDx;
+            }
 
             return getGradientColor(pos);
         }
diff --git a/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java
new file mode 100644
index 0000000..c582a91
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.graphics.MaskFilter
+ *
+ * Through the layoutlib_create tool, the original native methods of MaskFilter have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original MaskFilter class.
+ *
+ * This also serve as a base class for all MaskFilter delegate classes.
+ *
+ * @see DelegateManager
+ *
+ */
+public abstract class MaskFilter_Delegate {
+
+    // ---- delegate manager ----
+    protected static final DelegateManager<MaskFilter_Delegate> sManager =
+            new DelegateManager<MaskFilter_Delegate>();
+
+    // ---- delegate helper data ----
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    public static MaskFilter_Delegate getDelegate(int nativeShader) {
+        return sManager.getDelegate(nativeShader);
+    }
+
+    public abstract boolean isSupported();
+    public abstract String getSupportMessage();
+
+    // ---- native methods ----
+
+    /*package*/ static void nativeDestructor(int native_filter) {
+        sManager.removeDelegate(native_filter);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index b464f66..2d77d40 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -17,6 +17,8 @@
 package android.graphics;
 
 
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Matrix.ScaleToFit;
@@ -60,7 +62,6 @@
     public static AffineTransform getAffineTransform(Matrix m) {
         Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
         if (delegate == null) {
-            assert false;
             return null;
         }
 
@@ -70,7 +71,6 @@
     public static boolean hasPerspective(Matrix m) {
         Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
         if (delegate == null) {
-            assert false;
             return false;
         }
 
@@ -85,6 +85,14 @@
     }
 
     /**
+     * Sets the content of the matrix with the content of another matrix represented as an array
+     * of values.
+     */
+    public void set(float[] values) {
+        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
+    }
+
+    /**
      * Resets the matrix to be the identity matrix.
      */
     public void reset() {
@@ -106,6 +114,49 @@
         return true;
     }
 
+    public static float[] makeValues(AffineTransform matrix) {
+        float[] values = new float[MATRIX_SIZE];
+        values[0] = (float) matrix.getScaleX();
+        values[1] = (float) matrix.getShearX();
+        values[2] = (float) matrix.getTranslateX();
+        values[3] = (float) matrix.getShearY();
+        values[4] = (float) matrix.getScaleY();
+        values[5] = (float) matrix.getTranslateY();
+        values[6] = 0.f;
+        values[7] = 0.f;
+        values[8] = 1.f;
+
+        return values;
+    }
+
+    public static Matrix_Delegate make(AffineTransform matrix) {
+        return new Matrix_Delegate(makeValues(matrix));
+    }
+
+    public boolean mapRect(RectF dst, RectF src) {
+        // array with 4 corners
+        float[] corners = new float[] {
+                src.left, src.top,
+                src.right, src.top,
+                src.right, src.bottom,
+                src.left, src.bottom,
+        };
+
+        // apply the transform to them.
+        mapPoints(corners);
+
+        // now put the result in the rect. We take the min/max of Xs and min/max of Ys
+        dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
+        dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
+
+        dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
+        dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
+
+
+        return (computeTypeMask() & kRectStaysRect_Mask) != 0;
+    }
+
+
     /**
      * Returns an {@link AffineTransform} matching the matrix.
      */
@@ -142,7 +193,6 @@
     /*package*/ static boolean native_isIdentity(int native_object) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -152,7 +202,6 @@
     /*package*/ static boolean native_rectStaysRect(int native_object) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return true;
         }
 
@@ -162,7 +211,6 @@
     /*package*/ static void native_reset(int native_object) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
@@ -172,13 +220,11 @@
     /*package*/ static void native_set(int native_object, int other) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
         Matrix_Delegate src = sManager.getDelegate(other);
         if (src == null) {
-            assert false;
             return;
         }
 
@@ -188,7 +234,6 @@
     /*package*/ static void native_setTranslate(int native_object, float dx, float dy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
@@ -199,7 +244,6 @@
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
@@ -209,7 +253,6 @@
     /*package*/ static void native_setScale(int native_object, float sx, float sy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
@@ -227,7 +270,6 @@
     /*package*/ static void native_setRotate(int native_object, float degrees, float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
@@ -237,7 +279,6 @@
     /*package*/ static void native_setRotate(int native_object, float degrees) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
@@ -248,7 +289,6 @@
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
@@ -266,7 +306,6 @@
     /*package*/ static void native_setSinCos(int native_object, float sinValue, float cosValue) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
@@ -277,7 +316,6 @@
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
@@ -287,7 +325,6 @@
     /*package*/ static void native_setSkew(int native_object, float kx, float ky) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
@@ -311,19 +348,16 @@
 
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
         Matrix_Delegate a_mtx = sManager.getDelegate(a);
         if (a_mtx == null) {
-            assert false;
             return false;
         }
 
         Matrix_Delegate b_mtx = sManager.getDelegate(b);
         if (b_mtx == null) {
-            assert false;
             return false;
         }
 
@@ -335,7 +369,6 @@
     /*package*/ static boolean native_preTranslate(int native_object, float dx, float dy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -347,7 +380,6 @@
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -358,7 +390,6 @@
     /*package*/ static boolean native_preScale(int native_object, float sx, float sy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -370,7 +401,6 @@
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -381,7 +411,6 @@
     /*package*/ static boolean native_preRotate(int native_object, float degrees) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -397,7 +426,6 @@
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -408,7 +436,6 @@
     /*package*/ static boolean native_preSkew(int native_object, float kx, float ky) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -419,13 +446,11 @@
     /*package*/ static boolean native_preConcat(int native_object, int other_matrix) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
         Matrix_Delegate other = sManager.getDelegate(other_matrix);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -436,7 +461,6 @@
     /*package*/ static boolean native_postTranslate(int native_object, float dx, float dy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -448,7 +472,6 @@
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -459,7 +482,6 @@
     /*package*/ static boolean native_postScale(int native_object, float sx, float sy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -471,7 +493,6 @@
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -482,7 +503,6 @@
     /*package*/ static boolean native_postRotate(int native_object, float degrees) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -494,7 +514,6 @@
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -505,7 +524,6 @@
     /*package*/ static boolean native_postSkew(int native_object, float kx, float ky) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -516,13 +534,11 @@
     /*package*/ static boolean native_postConcat(int native_object, int other_matrix) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
         Matrix_Delegate other = sManager.getDelegate(other_matrix);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -534,7 +550,6 @@
             RectF dst, int stf) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
@@ -598,23 +613,23 @@
     /*package*/ static boolean native_setPolyToPoly(int native_object, float[] src, int srcIndex,
             float[] dst, int dstIndex, int pointCount) {
         // FIXME
-        throw new UnsupportedOperationException("Native delegate needed: Matrix_Delegate.native_setPolyToPoly");
+        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+                "Matrix.setPolyToPoly is not supported.",
+                null, null /*data*/);
+        return false;
     }
 
     /*package*/ static boolean native_invert(int native_object, int inverse) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
         Matrix_Delegate inv_mtx = sManager.getDelegate(inverse);
         if (inv_mtx == null) {
-            assert false;
             return false;
         }
 
-
         try {
             AffineTransform affineTransform = d.getAffineTransform();
             AffineTransform inverseTransform = affineTransform.createInverse();
@@ -635,57 +650,43 @@
             float[] src, int srcIndex, int ptCount, boolean isPts) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
         if (isPts) {
             d.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
         } else {
-            // src is vectors
-            // FIXME
-            throw new UnsupportedOperationException("Native delegate needed: Matrix_Delegate.native_mapPoints");
+            d.mapVectors(dst, dstIndex, src, srcIndex, ptCount);
         }
     }
 
     /*package*/ static boolean native_mapRect(int native_object, RectF dst, RectF src) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return false;
         }
 
-        // array with 4 corners
-        float[] corners = new float[] {
-                src.left, src.top,
-                src.right, src.top,
-                src.right, src.bottom,
-                src.left, src.bottom,
-        };
-
-        // apply the transform to them.
-        d.mapPoints(corners);
-
-        // now put the result in the rect. We take the min/max of Xs and min/max of Ys
-        dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
-        dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
-
-        dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
-        dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
-
-
-        return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
+        return d.mapRect(dst, src);
     }
 
     /*package*/ static float native_mapRadius(int native_object, float radius) {
-        // FIXME
-        throw new UnsupportedOperationException("Native delegate needed: Matrix_Delegate.native_mapRadius");
+        Matrix_Delegate d = sManager.getDelegate(native_object);
+        if (d == null) {
+            return 0.f;
+        }
+
+        float[] src = new float[] { radius, 0.f, 0.f, radius };
+        d.mapVectors(src, 0, src, 0, 2);
+
+        float l1 = getPointLength(src, 0);
+        float l2 = getPointLength(src, 2);
+
+        return (float) Math.sqrt(l1 * l2);
     }
 
     /*package*/ static void native_getValues(int native_object, float[] values) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
@@ -695,7 +696,6 @@
     /*package*/ static void native_setValues(int native_object, float[] values) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
         if (d == null) {
-            assert false;
             return;
         }
 
@@ -705,13 +705,11 @@
     /*package*/ static boolean native_equals(int native_a, int native_b) {
         Matrix_Delegate a = sManager.getDelegate(native_a);
         if (a == null) {
-            assert false;
             return false;
         }
 
         Matrix_Delegate b = sManager.getDelegate(native_b);
         if (b == null) {
-            assert false;
             return false;
         }
 
@@ -740,7 +738,6 @@
                 matrix[4], matrix[2], matrix[5]);
     }
 
-
     /**
      * Reset a matrix to the identity
      */
@@ -830,6 +827,10 @@
         reset();
     }
 
+    private Matrix_Delegate(float[] values) {
+        System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
+    }
+
     /**
      * Adds the given transformation to the current Matrix
      * <p/>This in effect does this = this*matrix
@@ -866,15 +867,15 @@
 
      private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
                            int pointCount) {
-         //checkPointArrays(src, srcIndex, dst, dstIndex, pointCount);
+         final int count = pointCount * 2;
 
          float[] tmpDest = dst;
          boolean inPlace = dst == src;
          if (inPlace) {
-             tmpDest = new float[dstIndex + pointCount * 2];
+             tmpDest = new float[dstIndex + count];
          }
 
-         for (int i = 0 ; i < pointCount * 2 ; i += 2) {
+         for (int i = 0 ; i < count ; i += 2) {
              // just in case we are doing in place, we better put this in temp vars
              float x = mValues[0] * src[i + srcIndex] +
                        mValues[1] * src[i + srcIndex + 1] +
@@ -888,7 +889,7 @@
          }
 
          if (inPlace) {
-             System.arraycopy(tmpDest, dstIndex, dst, dstIndex, pointCount * 2);
+             System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count);
          }
      }
 
@@ -903,6 +904,37 @@
          mapPoints(pts, 0, pts, 0, pts.length >> 1);
      }
 
+     private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) {
+         if (hasPerspective()) {
+             // transform the (0,0) point
+             float[] origin = new float[] { 0.f, 0.f};
+             mapPoints(origin);
+
+             // translate the vector data as points
+             mapPoints(dst, dstIndex, src, srcIndex, ptCount);
+
+             // then substract the transformed origin.
+             final int count = ptCount * 2;
+             for (int i = 0 ; i < count ; i += 2) {
+                 dst[dstIndex + i] = dst[dstIndex + i] - origin[0];
+                 dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1];
+             }
+         } else {
+             // make a copy of the matrix
+             Matrix_Delegate copy = new Matrix_Delegate(mValues);
+
+             // remove the translation
+             setTranslate(copy.mValues, 0, 0);
+
+             // map the content as points.
+             copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
+         }
+     }
+
+     private static float getPointLength(float[] src, int index) {
+         return (float) Math.sqrt(src[index] * src[index] + src[index + 1] * src[index + 1]);
+     }
+
     /**
      * multiply two matrices and store them in a 3rd.
      * <p/>This in effect does dest = a*b
@@ -1052,6 +1084,4 @@
 
         return tmp;
     }
-
-
 }
diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
index fe9bef9..7a6da95 100644
--- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
@@ -16,8 +16,10 @@
 
 package android.graphics;
 
+import com.android.ide.common.rendering.api.LayoutLog;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.layoutlib.bridge.impl.GcSnapshot;
 import com.android.ninepatch.NinePatchChunk;
 
 import android.graphics.drawable.NinePatchDrawable;
@@ -43,7 +45,7 @@
  * around to map int to instance of the delegate.
  *
  */
-public class NinePatch_Delegate {
+public final class NinePatch_Delegate {
 
     /**
      * Cache map for {@link NinePatchChunk}.
@@ -72,7 +74,7 @@
             oos = new ObjectOutputStream(baos);
             oos.writeObject(chunk);
         } catch (IOException e) {
-            Bridge.getLog().error("Failed to serialize NinePatchChunk.", e);
+            Bridge.getLog().error(null, "Failed to serialize NinePatchChunk.", e, null /*data*/);
             return null;
         } finally {
             if (oos != null) {
@@ -123,13 +125,12 @@
     }
 
    private static void draw(int canvas_instance,
-           int left, int top, int right, int bottom,
+           final int left, final int top, final int right, final int bottom,
            int bitmap_instance, byte[] c, int paint_instance_or_null,
-           int destDensity, int srcDensity) {
+           final int destDensity, final int srcDensity) {
        // get the delegate from the native int.
-       Bitmap_Delegate bitmap_delegate = Bitmap_Delegate.getDelegate(bitmap_instance);
+       final Bitmap_Delegate bitmap_delegate = Bitmap_Delegate.getDelegate(bitmap_instance);
        if (bitmap_delegate == null) {
-           assert false;
            return;
        }
 
@@ -143,7 +144,7 @@
            return;
        }
 
-       NinePatchChunk chunkObject = getChunk(c);
+       final NinePatchChunk chunkObject = getChunk(c);
        assert chunkObject != null;
        if (chunkObject == null) {
            return;
@@ -151,26 +152,19 @@
 
        Canvas_Delegate canvas_delegate = Canvas_Delegate.getDelegate(canvas_instance);
        if (canvas_delegate == null) {
-           assert false;
            return;
        }
 
        // this one can be null
        Paint_Delegate paint_delegate = Paint_Delegate.getDelegate(paint_instance_or_null);
 
-       Graphics2D graphics;
-       if (paint_delegate != null) {
-           graphics = canvas_delegate.createCustomGraphics(paint_delegate);
-       } else {
-           graphics = canvas_delegate.getGcSnapshot().create();
-       }
+       canvas_delegate.getSnapshot().draw(new GcSnapshot.Drawable() {
+               public void draw(Graphics2D graphics, Paint_Delegate paint) {
+                   chunkObject.draw(bitmap_delegate.getImage(), graphics,
+                           left, top, right - left, bottom - top, destDensity, srcDensity);
+               }
+           }, paint_delegate, true /*compositeOnly*/, false /*forceSrcMode*/);
 
-       try {
-           chunkObject.draw(bitmap_delegate.getImage(), graphics,
-                   left, top, right - left, bottom - top, destDensity, srcDensity);
-       } finally {
-           graphics.dispose();
-       }
     }
 
     /*package*/ static int nativeGetTransparentRegion(int bitmap, byte[] chunk, Rect location) {
@@ -203,10 +197,12 @@
                     sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk));
                 }
             } catch (IOException e) {
-                Bridge.getLog().error("Failed to deserialize NinePatchChunk content.", e);
+                Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                        "Failed to deserialize NinePatchChunk content.", e, null /*data*/);
                 return null;
             } catch (ClassNotFoundException e) {
-                Bridge.getLog().error("Failed to deserialize NinePatchChunk class.", e);
+                Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                        "Failed to deserialize NinePatchChunk class.", e, null /*data*/);
                 return null;
             } finally {
                 if (ois != null) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java
new file mode 100644
index 0000000..ec92507
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.graphics.PaintFlagsDrawFilter
+ *
+ * Through the layoutlib_create tool, the original native methods of PaintFlagsDrawFilter have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original PaintFlagsDrawFilter class.
+ *
+ * Because this extends {@link DrawFilter_Delegate}, there's no need to use a
+ * {@link DelegateManager}, as all the DrawFilter classes will be added to the manager owned by
+ * {@link DrawFilter_Delegate}.
+ *
+ * @see DrawFilter_Delegate
+ *
+ */
+public class PaintFlagsDrawFilter_Delegate extends DrawFilter_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Paint Flags Draw Filters are not supported.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeConstructor(int clearBits, int setBits) {
+        PaintFlagsDrawFilter_Delegate newDelegate = new PaintFlagsDrawFilter_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index fa26bcf..87164fb 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Paint.FontMetrics;
@@ -24,6 +26,8 @@
 
 import java.awt.BasicStroke;
 import java.awt.Font;
+import java.awt.Shape;
+import java.awt.Stroke;
 import java.awt.Toolkit;
 import java.awt.font.FontRenderContext;
 import java.awt.geom.AffineTransform;
@@ -82,6 +86,7 @@
     private int mShader;
     private int mPathEffect;
     private int mMaskFilter;
+    private int mRasterizer;
 
 
     // ---- Public Helper methods ----
@@ -114,6 +119,14 @@
         return mColor;
     }
 
+    public int getAlpha() {
+        return mColor >>> 24;
+    }
+
+    public void setAlpha(int alpha) {
+        mColor = (alpha << 24) | (mColor & 0x00FFFFFF);
+    }
+
     public int getTextAlign() {
         return mTextAlign;
     }
@@ -122,8 +135,15 @@
         return mStrokeWidth;
     }
 
-    public float getStrokeMiter() {
-        return mStrokeMiter;
+    /**
+     * returns the value of stroke miter needed by the java api.
+     */
+    public float getJavaStrokeMiter() {
+        float miter = mStrokeMiter * mStrokeWidth;
+        if (miter < 1.f) {
+            miter = 1.f;
+        }
+        return miter;
     }
 
     public int getJavaCap() {
@@ -150,24 +170,73 @@
         }
     }
 
-    public int getXfermode() {
-        return mXfermode;
+    public Stroke getJavaStroke() {
+        PathEffect_Delegate effectDelegate = PathEffect_Delegate.getDelegate(mPathEffect);
+        if (effectDelegate != null) {
+            if (effectDelegate.isSupported()) {
+                Stroke stroke = effectDelegate.getStroke(this);
+                assert stroke != null;
+                if (stroke != null) {
+                    return stroke;
+                }
+            } else {
+                Bridge.getLog().fidelityWarning(LayoutLog.TAG_PATHEFFECT,
+                        effectDelegate.getSupportMessage(),
+                        null, null /*data*/);
+            }
+        }
+
+        // if no custom stroke as been set, set the default one.
+        return new BasicStroke(
+                    getStrokeWidth(),
+                    getJavaCap(),
+                    getJavaJoin(),
+                    getJavaStrokeMiter());
     }
 
-    public int getColorFilter() {
-        return mColorFilter;
+    /**
+     * Returns the {@link Xfermode} delegate or null if none have been set
+     *
+     * @return the delegate or null.
+     */
+    public Xfermode_Delegate getXfermode() {
+        return  Xfermode_Delegate.getDelegate(mXfermode);
     }
 
-    public int getShader() {
-        return mShader;
+    /**
+     * Returns the {@link ColorFilter} delegate or null if none have been set
+     *
+     * @return the delegate or null.
+     */
+    public ColorFilter_Delegate getColorFilter() {
+        return ColorFilter_Delegate.getDelegate(mColorFilter);
     }
 
-    public int getPathEffect() {
-        return mPathEffect;
+    /**
+     * Returns the {@link Shader} delegate or null if none have been set
+     *
+     * @return the delegate or null.
+     */
+    public Shader_Delegate getShader() {
+        return Shader_Delegate.getDelegate(mShader);
     }
 
-    public int getMaskFilter() {
-        return mMaskFilter;
+    /**
+     * Returns the {@link MaskFilter} delegate or null if none have been set
+     *
+     * @return the delegate or null.
+     */
+    public MaskFilter_Delegate getMaskFilter() {
+        return MaskFilter_Delegate.getDelegate(mMaskFilter);
+    }
+
+    /**
+     * Returns the {@link Rasterizer} delegate or null if none have been set
+     *
+     * @return the delegate or null.
+     */
+    public Rasterizer_Delegate getRasterizer() {
+        return Rasterizer_Delegate.getDelegate(mRasterizer);
     }
 
     // ---- native methods ----
@@ -176,7 +245,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -187,7 +255,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -230,7 +297,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -241,7 +307,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -252,29 +317,26 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
-        return delegate.mColor >>> 24;
+        return delegate.getAlpha();
     }
 
     /*package*/ static void setAlpha(Paint thisPaint, int a) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return;
         }
 
-        delegate.mColor = (a << 24) | (delegate.mColor & 0x00FFFFFF);
+        delegate.setAlpha(a);
     }
 
     /*package*/ static float getStrokeWidth(Paint thisPaint) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 1.f;
         }
 
@@ -285,7 +347,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -296,7 +357,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 1.f;
         }
 
@@ -307,7 +367,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -317,14 +376,14 @@
     /*package*/ static void nSetShadowLayer(Paint thisPaint, float radius, float dx, float dy,
             int color) {
         // FIXME
-        throw new UnsupportedOperationException();
+        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+                "Paint.setShadowLayer is not supported.", null, null /*data*/);
     }
 
     /*package*/ static float getTextSize(Paint thisPaint) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 1.f;
         }
 
@@ -335,7 +394,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -347,7 +405,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 1.f;
         }
 
@@ -358,7 +415,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -370,7 +426,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 1.f;
         }
 
@@ -381,7 +436,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -393,7 +447,6 @@
         // get the delegate
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -410,7 +463,6 @@
         // get the delegate
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -427,7 +479,6 @@
         // get the delegate
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -438,7 +489,6 @@
         // get the delegate
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -467,7 +517,6 @@
         // get the delegate
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -504,7 +553,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(paint);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -516,7 +564,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -527,14 +574,12 @@
         // get the delegate from the native int.
         Paint_Delegate delegate_dst = sManager.getDelegate(native_dst);
         if (delegate_dst == null) {
-            assert false;
             return;
         }
 
         // get the delegate from the native int.
         Paint_Delegate delegate_src = sManager.getDelegate(native_src);
         if (delegate_src == null) {
-            assert false;
             return;
         }
 
@@ -545,7 +590,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -556,7 +600,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -567,7 +610,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -578,7 +620,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -589,7 +630,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -600,7 +640,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -608,15 +647,34 @@
     }
 
     /*package*/ static boolean native_getFillPath(int native_object, int src, int dst) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        Paint_Delegate paint = sManager.getDelegate(native_object);
+        if (paint == null) {
+            return false;
+        }
+
+        Path_Delegate srcPath = Path_Delegate.getDelegate(src);
+        if (srcPath == null) {
+            return true;
+        }
+
+        Path_Delegate dstPath = Path_Delegate.getDelegate(dst);
+        if (dstPath == null) {
+            return true;
+        }
+
+        Stroke stroke = paint.getJavaStroke();
+        Shape strokeShape = stroke.createStrokedShape(srcPath.getJavaShape());
+
+        dstPath.setJavaShape(strokeShape);
+
+        // FIXME figure out the return value?
+        return true;
     }
 
     /*package*/ static int native_setShader(int native_object, int shader) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return shader;
         }
 
@@ -627,18 +685,25 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return filter;
         }
 
-        return delegate.mColorFilter = filter;
+        delegate.mColorFilter = filter;
+
+        // since none of those are supported, display a fidelity warning right away
+        ColorFilter_Delegate filterDelegate = delegate.getColorFilter();
+        if (filterDelegate != null && filterDelegate.isSupported() == false) {
+            Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER,
+                    filterDelegate.getSupportMessage(), null, null /*data*/);
+        }
+
+        return filter;
     }
 
     /*package*/ static int native_setXfermode(int native_object, int xfermode) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return xfermode;
         }
 
@@ -649,7 +714,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return effect;
         }
 
@@ -660,18 +724,25 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return maskfilter;
         }
 
-        return delegate.mMaskFilter = maskfilter;
+        delegate.mMaskFilter = maskfilter;
+
+        // since none of those are supported, display a fidelity warning right away
+        MaskFilter_Delegate filterDelegate = delegate.getMaskFilter();
+        if (filterDelegate != null && filterDelegate.isSupported() == false) {
+            Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
+                    filterDelegate.getSupportMessage(), null, null /*data*/);
+        }
+
+        return maskfilter;
     }
 
     /*package*/ static int native_setTypeface(int native_object, int typeface) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -681,15 +752,28 @@
     }
 
     /*package*/ static int native_setRasterizer(int native_object, int rasterizer) {
-        // FIXME
-        throw new UnsupportedOperationException();
+        // get the delegate from the native int.
+        Paint_Delegate delegate = sManager.getDelegate(native_object);
+        if (delegate == null) {
+            return rasterizer;
+        }
+
+        delegate.mRasterizer = rasterizer;
+
+        // since none of those are supported, display a fidelity warning right away
+        Rasterizer_Delegate rasterizerDelegate = delegate.getRasterizer();
+        if (rasterizerDelegate != null && rasterizerDelegate.isSupported() == false) {
+            Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER,
+                    rasterizerDelegate.getSupportMessage(), null, null /*data*/);
+        }
+
+        return rasterizer;
     }
 
     /*package*/ static int native_getTextAlign(int native_object) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -700,7 +784,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return;
         }
 
@@ -711,7 +794,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_paint);
         if (delegate == null) {
-            assert false;
             return 0.f;
         }
 
@@ -736,7 +818,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
-            assert false;
             return 0.f;
         }
 
@@ -828,7 +909,7 @@
 
     // ---- Private delegate/helper methods ----
 
-    private Paint_Delegate() {
+    /*package*/ Paint_Delegate() {
         reset();
     }
 
@@ -854,19 +935,20 @@
         mShader = paint.mShader;
         mPathEffect = paint.mPathEffect;
         mMaskFilter = paint.mMaskFilter;
+        mRasterizer = paint.mRasterizer;
         updateFontObject();
     }
 
     private void reset() {
         mFlags = Paint.DEFAULT_PAINT_FLAGS;
-        mColor = 0;
-        mStyle = 0;
-        mCap = 0;
-        mJoin = 0;
+        mColor = 0xFF000000;
+        mStyle = Paint.Style.FILL.nativeInt;
+        mCap = Paint.Cap.BUTT.nativeInt;
+        mJoin = Paint.Join.MITER.nativeInt;
         mTextAlign = 0;
         mTypeface = Typeface.sDefaults[0].native_instance;
         mStrokeWidth = 1.f;
-        mStrokeMiter = 2.f;
+        mStrokeMiter = 4.f;
         mTextSize = 20.f;
         mTextScaleX = 1.f;
         mTextSkewX = 0.f;
@@ -875,12 +957,14 @@
         mShader = 0;
         mPathEffect = 0;
         mMaskFilter = 0;
+        mRasterizer = 0;
         updateFontObject();
     }
 
     /**
      * Update the {@link Font} object from the typeface, text size and scaling
      */
+    @SuppressWarnings("deprecation")
     private void updateFontObject() {
         if (mTypeface != 0) {
             // Get the fonts from the TypeFace object.
@@ -983,7 +1067,6 @@
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
         if (delegate == null) {
-            assert false;
             return;
         }
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path.java b/tools/layoutlib/bridge/src/android/graphics/Path.java
deleted file mode 100644
index c0bc005..0000000
--- a/tools/layoutlib/bridge/src/android/graphics/Path.java
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.GeneralPath;
-import java.awt.geom.PathIterator;
-import java.awt.geom.Rectangle2D;
-
-/**
- * The Path class encapsulates compound (multiple contour) geometric paths
- * consisting of straight line segments, quadratic curves, and cubic curves.
- * It can be drawn with canvas.drawPath(path, paint), either filled or stroked
- * (based on the paint's Style), or it can be used for clipping or to draw
- * text on a path.
- */
-public class Path {
-
-    private FillType mFillType = FillType.WINDING;
-    private GeneralPath mPath = new GeneralPath();
-
-    private float mLastX = 0;
-    private float mLastY = 0;
-
-    //---------- Custom methods ----------
-
-    public Shape getAwtShape() {
-        return mPath;
-    }
-
-    //----------
-
-    /**
-     * Create an empty path
-     */
-    public Path() {
-    }
-
-    /**
-     * Create a new path, copying the contents from the src path.
-     *
-     * @param src The path to copy from when initializing the new path
-     */
-    public Path(Path src) {
-        mPath.append(src.mPath, false /* connect */);
-    }
-
-    /**
-     * Clear any lines and curves from the path, making it empty.
-     * This does NOT change the fill-type setting.
-     */
-    public void reset() {
-        mPath = new GeneralPath();
-    }
-
-    /**
-     * Rewinds the path: clears any lines and curves from the path but
-     * keeps the internal data structure for faster reuse.
-     */
-    public void rewind() {
-        // FIXME
-        throw new UnsupportedOperationException();
-    }
-
-    /** Replace the contents of this with the contents of src.
-    */
-    public void set(Path src) {
-        mPath.append(src.mPath, false /* connect */);
-    }
-
-    /** Enum for the ways a path may be filled
-    */
-    public enum FillType {
-        // these must match the values in SkPath.h
-        WINDING         (GeneralPath.WIND_NON_ZERO, false),
-        EVEN_ODD        (GeneralPath.WIND_EVEN_ODD, false),
-        INVERSE_WINDING (GeneralPath.WIND_NON_ZERO, true),
-        INVERSE_EVEN_ODD(GeneralPath.WIND_EVEN_ODD, true);
-
-        FillType(int rule, boolean inverse) {
-            this.rule = rule;
-            this.inverse = inverse;
-        }
-
-        final int rule;
-        final boolean inverse;
-    }
-
-    /**
-     * Return the path's fill type. This defines how "inside" is
-     * computed. The default value is WINDING.
-     *
-     * @return the path's fill type
-     */
-    public FillType getFillType() {
-        return mFillType;
-    }
-
-    /**
-     * Set the path's fill type. This defines how "inside" is computed.
-     *
-     * @param ft The new fill type for this path
-     */
-    public void setFillType(FillType ft) {
-        mFillType = ft;
-        mPath.setWindingRule(ft.rule);
-    }
-
-    /**
-     * Returns true if the filltype is one of the INVERSE variants
-     *
-     * @return true if the filltype is one of the INVERSE variants
-     */
-    public boolean isInverseFillType() {
-        return mFillType.inverse;
-    }
-
-    /**
-     * Toggles the INVERSE state of the filltype
-     */
-    public void toggleInverseFillType() {
-        switch (mFillType) {
-            case WINDING:
-                mFillType = FillType.INVERSE_WINDING;
-                break;
-            case EVEN_ODD:
-                mFillType = FillType.INVERSE_EVEN_ODD;
-                break;
-            case INVERSE_WINDING:
-                mFillType = FillType.WINDING;
-                break;
-            case INVERSE_EVEN_ODD:
-                mFillType = FillType.EVEN_ODD;
-                break;
-        }
-    }
-
-    /**
-     * Returns true if the path is empty (contains no lines or curves)
-     *
-     * @return true if the path is empty (contains no lines or curves)
-     */
-    public boolean isEmpty() {
-        return mPath.getCurrentPoint() == null;
-    }
-
-    /**
-     * Returns true if the path specifies a rectangle. If so, and if rect is
-     * not null, set rect to the bounds of the path. If the path does not
-     * specify a rectangle, return false and ignore rect.
-     *
-     * @param rect If not null, returns the bounds of the path if it specifies
-     *             a rectangle
-     * @return     true if the path specifies a rectangle
-     */
-    public boolean isRect(RectF rect) {
-        // FIXME
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Compute the bounds of the path, and write the answer into bounds. If the
-     * path contains 0 or 1 points, the bounds is set to (0,0,0,0)
-     *
-     * @param bounds Returns the computed bounds of the path
-     * @param exact If true, return the exact (but slower) bounds, else return
-     *              just the bounds of all control points
-     */
-    public void computeBounds(RectF bounds, boolean exact) {
-        Rectangle2D rect = mPath.getBounds2D();
-        bounds.left = (float)rect.getMinX();
-        bounds.right = (float)rect.getMaxX();
-        bounds.top = (float)rect.getMinY();
-        bounds.bottom = (float)rect.getMaxY();
-    }
-
-    /**
-     * Hint to the path to prepare for adding more points. This can allow the
-     * path to more efficiently allocate its storage.
-     *
-     * @param extraPtCount The number of extra points that may be added to this
-     *                     path
-     */
-    public void incReserve(int extraPtCount) {
-        // pass
-    }
-
-    /**
-     * Set the beginning of the next contour to the point (x,y).
-     *
-     * @param x The x-coordinate of the start of a new contour
-     * @param y The y-coordinate of the start of a new contour
-     */
-    public void moveTo(float x, float y) {
-        mPath.moveTo(mLastX = x, mLastY = y);
-    }
-
-    /**
-     * Set the beginning of the next contour relative to the last point on the
-     * previous contour. If there is no previous contour, this is treated the
-     * same as moveTo().
-     *
-     * @param dx The amount to add to the x-coordinate of the end of the
-     *           previous contour, to specify the start of a new contour
-     * @param dy The amount to add to the y-coordinate of the end of the
-     *           previous contour, to specify the start of a new contour
-     */
-    public void rMoveTo(float dx, float dy) {
-        dx += mLastX;
-        dy += mLastY;
-        mPath.moveTo(mLastX = dx, mLastY = dy);
-    }
-
-    /**
-     * Add a line from the last point to the specified point (x,y).
-     * If no moveTo() call has been made for this contour, the first point is
-     * automatically set to (0,0).
-     *
-     * @param x The x-coordinate of the end of a line
-     * @param y The y-coordinate of the end of a line
-     */
-    public void lineTo(float x, float y) {
-        mPath.lineTo(mLastX = x, mLastY = y);
-    }
-
-    /**
-     * Same as lineTo, but the coordinates are considered relative to the last
-     * point on this contour. If there is no previous point, then a moveTo(0,0)
-     * is inserted automatically.
-     *
-     * @param dx The amount to add to the x-coordinate of the previous point on
-     *           this contour, to specify a line
-     * @param dy The amount to add to the y-coordinate of the previous point on
-     *           this contour, to specify a line
-     */
-    public void rLineTo(float dx, float dy) {
-        if (isEmpty()) {
-            mPath.moveTo(mLastX = 0, mLastY = 0);
-        }
-        dx += mLastX;
-        dy += mLastY;
-        mPath.lineTo(mLastX = dx, mLastY = dy);
-    }
-
-    /**
-     * Add a quadratic bezier from the last point, approaching control point
-     * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
-     * this contour, the first point is automatically set to (0,0).
-     *
-     * @param x1 The x-coordinate of the control point on a quadratic curve
-     * @param y1 The y-coordinate of the control point on a quadratic curve
-     * @param x2 The x-coordinate of the end point on a quadratic curve
-     * @param y2 The y-coordinate of the end point on a quadratic curve
-     */
-    public void quadTo(float x1, float y1, float x2, float y2) {
-        mPath.quadTo(x1, y1, mLastX = x2, mLastY = y2);
-    }
-
-    /**
-     * Same as quadTo, but the coordinates are considered relative to the last
-     * point on this contour. If there is no previous point, then a moveTo(0,0)
-     * is inserted automatically.
-     *
-     * @param dx1 The amount to add to the x-coordinate of the last point on
-     *            this contour, for the control point of a quadratic curve
-     * @param dy1 The amount to add to the y-coordinate of the last point on
-     *            this contour, for the control point of a quadratic curve
-     * @param dx2 The amount to add to the x-coordinate of the last point on
-     *            this contour, for the end point of a quadratic curve
-     * @param dy2 The amount to add to the y-coordinate of the last point on
-     *            this contour, for the end point of a quadratic curve
-     */
-    public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
-        if (isEmpty()) {
-            mPath.moveTo(mLastX = 0, mLastY = 0);
-        }
-        dx1 += mLastX;
-        dy1 += mLastY;
-        dx2 += mLastX;
-        dy2 += mLastY;
-        mPath.quadTo(dx1, dy1, mLastX = dx2, mLastY = dy2);
-    }
-
-    /**
-     * Add a cubic bezier from the last point, approaching control points
-     * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
-     * made for this contour, the first point is automatically set to (0,0).
-     *
-     * @param x1 The x-coordinate of the 1st control point on a cubic curve
-     * @param y1 The y-coordinate of the 1st control point on a cubic curve
-     * @param x2 The x-coordinate of the 2nd control point on a cubic curve
-     * @param y2 The y-coordinate of the 2nd control point on a cubic curve
-     * @param x3 The x-coordinate of the end point on a cubic curve
-     * @param y3 The y-coordinate of the end point on a cubic curve
-     */
-    public void cubicTo(float x1, float y1, float x2, float y2,
-                        float x3, float y3) {
-        mPath.curveTo(x1, y1, x2, y2, mLastX = x3, mLastY = y3);
-    }
-
-    /**
-     * Same as cubicTo, but the coordinates are considered relative to the
-     * current point on this contour. If there is no previous point, then a
-     * moveTo(0,0) is inserted automatically.
-     */
-    public void rCubicTo(float dx1, float dy1, float dx2, float dy2,
-                         float dx3, float dy3) {
-        if (isEmpty()) {
-            mPath.moveTo(mLastX = 0, mLastY = 0);
-        }
-        dx1 += mLastX;
-        dy1 += mLastY;
-        dx2 += mLastX;
-        dy2 += mLastY;
-        dx3 += mLastX;
-        dy3 += mLastY;
-        mPath.curveTo(dx1, dy1, dx2, dy2, mLastX = dx3, mLastY = dy3);
-    }
-
-    /**
-     * Append the specified arc to the path as a new contour. If the start of
-     * the path is different from the path's current last point, then an
-     * automatic lineTo() is added to connect the current contour to the
-     * start of the arc. However, if the path is empty, then we call moveTo()
-     * with the first point of the arc. The sweep angle is tread mod 360.
-     *
-     * @param oval        The bounds of oval defining shape and size of the arc
-     * @param startAngle  Starting angle (in degrees) where the arc begins
-     * @param sweepAngle  Sweep angle (in degrees) measured clockwise, treated
-     *                    mod 360.
-     * @param forceMoveTo If true, always begin a new contour with the arc
-     */
-    public void arcTo(RectF oval, float startAngle, float sweepAngle,
-                      boolean forceMoveTo) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Append the specified arc to the path as a new contour. If the start of
-     * the path is different from the path's current last point, then an
-     * automatic lineTo() is added to connect the current contour to the
-     * start of the arc. However, if the path is empty, then we call moveTo()
-     * with the first point of the arc.
-     *
-     * @param oval        The bounds of oval defining shape and size of the arc
-     * @param startAngle  Starting angle (in degrees) where the arc begins
-     * @param sweepAngle  Sweep angle (in degrees) measured clockwise
-     */
-    public void arcTo(RectF oval, float startAngle, float sweepAngle) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Close the current contour. If the current point is not equal to the
-     * first point of the contour, a line segment is automatically added.
-     */
-    public void close() {
-        mPath.closePath();
-    }
-
-    /**
-     * Specifies how closed shapes (e.g. rects, ovals) are oriented when they
-     * are added to a path.
-     */
-    public enum Direction {
-        /** clockwise */
-        CW  (0),    // must match enum in SkPath.h
-        /** counter-clockwise */
-        CCW (1);    // must match enum in SkPath.h
-
-        Direction(int ni) {
-            nativeInt = ni;
-        }
-        final int nativeInt;
-    }
-
-    /**
-     * Add a closed rectangle contour to the path
-     *
-     * @param rect The rectangle to add as a closed contour to the path
-     * @param dir  The direction to wind the rectangle's contour
-     */
-    public void addRect(RectF rect, Direction dir) {
-        if (rect == null) {
-            throw new NullPointerException("need rect parameter");
-        }
-
-        addRect(rect.left, rect.top, rect.right, rect.bottom, dir);
-    }
-
-    /**
-     * Add a closed rectangle contour to the path
-     *
-     * @param left   The left side of a rectangle to add to the path
-     * @param top    The top of a rectangle to add to the path
-     * @param right  The right side of a rectangle to add to the path
-     * @param bottom The bottom of a rectangle to add to the path
-     * @param dir    The direction to wind the rectangle's contour
-     */
-    public void addRect(float left, float top, float right, float bottom,
-                        Direction dir) {
-        moveTo(left, top);
-
-        switch (dir) {
-            case CW:
-                lineTo(right, top);
-                lineTo(right, bottom);
-                lineTo(left, bottom);
-                break;
-            case CCW:
-                lineTo(left, bottom);
-                lineTo(right, bottom);
-                lineTo(right, top);
-                break;
-        }
-
-        close();
-    }
-
-    /**
-     * Add a closed oval contour to the path
-     *
-     * @param oval The bounds of the oval to add as a closed contour to the path
-     * @param dir  The direction to wind the oval's contour
-     */
-    public void addOval(RectF oval, Direction dir) {
-        if (oval == null) {
-            throw new NullPointerException("need oval parameter");
-        }
-
-        // FIXME Need to support direction
-        Ellipse2D ovalShape = new Ellipse2D.Float(oval.left, oval.top, oval.width(), oval.height());
-
-        mPath.append(ovalShape, false /* connect */);
-    }
-
-    /**
-     * Add a closed circle contour to the path
-     *
-     * @param x   The x-coordinate of the center of a circle to add to the path
-     * @param y   The y-coordinate of the center of a circle to add to the path
-     * @param radius The radius of a circle to add to the path
-     * @param dir    The direction to wind the circle's contour
-     */
-    public void addCircle(float x, float y, float radius, Direction dir) {
-        // FIXME
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Add the specified arc to the path as a new contour.
-     *
-     * @param oval The bounds of oval defining the shape and size of the arc
-     * @param startAngle Starting angle (in degrees) where the arc begins
-     * @param sweepAngle Sweep angle (in degrees) measured clockwise
-     */
-    public void addArc(RectF oval, float startAngle, float sweepAngle) {
-        if (oval == null) {
-            throw new NullPointerException("need oval parameter");
-        }
-        // FIXME
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-        * Add a closed round-rectangle contour to the path
-     *
-     * @param rect The bounds of a round-rectangle to add to the path
-     * @param rx   The x-radius of the rounded corners on the round-rectangle
-     * @param ry   The y-radius of the rounded corners on the round-rectangle
-     * @param dir  The direction to wind the round-rectangle's contour
-     */
-    public void addRoundRect(RectF rect, float rx, float ry, Direction dir) {
-        if (rect == null) {
-            throw new NullPointerException("need rect parameter");
-        }
-        // FIXME
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Add a closed round-rectangle contour to the path. Each corner receives
-     * two radius values [X, Y]. The corners are ordered top-left, top-right,
-     * bottom-right, bottom-left
-     *
-     * @param rect The bounds of a round-rectangle to add to the path
-     * @param radii Array of 8 values, 4 pairs of [X,Y] radii
-     * @param dir  The direction to wind the round-rectangle's contour
-     */
-    public void addRoundRect(RectF rect, float[] radii, Direction dir) {
-        if (rect == null) {
-            throw new NullPointerException("need rect parameter");
-        }
-        if (radii.length < 8) {
-            throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values");
-        }
-        // FIXME
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Add a copy of src to the path, offset by (dx,dy)
-     *
-     * @param src The path to add as a new contour
-     * @param dx  The amount to translate the path in X as it is added
-     */
-    public void addPath(Path src, float dx, float dy) {
-        PathIterator iterator = src.mPath.getPathIterator(new AffineTransform(0, 0, dx, 0, 0, dy));
-        mPath.append(iterator, false /* connect */);
-    }
-
-    /**
-     * Add a copy of src to the path
-     *
-     * @param src The path that is appended to the current path
-     */
-    public void addPath(Path src) {
-        addPath(src, 0, 0);
-    }
-
-    /**
-     * Add a copy of src to the path, transformed by matrix
-     *
-     * @param src The path to add as a new contour
-     */
-    public void addPath(Path src, Matrix matrix) {
-        // FIXME
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Offset the path by (dx,dy), returning true on success
-     *
-     * @param dx  The amount in the X direction to offset the entire path
-     * @param dy  The amount in the Y direction to offset the entire path
-     * @param dst The translated path is written here. If this is null, then
-     *            the original path is modified.
-     */
-    public void offset(float dx, float dy, Path dst) {
-        GeneralPath newPath = new GeneralPath();
-
-        PathIterator iterator = mPath.getPathIterator(new AffineTransform(0, 0, dx, 0, 0, dy));
-
-        newPath.append(iterator, false /* connect */);
-
-        if (dst != null) {
-            dst.mPath = newPath;
-        } else {
-            mPath = newPath;
-        }
-    }
-
-    /**
-     * Offset the path by (dx,dy), returning true on success
-     *
-     * @param dx The amount in the X direction to offset the entire path
-     * @param dy The amount in the Y direction to offset the entire path
-     */
-    public void offset(float dx, float dy) {
-        offset(dx, dy, null /* dst */);
-    }
-
-    /**
-     * Sets the last point of the path.
-     *
-     * @param dx The new X coordinate for the last point
-     * @param dy The new Y coordinate for the last point
-     */
-    public void setLastPoint(float dx, float dy) {
-        mLastX = dx;
-        mLastY = dy;
-    }
-
-    /**
-     * Transform the points in this path by matrix, and write the answer
-     * into dst. If dst is null, then the the original path is modified.
-     *
-     * @param matrix The matrix to apply to the path
-     * @param dst    The transformed path is written here. If dst is null,
-     *               then the the original path is modified
-     */
-    public void transform(Matrix matrix, Path dst) {
-        // FIXME
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Transform the points in this path by matrix.
-     *
-     * @param matrix The matrix to apply to the path
-     */
-    public void transform(Matrix matrix) {
-        transform(matrix, null /* dst */);
-    }
-}
diff --git a/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java
new file mode 100644
index 0000000..d12bfea
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+import java.awt.Stroke;
+
+/**
+ * Delegate implementing the native methods of android.graphics.PathDashPathEffect
+ *
+ * Through the layoutlib_create tool, the original native methods of PathDashPathEffect have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original PathDashPathEffect class.
+ *
+ * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager},
+ * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}.
+ *
+ * @see PathEffect_Delegate
+ *
+ */
+public class PathDashPathEffect_Delegate extends PathEffect_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public Stroke getStroke(Paint_Delegate paint) {
+        // FIXME
+        return null;
+    }
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Path Dash Path Effects are not supported in Layout Preview mode.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeCreate(int native_path, float advance, float phase,
+            int native_style) {
+        PathDashPathEffect_Delegate newDelegate = new PathDashPathEffect_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
index ce7eef0..c588423 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
@@ -18,6 +18,8 @@
 
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
+import java.awt.Stroke;
+
 /**
  * Delegate implementing the native methods of android.graphics.PathEffect
  *
@@ -33,7 +35,7 @@
  * @see DelegateManager
  *
  */
-public class PathEffect_Delegate {
+public abstract class PathEffect_Delegate {
 
     // ---- delegate manager ----
     protected static final DelegateManager<PathEffect_Delegate> sManager =
@@ -49,6 +51,11 @@
         return sManager.getDelegate(nativeShader);
     }
 
+    public abstract Stroke getStroke(Paint_Delegate paint);
+    public abstract boolean isSupported();
+    public abstract String getSupportMessage();
+
+
     // ---- native methods ----
 
     /*package*/ static void nativeDestructor(int native_patheffect) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
new file mode 100644
index 0000000..a4e43c1
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -0,0 +1,716 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+import android.graphics.Path.Direction;
+import android.graphics.Path.FillType;
+
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Arc2D;
+import java.awt.geom.Area;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * Delegate implementing the native methods of android.graphics.Path
+ *
+ * Through the layoutlib_create tool, the original native methods of Path have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original Path class.
+ *
+ * @see DelegateManager
+ *
+ */
+public final class Path_Delegate {
+
+    // ---- delegate manager ----
+    private static final DelegateManager<Path_Delegate> sManager =
+            new DelegateManager<Path_Delegate>();
+
+    // ---- delegate data ----
+    private FillType mFillType = FillType.WINDING;
+    private GeneralPath mPath = new GeneralPath();
+
+    private float mLastX = 0;
+    private float mLastY = 0;
+
+    // ---- Public Helper methods ----
+
+    public static Path_Delegate getDelegate(int nPath) {
+        return sManager.getDelegate(nPath);
+    }
+
+    public Shape getJavaShape() {
+        return mPath;
+    }
+
+    public void setJavaShape(Shape shape) {
+        mPath.reset();
+        mPath.append(shape, false /*connect*/);
+    }
+
+    public void reset() {
+        mPath.reset();
+    }
+
+    public void setPathIterator(PathIterator iterator) {
+        mPath.reset();
+        mPath.append(iterator, false /*connect*/);
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int init1() {
+        // create the delegate
+        Path_Delegate newDelegate = new Path_Delegate();
+
+        return sManager.addDelegate(newDelegate);
+    }
+
+    /*package*/ static int init2(int nPath) {
+        // create the delegate
+        Path_Delegate newDelegate = new Path_Delegate();
+
+        // get the delegate to copy, which could be null if nPath is 0
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate != null) {
+            newDelegate.set(pathDelegate);
+        }
+
+        return sManager.addDelegate(newDelegate);
+    }
+
+    /*package*/ static void native_reset(int nPath) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.mPath.reset();
+    }
+
+    /*package*/ static void native_rewind(int nPath) {
+        // call out to reset since there's nothing to optimize in
+        // terms of data structs.
+        native_reset(nPath);
+    }
+
+    /*package*/ static void native_set(int native_dst, int native_src) {
+        Path_Delegate pathDstDelegate = sManager.getDelegate(native_dst);
+        if (pathDstDelegate == null) {
+            return;
+        }
+
+        Path_Delegate pathSrcDelegate = sManager.getDelegate(native_src);
+        if (pathSrcDelegate == null) {
+            return;
+        }
+
+        pathDstDelegate.set(pathSrcDelegate);
+    }
+
+    /*package*/ static int native_getFillType(int nPath) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return 0;
+        }
+
+        return pathDelegate.mFillType.nativeInt;
+    }
+
+    /*package*/ static void native_setFillType(int nPath, int ft) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.mFillType = Path.sFillTypeArray[ft];
+    }
+
+    /*package*/ static boolean native_isEmpty(int nPath) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return true;
+        }
+
+        return pathDelegate.isEmpty();
+    }
+
+    /*package*/ static boolean native_isRect(int nPath, RectF rect) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return false;
+        }
+
+        // create an Area that can test if the path is a rect
+        Area area = new Area(pathDelegate.mPath);
+        if (area.isRectangular()) {
+            if (rect != null) {
+                pathDelegate.fillBounds(rect);
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /*package*/ static void native_computeBounds(int nPath, RectF bounds) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.fillBounds(bounds);
+    }
+
+    /*package*/ static void native_incReserve(int nPath, int extraPtCount) {
+        // since we use a java2D path, there's no way to pre-allocate new points,
+        // so we do nothing.
+    }
+
+    /*package*/ static void native_moveTo(int nPath, float x, float y) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.moveTo(x, y);
+    }
+
+    /*package*/ static void native_rMoveTo(int nPath, float dx, float dy) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.rMoveTo(dx, dy);
+    }
+
+    /*package*/ static void native_lineTo(int nPath, float x, float y) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.lineTo(x, y);
+    }
+
+    /*package*/ static void native_rLineTo(int nPath, float dx, float dy) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.rLineTo(dx, dy);
+    }
+
+    /*package*/ static void native_quadTo(int nPath, float x1, float y1, float x2, float y2) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.quadTo(x1, y1, x2, y2);
+    }
+
+    /*package*/ static void native_rQuadTo(int nPath, float dx1, float dy1, float dx2, float dy2) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.rQuadTo(dx1, dy1, dx2, dy2);
+    }
+
+    /*package*/ static void native_cubicTo(int nPath, float x1, float y1,
+            float x2, float y2, float x3, float y3) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.cubicTo(x1, y1, x2, y2, x3, y3);
+    }
+
+    /*package*/ static void native_rCubicTo(int nPath, float x1, float y1,
+            float x2, float y2, float x3, float y3) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.rCubicTo(x1, y1, x2, y2, x3, y3);
+    }
+
+    /*package*/ static void native_arcTo(int nPath, RectF oval,
+                    float startAngle, float sweepAngle, boolean forceMoveTo) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.arcTo(oval, startAngle, sweepAngle, forceMoveTo);
+    }
+
+    /*package*/ static void native_close(int nPath) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.close();
+    }
+
+    /*package*/ static void native_addRect(int nPath, RectF rect, int dir) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.addRect(rect.left, rect.top, rect.right, rect.bottom, dir);
+    }
+
+    /*package*/ static void native_addRect(int nPath,
+            float left, float top, float right, float bottom, int dir) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.addRect(left, top, right, bottom, dir);
+    }
+
+    /*package*/ static void native_addOval(int nPath, RectF oval, int dir) {
+        // FIXME
+        throw new UnsupportedOperationException();
+    }
+
+    /*package*/ static void native_addCircle(int nPath, float x, float y, float radius, int dir) {
+        // FIXME
+        throw new UnsupportedOperationException();
+    }
+
+    /*package*/ static void native_addArc(int nPath, RectF oval,
+            float startAngle, float sweepAngle) {
+        // FIXME
+        throw new UnsupportedOperationException();
+    }
+
+    /*package*/ static void native_addRoundRect(int nPath, RectF rect,
+            float rx, float ry, int dir) {
+        // FIXME
+        throw new UnsupportedOperationException();
+    }
+
+    /*package*/ static void native_addRoundRect(int nPath, RectF r, float[] radii, int dir) {
+        // FIXME
+        throw new UnsupportedOperationException();
+    }
+
+    /*package*/ static void native_addPath(int nPath, int src, float dx, float dy) {
+        // FIXME
+        throw new UnsupportedOperationException();
+    }
+
+    /*package*/ static void native_addPath(int nPath, int src) {
+        native_addPath(nPath, src, 0, 0);
+    }
+
+    /*package*/ static void native_addPath(int nPath, int src, int matrix) {
+        // FIXME
+        throw new UnsupportedOperationException();
+    }
+
+    /*package*/ static void native_offset(int nPath, float dx, float dy, int dst_path) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        // could be null if the int is 0;
+        Path_Delegate dstDelegate = sManager.getDelegate(dst_path);
+
+        pathDelegate.offset(dx, dy, dstDelegate);
+    }
+
+    /*package*/ static void native_offset(int nPath, float dx, float dy) {
+        native_offset(nPath, dx, dy, 0);
+    }
+
+    /*package*/ static void native_setLastPoint(int nPath, float dx, float dy) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        pathDelegate.mLastX = dx;
+        pathDelegate.mLastY = dy;
+    }
+
+    /*package*/ static void native_transform(int nPath, int matrix,
+                                                int dst_path) {
+        Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+        if (pathDelegate == null) {
+            return;
+        }
+
+        Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
+        if (matrixDelegate == null) {
+            return;
+        }
+
+        // this can be null if dst_path is 0
+        Path_Delegate dstDelegate = sManager.getDelegate(dst_path);
+
+        pathDelegate.transform(matrixDelegate, dstDelegate);
+    }
+
+    /*package*/ static void native_transform(int nPath, int matrix) {
+        native_transform(nPath, matrix, 0);
+    }
+
+    /*package*/ static void finalizer(int nPath) {
+        sManager.removeDelegate(nPath);
+    }
+
+
+    // ---- Private helper methods ----
+
+    private void set(Path_Delegate delegate) {
+        mPath.reset();
+        setFillType(delegate.mFillType);
+        mPath.append(delegate.mPath, false /*connect*/);
+    }
+
+    private void setFillType(FillType fillType) {
+        mFillType = fillType;
+        mPath.setWindingRule(getWindingRule(fillType));
+    }
+
+    /**
+     * Returns the Java2D winding rules matching a given Android {@link FillType}.
+     * @param type the android fill type
+     * @return the matching java2d winding rule.
+     */
+    private static int getWindingRule(FillType type) {
+        switch (type) {
+            case WINDING:
+            case INVERSE_WINDING:
+                return GeneralPath.WIND_NON_ZERO;
+            case EVEN_ODD:
+            case INVERSE_EVEN_ODD:
+                return GeneralPath.WIND_EVEN_ODD;
+        }
+
+        assert false;
+        throw new IllegalArgumentException();
+    }
+
+    private static Direction getDirection(int direction) {
+        for (Direction d : Direction.values()) {
+            if (direction == d.nativeInt) {
+                return d;
+            }
+        }
+
+        assert false;
+        return null;
+    }
+
+    /**
+     * Returns whether the path is empty.
+     * @return true if the path is empty.
+     */
+    private boolean isEmpty() {
+        return mPath.getCurrentPoint() == null;
+    }
+
+    /**
+     * Fills the given {@link RectF} with the path bounds.
+     * @param bounds the RectF to be filled.
+     */
+    private void fillBounds(RectF bounds) {
+        Rectangle2D rect = mPath.getBounds2D();
+        bounds.left = (float)rect.getMinX();
+        bounds.right = (float)rect.getMaxX();
+        bounds.top = (float)rect.getMinY();
+        bounds.bottom = (float)rect.getMaxY();
+    }
+
+    /**
+     * Set the beginning of the next contour to the point (x,y).
+     *
+     * @param x The x-coordinate of the start of a new contour
+     * @param y The y-coordinate of the start of a new contour
+     */
+    private void moveTo(float x, float y) {
+        mPath.moveTo(mLastX = x, mLastY = y);
+    }
+
+    /**
+     * Set the beginning of the next contour relative to the last point on the
+     * previous contour. If there is no previous contour, this is treated the
+     * same as moveTo().
+     *
+     * @param dx The amount to add to the x-coordinate of the end of the
+     *           previous contour, to specify the start of a new contour
+     * @param dy The amount to add to the y-coordinate of the end of the
+     *           previous contour, to specify the start of a new contour
+     */
+    private void rMoveTo(float dx, float dy) {
+        dx += mLastX;
+        dy += mLastY;
+        mPath.moveTo(mLastX = dx, mLastY = dy);
+    }
+
+    /**
+     * Add a line from the last point to the specified point (x,y).
+     * If no moveTo() call has been made for this contour, the first point is
+     * automatically set to (0,0).
+     *
+     * @param x The x-coordinate of the end of a line
+     * @param y The y-coordinate of the end of a line
+     */
+    private void lineTo(float x, float y) {
+        mPath.lineTo(mLastX = x, mLastY = y);
+    }
+
+    /**
+     * Same as lineTo, but the coordinates are considered relative to the last
+     * point on this contour. If there is no previous point, then a moveTo(0,0)
+     * is inserted automatically.
+     *
+     * @param dx The amount to add to the x-coordinate of the previous point on
+     *           this contour, to specify a line
+     * @param dy The amount to add to the y-coordinate of the previous point on
+     *           this contour, to specify a line
+     */
+    private void rLineTo(float dx, float dy) {
+        if (isEmpty()) {
+            mPath.moveTo(mLastX = 0, mLastY = 0);
+        }
+        dx += mLastX;
+        dy += mLastY;
+        mPath.lineTo(mLastX = dx, mLastY = dy);
+    }
+
+    /**
+     * Add a quadratic bezier from the last point, approaching control point
+     * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
+     * this contour, the first point is automatically set to (0,0).
+     *
+     * @param x1 The x-coordinate of the control point on a quadratic curve
+     * @param y1 The y-coordinate of the control point on a quadratic curve
+     * @param x2 The x-coordinate of the end point on a quadratic curve
+     * @param y2 The y-coordinate of the end point on a quadratic curve
+     */
+    private void quadTo(float x1, float y1, float x2, float y2) {
+        mPath.quadTo(x1, y1, mLastX = x2, mLastY = y2);
+    }
+
+    /**
+     * Same as quadTo, but the coordinates are considered relative to the last
+     * point on this contour. If there is no previous point, then a moveTo(0,0)
+     * is inserted automatically.
+     *
+     * @param dx1 The amount to add to the x-coordinate of the last point on
+     *            this contour, for the control point of a quadratic curve
+     * @param dy1 The amount to add to the y-coordinate of the last point on
+     *            this contour, for the control point of a quadratic curve
+     * @param dx2 The amount to add to the x-coordinate of the last point on
+     *            this contour, for the end point of a quadratic curve
+     * @param dy2 The amount to add to the y-coordinate of the last point on
+     *            this contour, for the end point of a quadratic curve
+     */
+    private void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
+        if (isEmpty()) {
+            mPath.moveTo(mLastX = 0, mLastY = 0);
+        }
+        dx1 += mLastX;
+        dy1 += mLastY;
+        dx2 += mLastX;
+        dy2 += mLastY;
+        mPath.quadTo(dx1, dy1, mLastX = dx2, mLastY = dy2);
+    }
+
+    /**
+     * Add a cubic bezier from the last point, approaching control points
+     * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
+     * made for this contour, the first point is automatically set to (0,0).
+     *
+     * @param x1 The x-coordinate of the 1st control point on a cubic curve
+     * @param y1 The y-coordinate of the 1st control point on a cubic curve
+     * @param x2 The x-coordinate of the 2nd control point on a cubic curve
+     * @param y2 The y-coordinate of the 2nd control point on a cubic curve
+     * @param x3 The x-coordinate of the end point on a cubic curve
+     * @param y3 The y-coordinate of the end point on a cubic curve
+     */
+    private void cubicTo(float x1, float y1, float x2, float y2,
+                        float x3, float y3) {
+        mPath.curveTo(x1, y1, x2, y2, mLastX = x3, mLastY = y3);
+    }
+
+    /**
+     * Same as cubicTo, but the coordinates are considered relative to the
+     * current point on this contour. If there is no previous point, then a
+     * moveTo(0,0) is inserted automatically.
+     */
+    private void rCubicTo(float dx1, float dy1, float dx2, float dy2,
+                         float dx3, float dy3) {
+        if (isEmpty()) {
+            mPath.moveTo(mLastX = 0, mLastY = 0);
+        }
+        dx1 += mLastX;
+        dy1 += mLastY;
+        dx2 += mLastX;
+        dy2 += mLastY;
+        dx3 += mLastX;
+        dy3 += mLastY;
+        mPath.curveTo(dx1, dy1, dx2, dy2, mLastX = dx3, mLastY = dy3);
+    }
+
+    /**
+     * Append the specified arc to the path as a new contour. If the start of
+     * the path is different from the path's current last point, then an
+     * automatic lineTo() is added to connect the current contour to the
+     * start of the arc. However, if the path is empty, then we call moveTo()
+     * with the first point of the arc. The sweep angle is tread mod 360.
+     *
+     * @param oval        The bounds of oval defining shape and size of the arc
+     * @param startAngle  Starting angle (in degrees) where the arc begins
+     * @param sweepAngle  Sweep angle (in degrees) measured clockwise, treated
+     *                    mod 360.
+     * @param forceMoveTo If true, always begin a new contour with the arc
+     */
+    private void arcTo(RectF oval, float startAngle, float sweepAngle,
+                      boolean forceMoveTo) {
+        Arc2D arc = new Arc2D.Float(oval.left, oval.top, oval.width(), oval.height(), startAngle,
+                sweepAngle, Arc2D.OPEN);
+        mPath.append(arc, true /*connect*/);
+
+        resetLastPointFromPath();
+    }
+
+    /**
+     * Close the current contour. If the current point is not equal to the
+     * first point of the contour, a line segment is automatically added.
+     */
+    private void close() {
+        mPath.closePath();
+    }
+
+    private void resetLastPointFromPath() {
+        Point2D last = mPath.getCurrentPoint();
+        mLastX = (float) last.getX();
+        mLastY = (float) last.getY();
+    }
+
+    /**
+     * Add a closed rectangle contour to the path
+     *
+     * @param left   The left side of a rectangle to add to the path
+     * @param top    The top of a rectangle to add to the path
+     * @param right  The right side of a rectangle to add to the path
+     * @param bottom The bottom of a rectangle to add to the path
+     * @param dir    The direction to wind the rectangle's contour
+     */
+    private void addRect(float left, float top, float right, float bottom,
+                        int dir) {
+        moveTo(left, top);
+
+        Direction direction = getDirection(dir);
+
+        switch (direction) {
+            case CW:
+                lineTo(right, top);
+                lineTo(right, bottom);
+                lineTo(left, bottom);
+                break;
+            case CCW:
+                lineTo(left, bottom);
+                lineTo(right, bottom);
+                lineTo(right, top);
+                break;
+        }
+
+        close();
+
+        resetLastPointFromPath();
+    }
+
+    /**
+     * Offset the path by (dx,dy), returning true on success
+     *
+     * @param dx  The amount in the X direction to offset the entire path
+     * @param dy  The amount in the Y direction to offset the entire path
+     * @param dst The translated path is written here. If this is null, then
+     *            the original path is modified.
+     */
+    public void offset(float dx, float dy, Path_Delegate dst) {
+        GeneralPath newPath = new GeneralPath();
+
+        PathIterator iterator = mPath.getPathIterator(new AffineTransform(0, 0, dx, 0, 0, dy));
+
+        newPath.append(iterator, false /*connect*/);
+
+        if (dst != null) {
+            dst.mPath = newPath;
+        } else {
+            mPath = newPath;
+        }
+    }
+
+    /**
+     * Transform the points in this path by matrix, and write the answer
+     * into dst. If dst is null, then the the original path is modified.
+     *
+     * @param matrix The matrix to apply to the path
+     * @param dst    The transformed path is written here. If dst is null,
+     *               then the the original path is modified
+     */
+    public void transform(Matrix_Delegate matrix, Path_Delegate dst) {
+        if (matrix.hasPerspective()) {
+            assert false;
+            Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE,
+                    "android.graphics.Path#transform() only " +
+                    "supports affine transformations.", null, null /*data*/);
+        }
+
+        GeneralPath newPath = new GeneralPath();
+
+        PathIterator iterator = mPath.getPathIterator(matrix.getAffineTransform());
+
+        newPath.append(iterator, false /*connect*/);
+
+        if (dst != null) {
+            dst.mPath = newPath;
+        } else {
+            mPath = newPath;
+        }
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java
new file mode 100644
index 0000000..516a2b9
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+import java.awt.Composite;
+
+/**
+ * Delegate implementing the native methods of android.graphics.PixelXorXfermode
+ *
+ * Through the layoutlib_create tool, the original native methods of PixelXorXfermode have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original PixelXorXfermode class.
+ *
+ * Because this extends {@link Xfermode_Delegate}, there's no need to use a
+ * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by
+ * {@link Xfermode_Delegate}.
+ *
+ * @see Xfermode_Delegate
+ */
+public class PixelXorXfermode_Delegate extends Xfermode_Delegate {
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public Composite getComposite(int alpha) {
+        // FIXME
+        return null;
+    }
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Pixel XOR Xfermodes are not supported in Layout Preview mode.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeCreate(int opColor) {
+        PixelXorXfermode_Delegate newDelegate = new PixelXorXfermode_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
new file mode 100644
index 0000000..9038636
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.graphics.PorterDuffColorFilter
+ *
+ * Through the layoutlib_create tool, the original native methods of PorterDuffColorFilter have
+ * been replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original PorterDuffColorFilter class.
+ *
+ * Because this extends {@link ColorFilter_Delegate}, there's no need to use a
+ * {@link DelegateManager}, as all the Shader classes will be added to the manager
+ * owned by {@link ColorFilter_Delegate}.
+ *
+ * @see ColorFilter_Delegate
+ *
+ */
+public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "PorterDuff Color Filters are not supported.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int native_CreatePorterDuffFilter(int srcColor, int porterDuffMode) {
+        PorterDuffColorFilter_Delegate newDelegate = new PorterDuffColorFilter_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    /*package*/ static int nCreatePorterDuffFilter(int nativeFilter, int srcColor,
+            int porterDuffMode) {
+        // pass
+        return 0;
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
index a5885ea..147e1d0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
@@ -16,8 +16,13 @@
 
 package android.graphics;
 
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
+import java.awt.AlphaComposite;
+import java.awt.Composite;
+
 /**
  * Delegate implementing the native methods of android.graphics.PorterDuffXfermode
  *
@@ -41,8 +46,81 @@
 
     // ---- Public Helper methods ----
 
-    public int getMode() {
-        return mMode;
+    public PorterDuff.Mode getMode() {
+        return getPorterDuffMode(mMode);
+    }
+
+    @Override
+    public Composite getComposite(int alpha) {
+        return getComposite(getPorterDuffMode(mMode), alpha);
+    }
+
+    @Override
+    public boolean isSupported() {
+        return true;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        // no message since isSupported returns true;
+        return null;
+    }
+
+    public static PorterDuff.Mode getPorterDuffMode(int mode) {
+        for (PorterDuff.Mode m : PorterDuff.Mode.values()) {
+            if (m.nativeInt == mode) {
+                return m;
+            }
+        }
+
+        Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                String.format("Unknown PorterDuff.Mode: %d", mode), null /*data*/);
+        assert false;
+        return PorterDuff.Mode.SRC_OVER;
+    }
+
+    public static Composite getComposite(PorterDuff.Mode mode, int alpha) {
+        float falpha = alpha != 0xFF ? (float)alpha / 255.f : 1.f;
+        switch (mode) {
+            case CLEAR:
+                return AlphaComposite.getInstance(AlphaComposite.CLEAR, falpha);
+            case DARKEN:
+                break;
+            case DST:
+                return AlphaComposite.getInstance(AlphaComposite.DST, falpha);
+            case DST_ATOP:
+                return AlphaComposite.getInstance(AlphaComposite.DST_ATOP, falpha);
+            case DST_IN:
+                return AlphaComposite.getInstance(AlphaComposite.DST_IN, falpha);
+            case DST_OUT:
+                return AlphaComposite.getInstance(AlphaComposite.DST_OUT, falpha);
+            case DST_OVER:
+                return AlphaComposite.getInstance(AlphaComposite.DST_OVER, falpha);
+            case LIGHTEN:
+                break;
+            case MULTIPLY:
+                break;
+            case SCREEN:
+                break;
+            case SRC:
+                return AlphaComposite.getInstance(AlphaComposite.SRC, falpha);
+            case SRC_ATOP:
+                return AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, falpha);
+            case SRC_IN:
+                return AlphaComposite.getInstance(AlphaComposite.SRC_IN, falpha);
+            case SRC_OUT:
+                return AlphaComposite.getInstance(AlphaComposite.SRC_OUT, falpha);
+            case SRC_OVER:
+                return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha);
+            case XOR:
+                return AlphaComposite.getInstance(AlphaComposite.XOR, falpha);
+        }
+
+        Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
+                String.format("Unsupported PorterDuff Mode: %s", mode.name()),
+                null, null /*data*/);
+
+        return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha);
     }
 
     // ---- native methods ----
@@ -57,5 +135,4 @@
     private PorterDuffXfermode_Delegate(int mode) {
         mMode = mode;
     }
-
 }
diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
index eebf378..ffdf5dd 100644
--- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
@@ -16,15 +16,12 @@
 
 package android.graphics;
 
+import com.android.ide.common.rendering.api.LayoutLog;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Shader.TileMode;
 
-import java.awt.Paint;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-
 /**
  * Delegate implementing the native methods of android.graphics.RadialGradient
  *
@@ -49,7 +46,7 @@
     // ---- Public Helper methods ----
 
     @Override
-    public Paint getJavaPaint() {
+    public java.awt.Paint getJavaPaint() {
         return mJavaPaint;
     }
 
@@ -57,17 +54,8 @@
 
     /*package*/ static int nativeCreate1(float x, float y, float radius,
             int colors[], float positions[], int tileMode) {
-        // figure out the tile
-        TileMode tile = null;
-        for (TileMode tm : TileMode.values()) {
-            if (tm.nativeInt == tileMode) {
-                tile = tm;
-                break;
-            }
-        }
-
         RadialGradient_Delegate newDelegate = new RadialGradient_Delegate(x, y, radius,
-                colors, positions, tile);
+                colors, positions, Shader_Delegate.getTileMode(tileMode));
         return sManager.addDelegate(newDelegate);
     }
 
@@ -133,20 +121,22 @@
                 java.awt.RenderingHints       hints) {
             precomputeGradientColors();
 
-            AffineTransform canvasMatrix;
+            java.awt.geom.AffineTransform canvasMatrix;
             try {
                 canvasMatrix = xform.createInverse();
-            } catch (NoninvertibleTransformException e) {
-                Bridge.getLog().error(null, "Unable to inverse matrix in RadialGradient", e);
-                canvasMatrix = new AffineTransform();
+            } catch (java.awt.geom.NoninvertibleTransformException e) {
+                Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
+                        "Unable to inverse matrix in RadialGradient", e, null /*data*/);
+                canvasMatrix = new java.awt.geom.AffineTransform();
             }
 
-            AffineTransform localMatrix = getLocalMatrix();
+            java.awt.geom.AffineTransform localMatrix = getLocalMatrix();
             try {
                 localMatrix = localMatrix.createInverse();
-            } catch (NoninvertibleTransformException e) {
-                Bridge.getLog().error(null, "Unable to inverse matrix in RadialGradient", e);
-                localMatrix = new AffineTransform();
+            } catch (java.awt.geom.NoninvertibleTransformException e) {
+                Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
+                        "Unable to inverse matrix in RadialGradient", e, null /*data*/);
+                localMatrix = new java.awt.geom.AffineTransform();
             }
 
             return new RadialGradientPaintContext(canvasMatrix, localMatrix, colorModel);
@@ -154,12 +144,14 @@
 
         private class RadialGradientPaintContext implements java.awt.PaintContext {
 
-            private final AffineTransform mCanvasMatrix;
-            private final AffineTransform mLocalMatrix;
+            private final java.awt.geom.AffineTransform mCanvasMatrix;
+            private final java.awt.geom.AffineTransform mLocalMatrix;
             private final java.awt.image.ColorModel mColorModel;
 
-            public RadialGradientPaintContext(AffineTransform canvasMatrix,
-                    AffineTransform localMatrix, java.awt.image.ColorModel colorModel) {
+            public RadialGradientPaintContext(
+                    java.awt.geom.AffineTransform canvasMatrix,
+                    java.awt.geom.AffineTransform localMatrix,
+                    java.awt.image.ColorModel colorModel) {
                 mCanvasMatrix = canvasMatrix;
                 mLocalMatrix = localMatrix;
                 mColorModel = colorModel;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java
new file mode 100644
index 0000000..9fd67be
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/Rasterizer_Delegate.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+/**
+ * Delegate implementing the native methods of android.graphics.Rasterizer
+ *
+ * Through the layoutlib_create tool, the original native methods of Rasterizer have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original Rasterizer class.
+ *
+ * This also serve as a base class for all Rasterizer delegate classes.
+ *
+ * @see DelegateManager
+ *
+ */
+public abstract class Rasterizer_Delegate {
+
+    // ---- delegate manager ----
+    protected static final DelegateManager<Rasterizer_Delegate> sManager =
+            new DelegateManager<Rasterizer_Delegate>();
+
+    // ---- delegate helper data ----
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    public static Rasterizer_Delegate getDelegate(int nativeShader) {
+        return sManager.getDelegate(nativeShader);
+    }
+
+    public abstract boolean isSupported();
+    public abstract String getSupportMessage();
+
+    // ---- native methods ----
+
+    /*package*/ static void finalizer(int native_instance) {
+        sManager.removeDelegate(native_instance);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
new file mode 100644
index 0000000..9b6fb82
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+import android.os.Parcel;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * Delegate implementing the native methods of android.graphics.Region
+ *
+ * Through the layoutlib_create tool, the original native methods of Region have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original Region class.
+ *
+ * This also serve as a base class for all Region delegate classes.
+ *
+ * @see DelegateManager
+ *
+ */
+public class Region_Delegate {
+
+    // ---- delegate manager ----
+    protected static final DelegateManager<Region_Delegate> sManager =
+            new DelegateManager<Region_Delegate>();
+
+    // ---- delegate helper data ----
+
+    // ---- delegate data ----
+    private Area mArea = new Area();
+
+    // ---- Public Helper methods ----
+
+    public static Region_Delegate getDelegate(int nativeShader) {
+        return sManager.getDelegate(nativeShader);
+    }
+
+    public Area getJavaArea() {
+        return mArea;
+    }
+
+    /**
+     * Combines two {@link Shape} into another one (actually an {@link Area}), according
+     * to the given {@link Region.Op}.
+     *
+     * If the Op is not one that combines two shapes, then this return null
+     *
+     * @param shape1 the firt shape to combine which can be null if there's no original clip.
+     * @param shape2 the 2nd shape to combine
+     * @param regionOp the operande for the combine
+     * @return a new area or null.
+     */
+    public static Area combineShapes(Shape shape1, Shape shape2, int regionOp) {
+        if (regionOp == Region.Op.DIFFERENCE.nativeInt) {
+            // if shape1 is null (empty), then the result is null.
+            if (shape1 == null) {
+                return null;
+            }
+
+            // result is always a new area.
+            Area result = new Area(shape1);
+            result.subtract(shape2 instanceof Area ? (Area) shape2 : new Area(shape2));
+            return result;
+
+        } else if (regionOp == Region.Op.INTERSECT.nativeInt) {
+            // if shape1 is null, then the result is simply shape2.
+            if (shape1 == null) {
+                return new Area(shape2);
+            }
+
+            // result is always a new area.
+            Area result = new Area(shape1);
+            result.intersect(shape2 instanceof Area ? (Area) shape2 : new Area(shape2));
+            return result;
+
+        } else if (regionOp == Region.Op.UNION.nativeInt) {
+            // if shape1 is null, then the result is simply shape2.
+            if (shape1 == null) {
+                return new Area(shape2);
+            }
+
+            // result is always a new area.
+            Area result = new Area(shape1);
+            result.add(shape2 instanceof Area ? (Area) shape2 : new Area(shape2));
+            return result;
+
+        } else if (regionOp == Region.Op.XOR.nativeInt) {
+            // if shape1 is null, then the result is simply shape2
+            if (shape1 == null) {
+                return new Area(shape2);
+            }
+
+            // result is always a new area.
+            Area result = new Area(shape1);
+            result.exclusiveOr(shape2 instanceof Area ? (Area) shape2 : new Area(shape2));
+            return result;
+
+        } else if (regionOp == Region.Op.REVERSE_DIFFERENCE.nativeInt) {
+            // result is always a new area.
+            Area result = new Area(shape2);
+
+            if (shape1 != null) {
+                result.subtract(shape1 instanceof Area ? (Area) shape1 : new Area(shape1));
+            }
+
+            return result;
+        }
+
+        return null;
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static boolean isEmpty(Region thisRegion) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return true;
+        }
+
+        return regionDelegate.mArea.isEmpty();
+    }
+
+    /*package*/ static boolean isRect(Region thisRegion) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return true;
+        }
+
+        return regionDelegate.mArea.isRectangular();
+    }
+
+    /*package*/ static boolean isComplex(Region thisRegion) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return true;
+        }
+
+        return regionDelegate.mArea.isSingular() == false;
+    }
+
+    /*package*/ static boolean contains(Region thisRegion, int x, int y) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return false;
+        }
+
+        return regionDelegate.mArea.contains(x, y);
+    }
+
+    /*package*/ static boolean quickContains(Region thisRegion,
+            int left, int top, int right, int bottom) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return false;
+        }
+
+        return regionDelegate.mArea.isRectangular() &&
+                regionDelegate.mArea.contains(left, top, right - left, bottom - top);
+    }
+
+    /*package*/ static boolean quickReject(Region thisRegion,
+            int left, int top, int right, int bottom) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return false;
+        }
+
+        return regionDelegate.mArea.isEmpty() ||
+                regionDelegate.mArea.intersects(left, top, right - left, bottom - top) == false;
+    }
+
+    /*package*/ static boolean quickReject(Region thisRegion, Region rgn) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return false;
+        }
+
+        Region_Delegate targetRegionDelegate = sManager.getDelegate(rgn.mNativeRegion);
+        if (targetRegionDelegate == null) {
+            return false;
+        }
+
+        return regionDelegate.mArea.isEmpty() ||
+                regionDelegate.mArea.getBounds().intersects(
+                        targetRegionDelegate.mArea.getBounds()) == false;
+
+    }
+
+    /*package*/ static void translate(Region thisRegion, int dx, int dy, Region dst) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return;
+        }
+
+        Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion);
+        if (targetRegionDelegate == null) {
+            return;
+        }
+
+        if (regionDelegate.mArea.isEmpty()) {
+            targetRegionDelegate.mArea = new Area();
+        } else {
+            targetRegionDelegate.mArea = new Area(regionDelegate.mArea);
+            AffineTransform mtx = new AffineTransform();
+            mtx.translate(dx, dy);
+            targetRegionDelegate.mArea.transform(mtx);
+        }
+    }
+
+    /*package*/ static void scale(Region thisRegion, float scale, Region dst) {
+        Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
+        if (regionDelegate == null) {
+            return;
+        }
+
+        Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion);
+        if (targetRegionDelegate == null) {
+            return;
+        }
+
+        if (regionDelegate.mArea.isEmpty()) {
+            targetRegionDelegate.mArea = new Area();
+        } else {
+            targetRegionDelegate.mArea = new Area(regionDelegate.mArea);
+            AffineTransform mtx = new AffineTransform();
+            mtx.scale(scale, scale);
+            targetRegionDelegate.mArea.transform(mtx);
+        }
+    }
+
+    /*package*/ static int nativeConstructor() {
+        Region_Delegate newDelegate = new Region_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    /*package*/ static void nativeDestructor(int native_region) {
+        sManager.removeDelegate(native_region);
+    }
+
+    /*package*/ static boolean nativeSetRegion(int native_dst, int native_src) {
+        Region_Delegate dstRegion = sManager.getDelegate(native_dst);
+        if (dstRegion == null) {
+            return true;
+        }
+
+        Region_Delegate srcRegion = sManager.getDelegate(native_src);
+        if (srcRegion == null) {
+            return true;
+        }
+
+        dstRegion.mArea.reset();
+        dstRegion.mArea.add(srcRegion.mArea);
+
+        return true;
+    }
+
+    /*package*/ static boolean nativeSetRect(int native_dst,
+            int left, int top, int right, int bottom) {
+        Region_Delegate dstRegion = sManager.getDelegate(native_dst);
+        if (dstRegion == null) {
+            return true;
+        }
+
+        dstRegion.mArea = new Area(new Rectangle2D.Float(left, top, right - left, bottom - top));
+        return dstRegion.mArea.getBounds().isEmpty() == false;
+    }
+
+    /*package*/ static boolean nativeSetPath(int native_dst, int native_path, int native_clip) {
+        Region_Delegate dstRegion = sManager.getDelegate(native_dst);
+        if (dstRegion == null) {
+            return true;
+        }
+
+        Path_Delegate path = Path_Delegate.getDelegate(native_path);
+        if (path == null) {
+            return true;
+        }
+
+        dstRegion.mArea = new Area(path.getJavaShape());
+
+        Region_Delegate clip = sManager.getDelegate(native_clip);
+        if (clip != null) {
+            dstRegion.mArea.subtract(clip.getJavaArea());
+        }
+
+        return dstRegion.mArea.getBounds().isEmpty() == false;
+    }
+
+    /*package*/ static boolean nativeGetBounds(int native_region, Rect rect) {
+        Region_Delegate region = sManager.getDelegate(native_region);
+        if (region == null) {
+            return true;
+        }
+
+        Rectangle bounds = region.mArea.getBounds();
+        if (bounds.isEmpty()) {
+            rect.left = rect.top = rect.right = rect.bottom = 0;
+            return false;
+        }
+
+        rect.left = bounds.x;
+        rect.top = bounds.y;
+        rect.right = bounds.x + bounds.width;
+        rect.bottom = bounds.y + bounds.height;
+        return true;
+    }
+
+    /*package*/ static boolean nativeGetBoundaryPath(int native_region, int native_path) {
+        Region_Delegate region = sManager.getDelegate(native_region);
+        if (region == null) {
+            return false;
+        }
+
+        Path_Delegate path = Path_Delegate.getDelegate(native_path);
+        if (path == null) {
+            return false;
+        }
+
+        if (region.mArea.isEmpty()) {
+            path.reset();
+            return false;
+        }
+
+        path.setPathIterator(region.mArea.getPathIterator(new AffineTransform()));
+        return true;
+    }
+
+    /*package*/ static boolean nativeOp(int native_dst,
+            int left, int top, int right, int bottom, int op) {
+        Region_Delegate region = sManager.getDelegate(native_dst);
+        if (region == null) {
+            return false;
+        }
+
+        region.mArea = combineShapes(region.mArea,
+                new Rectangle2D.Float(left, top, right - left, bottom - top), op);
+
+        assert region.mArea != null;
+        if (region.mArea != null) {
+            region.mArea = new Area();
+        }
+
+        return region.mArea.getBounds().isEmpty() == false;
+    }
+
+    /*package*/ static boolean nativeOp(int native_dst, Rect rect, int native_region, int op) {
+        Region_Delegate region = sManager.getDelegate(native_dst);
+        if (region == null) {
+            return false;
+        }
+
+        region.mArea = combineShapes(region.mArea,
+                new Rectangle2D.Float(rect.left, rect.top, rect.width(), rect.height()), op);
+
+        assert region.mArea != null;
+        if (region.mArea != null) {
+            region.mArea = new Area();
+        }
+
+        return region.mArea.getBounds().isEmpty() == false;
+    }
+
+    /*package*/ static boolean nativeOp(int native_dst,
+            int native_region1, int native_region2, int op) {
+        Region_Delegate dstRegion = sManager.getDelegate(native_dst);
+        if (dstRegion == null) {
+            return true;
+        }
+
+        Region_Delegate region1 = sManager.getDelegate(native_region1);
+        if (region1 == null) {
+            return false;
+        }
+
+        Region_Delegate region2 = sManager.getDelegate(native_region2);
+        if (region2 == null) {
+            return false;
+        }
+
+        dstRegion.mArea = combineShapes(region1.mArea, region2.mArea, op);
+
+        assert dstRegion.mArea != null;
+        if (dstRegion.mArea != null) {
+            dstRegion.mArea = new Area();
+        }
+
+        return dstRegion.mArea.getBounds().isEmpty() == false;
+
+    }
+
+    /*package*/ static int nativeCreateFromParcel(Parcel p) {
+        // 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.",
+                null /*data*/);
+        return 0;
+    }
+
+    /*package*/ static boolean nativeWriteToParcel(int native_region,
+                                                      Parcel p) {
+        // 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.",
+                null /*data*/);
+        return false;
+    }
+
+    /*package*/ static boolean nativeEquals(int native_r1, int native_r2) {
+        Region_Delegate region1 = sManager.getDelegate(native_r1);
+        if (region1 == null) {
+            return false;
+        }
+
+        Region_Delegate region2 = sManager.getDelegate(native_r2);
+        if (region2 == null) {
+            return false;
+        }
+
+        return region1.mArea.equals(region2.mArea);
+    }
+
+    // ---- Private delegate/helper methods ----
+
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
index 7bf1443..7903ac9 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
@@ -18,7 +18,7 @@
 
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
-import java.awt.geom.AffineTransform;
+import android.graphics.Shader.TileMode;
 
 /**
  * Delegate implementing the native methods of android.graphics.Shader
@@ -52,7 +52,25 @@
         return sManager.getDelegate(nativeShader);
     }
 
+    /**
+     * Returns the {@link TileMode} matching the given int.
+     * @param tileMode the tile mode int value
+     * @return the TileMode enum.
+     */
+    public static TileMode getTileMode(int tileMode) {
+        for (TileMode tm : TileMode.values()) {
+            if (tm.nativeInt == tileMode) {
+                return tm;
+            }
+        }
+
+        assert false;
+        return TileMode.CLAMP;
+    }
+
     public abstract java.awt.Paint getJavaPaint();
+    public abstract boolean isSupported();
+    public abstract String getSupportMessage();
 
     // ---- native methods ----
 
@@ -64,27 +82,16 @@
         // get the delegate from the native int.
         Shader_Delegate shaderDelegate = sManager.getDelegate(native_shader);
         if (shaderDelegate == null) {
-            assert false;
             return false;
         }
 
-        Matrix_Delegate localMatrixDelegate = null;
-        if (shaderDelegate.mLocalMatrix > 0) {
-            localMatrixDelegate = Matrix_Delegate.getDelegate(shaderDelegate.mLocalMatrix);
-            if (localMatrixDelegate == null) {
-                assert false;
-                return false;
-            }
-        }
+        // can be null if shader has no matrix (int is 0)
+        Matrix_Delegate localMatrixDelegate = Matrix_Delegate.getDelegate(
+                shaderDelegate.mLocalMatrix);
 
-        Matrix_Delegate destMatrixDelegate = null;
-        if (matrix_instance > 0) {
-            destMatrixDelegate = Matrix_Delegate.getDelegate(shaderDelegate.mLocalMatrix);
-            if (destMatrixDelegate == null) {
-                assert false;
-                return false;
-            }
-
+        // can be null if the int is 0.
+        Matrix_Delegate destMatrixDelegate = Matrix_Delegate.getDelegate(matrix_instance);
+        if (destMatrixDelegate != null) {
             if (localMatrixDelegate != null) {
                 destMatrixDelegate.set(localMatrixDelegate);
             } else {
@@ -102,7 +109,6 @@
         // get the delegate from the native int.
         Shader_Delegate shaderDelegate = sManager.getDelegate(native_shader);
         if (shaderDelegate == null) {
-            assert false;
             return;
         }
 
@@ -111,19 +117,13 @@
 
     // ---- Private delegate/helper methods ----
 
-    protected AffineTransform getLocalMatrix() {
-        Matrix_Delegate localMatrixDelegate = null;
-        if (mLocalMatrix > 0) {
-            localMatrixDelegate = Matrix_Delegate.getDelegate(mLocalMatrix);
-            if (localMatrixDelegate == null) {
-                assert false;
-                return new AffineTransform();
-            }
-
+    protected java.awt.geom.AffineTransform getLocalMatrix() {
+        Matrix_Delegate localMatrixDelegate = Matrix_Delegate.getDelegate(mLocalMatrix);
+        if (localMatrixDelegate != null) {
             return localMatrixDelegate.getAffineTransform();
         }
 
-        return new AffineTransform();
+        return new java.awt.geom.AffineTransform();
     }
 
 }
diff --git a/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java
new file mode 100644
index 0000000..0f92ca5
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+import java.awt.Stroke;
+
+/**
+ * Delegate implementing the native methods of android.graphics.SumPathEffect
+ *
+ * Through the layoutlib_create tool, the original native methods of SumPathEffect have been
+ * replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original SumPathEffect class.
+ *
+ * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager},
+ * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}.
+ *
+ * @see PathEffect_Delegate
+ *
+ */
+public class SumPathEffect_Delegate extends PathEffect_Delegate {
+
+    // ---- delegate data ----
+
+    // ---- Public Helper methods ----
+
+    @Override
+    public Stroke getStroke(Paint_Delegate paint) {
+        // FIXME
+        return null;
+    }
+
+    @Override
+    public boolean isSupported() {
+        return false;
+    }
+
+    @Override
+    public String getSupportMessage() {
+        return "Sum Path Effects are not supported in Layout Preview mode.";
+    }
+
+    // ---- native methods ----
+
+    /*package*/ static int nativeCreate(int first, int second) {
+        SumPathEffect_Delegate newDelegate = new SumPathEffect_Delegate();
+        return sManager.addDelegate(newDelegate);
+    }
+
+    // ---- Private delegate/helper methods ----
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
index 97c3cfd..048990a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
@@ -16,13 +16,10 @@
 
 package android.graphics;
 
+import com.android.ide.common.rendering.api.LayoutLog;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
-import java.awt.Paint;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-
 /**
  * Delegate implementing the native methods of android.graphics.SweepGradient
  *
@@ -47,7 +44,7 @@
     // ---- Public Helper methods ----
 
     @Override
-    public Paint getJavaPaint() {
+    public java.awt.Paint getJavaPaint() {
         return mJavaPaint;
     }
 
@@ -116,20 +113,22 @@
                 java.awt.RenderingHints       hints) {
             precomputeGradientColors();
 
-            AffineTransform canvasMatrix;
+            java.awt.geom.AffineTransform canvasMatrix;
             try {
                 canvasMatrix = xform.createInverse();
-            } catch (NoninvertibleTransformException e) {
-                Bridge.getLog().error(null, "Unable to inverse matrix in SweepGradient", e);
-                canvasMatrix = new AffineTransform();
+            } catch (java.awt.geom.NoninvertibleTransformException e) {
+                Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
+                        "Unable to inverse matrix in SweepGradient", e, null /*data*/);
+                canvasMatrix = new java.awt.geom.AffineTransform();
             }
 
-            AffineTransform localMatrix = getLocalMatrix();
+            java.awt.geom.AffineTransform localMatrix = getLocalMatrix();
             try {
                 localMatrix = localMatrix.createInverse();
-            } catch (NoninvertibleTransformException e) {
-                Bridge.getLog().error(null, "Unable to inverse matrix in SweepGradient", e);
-                localMatrix = new AffineTransform();
+            } catch (java.awt.geom.NoninvertibleTransformException e) {
+                Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
+                        "Unable to inverse matrix in SweepGradient", e, null /*data*/);
+                localMatrix = new java.awt.geom.AffineTransform();
             }
 
             return new SweepGradientPaintContext(canvasMatrix, localMatrix, colorModel);
@@ -137,12 +136,14 @@
 
         private class SweepGradientPaintContext implements java.awt.PaintContext {
 
-            private final AffineTransform mCanvasMatrix;
-            private final AffineTransform mLocalMatrix;
+            private final java.awt.geom.AffineTransform mCanvasMatrix;
+            private final java.awt.geom.AffineTransform mLocalMatrix;
             private final java.awt.image.ColorModel mColorModel;
 
-            public SweepGradientPaintContext(AffineTransform canvasMatrix,
-                    AffineTransform localMatrix, java.awt.image.ColorModel colorModel) {
+            public SweepGradientPaintContext(
+                    java.awt.geom.AffineTransform canvasMatrix,
+                    java.awt.geom.AffineTransform localMatrix,
+                    java.awt.image.ColorModel colorModel) {
                 mCanvasMatrix = canvasMatrix;
                 mLocalMatrix = localMatrix;
                 mColorModel = colorModel;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 0b54a0e..00a2a57 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.layoutlib.bridge.impl.FontLoader;
 
@@ -78,14 +80,12 @@
     public static List<Font> getFonts(int native_int) {
         Typeface_Delegate delegate = sManager.getDelegate(native_int);
         if (delegate == null) {
-            assert false;
             return null;
         }
 
         return delegate.mFonts;
     }
 
-
     // ---- native methods ----
 
     /*package*/ static synchronized int nativeCreate(String familyName, int style) {
@@ -109,7 +109,6 @@
     /*package*/ static synchronized int nativeCreateFromTypeface(int native_instance, int style) {
         Typeface_Delegate delegate = sManager.getDelegate(native_instance);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
@@ -127,13 +126,15 @@
     }
 
     /*package*/ static synchronized int nativeCreateFromAsset(AssetManager mgr, String path) {
-        // FIXME
-        throw new UnsupportedOperationException("Native delegate needed: Typeface_Delegate.nativeCreateFromAsset");
+        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+                "Typeface.createFromAsset() is not supported.", null /*throwable*/, null /*data*/);
+        return 0;
     }
 
     /*package*/ static synchronized int nativeCreateFromFile(String path) {
-        // FIXME
-        throw new UnsupportedOperationException("Native delegate needed: Typeface_Delegate.nativeCreateFromFile");
+        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+                "Typeface.createFromFile() is not supported.", null /*throwable*/, null /*data*/);
+        return 0;
     }
 
     /*package*/ static void nativeUnref(int native_instance) {
@@ -143,7 +144,6 @@
     /*package*/ static int nativeGetStyle(int native_instance) {
         Typeface_Delegate delegate = sManager.getDelegate(native_instance);
         if (delegate == null) {
-            assert false;
             return 0;
         }
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
index 0c1170d..312318a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
@@ -18,6 +18,8 @@
 
 import com.android.layoutlib.bridge.impl.DelegateManager;
 
+import java.awt.Composite;
+
 /**
  * Delegate implementing the native methods of android.graphics.Xfermode
  *
@@ -33,7 +35,7 @@
  * @see DelegateManager
  *
  */
-public class Xfermode_Delegate {
+public abstract class Xfermode_Delegate {
 
     // ---- delegate manager ----
     protected static final DelegateManager<Xfermode_Delegate> sManager =
@@ -49,6 +51,11 @@
         return sManager.getDelegate(native_instance);
     }
 
+    public abstract Composite getComposite(int alpha);
+    public abstract boolean isSupported();
+    public abstract String getSupportMessage();
+
+
     // ---- native methods ----
 
     /*package*/ static void finalizer(int native_instance) {
diff --git a/tools/layoutlib/bridge/src/android/view/SurfaceView.java b/tools/layoutlib/bridge/src/android/view/SurfaceView.java
index f7db98a..ce32da9 100644
--- a/tools/layoutlib/bridge/src/android/view/SurfaceView.java
+++ b/tools/layoutlib/bridge/src/android/view/SurfaceView.java
@@ -16,7 +16,7 @@
 
 package android.view;
 
-import com.android.layoutlib.bridge.android.MockView;
+import com.android.layoutlib.bridge.MockView;
 
 import android.content.Context;
 import android.graphics.Canvas;
diff --git a/tools/layoutlib/bridge/src/android/webkit/WebView.java b/tools/layoutlib/bridge/src/android/webkit/WebView.java
index a20a9d1..3b66188 100644
--- a/tools/layoutlib/bridge/src/android/webkit/WebView.java
+++ b/tools/layoutlib/bridge/src/android/webkit/WebView.java
@@ -16,7 +16,7 @@
 
 package android.webkit;
 
-import com.android.layoutlib.bridge.android.MockView;
+import com.android.layoutlib.bridge.MockView;
 
 import android.content.Context;
 import android.graphics.Bitmap;
diff --git a/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java
new file mode 100644
index 0000000..7fa1679
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link XmlUtils}
+ *
+ * Through the layoutlib_create tool, the original  methods of XmlUtils have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class XmlUtils_Delegate {
+    /*package*/ static final int convertValueToInt(CharSequence charSeq, int defaultValue) {
+        if (null == charSeq)
+            return defaultValue;
+
+        String nm = charSeq.toString();
+
+        // This code is copied from the original implementation. The issue is that
+        // The Dalvik libraries are able to handle Integer.parse("XXXXXXXX", 16) where XXXXXXX
+        // is > 80000000 but the Java VM cannot.
+
+        int sign = 1;
+        int index = 0;
+        int len = nm.length();
+        int base = 10;
+
+        if ('-' == nm.charAt(0)) {
+            sign = -1;
+            index++;
+        }
+
+        if ('0' == nm.charAt(index)) {
+            //  Quick check for a zero by itself
+            if (index == (len - 1))
+                return 0;
+
+            char c = nm.charAt(index + 1);
+
+            if ('x' == c || 'X' == c) {
+                index += 2;
+                base = 16;
+            } else {
+                index++;
+                base = 8;
+            }
+        }
+        else if ('#' == nm.charAt(index)) {
+            index++;
+            base = 16;
+        }
+
+        return ((int)Long.parseLong(nm.substring(index), base)) * sign;
+    }
+}
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 9de6e8f..37576b4 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -16,24 +16,27 @@
 
 package com.android.layoutlib.bridge;
 
-import com.android.layoutlib.api.Capability;
-import com.android.layoutlib.api.LayoutBridge;
-import com.android.layoutlib.api.LayoutLog;
-import com.android.layoutlib.api.SceneParams;
-import com.android.layoutlib.api.SceneResult;
-import com.android.layoutlib.api.SceneResult.SceneStatus;
+import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
+import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
+
+import com.android.ide.common.rendering.api.Capability;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.Params;
+import com.android.ide.common.rendering.api.RenderSession;
+import com.android.ide.common.rendering.api.Result;
 import com.android.layoutlib.bridge.android.BridgeAssetManager;
 import com.android.layoutlib.bridge.impl.FontLoader;
-import com.android.layoutlib.bridge.impl.LayoutSceneImpl;
+import com.android.layoutlib.bridge.impl.RenderSessionImpl;
 import com.android.ninepatch.NinePatchChunk;
 import com.android.tools.layoutlib.create.MethodAdapter;
 import com.android.tools.layoutlib.create.OverrideMethod;
 
 import android.graphics.Bitmap;
+import android.graphics.Typeface;
 import android.graphics.Typeface_Delegate;
 import android.os.Looper;
-import android.util.Finalizers;
 
+import java.io.File;
 import java.lang.ref.SoftReference;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
@@ -48,7 +51,7 @@
  * <p/>To use this bridge, simply instantiate an object of type {@link Bridge} and call
  * {@link #createScene(SceneParams)}
  */
-public final class Bridge extends LayoutBridge {
+public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
 
     public static class StaticMethodNotImplementedException extends RuntimeException {
         private static final long serialVersionUID = 1L;
@@ -134,27 +137,17 @@
      */
     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, Throwable t) {
-            String message = t.getMessage();
-            if (message == null) {
-                message = t.getClass().getName();
-            }
-
+        public void error(String tag, String message, Throwable throwable, Object data) {
             System.err.println(message);
         }
 
         @Override
-        public void error(String tag, String message, Throwable throwable) {
-            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);
         }
     };
@@ -170,7 +163,7 @@
 
     @Override
     public int getApiLevel() {
-        return LayoutBridge.API_CURRENT;
+        return com.android.ide.common.rendering.api.Bridge.API_CURRENT;
     }
 
     @Override
@@ -178,12 +171,9 @@
         return mCapabilities;
     }
 
-    /*
-     * (non-Javadoc)
-     * @see com.android.layoutlib.api.ILayoutLibBridge#init(java.lang.String, java.util.Map)
-     */
     @Override
-    public boolean init(String fontOsLocation, Map<String, Map<String, Integer>> enumValueMap) {
+    public boolean init(File fontLocation, Map<String, Map<String, Integer>> enumValueMap,
+            LayoutLog log) {
         sEnumValueMap = enumValueMap;
 
         // don't use EnumSet.allOf(), because the bridge doesn't come with its specific version
@@ -195,11 +185,10 @@
                 Capability.RENDER,
                 Capability.EMBEDDED_LAYOUT,
                 Capability.VIEW_MANIPULATION,
-                Capability.ANIMATE);
+                Capability.PLAY_ANIMATION,
+                Capability.ANIMATED_VIEW_MANIPULATION);
 
 
-        Finalizers.init();
-
         BridgeAssetManager.initSystem();
 
         // When DEBUG_LAYOUT is set and is not 0 or false, setup a default listener
@@ -218,7 +207,7 @@
                 @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
@@ -232,7 +221,7 @@
         }
 
         // load the fonts.
-        FontLoader fontLoader = FontLoader.create(fontOsLocation);
+        FontLoader fontLoader = FontLoader.create(fontLocation.getAbsolutePath());
         if (fontLoader != null) {
             Typeface_Delegate.init(fontLoader);
         } else {
@@ -242,11 +231,6 @@
         // now parse com.android.internal.R (and only this one as android.R is a subset of
         // the internal version), and put the content in the maps.
         try {
-            // WARNING: this only works because the class is already loaded, and therefore
-            // the objects returned by Field.get() are the same as the ones used by
-            // the code accessing the R class.
-            // int[] does not implement equals/hashCode, and if the parsing used a different class
-            // loader for the R class, this would NOT work.
             Class<?> r = com.android.internal.R.class;
 
             for (Class<?> inner : r.getDeclaredClasses()) {
@@ -262,7 +246,9 @@
                     if (Modifier.isStatic(modifiers)) {
                         Class<?> type = f.getType();
                         if (type.isArray() && type.getComponentType() == int.class) {
-                            // if the object is an int[] we put it in sRArrayMap
+                            // if the object is an int[] we put it in sRArrayMap using an IntArray
+                            // wrapper that properly implements equals and hashcode for the array
+                            // objects, as required by the map contract.
                             sRArrayMap.put(new IntArray((int[]) f.get(null)), f.getName());
                         } else if (type == int.class) {
                             Integer value = (Integer) f.get(null);
@@ -274,12 +260,12 @@
                     }
                 }
             }
-        } catch (IllegalArgumentException e) {
-            // FIXME: log/return the error (there's no logger object at this point!)
-            e.printStackTrace();
-            return false;
-        } catch (IllegalAccessException e) {
-            e.printStackTrace();
+        } catch (Throwable throwable) {
+            if (log != null) {
+                log.error(LayoutLog.TAG_BROKEN,
+                        "Failed to load com.android.internal.R from the layout library jar",
+                        throwable);
+            }
             return false;
         }
 
@@ -289,6 +275,10 @@
     @Override
     public boolean dispose() {
         BridgeAssetManager.clearSystem();
+
+        // dispose of the default typeface.
+        Typeface.sDefaults = null;
+
         return true;
     }
 
@@ -302,10 +292,10 @@
      * @since 5
      */
     @Override
-    public BridgeLayoutScene createScene(SceneParams params) {
+    public RenderSession createSession(Params params) {
         try {
-            SceneResult lastResult = SceneStatus.SUCCESS.createResult();
-            LayoutSceneImpl scene = new LayoutSceneImpl(params);
+            Result lastResult = SUCCESS.createResult();
+            RenderSessionImpl scene = new RenderSessionImpl(params);
             try {
                 prepareThread();
                 lastResult = scene.init(params.getTimeout());
@@ -320,15 +310,15 @@
                 cleanupThread();
             }
 
-            return new BridgeLayoutScene(scene, lastResult);
+            return new BridgeRenderSession(scene, lastResult);
         } catch (Throwable t) {
             // get the real cause of the exception.
             Throwable t2 = t;
             while (t2.getCause() != null) {
                 t2 = t.getCause();
             }
-            return new BridgeLayoutScene(null,
-                    SceneStatus.ERROR_UNKNOWN.createResult(t2.getMessage(), t2));
+            return new BridgeRenderSession(null,
+                    ERROR_UNKNOWN.createResult(t2.getMessage(), t));
         }
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
index 791e53b..194687e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
@@ -48,6 +48,7 @@
 
     public final static String PREFIX_ANDROID = "android:";
 
+    public final static String RES_ANIMATOR = "animator";
     public final static String RES_STYLE = "style";
     public final static String RES_ATTR = "attr";
     public final static String RES_DIMEN = "dimen";
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java
deleted file mode 100644
index f43559f..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge;
-
-import com.android.layoutlib.api.IXmlPullParser;
-import com.android.layoutlib.api.LayoutScene;
-import com.android.layoutlib.api.SceneParams;
-import com.android.layoutlib.api.SceneResult;
-import com.android.layoutlib.api.ViewInfo;
-import com.android.layoutlib.bridge.impl.LayoutSceneImpl;
-
-import android.view.View;
-import android.view.ViewGroup;
-
-import java.awt.image.BufferedImage;
-import java.util.Map;
-
-/**
- * An implementation of {@link LayoutScene}.
- *
- * This is a pretty basic class that does almost nothing. All of the work is done in
- * {@link LayoutSceneImpl}.
- *
- */
-public class BridgeLayoutScene extends LayoutScene {
-
-    private final LayoutSceneImpl mScene;
-    private SceneResult mLastResult;
-
-    @Override
-    public SceneResult getResult() {
-        return mLastResult;
-    }
-
-    @Override
-    public BufferedImage getImage() {
-        return mScene.getImage();
-    }
-
-    @Override
-    public ViewInfo getRootView() {
-        return mScene.getViewInfo();
-    }
-
-    @Override
-    public Map<String, String> getDefaultViewPropertyValues(Object viewObject) {
-        return mScene.getDefaultViewPropertyValues(viewObject);
-    }
-
-    @Override
-    public SceneResult render(long timeout) {
-        try {
-            Bridge.prepareThread();
-            mLastResult = mScene.acquire(timeout);
-            if (mLastResult.isSuccess()) {
-                mLastResult = mScene.render();
-            }
-        } finally {
-            mScene.release();
-            Bridge.cleanupThread();
-        }
-
-        return mLastResult;
-    }
-
-    @Override
-    public SceneResult animate(Object targetObject, String animationName,
-            boolean isFrameworkAnimation, IAnimationListener listener) {
-        try {
-            Bridge.prepareThread();
-            mLastResult = mScene.acquire(SceneParams.DEFAULT_TIMEOUT);
-            if (mLastResult.isSuccess()) {
-                mLastResult = mScene.animate(targetObject, animationName, isFrameworkAnimation,
-                        listener);
-            }
-        } finally {
-            mScene.release();
-            Bridge.cleanupThread();
-        }
-
-        return mLastResult;
-    }
-
-    @Override
-    public SceneResult insertChild(Object parentView, IXmlPullParser childXml, int index,
-            IAnimationListener listener) {
-        if (parentView instanceof ViewGroup == false) {
-            throw new IllegalArgumentException("parentView is not a ViewGroup");
-        }
-
-        try {
-            Bridge.prepareThread();
-            mLastResult = mScene.acquire(SceneParams.DEFAULT_TIMEOUT);
-            if (mLastResult.isSuccess()) {
-                mLastResult = mScene.insertChild((ViewGroup) parentView, childXml, index, listener);
-            }
-        } finally {
-            mScene.release();
-            Bridge.cleanupThread();
-        }
-
-        return mLastResult;
-    }
-
-
-    @Override
-    public SceneResult moveChild(Object parentView, Object childView, int index,
-            Map<String, String> layoutParams, IAnimationListener listener) {
-        if (parentView instanceof ViewGroup == false) {
-            throw new IllegalArgumentException("parentView is not a ViewGroup");
-        }
-        if (childView instanceof View == false) {
-            throw new IllegalArgumentException("childView is not a View");
-        }
-
-        try {
-            Bridge.prepareThread();
-            mLastResult = mScene.acquire(SceneParams.DEFAULT_TIMEOUT);
-            if (mLastResult.isSuccess()) {
-                mLastResult = mScene.moveChild((ViewGroup) parentView, (View) childView, index,
-                        layoutParams, listener);
-            }
-        } finally {
-            mScene.release();
-            Bridge.cleanupThread();
-        }
-
-        return mLastResult;
-    }
-
-    @Override
-    public SceneResult removeChild(Object childView, IAnimationListener listener) {
-        if (childView instanceof View == false) {
-            throw new IllegalArgumentException("childView is not a View");
-        }
-
-        try {
-            Bridge.prepareThread();
-            mLastResult = mScene.acquire(SceneParams.DEFAULT_TIMEOUT);
-            if (mLastResult.isSuccess()) {
-                mLastResult = mScene.removeChild((View) childView, listener);
-            }
-        } finally {
-            mScene.release();
-            Bridge.cleanupThread();
-        }
-
-        return mLastResult;
-    }
-
-    @Override
-    public void dispose() {
-    }
-
-    /*package*/ BridgeLayoutScene(LayoutSceneImpl scene, SceneResult lastResult) {
-        mScene = scene;
-        mScene.setScene(this);
-        mLastResult = lastResult;
-    }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
new file mode 100644
index 0000000..bc2301d
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge;
+
+import com.android.ide.common.rendering.api.IAnimationListener;
+import com.android.ide.common.rendering.api.ILayoutPullParser;
+import com.android.ide.common.rendering.api.Params;
+import com.android.ide.common.rendering.api.RenderSession;
+import com.android.ide.common.rendering.api.Result;
+import com.android.ide.common.rendering.api.ViewInfo;
+import com.android.ide.common.rendering.api.Result.Status;
+import com.android.layoutlib.bridge.impl.RenderSessionImpl;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+
+import java.awt.image.BufferedImage;
+import java.util.Map;
+
+/**
+ * An implementation of {@link RenderSession}.
+ *
+ * This is a pretty basic class that does almost nothing. All of the work is done in
+ * {@link RenderSessionImpl}.
+ *
+ */
+public class BridgeRenderSession extends RenderSession {
+
+    private final RenderSessionImpl mSession;
+    private Result mLastResult;
+
+    @Override
+    public Result getResult() {
+        return mLastResult;
+    }
+
+    @Override
+    public BufferedImage getImage() {
+        return mSession.getImage();
+    }
+
+    @Override
+    public ViewInfo getRootView() {
+        return mSession.getViewInfo();
+    }
+
+    @Override
+    public Map<String, String> getDefaultProperties(Object viewObject) {
+        return mSession.getDefaultProperties(viewObject);
+    }
+
+    @Override
+    public Result getProperty(Object objectView, String propertyName) {
+        // TODO Auto-generated method stub
+        return super.getProperty(objectView, propertyName);
+    }
+
+    @Override
+    public Result setProperty(Object objectView, String propertyName, String propertyValue) {
+        // TODO Auto-generated method stub
+        return super.setProperty(objectView, propertyName, propertyValue);
+    }
+
+    @Override
+    public Result getViewParent(Object viewObject) {
+        if (viewObject instanceof View) {
+            return Status.SUCCESS.createResult(((View)viewObject).getParent());
+        }
+
+        throw new IllegalArgumentException("viewObject is not a View");
+    }
+
+    @Override
+    public Result getViewIndex(Object viewObject) {
+        if (viewObject instanceof View) {
+            View view = (View) viewObject;
+            ViewParent parentView = view.getParent();
+
+            if (parentView instanceof ViewGroup) {
+                Status.SUCCESS.createResult(((ViewGroup) parentView).indexOfChild(view));
+            }
+
+            return Status.SUCCESS.createResult();
+        }
+
+        throw new IllegalArgumentException("viewObject is not a View");
+    }
+
+    @Override
+    public Result render(long timeout) {
+        try {
+            Bridge.prepareThread();
+            mLastResult = mSession.acquire(timeout);
+            if (mLastResult.isSuccess()) {
+                mLastResult = mSession.render();
+            }
+        } finally {
+            mSession.release();
+            Bridge.cleanupThread();
+        }
+
+        return mLastResult;
+    }
+
+    @Override
+    public Result animate(Object targetObject, String animationName,
+            boolean isFrameworkAnimation, IAnimationListener listener) {
+        try {
+            Bridge.prepareThread();
+            mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+            if (mLastResult.isSuccess()) {
+                mLastResult = mSession.animate(targetObject, animationName, isFrameworkAnimation,
+                        listener);
+            }
+        } finally {
+            mSession.release();
+            Bridge.cleanupThread();
+        }
+
+        return mLastResult;
+    }
+
+    @Override
+    public Result insertChild(Object parentView, ILayoutPullParser childXml, int index,
+            IAnimationListener listener) {
+        if (parentView instanceof ViewGroup == false) {
+            throw new IllegalArgumentException("parentView is not a ViewGroup");
+        }
+
+        try {
+            Bridge.prepareThread();
+            mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+            if (mLastResult.isSuccess()) {
+                mLastResult = mSession.insertChild((ViewGroup) parentView, childXml, index,
+                        listener);
+            }
+        } finally {
+            mSession.release();
+            Bridge.cleanupThread();
+        }
+
+        return mLastResult;
+    }
+
+
+    @Override
+    public Result moveChild(Object parentView, Object childView, int index,
+            Map<String, String> layoutParams, IAnimationListener listener) {
+        if (parentView instanceof ViewGroup == false) {
+            throw new IllegalArgumentException("parentView is not a ViewGroup");
+        }
+        if (childView instanceof View == false) {
+            throw new IllegalArgumentException("childView is not a View");
+        }
+
+        try {
+            Bridge.prepareThread();
+            mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+            if (mLastResult.isSuccess()) {
+                mLastResult = mSession.moveChild((ViewGroup) parentView, (View) childView, index,
+                        layoutParams, listener);
+            }
+        } finally {
+            mSession.release();
+            Bridge.cleanupThread();
+        }
+
+        return mLastResult;
+    }
+
+    @Override
+    public Result removeChild(Object childView, IAnimationListener listener) {
+        if (childView instanceof View == false) {
+            throw new IllegalArgumentException("childView is not a View");
+        }
+
+        try {
+            Bridge.prepareThread();
+            mLastResult = mSession.acquire(Params.DEFAULT_TIMEOUT);
+            if (mLastResult.isSuccess()) {
+                mLastResult = mSession.removeChild((View) childView, listener);
+            }
+        } finally {
+            mSession.release();
+            Bridge.cleanupThread();
+        }
+
+        return mLastResult;
+    }
+
+    @Override
+    public void dispose() {
+    }
+
+    /*package*/ BridgeRenderSession(RenderSessionImpl scene, Result lastResult) {
+        mSession = scene;
+        if (scene != null) {
+            mSession.setScene(this);
+        }
+        mLastResult = lastResult;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
new file mode 100644
index 0000000..1ca3182
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+/**
+ * Base class for mocked views.
+ * 
+ * TODO: implement onDraw and draw a rectangle in a random color with the name of the class
+ * (or better the id of the view).
+ */
+public class MockView extends TextView {
+    
+    public MockView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        
+        setText(this.getClass().getSimpleName());
+        setTextColor(0xFF000000);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        canvas.drawARGB(0xFF, 0x7F, 0x7F, 0x7F);
+
+        super.onDraw(canvas);
+    }
+}
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 f484e7a..82e217a 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
@@ -16,9 +16,10 @@
 
 package com.android.layoutlib.bridge.android;
 
-import com.android.layoutlib.api.IProjectCallback;
-import com.android.layoutlib.api.ResourceValue;
-import com.android.layoutlib.api.StyleResourceValue;
+import com.android.ide.common.rendering.api.IProjectCallback;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.StyleResourceValue;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.BridgeConstants;
 import com.android.layoutlib.bridge.impl.Stack;
@@ -92,7 +93,7 @@
 
     // cache for TypedArray generated from IStyleResourceValue object
     private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache;
-    private BridgeInflater mInflater;
+    private BridgeInflater mBridgeInflater;
 
     private final IProjectCallback mProjectCallback;
     private BridgeContentResolver mContentResolver;
@@ -105,11 +106,11 @@
      * @param themeName The name of the theme to use.
      * @param projectResources the resources of the project. The map contains (String, map) pairs
      * where the string is the type of the resource reference used in the layout file, and the
-     * map contains (String, {@link IResourceValue}) pairs where the key is the resource name,
+     * map contains (String, {@link }) pairs where the key is the resource name,
      * and the value is the resource value.
      * @param frameworkResources the framework resources. The map contains (String, map) pairs
      * where the string is the type of the resource reference used in the layout file, and the map
-     * contains (String, {@link IResourceValue}) pairs where the key is the resource name, and the
+     * contains (String, {@link ResourceValue}) pairs where the key is the resource name, and the
      * value is the resource value.
      * @param styleInheritanceMap
      * @param projectCallback
@@ -160,7 +161,7 @@
     }
 
     public void setBridgeInflater(BridgeInflater inflater) {
-        mInflater = inflater;
+        mBridgeInflater = inflater;
     }
 
     public void addViewKey(View view, Object viewKey) {
@@ -221,7 +222,7 @@
 
     @Override
     public LayoutInflater getLayoutInflater() {
-        return mInflater;
+        return mBridgeInflater;
     }
 
     // ------------ Context methods
@@ -244,7 +245,7 @@
     @Override
     public Object getSystemService(String service) {
         if (LAYOUT_INFLATER_SERVICE.equals(service)) {
-            return mInflater;
+            return mBridgeInflater;
         }
 
         // AutoCompleteTextView and MultiAutoCompleteTextView want a window
@@ -253,6 +254,11 @@
             return null;
         }
 
+        // needed by SearchView
+        if (INPUT_METHOD_SERVICE.equals(service)) {
+            return null;
+        }
+
         throw new UnsupportedOperationException("Unsupported Service: " + service);
     }
 
@@ -321,7 +327,7 @@
 
             isPlatformFile = parser.isPlatformFile();
 
-            Object key = parser.getViewKey();
+            Object key = parser.getViewCookie();
             if (key != null) {
                 defaultPropMap = mDefaultPropMaps.get(key);
                 if (defaultPropMap == null) {
@@ -336,7 +342,8 @@
             isPlatformFile = false;
         } else if (set != null) { // null parser is ok
             // really this should not be happening since its instantiated in Bridge
-            Bridge.getLog().error(null, "Parser is not a BridgeXmlBlockParser!");
+            Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                    "Parser is not a BridgeXmlBlockParser!", null /*data*/);
             return null;
         }
 
@@ -382,8 +389,10 @@
                         defStyleValues = (StyleResourceValue)item;
                     }
                 } else {
-                    // TODO: log the error properly
-                    System.out.println("Failed to find defStyle: " + defStyleName);
+                    Bridge.getLog().error(null,
+                            String.format(
+                                    "Failed to find style '%s' in current theme", defStyleName),
+                            null /*data*/);
                 }
             }
         }
@@ -440,7 +449,7 @@
                 } 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));
                 }
             }
         }
@@ -493,31 +502,34 @@
     /**
      * Resolves the value of a resource, if the value references a theme or resource value.
      * <p/>
-     * This method ensures that it returns a {@link IResourceValue} object that does not
+     * This method ensures that it returns a {@link ResourceValue} object that does not
      * reference another resource.
      * If the resource cannot be resolved, it returns <code>null</code>.
      * <p/>
      * If a value that does not need to be resolved is given, the method will return a new
-     * instance of IResourceValue that contains the input value.
+     * instance of {@link ResourceValue} that contains the input value.
      *
      * @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 IResourceValue referenced by this value
-        ResourceValue resValue = findResValue(value, false /*forceFrameworkOnly*/);
+        // get the ResourceValue referenced by this value
+        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 IResourceValue. the isFramework flag doesn't
+        // 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.
@@ -525,9 +537,9 @@
     }
 
     /**
-     * Returns the {@link IResourceValue} referenced by the value of <var>value</var>.
+     * Returns the {@link ResourceValue} referenced by the value of <var>value</var>.
      * <p/>
-     * This method ensures that it returns a {@link IResourceValue} object that does not
+     * This method ensures that it returns a {@link ResourceValue} object that does not
      * reference another resource.
      * If the resource cannot be resolved, it returns <code>null</code>.
      * <p/>
@@ -535,7 +547,7 @@
      * value.
      *
      * @param value the value containing the reference to resolve.
-     * @return a {@link IResourceValue} object or <code>null</code>
+     * @return a {@link ResourceValue} object or <code>null</code>
      */
     public ResourceValue resolveResValue(ResourceValue value) {
         if (value == null) {
@@ -547,7 +559,7 @@
             return value;
         }
 
-        // else attempt to find another IResourceValue referenced by this one.
+        // else attempt to find another ResourceValue referenced by this one.
         ResourceValue resolvedValue = findResValue(value.getValue(), value.isFramework());
 
         // if the value did not reference anything, then we simply return the input value
@@ -560,7 +572,7 @@
     }
 
     /**
-     * Searches for, and returns a {@link IResourceValue} by its reference.
+     * Searches for, and returns a {@link ResourceValue} by its reference.
      * <p/>
      * The reference format can be:
      * <pre>@resType/resName</pre>
@@ -577,7 +589,7 @@
      * @param reference the resource reference to search for.
      * @param forceFrameworkOnly if true all references are considered to be toward framework
      *      resource even if the reference does not include the android: prefix.
-     * @return a {@link IResourceValue} or <code>null</code>.
+     * @return a {@link ResourceValue} or <code>null</code>.
      */
     ResourceValue findResValue(String reference, boolean forceFrameworkOnly) {
         if (reference == null) {
@@ -591,7 +603,7 @@
 
             boolean frameworkOnly = false;
 
-            // eleminate the prefix from the string
+            // eliminate the prefix from the string
             if (reference.startsWith(BridgeConstants.PREFIX_ANDROID_THEME_REF)) {
                 frameworkOnly = true;
                 reference = reference.substring(BridgeConstants.PREFIX_ANDROID_THEME_REF.length());
@@ -670,14 +682,14 @@
     }
 
     /**
-     * Searches for, and returns a {@link IResourceValue} by its name, and type.
+     * Searches for, and returns a {@link ResourceValue} by its name, and type.
      * @param resType the type of the resource
      * @param resName  the name of the resource
      * @param frameworkOnly if <code>true</code>, the method does not search in the
      * project resources
      */
     private ResourceValue findResValue(String resType, String resName, boolean frameworkOnly) {
-        // map of IResouceValue for the given type
+        // map of ResouceValue for the given type
         Map<String, ResourceValue> typeMap;
 
         // if allowed, search in the project resources first.
@@ -698,9 +710,26 @@
             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.
+        // This is normal if the resource is an ID that is generated automatically.
+        // For other resources, we output a warning
+        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,
+                    new ResourceValue(resType, resName, frameworkOnly));
+        }
         return null;
     }
 
@@ -739,11 +768,11 @@
     }
 
     /**
-     * Returns the {@link IResourceValue} matching a given name in a given style. If the
+     * Returns the {@link ResourceValue} matching a given name in a given style. If the
      * item is not directly available in the style, the method looks in its parent style.
      * @param style the style to search in
      * @param itemName the name of the item to search for.
-     * @return the {@link IResourceValue} object or <code>null</code>
+     * @return the {@link ResourceValue} object or <code>null</code>
      */
     public ResourceValue findItemInStyle(StyleResourceValue style, String itemName) {
         ResourceValue item = style.findValue(itemName);
@@ -871,8 +900,8 @@
         return null;
     }
 
-    int getFrameworkIdValue(String idName, int defValue) {
-        Integer value = Bridge.getResourceValue(BridgeConstants.RES_ID, idName);
+    int getFrameworkResourceValue(String resType, String resName, int defValue) {
+        Integer value = Bridge.getResourceValue(resType, resName);
         if (value != null) {
             return value.intValue();
         }
@@ -880,9 +909,9 @@
         return defValue;
     }
 
-    int getProjectIdValue(String idName, int defValue) {
+    int getProjectResourceValue(String resType, String resName, int defValue) {
         if (mProjectCallback != null) {
-            Integer value = mProjectCallback.getResourceValue(BridgeConstants.RES_ID, idName);
+            Integer value = mProjectCallback.getResourceValue(resType, resName);
             if (value != null) {
                 return value.intValue();
             }
@@ -1303,4 +1332,15 @@
     public Context getApplicationContext() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public void startActivities(Intent[] arg0) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean isRestricted() {
+        return false;
+    }
 }
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 dbf83e7..e95d295 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
@@ -16,8 +16,9 @@
 
 package com.android.layoutlib.bridge.android;
 
-import com.android.layoutlib.api.IProjectCallback;
-import com.android.layoutlib.api.ResourceValue;
+import com.android.ide.common.rendering.api.IProjectCallback;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.BridgeConstants;
 
@@ -178,8 +179,10 @@
 
                         return inflate(bridgeParser, root);
                     } catch (Exception e) {
-                        Bridge.getLog().error(null, e);
-                        // return null below.
+                        Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
+                                "Failed to parse file " + f.getAbsolutePath(), e, null /*data*/);
+
+                        return null;
                     }
                 }
             }
@@ -217,14 +220,14 @@
                 BridgeXmlBlockParser parser = (BridgeXmlBlockParser) attrs;
 
                 // get the view key
-                Object viewKey = parser.getViewKey();
+                Object viewKey = parser.getViewCookie();
 
                 // if there's no view key and the depth is 1 (ie this is the first tag),
                 // look for a previous parser in the context, and check if this one has a viewkey.
                 if (viewKey == null && parser.getDepth() == 1) {
                     BridgeXmlBlockParser previousParser = bc.getPreviousParser();
                     if (previousParser != null) {
-                        viewKey = previousParser.getViewKey();
+                        viewKey = previousParser.getViewCookie();
                     }
                 }
 
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 c1e2046..23d81a2 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
@@ -16,8 +16,9 @@
 
 package com.android.layoutlib.bridge.android;
 
-import com.android.layoutlib.api.IProjectCallback;
-import com.android.layoutlib.api.ResourceValue;
+import com.android.ide.common.rendering.api.IProjectCallback;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.BridgeConstants;
 import com.android.layoutlib.bridge.impl.ResourceHelper;
@@ -43,7 +44,6 @@
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
-import java.io.IOException;
 import java.io.InputStream;
 
 /**
@@ -143,6 +143,8 @@
             try {
                 return ResourceHelper.getColor(value.getValue());
             } catch (NumberFormatException e) {
+                Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e,
+                        null /*data*/);
                 return 0;
             }
         }
@@ -174,19 +176,26 @@
                         return ColorStateList.createFromXml(this,
                                 new BridgeXmlBlockParser(parser, mContext, resValue.isFramework()));
                     } catch (XmlPullParserException e) {
-                        Bridge.getLog().error(null, e);
-                    } catch (FileNotFoundException e) {
-                        // will not happen, since we pre-check
-                    } catch (IOException e) {
-                        Bridge.getLog().error(null, e);
-                    }
+                        Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                                "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, null /*data*/);
 
+                        return null;
+                    }
                 } else {
                     // try to load the color state list from an int
                     try {
                         int color = ResourceHelper.getColor(value);
                         return ColorStateList.valueOf(color);
                     } catch (NumberFormatException e) {
+                        Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
+                                "Failed to convert " + value + " into a ColorStateList", e,
+                                null /*data*/);
                         return null;
                     }
                 }
@@ -245,7 +254,8 @@
                     return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
                 }
             } catch (XmlPullParserException e) {
-                Bridge.getLog().error(null, e);
+                Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                        "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.
@@ -279,7 +289,8 @@
                     return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
                 }
             } catch (XmlPullParserException e) {
-                Bridge.getLog().error(null, e);
+                Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                        "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.
@@ -294,7 +305,6 @@
         return null;
     }
 
-
     @Override
     public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
         return mContext.obtainStyledAttributes(set, attrs);
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 fcbf5fa..84bb4d1 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
@@ -16,15 +16,17 @@
 
 package com.android.layoutlib.bridge.android;
 
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.StyleResourceValue;
 import com.android.internal.util.XmlUtils;
-import com.android.layoutlib.api.ResourceValue;
-import com.android.layoutlib.api.StyleResourceValue;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.BridgeConstants;
 import com.android.layoutlib.bridge.impl.ResourceHelper;
 
 import org.kxml2.io.KXmlParser;
 import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -43,30 +45,30 @@
  */
 public final class BridgeTypedArray extends TypedArray {
 
-    private BridgeResources mResources;
+    private BridgeResources mBridgeResources;
     private BridgeContext mContext;
-    private ResourceValue[] mData;
+    private ResourceValue[] mResourceData;
     private String[] mNames;
     private final boolean mPlatformFile;
 
     public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len,
             boolean platformFile) {
         super(null, null, null, 0);
-        mResources = resources;
+        mBridgeResources = resources;
         mContext = context;
         mPlatformFile = platformFile;
-        mData = new ResourceValue[len];
+        mResourceData = new ResourceValue[len];
         mNames = new String[len];
     }
 
     /** A bridge-specific method that sets a value in the type array */
     public void bridgeSetValue(int index, String name, ResourceValue value) {
-        mData[index] = value;
+        mResourceData[index] = value;
         mNames[index] = name;
     }
 
     /**
-     * Seals the array after all calls to {@link #bridgeSetValue(int, String, IResourceValue)} have
+     * Seals the array after all calls to {@link #bridgeSetValue(int, String, ResourceValue)} have
      * been done.
      * <p/>This allows to compute the list of non default values, permitting
      * {@link #getIndexCount()} to return the proper value.
@@ -75,7 +77,7 @@
         // fills TypedArray.mIndices which is used to implement getIndexCount/getIndexAt
         // first count the array size
         int count = 0;
-        for (ResourceValue data : mData) {
+        for (ResourceValue data : mResourceData) {
             if (data != null) {
                 count++;
             }
@@ -87,8 +89,8 @@
 
         // fill the array with the indices.
         int index = 1;
-        for (int i = 0 ; i < mData.length ; i++) {
-            if (mData[i] != null) {
+        for (int i = 0 ; i < mResourceData.length ; i++) {
+            if (mResourceData[i] != null) {
                 mIndices[index++] = i;
             }
         }
@@ -99,7 +101,7 @@
      */
     @Override
     public int length() {
-        return mData.length;
+        return mResourceData.length;
     }
 
     /**
@@ -107,7 +109,7 @@
      */
     @Override
     public Resources getResources() {
-        return mResources;
+        return mBridgeResources;
     }
 
     /**
@@ -120,9 +122,9 @@
      */
     @Override
     public CharSequence getText(int index) {
-        if (mData[index] != null) {
+        if (mResourceData[index] != null) {
             // FIXME: handle styled strings!
-            return mData[index].getValue();
+            return mResourceData[index].getValue();
         }
 
         return null;
@@ -138,8 +140,8 @@
      */
     @Override
     public String getString(int index) {
-        if (mData[index] != null) {
-            return mData[index].getValue();
+        if (mResourceData[index] != null) {
+            return mResourceData[index].getValue();
         }
 
         return null;
@@ -155,11 +157,11 @@
      */
     @Override
     public boolean getBoolean(int index, boolean defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
         if (s != null) {
             return XmlUtils.convertValueToBoolean(s, defValue);
         }
@@ -177,11 +179,11 @@
      */
     @Override
     public int getInt(int index, int defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
 
         try {
             return (s == null) ? defValue : XmlUtils.convertValueToInt(s, defValue);
@@ -205,9 +207,10 @@
                 if (i != null) {
                     result |= i.intValue();
                 } else {
-                    Bridge.getLog().warning(null, String.format(
-                            "Unknown constant \"%s\" in attribute \"%2$s\"",
-                            keyword, mNames[index]));
+                    Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
+                            String.format(
+                                "\"%s\" in attribute \"%2$s\" is not a valid value",
+                                keyword, mNames[index]), null /*data*/);
                 }
             }
             return result;
@@ -225,19 +228,20 @@
      */
     @Override
     public float getFloat(int index, float defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
 
         if (s != null) {
             try {
                 return Float.parseFloat(s);
             } catch (NumberFormatException e) {
-                Bridge.getLog().warning(null, String.format(
-                        "Unable to convert \"%s\" into a float in attribute \"%2$s\"",
-                        s, mNames[index]));
+                Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
+                        String.format(
+                            "\"%s\" in attribute \"%2$s\" cannot be converted to float.",
+                            s, mNames[index]), null /*data*/);
 
                 // we'll return the default value below.
             }
@@ -259,17 +263,15 @@
      */
     @Override
     public int getColor(int index, int defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
         try {
             return ResourceHelper.getColor(s);
         } catch (NumberFormatException e) {
-            Bridge.getLog().warning(null, String.format(
-                    "Unable to convert \"%s\" into a color in attribute \"%2$s\"",
-                    s, mNames[index]));
+            Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, null /*data*/);
 
             // we'll return the default value below.
         }
@@ -288,27 +290,20 @@
      */
     @Override
     public ColorStateList getColorStateList(int index) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return null;
         }
 
-        String value = mData[index].getValue();
+        String value = mResourceData[index].getValue();
 
         if (value == null) {
             return null;
         }
 
-        try {
-            int color = ResourceHelper.getColor(value);
-            return ColorStateList.valueOf(color);
-        } catch (NumberFormatException e) {
-            // if it's not a color value, we'll attempt to read the xml based color below.
-        }
-
         // let the framework inflate the ColorStateList from the XML file.
-        try {
-            File f = new File(value);
-            if (f.isFile()) {
+        File f = new File(value);
+        if (f.isFile()) {
+            try {
                 KXmlParser parser = new KXmlParser();
                 parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
                 parser.setInput(new FileReader(f));
@@ -318,20 +313,28 @@
                         // FIXME: we need to know if this resource is platform or not
                         new BridgeXmlBlockParser(parser, mContext, false));
                 return colorStateList;
-            }
-        } 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, e);
+            } catch (XmlPullParserException e) {
+                Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                        "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, null /*data*/);
 
-            // return null below.
+                return null;
+            }
         }
 
-        // looks like were unable to resolve the color value.
+        try {
+            int color = ResourceHelper.getColor(value);
+            return ColorStateList.valueOf(color);
+        } catch (NumberFormatException e) {
+            Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, null /*data*/);
+        }
+
         assert false;
-        Bridge.getLog().warning(null, String.format(
-                "Unable to resolve color value \"%1$s\" in attribute \"%2$s\"",
-                value, mNames[index]));
 
         return null;
     }
@@ -347,19 +350,20 @@
      */
     @Override
     public int getInteger(int index, int defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
 
         if (s != null) {
             try {
                 return Integer.parseInt(s);
             } catch (NumberFormatException e) {
-                Bridge.getLog().warning(null, String.format(
-                        "Unable to convert \"%s\" into a integer in attribute \"%2$s\"",
-                        s, mNames[index]));
+                Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
+                        String.format(
+                            "\"%s\" in attribute \"%2$s\" cannont be converted to an integer.",
+                            s, mNames[index]), null /*data*/);
 
                 // The default value is returned below.
             }
@@ -386,11 +390,11 @@
      */
     @Override
     public float getDimension(int index, float defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
 
         if (s == null) {
             return defValue;
@@ -402,14 +406,16 @@
         }
 
         if (ResourceHelper.stringToFloat(s, mValue)) {
-            return mValue.getDimension(mResources.mMetrics);
+            return mValue.getDimension(mBridgeResources.mMetrics);
         }
 
         // looks like we were unable to resolve the dimension value
+        Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
+                String.format(
+                    "\"%1$s\" in attribute \"%2$s\" is not a valid format.",
+                    s, mNames[index]), null /*data*/);
+
         assert false;
-        Bridge.getLog().warning(null, String.format(
-                "Unable to resolve dimension value \"%1$s\" in attribute \"%2$s\"",
-                s, mNames[index]));
 
         return defValue;
     }
@@ -456,11 +462,11 @@
      */
     @Override
     public int getDimensionPixelSize(int index, int defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
 
         if (s == null) {
             return defValue;
@@ -522,11 +528,11 @@
      */
     @Override
     public float getFraction(int index, int base, int pbase, float defValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return defValue;
         }
 
-        String value = mData[index].getValue();
+        String value = mResourceData[index].getValue();
         if (value == null) {
             return defValue;
         }
@@ -536,10 +542,12 @@
         }
 
         // looks like we were unable to resolve the fraction value
+        Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
+                String.format(
+                    "\"%1$s\" in attribute \"%2$s\" cannont be converted to a fraction.",
+                    value, mNames[index]), null /*data*/);
+
         assert false;
-        Bridge.getLog().warning(null, String.format(
-                "Unable to resolve fraction value \"%1$s\" in attribute \"%2$s\"",
-                value, mNames[index]));
 
         return defValue;
     }
@@ -560,8 +568,8 @@
      */
     @Override
     public int getResourceId(int index, int defValue) {
-        // get the IResource for this index
-        ResourceValue resValue = mData[index];
+        // get the Resource for this index
+        ResourceValue resValue = mResourceData[index];
 
         // no data, return the default value.
         if (resValue == null) {
@@ -574,19 +582,21 @@
             return mContext.getDynamicIdByStyle((StyleResourceValue)resValue);
         }
 
-        // if the attribute was a reference to an id, and not a declaration of an id (@+id), then
-        // the xml attribute value was "resolved" which leads us to a IResourceValue with
-        // getType() returning "id" and getName() returning the id name
+        // if the attribute was a reference to a resource, and not a declaration of an id (@+id),
+        // then the xml attribute value was "resolved" which leads us to a ResourceValue with a
+        // valid getType() and getName() returning a resource name.
         // (and getValue() returning null!). We need to handle this!
-        if (resValue.getType() != null && resValue.getType().equals(BridgeConstants.RES_ID)) {
+        if (resValue.getType() != null && resValue.getType().startsWith("@+") == false) {
             // if this is a framework id
             if (mPlatformFile || resValue.isFramework()) {
                 // look for idName in the android R classes
-                return mContext.getFrameworkIdValue(resValue.getName(), defValue);
+                return mContext.getFrameworkResourceValue(
+                        resValue.getType(), resValue.getName(), defValue);
             }
 
             // look for idName in the project R class.
-            return mContext.getProjectIdValue(resValue.getName(), defValue);
+            return mContext.getProjectResourceValue(
+                    resValue.getType(), resValue.getName(), defValue);
         }
 
         // else, try to get the value, and resolve it somehow.
@@ -623,11 +633,11 @@
             // if this is a framework id
             if (mPlatformFile || value.startsWith("@android") || value.startsWith("@+android")) {
                 // look for idName in the android R classes
-                return mContext.getFrameworkIdValue(idName, defValue);
+                return mContext.getFrameworkResourceValue(BridgeConstants.RES_ID, idName, defValue);
             }
 
             // look for idName in the project R class.
-            return mContext.getProjectIdValue(idName, defValue);
+            return mContext.getProjectResourceValue(BridgeConstants.RES_ID, idName, defValue);
         }
 
         // not a direct id valid reference? resolve it
@@ -644,9 +654,13 @@
             return idValue.intValue();
         }
 
+        Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
+                String.format(
+                    "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]),
+                    resValue);
+
         assert false;
-        Bridge.getLog().warning(null, String.format(
-                "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]));
+
         return defValue;
     }
 
@@ -662,29 +676,17 @@
      */
     @Override
     public Drawable getDrawable(int index) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return null;
         }
 
-        ResourceValue value = mData[index];
+        ResourceValue value = mResourceData[index];
         String stringValue = value.getValue();
         if (stringValue == null || BridgeConstants.REFERENCE_NULL.equals(stringValue)) {
             return null;
         }
 
-        Drawable d = ResourceHelper.getDrawable(value, mContext, mData[index].isFramework());
-
-        if (d != null) {
-            return d;
-        }
-
-        // looks like we were unable to resolve the drawable
-        assert false;
-        Bridge.getLog().warning(null, String.format(
-                "Unable to resolve drawable \"%1$s\" in attribute \"%2$s\"", stringValue,
-                mNames[index]));
-
-        return null;
+        return ResourceHelper.getDrawable(value, mContext, mResourceData[index].isFramework());
     }
 
 
@@ -700,18 +702,19 @@
      */
     @Override
     public CharSequence[] getTextArray(int index) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return null;
         }
 
-        String value = mData[index].getValue();
+        String value = mResourceData[index].getValue();
         if (value != null) {
             return new CharSequence[] { value };
         }
 
-        Bridge.getLog().warning(null, String.format(
-                String.format("Unknown value for getTextArray(%d) => %s", //DEBUG
-                index, mData[index].getName())));
+        Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
+                String.format(
+                    String.format("Unknown value for getTextArray(%d) => %s", //DEBUG
+                    index, mResourceData[index].getName())), null /*data*/);
 
         return null;
     }
@@ -727,11 +730,11 @@
      */
     @Override
     public boolean getValue(int index, TypedValue outValue) {
-        if (mData[index] == null) {
+        if (mResourceData[index] == null) {
             return false;
         }
 
-        String s = mData[index].getValue();
+        String s = mResourceData[index].getValue();
 
         return ResourceHelper.stringToFloat(s, outValue);
     }
@@ -745,7 +748,7 @@
      */
     @Override
     public boolean hasValue(int index) {
-        return mData[index] != null;
+        return mResourceData[index] != null;
     }
 
     /**
@@ -792,6 +795,6 @@
 
     @Override
     public String toString() {
-        return mData.toString();
+        return mResourceData.toString();
     }
  }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 74e5a65..443d881 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -106,7 +106,7 @@
         // pass for now.
     }
 
-    public IBinder prepareDrag(IWindow window, boolean localOnly,
+    public IBinder prepareDrag(IWindow window, int flags,
             int thumbnailWidth, int thumbnailHeight, Surface outSurface)
             throws RemoteException {
         // pass for now
@@ -160,4 +160,10 @@
         // pass for now.
         return null;
     }
+
+    public IBinder prepareDrag(IWindow arg0, boolean arg1, int arg2, int arg3, Surface arg4)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
index 73bee96..38800da 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
@@ -16,7 +16,8 @@
 
 package com.android.layoutlib.bridge.android;
 
-import com.android.layoutlib.api.IXmlPullParser;
+
+import com.android.ide.common.rendering.api.ILayoutPullParser;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -65,17 +66,17 @@
         return mPlatformFile;
     }
 
-    public IXmlPullParser getParser(String layoutName) {
-        if (mParser instanceof IXmlPullParser) {
-            return ((IXmlPullParser)mParser).getParser(layoutName);
+    public ILayoutPullParser getParser(String layoutName) {
+        if (mParser instanceof ILayoutPullParser) {
+            return ((ILayoutPullParser)mParser).getParser(layoutName);
         }
 
         return null;
     }
 
-    public Object getViewKey() {
-        if (mParser instanceof IXmlPullParser) {
-            return ((IXmlPullParser)mParser).getViewKey();
+    public Object getViewCookie() {
+        if (mParser instanceof ILayoutPullParser) {
+            return ((ILayoutPullParser)mParser).getViewCookie();
         }
 
         return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java
index 92b98e5..ba45217 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java
@@ -16,7 +16,7 @@
 
 package com.android.layoutlib.bridge.android;
 
-import com.android.layoutlib.api.ResourceValue;
+import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.BridgeConstants;
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/MockView.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/MockView.java
deleted file mode 100644
index e5bddcb..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/MockView.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.android;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.widget.TextView;
-
-/**
- * Base class for mocked views.
- * 
- * TODO: implement onDraw and draw a rectangle in a random color with the name of the class
- * (or better the id of the view).
- */
-public class MockView extends TextView {
-    
-    public MockView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        
-        setText(this.getClass().getSimpleName());
-        setTextColor(0xFF000000);
-    }
-
-    @Override
-    public void onDraw(Canvas canvas) {
-        canvas.drawARGB(0xFF, 0x7F, 0x7F, 0x7F);
-
-        super.onDraw(canvas);
-    }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java
index 4ee813c..2bd7cc7 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java
@@ -16,10 +16,10 @@
 
 package com.android.layoutlib.bridge.impl;
 
-import com.android.layoutlib.api.LayoutScene;
-import com.android.layoutlib.api.SceneResult;
-import com.android.layoutlib.api.LayoutScene.IAnimationListener;
-import com.android.layoutlib.api.SceneResult.SceneStatus;
+import com.android.ide.common.rendering.api.IAnimationListener;
+import com.android.ide.common.rendering.api.RenderSession;
+import com.android.ide.common.rendering.api.Result;
+import com.android.ide.common.rendering.api.Result.Status;
 import com.android.layoutlib.bridge.Bridge;
 
 import android.animation.ValueAnimator;
@@ -28,7 +28,7 @@
 import android.os.Message;
 import android.os.Handler_Delegate.IHandlerCallback;
 
-import java.util.LinkedList;
+import java.util.PriorityQueue;
 import java.util.Queue;
 
 /**
@@ -39,13 +39,13 @@
  * <p/>
  * Classes should implement {@link #preAnimation()} and {@link #postAnimation()}.
  * <p/>
- * If {@link #preAnimation()} does not start an animation something then the thread doesn't do
+ * If {@link #preAnimation()} does not start an animation somehow then the thread doesn't do
  * anything.
  *
  */
 public abstract class AnimationThread extends Thread {
 
-    private static class MessageBundle {
+    private static class MessageBundle implements Comparable<MessageBundle> {
         final Handler mTarget;
         final Message mMessage;
         final long mUptimeMillis;
@@ -55,20 +55,28 @@
             mMessage = message;
             mUptimeMillis = uptimeMillis;
         }
+
+        public int compareTo(MessageBundle bundle) {
+            if (mUptimeMillis < bundle.mUptimeMillis) {
+                return -1;
+            }
+            return 1;
+        }
     }
 
-    private final LayoutSceneImpl mScene;
+    private final RenderSessionImpl mSession;
 
-    Queue<MessageBundle> mQueue = new LinkedList<MessageBundle>();
+    private Queue<MessageBundle> mQueue = new PriorityQueue<MessageBundle>();
     private final IAnimationListener mListener;
 
-    public AnimationThread(LayoutSceneImpl scene, String threadName, IAnimationListener listener) {
+    public AnimationThread(RenderSessionImpl scene, String threadName,
+            IAnimationListener listener) {
         super(threadName);
-        mScene = scene;
+        mSession = scene;
         mListener = listener;
     }
 
-    public abstract SceneResult preAnimation();
+    public abstract Result preAnimation();
     public abstract void postAnimation();
 
     @Override
@@ -87,13 +95,13 @@
             });
 
             // call out to the pre-animation work, which should start an animation or more.
-            SceneResult result = preAnimation();
+            Result result = preAnimation();
             if (result.isSuccess() == false) {
                 mListener.done(result);
             }
 
             // loop the animation
-            LayoutScene scene = mScene.getScene();
+            RenderSession session = mSession.getSession();
             do {
                 // check early.
                 if (mListener.isCanceled()) {
@@ -123,7 +131,7 @@
                 }
 
                 // ready to do the work, acquire the scene.
-                result = mScene.acquire(250);
+                result = mSession.acquire(250);
                 if (result.isSuccess() == false) {
                     mListener.done(result);
                     return;
@@ -138,15 +146,21 @@
                     }
 
                     bundle.mTarget.handleMessage(bundle.mMessage);
-                    if (mScene.render().isSuccess()) {
-                        mListener.onNewFrame(scene);
+                    if (mSession.render().isSuccess()) {
+                        mListener.onNewFrame(session);
                     }
                 } finally {
-                    mScene.release();
+                    mSession.release();
                 }
             } while (mListener.isCanceled() == false && mQueue.size() > 0);
 
-            mListener.done(SceneStatus.SUCCESS.createResult());
+            mListener.done(Status.SUCCESS.createResult());
+
+        } catch (Throwable throwable) {
+            // can't use Bridge.getLog() as the exception might be thrown outside
+            // of an acquire/release block.
+            mListener.done(Status.ERROR_UNKNOWN.createResult("Error playing animation", throwable));
+
         } finally {
             postAnimation();
             Handler_Delegate.setCallback(null);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
index b272963..05a258d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
@@ -55,11 +55,21 @@
 
     /**
      * Returns the delegate from the given native int.
+     * <p>
+     * If the int is zero, then this will always return null.
+     * <p>
+     * If the int is non zero and the delegate is not found, this will throw an assert.
+     *
      * @param native_object the native int.
      * @return the delegate or null if not found.
      */
     public T getDelegate(int native_object) {
-        return mDelegates.get(native_object);
+        if (native_object > 0) {
+            T delegate =  mDelegates.get(native_object);
+            assert delegate != null;
+            return delegate;
+        }
+        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 8c6b1be..21d6b1a 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
@@ -16,59 +16,340 @@
 
 package com.android.layoutlib.bridge.impl;
 
-import android.graphics.Canvas;
-import android.graphics.Region;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
 
+import android.graphics.Bitmap_Delegate;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint_Delegate;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.graphics.Region_Delegate;
+import android.graphics.Shader_Delegate;
+import android.graphics.Xfermode_Delegate;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
 import java.awt.Graphics2D;
+import java.awt.RenderingHints;
 import java.awt.Shape;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Area;
 import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
 
 /**
  * Class representing a graphics context snapshot, as well as a context stack as a linked list.
  * <p>
  * This is based on top of {@link Graphics2D} but can operate independently if none are available
  * yet when setting transforms and clip information.
+ * <p>
+ * This allows for drawing through {@link #draw(Drawable, Paint_Delegate)} and
+ * {@link #draw(Drawable, Paint_Delegate)}
  *
+ * Handling of layers (created with {@link Canvas#saveLayer(RectF, Paint, int)}) is handled through
+ * a list of Graphics2D for each layers. The class actually maintains a list of {@link Layer}
+ * for each layer. Doing a save() will duplicate this list so that each graphics2D object
+ * ({@link Layer#getGraphics()}) is configured only for the new snapshot.
  */
 public class GcSnapshot {
 
     private final GcSnapshot mPrevious;
     private final int mFlags;
 
-    private Graphics2D mGraphics2D = null;
+    /** list of layers. The first item in the list is always the  */
+    private final ArrayList<Layer> mLayers = new ArrayList<Layer>();
+
     /** temp transform in case transformation are set before a Graphics2D exists */
     private AffineTransform mTransform = null;
     /** temp clip in case clipping is set before a Graphics2D exists */
     private Area mClip = null;
 
-    /**
-     * Creates a new {@link GcSnapshot} on top of another one.
-     * <p/>
-     * This is basically the equivalent of {@link Canvas#save(int)}
-     * @param previous the previous snapshot head.
-     * @param flags the flags regarding what should be saved.
+    // local layer data
+    /** a local layer created with {@link Canvas#saveLayer(RectF, Paint, int)}.
+     * If this is null, this does not mean there's no layer, just that the snapshot is not the
+     * one that created the layer.
+     * @see #getLayerSnapshot()
      */
-    public GcSnapshot(GcSnapshot previous, int flags) {
-        assert previous != null;
-        mPrevious = previous;
-        mFlags = flags;
-        mGraphics2D = (Graphics2D) previous.mGraphics2D.create();
+    private final Layer mLocalLayer;
+    private final Paint_Delegate mLocalLayerPaint;
+    private final Rect mLayerBounds;
+
+    public interface Drawable {
+        void draw(Graphics2D graphics, Paint_Delegate paint);
+    }
+
+    /**
+     * Class containing information about a layer.
+     *
+     * This contains graphics, bitmap and layer information.
+     */
+    private static class Layer {
+        private final Graphics2D mGraphics;
+        private final Bitmap_Delegate mBitmap;
+        private final BufferedImage mImage;
+        /** the flags that were used to configure the layer. This is never changed, and passed
+         * as is when {@link #makeCopy()} is called */
+        private final int mFlags;
+        /** the original content of the layer when the next object was created. This is not
+         * passed in {@link #makeCopy()} and instead is recreated when a new layer is added
+         * (depending on its flags) */
+        private BufferedImage mOriginalCopy;
+
+        /**
+         * Creates a layer with a graphics and a bitmap. This is only used to create
+         * the base layer.
+         *
+         * @param graphics the graphics
+         * @param bitmap the bitmap
+         */
+        Layer(Graphics2D graphics, Bitmap_Delegate bitmap) {
+            mGraphics = graphics;
+            mBitmap = bitmap;
+            mImage = mBitmap.getImage();
+            mFlags = 0;
+        }
+
+        /**
+         * Creates a layer with a graphics and an image. If the image belongs to a
+         * {@link Bitmap_Delegate} (case of the base layer), then
+         * {@link Layer#Layer(Graphics2D, Bitmap_Delegate)} should be used.
+         *
+         * @param graphics the graphics the new graphics for this layer
+         * @param image the image the image from which the graphics came
+         * @param flags the flags that were used to save this layer
+         */
+        Layer(Graphics2D graphics, BufferedImage image, int flags) {
+            mGraphics = graphics;
+            mBitmap = null;
+            mImage = image;
+            mFlags = flags;
+        }
+
+        /** The Graphics2D, guaranteed to be non null */
+        Graphics2D getGraphics() {
+            return mGraphics;
+        }
+
+        /** The BufferedImage, guaranteed to be non null */
+        BufferedImage getImage() {
+            return mImage;
+        }
+
+        /** Returns the layer save flags. This is only valid for additional layers.
+         * For the base layer this will always return 0;
+         * For a given layer, all further copies of this {@link Layer} object in new snapshots
+         * will always return the same value.
+         */
+        int getFlags() {
+            return mFlags;
+        }
+
+        Layer makeCopy() {
+            if (mBitmap != null) {
+                return new Layer((Graphics2D) mGraphics.create(), mBitmap);
+            }
+
+            return new Layer((Graphics2D) mGraphics.create(), mImage, mFlags);
+        }
+
+        /** sets an optional copy of the original content to be used during restore */
+        void setOriginalCopy(BufferedImage image) {
+            mOriginalCopy = image;
+        }
+
+        BufferedImage getOriginalCopy() {
+            return mOriginalCopy;
+        }
+
+        void change() {
+            if (mBitmap != null) {
+                mBitmap.change();
+            }
+        }
+
+        /**
+         * Sets the clip for the graphics2D object associated with the layer.
+         * This should be used over the normal Graphics2D setClip method.
+         *
+         * @param clipShape the shape to use a the clip shape.
+         */
+        void setClip(Shape clipShape) {
+            // because setClip is only guaranteed to work with rectangle shape,
+            // first reset the clip to max and then intersect the current (empty)
+            // clip with the shap.
+            mGraphics.setClip(null);
+            mGraphics.clip(clipShape);
+        }
+
+        /**
+         * Clips the layer with the given shape. This performs an intersect between the current
+         * clip shape and the given shape.
+         * @param shape the new clip shape.
+         */
+        public void clip(Shape shape) {
+            mGraphics.clip(shape);
+        }
+    }
+
+    /**
+     * Creates the root snapshot associating it with a given bitmap.
+     * <p>
+     * If <var>bitmap</var> is null, then {@link GcSnapshot#setBitmap(Bitmap_Delegate)} must be
+     * called before the snapshot can be used to draw. Transform and clip operations are permitted
+     * before.
+     *
+     * @param image the image to associate to the snapshot or null.
+     * @return the root snapshot
+     */
+    public static GcSnapshot createDefaultSnapshot(Bitmap_Delegate bitmap) {
+        GcSnapshot snapshot = new GcSnapshot();
+        if (bitmap != null) {
+            snapshot.setBitmap(bitmap);
+        }
+
+        return snapshot;
+    }
+
+    /**
+     * Saves the current state according to the given flags and returns the new current snapshot.
+     * <p/>
+     * This is the equivalent of {@link Canvas#save(int)}
+     *
+     * @param flags the save flags.
+     * @return the new snapshot
+     *
+     * @see Canvas#save(int)
+     */
+    public GcSnapshot save(int flags) {
+        return new GcSnapshot(this, null /*layerbounds*/, null /*paint*/, flags);
+    }
+
+    /**
+     * Saves the current state and creates a new layer, and returns the new current snapshot.
+     * <p/>
+     * This is the equivalent of {@link Canvas#saveLayer(RectF, Paint, int)}
+     *
+     * @param layerBounds the layer bounds
+     * @param paint the Paint information used to blit the layer back into the layers underneath
+     *          upon restore
+     * @param flags the save flags.
+     * @return the new snapshot
+     *
+     * @see Canvas#saveLayer(RectF, Paint, int)
+     */
+    public GcSnapshot saveLayer(RectF layerBounds, Paint_Delegate paint, int flags) {
+        return new GcSnapshot(this, layerBounds, paint, flags);
     }
 
     /**
      * Creates the root snapshot.
      * {@link #setGraphics2D(Graphics2D)} will have to be called on it when possible.
      */
-    public GcSnapshot() {
+    private GcSnapshot() {
         mPrevious = null;
         mFlags = 0;
+        mLocalLayer = null;
+        mLocalLayerPaint = null;
+        mLayerBounds = null;
+    }
+
+    /**
+     * Creates a new {@link GcSnapshot} on top of another one, with a layer data to be restored
+     * into the main graphics when {@link #restore()} is called.
+     *
+     * @param previous the previous snapshot head.
+     * @param layerBounds the region of the layer. Optional, if null, this is a normal save()
+     * @param paint the Paint information used to blit the layer back into the layers underneath
+     *          upon restore
+     * @param flags the flags regarding what should be saved.
+     */
+    private GcSnapshot(GcSnapshot previous, RectF layerBounds, Paint_Delegate paint, int flags) {
+        assert previous != null;
+        mPrevious = previous;
+        mFlags = flags;
+
+        // make a copy of the current layers before adding the new one.
+        // This keeps the same BufferedImage reference but creates new Graphics2D for this
+        // snapshot.
+        // It does not copy whatever original copy the layers have, as they will be done
+        // only if the new layer doesn't clip drawing to itself.
+        for (Layer layer : mPrevious.mLayers) {
+            mLayers.add(layer.makeCopy());
+        }
+
+        if (layerBounds != null) {
+            // get the current transform
+            AffineTransform matrix = mLayers.get(0).getGraphics().getTransform();
+
+            // transform the layerBounds with the current transform and stores it into a int rect
+            RectF rect2 = new RectF();
+            mapRect(matrix, rect2, layerBounds);
+            mLayerBounds = new Rect();
+            rect2.round(mLayerBounds);
+
+            // get the base layer (always at index 0)
+            Layer baseLayer = mLayers.get(0);
+
+            // create the image for the layer
+            BufferedImage layerImage = new BufferedImage(
+                    baseLayer.getImage().getWidth(),
+                    baseLayer.getImage().getHeight(),
+                    (mFlags & Canvas.HAS_ALPHA_LAYER_SAVE_FLAG) != 0 ?
+                            BufferedImage.TYPE_INT_ARGB :
+                                BufferedImage.TYPE_INT_RGB);
+
+            // create a graphics for it so that drawing can be done.
+            Graphics2D layerGraphics = layerImage.createGraphics();
+
+            // because this layer inherits the current context for transform and clip,
+            // set them to one from the base layer.
+            AffineTransform currentMtx = baseLayer.getGraphics().getTransform();
+            layerGraphics.setTransform(currentMtx);
+
+            // create a new layer for this new layer and add it to the list at the end.
+            mLayers.add(mLocalLayer = new Layer(layerGraphics, layerImage, flags));
+
+            // set the clip on it.
+            Shape currentClip = baseLayer.getGraphics().getClip();
+            mLocalLayer.setClip(currentClip);
+
+            // if the drawing is not clipped to the local layer only, we save the current content
+            // of all other layers. We are only interested in the part that will actually
+            // be drawn, so we create as small bitmaps as we can.
+            // This is so that we can erase the drawing that goes in the layers below that will
+            // be coming from the layer itself.
+            if ((mFlags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) == 0) {
+                int w = mLayerBounds.width();
+                int h = mLayerBounds.height();
+                for (int i = 0 ; i < mLayers.size() - 1 ; i++) {
+                    Layer layer = mLayers.get(i);
+                    BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+                    Graphics2D graphics = image.createGraphics();
+                    graphics.drawImage(layer.getImage(),
+                            0, 0, w, h,
+                            mLayerBounds.left, mLayerBounds.top,
+                                    mLayerBounds.right, mLayerBounds.bottom,
+                            null);
+                    graphics.dispose();
+                    layer.setOriginalCopy(image);
+                }
+            }
+        } else {
+            mLocalLayer = null;
+            mLayerBounds = null;
+        }
+
+        mLocalLayerPaint  = paint;
     }
 
     public void dispose() {
-        if (mGraphics2D != null) {
-            mGraphics2D.dispose();
+        for (Layer layer : mLayers) {
+            layer.getGraphics().dispose();
         }
 
         if (mPrevious != null) {
@@ -102,35 +383,43 @@
     }
 
     /**
-     * Sets the Graphics2D object for this snapshot if it was created through {@link #GcSnapshot()}.
+     * Link the snapshot to a Bitmap_Delegate.
+     * <p/>
+     * This is only for the case where the snapshot was created with a null image when calling
+     * {@link #createDefaultSnapshot(Bitmap_Delegate)}, and is therefore not yet linked to
+     * a previous snapshot.
+     * <p/>
      * If any transform or clip information was set before, they are put into the Graphics object.
-     * @param graphics2D the graphics object to set.
+     * @param bitmap the bitmap to link to.
      */
-    public void setGraphics2D(Graphics2D graphics2D) {
-        mGraphics2D = graphics2D;
-        if (mTransform != null) {
-            mGraphics2D.setTransform(mTransform);
-            mTransform = null;
-        }
+    public void setBitmap(Bitmap_Delegate bitmap) {
+        // create a new Layer for the bitmap. This will be the base layer.
+        Graphics2D graphics2D = bitmap.getImage().createGraphics();
+        Layer baseLayer = new Layer(graphics2D, bitmap);
 
-        if (mClip != null) {
-            mGraphics2D.setClip(mClip);
-            mClip = null;
-        }
-    }
+        // 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.
 
-    /**
-     * Creates and return a copy of the current {@link Graphics2D}.
-     * @return a new {@link Graphics2D}.
-     */
-    public Graphics2D create() {
-        assert mGraphics2D != null;
-        return (Graphics2D) mGraphics2D.create();
+        graphics2D.setTransform(getTransform());
+        // reset mTransform in case there was one.
+        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);
+
     }
 
     public void translate(float dx, float dy) {
-        if (mGraphics2D != null) {
-            mGraphics2D.translate(dx, dy);
+        if (mLayers.size() > 0) {
+            for (Layer layer : mLayers) {
+                layer.getGraphics().translate(dx, dy);
+            }
         } else {
             if (mTransform == null) {
                 mTransform = new AffineTransform();
@@ -140,8 +429,10 @@
     }
 
     public void rotate(double radians) {
-        if (mGraphics2D != null) {
-            mGraphics2D.rotate(radians);
+        if (mLayers.size() > 0) {
+            for (Layer layer : mLayers) {
+                layer.getGraphics().rotate(radians);
+            }
         } else {
             if (mTransform == null) {
                 mTransform = new AffineTransform();
@@ -151,8 +442,10 @@
     }
 
     public void scale(float sx, float sy) {
-        if (mGraphics2D != null) {
-            mGraphics2D.scale(sx, sy);
+        if (mLayers.size() > 0) {
+            for (Layer layer : mLayers) {
+                layer.getGraphics().scale(sx, sy);
+            }
         } else {
             if (mTransform == null) {
                 mTransform = new AffineTransform();
@@ -162,8 +455,9 @@
     }
 
     public AffineTransform getTransform() {
-        if (mGraphics2D != null) {
-            return mGraphics2D.getTransform();
+        if (mLayers.size() > 0) {
+            // all graphics2D in the list have the same transform
+            return mLayers.get(0).getGraphics().getTransform();
         } else {
             if (mTransform == null) {
                 mTransform = new AffineTransform();
@@ -173,8 +467,10 @@
     }
 
     public void setTransform(AffineTransform transform) {
-        if (mGraphics2D != null) {
-            mGraphics2D.setTransform(transform);
+        if (mLayers.size() > 0) {
+            for (Layer layer : mLayers) {
+                layer.getGraphics().setTransform(transform);
+            }
         } else {
             if (mTransform == null) {
                 mTransform = new AffineTransform();
@@ -183,67 +479,61 @@
         }
     }
 
-    public boolean clipRect(float left, float top, float right, float bottom, int regionOp) {
-        if (mGraphics2D != null) {
-            if (regionOp == Region.Op.DIFFERENCE.nativeInt) {
-                Area newClip = new Area(mGraphics2D.getClip());
-                newClip.subtract(new Area(
-                        new Rectangle2D.Float(left, top, right - left, bottom - top)));
-                mGraphics2D.setClip(newClip);
-
-            } else if (regionOp == Region.Op.INTERSECT.nativeInt) {
-                mGraphics2D.clipRect((int) left, (int) top,
-                        (int) (right - left), (int) (bottom - top));
-
-            } else if (regionOp == Region.Op.UNION.nativeInt) {
-                Area newClip = new Area(mGraphics2D.getClip());
-                newClip.add(new Area(
-                        new Rectangle2D.Float(left, top, right - left, bottom - top)));
-                mGraphics2D.setClip(newClip);
-
-            } else if (regionOp == Region.Op.XOR.nativeInt) {
-                Area newClip = new Area(mGraphics2D.getClip());
-                newClip.exclusiveOr(new Area(
-                        new Rectangle2D.Float(left, top, right - left, bottom - top)));
-                mGraphics2D.setClip(newClip);
-
-            } else if (regionOp == Region.Op.REVERSE_DIFFERENCE.nativeInt) {
-                Area newClip = new Area(
-                        new Rectangle2D.Float(left, top, right - left, bottom - top));
-                newClip.subtract(new Area(mGraphics2D.getClip()));
-                mGraphics2D.setClip(newClip);
-            } else if (regionOp == Region.Op.REPLACE.nativeInt) {
-                mGraphics2D.setClip((int) left, (int) top,
-                        (int) (right - left), (int) (bottom - top));
+    public boolean clip(Shape shape, int regionOp) {
+        // Simple case of intersect with existing layers.
+        // Because Graphics2D#setClip works a bit peculiarly, we optimize
+        // the case of clipping by intersection, as it's supported natively.
+        if (regionOp == Region.Op.INTERSECT.nativeInt && mLayers.size() > 0) {
+            for (Layer layer : mLayers) {
+                layer.clip(shape);
             }
 
-            return mGraphics2D.getClip().getBounds().isEmpty() == false;
+            Shape currentClip = getClip();
+            return currentClip != null && currentClip.getBounds().isEmpty() == false;
+        }
+
+        Area area = null;
+
+        if (regionOp == Region.Op.REPLACE.nativeInt) {
+            area = new Area(shape);
         } else {
-            if (mClip == null) {
-                mClip = new Area();
+            area = Region_Delegate.combineShapes(getClip(), shape, regionOp);
+        }
+
+        assert area != null;
+
+        if (mLayers.size() > 0) {
+            if (area != null) {
+                for (Layer layer : mLayers) {
+                    layer.setClip(area);
+                }
             }
 
-            if (regionOp == Region.Op.DIFFERENCE.nativeInt) {
-                //FIXME
-            } else if (regionOp == Region.Op.DIFFERENCE.nativeInt) {
-            } else if (regionOp == Region.Op.INTERSECT.nativeInt) {
-            } else if (regionOp == Region.Op.UNION.nativeInt) {
-            } else if (regionOp == Region.Op.XOR.nativeInt) {
-            } else if (regionOp == Region.Op.REVERSE_DIFFERENCE.nativeInt) {
-            } else if (regionOp == Region.Op.REPLACE.nativeInt) {
+            Shape currentClip = getClip();
+            return currentClip != null && currentClip.getBounds().isEmpty() == false;
+        } else {
+            if (area != null) {
+                mClip = area;
+            } else {
+                mClip = new Area();
             }
 
             return mClip.getBounds().isEmpty() == false;
         }
     }
 
+    public boolean clipRect(float left, float top, float right, float bottom, int regionOp) {
+        return clip(new Rectangle2D.Float(left, top, right - left, bottom - top), regionOp);
+    }
+
+    /**
+     * Returns the current clip, or null if none have been setup.
+     */
     public Shape getClip() {
-        if (mGraphics2D != null) {
-            return mGraphics2D.getClip();
+        if (mLayers.size() > 0) {
+            // they all have the same clip
+            return mLayers.get(0).getGraphics().getClip();
         } else {
-            if (mClip == null) {
-                mClip = new Area();
-            }
             return mClip;
         }
     }
@@ -263,26 +553,251 @@
         }
     }
 
+    /**
+     * Executes the Drawable's draw method, with a null paint delegate.
+     * <p/>
+     * Note that the method can be called several times if there are more than one active layer.
+     * @param drawable
+     */
+    public void draw(Drawable drawable) {
+        draw(drawable, null, false /*compositeOnly*/, false /*forceSrcMode*/);
+    }
+
+    /**
+     * Executes the Drawable's draw method.
+     * <p/>
+     * Note that the method can be called several times if there are more than one active layer.
+     * @param drawable
+     * @param paint
+     * @param compositeOnly whether the paint is used for composite only. This is typically
+     *          the case for bitmaps.
+     * @param forceSrcMode if true, this overrides the composite to be SRC
+     */
+    public void draw(Drawable drawable, Paint_Delegate paint, boolean compositeOnly,
+            boolean forceSrcMode) {
+        // the current snapshot may not have a mLocalLayer (ie it was created on save() instead
+        // of saveLayer(), but that doesn't mean there's no layer.
+        // mLayers however saves all the information we need (flags).
+        if (mLayers.size() == 1) {
+            // no layer, only base layer. easy case.
+            drawInLayer(mLayers.get(0), drawable, paint, compositeOnly, forceSrcMode);
+        } else {
+            // draw in all the layers until the layer save flags tells us to stop (ie drawing
+            // in that layer is limited to the layer itself.
+            int flags;
+            int i = mLayers.size() - 1;
+
+            do {
+                Layer layer = mLayers.get(i);
+
+                drawInLayer(layer, drawable, paint, compositeOnly, forceSrcMode);
+
+                // then go to previous layer, only if there are any left, and its flags
+                // doesn't restrict drawing to the layer itself.
+                i--;
+                flags = layer.getFlags();
+            } while (i >= 0 && (flags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) == 0);
+        }
+    }
+
+    private void drawInLayer(Layer layer, Drawable drawable, Paint_Delegate paint,
+            boolean compositeOnly, boolean forceSrcMode) {
+        Graphics2D originalGraphics = layer.getGraphics();
+        // get a Graphics2D object configured with the drawing parameters.
+        Graphics2D configuredGraphics2D =
+            paint != null ?
+                    createCustomGraphics(originalGraphics, paint, compositeOnly, forceSrcMode) :
+                        (Graphics2D) originalGraphics.create();
+
+        try {
+            drawable.draw(configuredGraphics2D, paint);
+            layer.change();
+        } finally {
+            // dispose Graphics2D object
+            configuredGraphics2D.dispose();
+        }
+    }
+
     private GcSnapshot doRestore() {
-        // if this snapshot does not save everything, then set the previous snapshot
-        // to this snapshot content
         if (mPrevious != null) {
+            if (mLocalLayer != null) {
+                // prepare to blit the layers in which we have draw, in the layer beneath
+                // them, starting with the top one (which is the current local layer).
+                int i = mLayers.size() - 1;
+                int flags;
+                do {
+                    Layer dstLayer = mLayers.get(i - 1);
+
+                    restoreLayer(dstLayer);
+
+                    flags = dstLayer.getFlags();
+                    i--;
+                } while (i > 0 && (flags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) == 0);
+            }
+
+            // if this snapshot does not save everything, then set the previous snapshot
+            // to this snapshot content
+
             // didn't save the matrix? set the current matrix on the previous snapshot
             if ((mFlags & Canvas.MATRIX_SAVE_FLAG) == 0) {
-                mPrevious.mGraphics2D.setTransform(getTransform());
+                AffineTransform mtx = getTransform();
+                for (Layer layer : mPrevious.mLayers) {
+                    layer.getGraphics().setTransform(mtx);
+                }
             }
 
             // didn't save the clip? set the current clip on the previous snapshot
             if ((mFlags & Canvas.CLIP_SAVE_FLAG) == 0) {
-                mPrevious.mGraphics2D.setClip(mGraphics2D.getClip());
+                Shape clip = getClip();
+                for (Layer layer : mPrevious.mLayers) {
+                    layer.setClip(clip);
+                }
             }
         }
 
-        if (mGraphics2D != null) {
-            mGraphics2D.dispose();
+        for (Layer layer : mLayers) {
+            layer.getGraphics().dispose();
         }
 
         return mPrevious;
     }
 
+    private void restoreLayer(Layer dstLayer) {
+
+        Graphics2D baseGfx = dstLayer.getImage().createGraphics();
+
+        // if the layer contains an original copy this means the flags
+        // didn't restrict drawing to the local layer and we need to make sure the
+        // layer bounds in the layer beneath didn't receive any drawing.
+        // so we use the originalCopy to erase the new drawings in there.
+        BufferedImage originalCopy = dstLayer.getOriginalCopy();
+        if (originalCopy != null) {
+            Graphics2D g = (Graphics2D) baseGfx.create();
+            g.setComposite(AlphaComposite.Src);
+
+            g.drawImage(originalCopy,
+                    mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom,
+                    0, 0, mLayerBounds.width(), mLayerBounds.height(),
+                    null);
+            g.dispose();
+        }
+
+        // now draw put the content of the local layer onto the layer,
+        // using the paint information
+        Graphics2D g = createCustomGraphics(baseGfx, mLocalLayerPaint,
+                true /*alphaOnly*/, false /*forceSrcMode*/);
+
+        g.drawImage(mLocalLayer.getImage(),
+                mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom,
+                mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom,
+                null);
+        g.dispose();
+
+        baseGfx.dispose();
+    }
+
+    /**
+     * Creates a new {@link Graphics2D} based on the {@link Paint} parameters.
+     * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used.
+     */
+    private Graphics2D createCustomGraphics(Graphics2D original, Paint_Delegate paint,
+            boolean compositeOnly, boolean forceSrcMode) {
+        // make new one graphics
+        Graphics2D g = (Graphics2D) original.create();
+
+        // configure it
+
+        if (paint.isAntiAliased()) {
+            g.setRenderingHint(
+                    RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+            g.setRenderingHint(
+                    RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+        }
+
+        boolean customShader = false;
+
+        // get the shader first, as it'll replace the color if it can be used it.
+        if (compositeOnly == false) {
+            Shader_Delegate shaderDelegate = paint.getShader();
+            if (shaderDelegate != null) {
+                if (shaderDelegate.isSupported()) {
+                    java.awt.Paint shaderPaint = shaderDelegate.getJavaPaint();
+                    assert shaderPaint != null;
+                    if (shaderPaint != null) {
+                        g.setPaint(shaderPaint);
+                        customShader = true;
+                    }
+                } else {
+                    Bridge.getLog().fidelityWarning(LayoutLog.TAG_SHADER,
+                            shaderDelegate.getSupportMessage(),
+                            null /*throwable*/, null /*data*/);
+                }
+            }
+
+            // if no shader, use the paint color
+            if (customShader == false) {
+                g.setColor(new Color(paint.getColor(), true /*hasAlpha*/));
+            }
+
+            // set the stroke
+            g.setStroke(paint.getJavaStroke());
+        }
+
+        // the alpha for the composite. Always opaque if the normal paint color is used since
+        // it contains the alpha
+        int alpha = (compositeOnly || customShader) ? paint.getAlpha() : 0xFF;
+
+        if (forceSrcMode) {
+            g.setComposite(AlphaComposite.getInstance(
+                    AlphaComposite.SRC, (float) alpha / 255.f));
+        } else {
+            boolean customXfermode = false;
+            Xfermode_Delegate xfermodeDelegate = paint.getXfermode();
+            if (xfermodeDelegate != null) {
+                if (xfermodeDelegate.isSupported()) {
+                    Composite composite = xfermodeDelegate.getComposite(alpha);
+                    assert composite != null;
+                    if (composite != null) {
+                        g.setComposite(composite);
+                        customXfermode = true;
+                    }
+                } else {
+                    Bridge.getLog().fidelityWarning(LayoutLog.TAG_XFERMODE,
+                            xfermodeDelegate.getSupportMessage(),
+                            null /*throwable*/, null /*data*/);
+                }
+            }
+
+            // if there was no custom xfermode, but we have alpha (due to a shader and a non
+            // opaque alpha channel in the paint color), then we create an AlphaComposite anyway
+            // that will handle the alpha.
+            if (customXfermode == false && alpha != 0xFF) {
+                g.setComposite(AlphaComposite.getInstance(
+                        AlphaComposite.SRC_OVER, (float) alpha / 255.f));
+            }
+        }
+
+        return g;
+    }
+
+    private void mapRect(AffineTransform matrix, RectF dst, RectF src) {
+        // array with 4 corners
+        float[] corners = new float[] {
+                src.left, src.top,
+                src.right, src.top,
+                src.right, src.bottom,
+                src.left, src.bottom,
+        };
+
+        // apply the transform to them.
+        matrix.transform(corners, 0, corners, 0, 4);
+
+        // now put the result in the rect. We take the min/max of Xs and min/max of Ys
+        dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
+        dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
+
+        dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
+        dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
+    }
+
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
deleted file mode 100644
index 24cf380..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
+++ /dev/null
@@ -1,1157 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.impl;
-
-import static com.android.layoutlib.api.SceneResult.SceneStatus.ERROR_LOCK_INTERRUPTED;
-import static com.android.layoutlib.api.SceneResult.SceneStatus.ERROR_TIMEOUT;
-import static com.android.layoutlib.api.SceneResult.SceneStatus.SUCCESS;
-
-import com.android.internal.util.XmlUtils;
-import com.android.layoutlib.api.IProjectCallback;
-import com.android.layoutlib.api.IXmlPullParser;
-import com.android.layoutlib.api.LayoutBridge;
-import com.android.layoutlib.api.LayoutScene;
-import com.android.layoutlib.api.ResourceDensity;
-import com.android.layoutlib.api.ResourceValue;
-import com.android.layoutlib.api.SceneParams;
-import com.android.layoutlib.api.SceneResult;
-import com.android.layoutlib.api.StyleResourceValue;
-import com.android.layoutlib.api.ViewInfo;
-import com.android.layoutlib.api.LayoutScene.IAnimationListener;
-import com.android.layoutlib.api.SceneParams.RenderingMode;
-import com.android.layoutlib.api.SceneResult.SceneStatus;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.BridgeConstants;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.BridgeInflater;
-import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
-import com.android.layoutlib.bridge.android.BridgeWindow;
-import com.android.layoutlib.bridge.android.BridgeWindowSession;
-import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-
-import android.animation.Animator;
-import android.animation.AnimatorInflater;
-import android.animation.LayoutTransition;
-import android.app.Fragment_Delegate;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap_Delegate;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.View.AttachInfo;
-import android.view.View.MeasureSpec;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.FrameLayout;
-import android.widget.TabHost;
-import android.widget.TabWidget;
-
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Class managing a layout "scene".
- *
- * A scene is a stateful representation of a layout file. It is initialized with data coming through
- * the {@link LayoutBridge} API to inflate the layout. Further actions and rendering can then
- * be done on the layout.
- *
- */
-public class LayoutSceneImpl {
-
-    private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
-    private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
-
-    /**
-     * The current context being rendered. This is set through {@link #acquire(long)} and
-     * {@link #init(long)}, and unset in {@link #release()}.
-     */
-    private static BridgeContext sCurrentContext = null;
-
-    private final SceneParams mParams;
-
-    // scene state
-    private LayoutScene mScene;
-    private BridgeContext mContext;
-    private BridgeXmlBlockParser mBlockParser;
-    private BridgeInflater mInflater;
-    private StyleResourceValue mCurrentTheme;
-    private int mScreenOffset;
-    private ResourceValue mWindowBackground;
-    private FrameLayout mViewRoot;
-    private Canvas mCanvas;
-    private int mMeasuredScreenWidth = -1;
-    private int mMeasuredScreenHeight = -1;
-
-    // information being returned through the API
-    private BufferedImage mImage;
-    private ViewInfo mViewInfo;
-
-    private static final class PostInflateException extends Exception {
-        private static final long serialVersionUID = 1L;
-
-        public PostInflateException(String message) {
-            super(message);
-        }
-    }
-
-    /**
-     * Creates a layout scene with all the information coming from the layout bridge API.
-     * <p>
-     * This <b>must</b> be followed by a call to {@link LayoutSceneImpl#init()}, which act as a
-     * call to {@link LayoutSceneImpl#acquire(long)}
-     *
-     * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams)
-     */
-    public LayoutSceneImpl(SceneParams params) {
-        // copy the params.
-        mParams = new SceneParams(params);
-    }
-
-    /**
-     * Initializes and acquires the scene, creating various Android objects such as context,
-     * inflater, and parser.
-     *
-     * @param timeout the time to wait if another rendering is happening.
-     *
-     * @return whether the scene was prepared
-     *
-     * @see #acquire(long)
-     * @see #release()
-     */
-    public SceneResult init(long timeout) {
-        // acquire the lock. if the result is null, lock was just acquired, otherwise, return
-        // the result.
-        SceneResult result = acquireLock(timeout);
-        if (result != null) {
-            return result;
-        }
-
-        Bridge.setLog(mParams.getLog());
-
-        // setup the display Metrics.
-        DisplayMetrics metrics = new DisplayMetrics();
-        metrics.densityDpi = mParams.getDensity();
-        metrics.density = mParams.getDensity() / (float) DisplayMetrics.DENSITY_DEFAULT;
-        metrics.scaledDensity = metrics.density;
-        metrics.widthPixels = mParams.getScreenWidth();
-        metrics.heightPixels = mParams.getScreenHeight();
-        metrics.xdpi = mParams.getXdpi();
-        metrics.ydpi = mParams.getYdpi();
-
-        // find the current theme and compute the style inheritance map
-        Map<StyleResourceValue, StyleResourceValue> styleParentMap =
-            new HashMap<StyleResourceValue, StyleResourceValue>();
-
-        mCurrentTheme = computeStyleMaps(mParams.getThemeName(), mParams.getIsProjectTheme(),
-                mParams.getProjectResources().get(BridgeConstants.RES_STYLE),
-                mParams.getFrameworkResources().get(BridgeConstants.RES_STYLE), styleParentMap);
-
-        // build the context
-        mContext = new BridgeContext(mParams.getProjectKey(), metrics, mCurrentTheme,
-                mParams.getProjectResources(), mParams.getFrameworkResources(),
-                styleParentMap, mParams.getProjectCallback());
-
-        // set the current rendering context
-        sCurrentContext = mContext;
-
-        // make sure the Resources object references the context (and other objects) for this
-        // scene
-        mContext.initResources();
-
-        // get the screen offset and window-background resource
-        mWindowBackground = null;
-        mScreenOffset = 0;
-        if (mCurrentTheme != null && mParams.isCustomBackgroundEnabled() == false) {
-            mWindowBackground = mContext.findItemInStyle(mCurrentTheme, "windowBackground");
-            mWindowBackground = mContext.resolveResValue(mWindowBackground);
-
-            mScreenOffset = getScreenOffset(mParams.getFrameworkResources(), mCurrentTheme,
-                    mContext);
-        }
-
-        // build the inflater and parser.
-        mInflater = new BridgeInflater(mContext, mParams.getProjectCallback());
-        mContext.setBridgeInflater(mInflater);
-        mInflater.setFactory2(mContext);
-
-        mBlockParser = new BridgeXmlBlockParser(mParams.getLayoutDescription(),
-                mContext, false /* platformResourceFlag */);
-
-        return SceneStatus.SUCCESS.createResult();
-    }
-
-    /**
-     * Prepares the scene for action.
-     * <p>
-     * This call is blocking if another rendering/inflating is currently happening, and will return
-     * whether the preparation worked.
-     *
-     * The preparation can fail if another rendering took too long and the timeout was elapsed.
-     *
-     * More than one call to this from the same thread will have no effect and will return
-     * {@link SceneResult#SUCCESS}.
-     *
-     * After scene actions have taken place, only one call to {@link #release()} must be
-     * done.
-     *
-     * @param timeout the time to wait if another rendering is happening.
-     *
-     * @return whether the scene was prepared
-     *
-     * @see #release()
-     *
-     * @throws IllegalStateException if {@link #init(long)} was never called.
-     */
-    public SceneResult acquire(long timeout) {
-        if (mContext == null) {
-            throw new IllegalStateException("After scene creation, #init() must be called");
-        }
-
-        // acquire the lock. if the result is null, lock was just acquired, otherwise, return
-        // the result.
-        SceneResult result = acquireLock(timeout);
-        if (result != null) {
-            return result;
-        }
-
-        // make sure the Resources object references the context (and other objects) for this
-        // scene
-        mContext.initResources();
-        sCurrentContext = mContext;
-        Bridge.setLog(mParams.getLog());
-
-        return SUCCESS.createResult();
-    }
-
-    /**
-     * Acquire the lock so that the scene can be acted upon.
-     * <p>
-     * This returns null if the lock was just acquired, otherwise it returns
-     * {@link SceneResult#SUCCESS} if the lock already belonged to that thread, or another
-     * instance (see {@link SceneResult#getStatus()}) if an error occurred.
-     *
-     * @param timeout the time to wait if another rendering is happening.
-     * @return null if the lock was just acquire or another result depending on the state.
-     *
-     * @throws IllegalStateException if the current context is different than the one owned by
-     *      the scene.
-     */
-    private SceneResult acquireLock(long timeout) {
-        ReentrantLock lock = Bridge.getLock();
-        if (lock.isHeldByCurrentThread() == false) {
-            try {
-                boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS);
-
-                if (acquired == false) {
-                    return ERROR_TIMEOUT.createResult();
-                }
-            } catch (InterruptedException e) {
-                return ERROR_LOCK_INTERRUPTED.createResult();
-            }
-        } else {
-            // This thread holds the lock already. Checks that this wasn't for a different context.
-            // If this is called by init, mContext will be null and so should sCurrentContext
-            // anyway
-            if (mContext != sCurrentContext) {
-                throw new IllegalStateException("Acquiring different scenes from same thread without releases");
-            }
-            return SUCCESS.createResult();
-        }
-
-        return null;
-    }
-
-    /**
-     * Cleans up the scene after an action.
-     */
-    public void release() {
-        ReentrantLock lock = Bridge.getLock();
-
-        // with the use of finally blocks, it is possible to find ourself calling this
-        // without a successful call to prepareScene. This test makes sure that unlock() will
-        // not throw IllegalMonitorStateException.
-        if (lock.isHeldByCurrentThread()) {
-            // Make sure to remove static references, otherwise we could not unload the lib
-            mContext.disposeResources();
-            Bridge.setLog(null);
-            sCurrentContext = null;
-
-            lock.unlock();
-        }
-    }
-
-    /**
-     * Inflates the layout.
-     * <p>
-     * {@link #acquire(long)} must have been called before this.
-     *
-     * @throws IllegalStateException if the current context is different than the one owned by
-     *      the scene, or if {@link #init(long)} was not called.
-     */
-    public SceneResult inflate() {
-        checkLock();
-
-        try {
-
-            mViewRoot = new FrameLayout(mContext);
-
-            // Sets the project callback (custom view loader) to the fragment delegate so that
-            // it can instantiate the custom Fragment.
-            Fragment_Delegate.setProjectCallback(mParams.getProjectCallback());
-
-            View view = mInflater.inflate(mBlockParser, mViewRoot);
-
-            // post-inflate process. For now this supports TabHost/TabWidget
-            postInflateProcess(view, mParams.getProjectCallback());
-
-            Fragment_Delegate.setProjectCallback(null);
-
-            // set the AttachInfo on the root view.
-            AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
-                    new Handler(), null);
-            info.mHasWindowFocus = true;
-            info.mWindowVisibility = View.VISIBLE;
-            info.mInTouchMode = false; // this is so that we can display selections.
-            mViewRoot.dispatchAttachedToWindow(info, 0);
-
-            // get the background drawable
-            if (mWindowBackground != null) {
-                Drawable d = ResourceHelper.getDrawable(mWindowBackground,
-                        mContext, true /* isFramework */);
-                mViewRoot.setBackgroundDrawable(d);
-            }
-
-            return SceneStatus.SUCCESS.createResult();
-        } catch (PostInflateException e) {
-            return SceneStatus.ERROR_INFLATION.createResult(e.getMessage(), e);
-        } catch (Throwable e) {
-            // get the real cause of the exception.
-            Throwable t = e;
-            while (t.getCause() != null) {
-                t = t.getCause();
-            }
-
-            // log it
-            mParams.getLog().error("Scene inflate failed", t);
-
-            return SceneStatus.ERROR_INFLATION.createResult(t.getMessage(), t);
-        }
-    }
-
-    /**
-     * Renders the scene.
-     * <p>
-     * {@link #acquire(long)} must have been called before this.
-     *
-     * @throws IllegalStateException if the current context is different than the one owned by
-     *      the scene, or if {@link #acquire(long)} was not called.
-     *
-     * @see SceneParams#getRenderingMode()
-     * @see LayoutScene#render(long)
-     */
-    public SceneResult render() {
-        checkLock();
-
-        try {
-            if (mViewRoot == null) {
-                return SceneStatus.ERROR_NOT_INFLATED.createResult();
-            }
-            // measure the views
-            int w_spec, h_spec;
-
-            RenderingMode renderingMode = mParams.getRenderingMode();
-
-            // only do the screen measure when needed.
-            boolean newRenderSize = false;
-            if (mMeasuredScreenWidth == -1) {
-                newRenderSize = true;
-                mMeasuredScreenWidth = mParams.getScreenWidth();
-                mMeasuredScreenHeight = mParams.getScreenHeight();
-
-                if (renderingMode != RenderingMode.NORMAL) {
-                    // measure the full size needed by the layout.
-                    w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth,
-                            renderingMode.isHorizExpand() ?
-                                    MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
-                                    : MeasureSpec.EXACTLY);
-                    h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight - mScreenOffset,
-                            renderingMode.isVertExpand() ?
-                                    MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
-                                    : MeasureSpec.EXACTLY);
-                    mViewRoot.measure(w_spec, h_spec);
-
-                    if (renderingMode.isHorizExpand()) {
-                        int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth();
-                        if (neededWidth > mMeasuredScreenWidth) {
-                            mMeasuredScreenWidth = neededWidth;
-                        }
-                    }
-
-                    if (renderingMode.isVertExpand()) {
-                        int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight();
-                        if (neededHeight > mMeasuredScreenHeight - mScreenOffset) {
-                            mMeasuredScreenHeight = neededHeight + mScreenOffset;
-                        }
-                    }
-                }
-            }
-
-            // remeasure with the size we need
-            // This must always be done before the call to layout
-            w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, MeasureSpec.EXACTLY);
-            h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight - mScreenOffset,
-                    MeasureSpec.EXACTLY);
-            mViewRoot.measure(w_spec, h_spec);
-
-            // now do the layout.
-            mViewRoot.layout(0, mScreenOffset, mMeasuredScreenWidth, mMeasuredScreenHeight);
-
-            // draw the views
-            // create the BufferedImage into which the layout will be rendered.
-            if (newRenderSize || mCanvas == null) {
-                if (mParams.getImageFactory() != null) {
-                    mImage = mParams.getImageFactory().getImage(mMeasuredScreenWidth,
-                            mMeasuredScreenHeight - mScreenOffset);
-                } else {
-                    mImage = new BufferedImage(mMeasuredScreenWidth,
-                            mMeasuredScreenHeight - mScreenOffset, BufferedImage.TYPE_INT_ARGB);
-                }
-
-                if (mParams.isCustomBackgroundEnabled()) {
-                    Graphics2D gc = mImage.createGraphics();
-                    gc.setColor(new Color(mParams.getCustomBackgroundColor(), true));
-                    gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight - mScreenOffset);
-                    gc.dispose();
-                }
-
-                // create an Android bitmap around the BufferedImage
-                Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
-                        true /*isMutable*/,
-                        ResourceDensity.getEnum(mParams.getDensity()));
-
-                // create a Canvas around the Android bitmap
-                mCanvas = new Canvas(bitmap);
-                mCanvas.setDensity(mParams.getDensity());
-            }
-
-            mViewRoot.draw(mCanvas);
-
-            mViewInfo = visit(((ViewGroup)mViewRoot).getChildAt(0), mContext);
-
-            // success!
-            return SceneStatus.SUCCESS.createResult();
-        } catch (Throwable e) {
-            // get the real cause of the exception.
-            Throwable t = e;
-            while (t.getCause() != null) {
-                t = t.getCause();
-            }
-
-            // log it
-            mParams.getLog().error("Scene Render failed", t);
-
-            return SceneStatus.ERROR_UNKNOWN.createResult(t.getMessage(), t);
-        }
-    }
-
-    /**
-     * Animate an object
-     * <p>
-     * {@link #acquire(long)} must have been called before this.
-     *
-     * @throws IllegalStateException if the current context is different than the one owned by
-     *      the scene, or if {@link #acquire(long)} was not called.
-     *
-     * @see LayoutScene#animate(Object, String, boolean, IAnimationListener)
-     */
-    public SceneResult animate(Object targetObject, String animationName,
-            boolean isFrameworkAnimation, IAnimationListener listener) {
-        checkLock();
-
-        // find the animation file.
-        ResourceValue animationResource = null;
-        int animationId = 0;
-        if (isFrameworkAnimation) {
-            animationResource = mContext.getFrameworkResource("anim", animationName);
-            if (animationResource != null) {
-                animationId = Bridge.getResourceValue("anim", animationName);
-            }
-        } else {
-            animationResource = mContext.getProjectResource("anim", animationName);
-            if (animationResource != null) {
-                animationId = mContext.getProjectCallback().getResourceValue("anim", animationName);
-            }
-        }
-
-        if (animationResource != null) {
-            try {
-                Animator anim = AnimatorInflater.loadAnimator(mContext, animationId);
-                if (anim != null) {
-                    anim.setTarget(targetObject);
-
-                    new PlayAnimationThread(anim, this, animationName, listener).start();
-
-                    return SceneStatus.SUCCESS.createResult();
-                }
-            } catch (Exception e) {
-                // get the real cause of the exception.
-                Throwable t = e;
-                while (t.getCause() != null) {
-                    t = t.getCause();
-                }
-
-                return SceneStatus.ERROR_UNKNOWN.createResult(t.getMessage(), t);
-            }
-        }
-
-        return SceneStatus.ERROR_ANIM_NOT_FOUND.createResult();
-    }
-
-    /**
-     * Insert a new child into an existing parent.
-     * <p>
-     * {@link #acquire(long)} must have been called before this.
-     *
-     * @throws IllegalStateException if the current context is different than the one owned by
-     *      the scene, or if {@link #acquire(long)} was not called.
-     *
-     * @see LayoutScene#insertChild(Object, IXmlPullParser, int, IAnimationListener)
-     */
-    public SceneResult insertChild(final ViewGroup parentView, IXmlPullParser childXml,
-            final int index, IAnimationListener listener) {
-        checkLock();
-
-        // create a block parser for the XML
-        BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(childXml, mContext,
-                false /* platformResourceFlag */);
-
-        // inflate the child without adding it to the root since we want to control where it'll
-        // get added. We do pass the parentView however to ensure that the layoutParams will
-        // be created correctly.
-        final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/);
-
-        invalidateRenderingSize();
-
-        if (listener != null) {
-            new AnimationThread(this, "insertChild", listener) {
-
-                @Override
-                public SceneResult preAnimation() {
-                    parentView.setLayoutTransition(new LayoutTransition());
-                    return addView(parentView, child, index);
-                }
-
-                @Override
-                public void postAnimation() {
-                    parentView.setLayoutTransition(null);
-                }
-            }.start();
-
-            // always return success since the real status will come through the listener.
-            return SceneStatus.SUCCESS.createResult(child);
-        }
-
-        // add it to the parentView in the correct location
-        SceneResult result = addView(parentView, child, index);
-        if (result.isSuccess() == false) {
-            return result;
-        }
-
-        result = render();
-        if (result.isSuccess()) {
-            result = result.getCopyWithData(child);
-        }
-
-        return result;
-    }
-
-    /**
-     * Adds a given view to a given parent at a given index.
-     *
-     * @param parent the parent to receive the view
-     * @param view the view to add to the parent
-     * @param index the index where to do the add.
-     *
-     * @return a SceneResult with {@link SceneStatus#SUCCESS} or
-     *     {@link SceneStatus#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
-     *     adding views.
-     */
-    private SceneResult addView(ViewGroup parent, View view, int index) {
-        try {
-            parent.addView(view, index);
-            return SceneStatus.SUCCESS.createResult();
-        } catch (UnsupportedOperationException e) {
-            // looks like this is a view class that doesn't support children manipulation!
-            return SceneStatus.ERROR_VIEWGROUP_NO_CHILDREN.createResult();
-        }
-    }
-
-    /**
-     * Moves a view to a new parent at a given location
-     * <p>
-     * {@link #acquire(long)} must have been called before this.
-     *
-     * @throws IllegalStateException if the current context is different than the one owned by
-     *      the scene, or if {@link #acquire(long)} was not called.
-     *
-     * @see LayoutScene#moveChild(Object, Object, int, Map, IAnimationListener)
-     */
-    public SceneResult moveChild(final ViewGroup parentView, final View childView, final int index,
-            Map<String, String> layoutParamsMap, IAnimationListener listener) {
-        checkLock();
-
-        invalidateRenderingSize();
-
-        LayoutParams layoutParams = null;
-        if (layoutParamsMap != null) {
-            // need to create a new LayoutParams object for the new parent.
-            layoutParams = parentView.generateLayoutParams(
-                    new BridgeLayoutParamsMapAttributes(layoutParamsMap));
-        }
-
-        if (listener != null) {
-            final LayoutParams params = layoutParams;
-            new AnimationThread(this, "moveChild", listener) {
-
-                @Override
-                public SceneResult preAnimation() {
-                    parentView.setLayoutTransition(new LayoutTransition());
-                    return moveView(parentView, childView, index, params);
-                }
-
-                @Override
-                public void postAnimation() {
-                    parentView.setLayoutTransition(null);
-                }
-            }.start();
-
-            // always return success since the real status will come through the listener.
-            return SceneStatus.SUCCESS.createResult(layoutParams);
-        }
-
-        SceneResult result = moveView(parentView, childView, index, layoutParams);
-        if (result.isSuccess() == false) {
-            return result;
-        }
-
-        result = render();
-        if (layoutParams != null && result.isSuccess()) {
-            result = result.getCopyWithData(layoutParams);
-        }
-
-        return result;
-    }
-
-    /**
-     * Moves a View from its current parent to a new given parent at a new given location, with
-     * an optional new {@link LayoutParams} instance
-     *
-     * @param parent the new parent
-     * @param view the view to move
-     * @param index the new location in the new parent
-     * @param params an option (can be null) {@link LayoutParams} instance.
-     *
-     * @return a SceneResult with {@link SceneStatus#SUCCESS} or
-     *     {@link SceneStatus#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
-     *     adding views.
-     */
-    private SceneResult moveView(ViewGroup parent, View view, int index, LayoutParams params) {
-        try {
-            ViewGroup previousParent = (ViewGroup) view.getParent();
-            previousParent.removeView(view);
-
-            // add it to the parentView in the correct location
-
-            if (params != null) {
-                parent.addView(view, index, params);
-            } else {
-                parent.addView(view, index);
-            }
-
-            return SceneStatus.SUCCESS.createResult();
-        } catch (UnsupportedOperationException e) {
-            // looks like this is a view class that doesn't support children manipulation!
-            return SceneStatus.ERROR_VIEWGROUP_NO_CHILDREN.createResult();
-        }
-    }
-
-    /**
-     * Removes a child from its current parent.
-     * <p>
-     * {@link #acquire(long)} must have been called before this.
-     *
-     * @throws IllegalStateException if the current context is different than the one owned by
-     *      the scene, or if {@link #acquire(long)} was not called.
-     *
-     * @see LayoutScene#removeChild(Object, IAnimationListener)
-     */
-    public SceneResult removeChild(final View childView, IAnimationListener listener) {
-        checkLock();
-
-        invalidateRenderingSize();
-
-        final ViewGroup parent = (ViewGroup) childView.getParent();
-
-        if (listener != null) {
-            new AnimationThread(this, "moveChild", listener) {
-
-                @Override
-                public SceneResult preAnimation() {
-                    parent.setLayoutTransition(new LayoutTransition());
-                    return removeView(parent, childView);
-                }
-
-                @Override
-                public void postAnimation() {
-                    parent.setLayoutTransition(null);
-                }
-            }.start();
-
-            // always return success since the real status will come through the listener.
-            return SceneStatus.SUCCESS.createResult();
-        }
-
-        SceneResult result = removeView(parent, childView);
-        if (result.isSuccess() == false) {
-            return result;
-        }
-
-        return render();
-    }
-
-    /**
-     * Removes a given view from its current parent.
-     *
-     * @param view the view to remove from its parent
-     *
-     * @return a SceneResult with {@link SceneStatus#SUCCESS} or
-     *     {@link SceneStatus#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
-     *     adding views.
-     */
-    private SceneResult removeView(ViewGroup parent, View view) {
-        try {
-            parent.removeView(view);
-            return SceneStatus.SUCCESS.createResult();
-        } catch (UnsupportedOperationException e) {
-            // looks like this is a view class that doesn't support children manipulation!
-            return SceneStatus.ERROR_VIEWGROUP_NO_CHILDREN.createResult();
-        }
-    }
-
-    /**
-     * Checks that the lock is owned by the current thread and that the current context is the one
-     * from this scene.
-     *
-     * @throws IllegalStateException if the current context is different than the one owned by
-     *      the scene, or if {@link #acquire(long)} was not called.
-     */
-    private void checkLock() {
-        ReentrantLock lock = Bridge.getLock();
-        if (lock.isHeldByCurrentThread() == false) {
-            throw new IllegalStateException("scene must be acquired first. see #acquire(long)");
-        }
-        if (sCurrentContext != mContext) {
-            throw new IllegalStateException("Thread acquired a scene but is rendering a different one");
-        }
-    }
-
-
-    /**
-     * Compute style information from the given list of style for the project and framework.
-     * @param themeName the name of the current theme.  In order to differentiate project and
-     * platform themes sharing the same name, all project themes must be prepended with
-     * a '*' character.
-     * @param isProjectTheme Is this a project theme
-     * @param inProjectStyleMap the project style map
-     * @param inFrameworkStyleMap the framework style map
-     * @param outInheritanceMap the map of style inheritance. This is filled by the method
-     * @return the {@link IStyleResourceValue} matching <var>themeName</var>
-     */
-    private StyleResourceValue computeStyleMaps(
-            String themeName, boolean isProjectTheme, Map<String,
-            ResourceValue> inProjectStyleMap, Map<String, ResourceValue> inFrameworkStyleMap,
-            Map<StyleResourceValue, StyleResourceValue> outInheritanceMap) {
-
-        if (inProjectStyleMap != null && inFrameworkStyleMap != null) {
-            // first, get the theme
-            ResourceValue theme = null;
-
-            // project theme names have been prepended with a *
-            if (isProjectTheme) {
-                theme = inProjectStyleMap.get(themeName);
-            } else {
-                theme = inFrameworkStyleMap.get(themeName);
-            }
-
-            if (theme instanceof StyleResourceValue) {
-                // compute the inheritance map for both the project and framework styles
-                computeStyleInheritance(inProjectStyleMap.values(), inProjectStyleMap,
-                        inFrameworkStyleMap, outInheritanceMap);
-
-                // Compute the style inheritance for the framework styles/themes.
-                // Since, for those, the style parent values do not contain 'android:'
-                // we want to force looking in the framework style only to avoid using
-                // similarly named styles from the project.
-                // To do this, we pass null in lieu of the project style map.
-                computeStyleInheritance(inFrameworkStyleMap.values(), null /*inProjectStyleMap */,
-                        inFrameworkStyleMap, outInheritanceMap);
-
-                return (StyleResourceValue)theme;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Compute the parent style for all the styles in a given list.
-     * @param styles the styles for which we compute the parent.
-     * @param inProjectStyleMap the map of project styles.
-     * @param inFrameworkStyleMap the map of framework styles.
-     * @param outInheritanceMap the map of style inheritance. This is filled by the method.
-     */
-    private void computeStyleInheritance(Collection<ResourceValue> styles,
-            Map<String, ResourceValue> inProjectStyleMap,
-            Map<String, ResourceValue> inFrameworkStyleMap,
-            Map<StyleResourceValue, StyleResourceValue> outInheritanceMap) {
-        for (ResourceValue value : styles) {
-            if (value instanceof StyleResourceValue) {
-                StyleResourceValue style = (StyleResourceValue)value;
-                StyleResourceValue parentStyle = null;
-
-                // first look for a specified parent.
-                String parentName = style.getParentStyle();
-
-                // no specified parent? try to infer it from the name of the style.
-                if (parentName == null) {
-                    parentName = getParentName(value.getName());
-                }
-
-                if (parentName != null) {
-                    parentStyle = getStyle(parentName, inProjectStyleMap, inFrameworkStyleMap);
-
-                    if (parentStyle != null) {
-                        outInheritanceMap.put(style, parentStyle);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Searches for and returns the {@link IStyleResourceValue} from a given name.
-     * <p/>The format of the name can be:
-     * <ul>
-     * <li>[android:]&lt;name&gt;</li>
-     * <li>[android:]style/&lt;name&gt;</li>
-     * <li>@[android:]style/&lt;name&gt;</li>
-     * </ul>
-     * @param parentName the name of the style.
-     * @param inProjectStyleMap the project style map. Can be <code>null</code>
-     * @param inFrameworkStyleMap the framework style map.
-     * @return The matching {@link IStyleResourceValue} object or <code>null</code> if not found.
-     */
-    private StyleResourceValue getStyle(String parentName,
-            Map<String, ResourceValue> inProjectStyleMap,
-            Map<String, ResourceValue> inFrameworkStyleMap) {
-        boolean frameworkOnly = false;
-
-        String name = parentName;
-
-        // remove the useless @ if it's there
-        if (name.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) {
-            name = name.substring(BridgeConstants.PREFIX_RESOURCE_REF.length());
-        }
-
-        // check for framework identifier.
-        if (name.startsWith(BridgeConstants.PREFIX_ANDROID)) {
-            frameworkOnly = true;
-            name = name.substring(BridgeConstants.PREFIX_ANDROID.length());
-        }
-
-        // at this point we could have the format <type>/<name>. we want only the name as long as
-        // the type is style.
-        if (name.startsWith(BridgeConstants.REFERENCE_STYLE)) {
-            name = name.substring(BridgeConstants.REFERENCE_STYLE.length());
-        } else if (name.indexOf('/') != -1) {
-            return null;
-        }
-
-        ResourceValue parent = null;
-
-        // if allowed, search in the project resources.
-        if (frameworkOnly == false && inProjectStyleMap != null) {
-            parent = inProjectStyleMap.get(name);
-        }
-
-        // if not found, then look in the framework resources.
-        if (parent == null) {
-            parent = inFrameworkStyleMap.get(name);
-        }
-
-        // make sure the result is the proper class type and return it.
-        if (parent instanceof StyleResourceValue) {
-            return (StyleResourceValue)parent;
-        }
-
-        assert false;
-        mParams.getLog().error(null,
-                String.format("Unable to resolve parent style name: %s", parentName));
-
-        return null;
-    }
-
-    /**
-     * Computes the name of the parent style, or <code>null</code> if the style is a root style.
-     */
-    private String getParentName(String styleName) {
-        int index = styleName.lastIndexOf('.');
-        if (index != -1) {
-            return styleName.substring(0, index);
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns the top screen offset. This depends on whether the current theme defines the user
-     * of the title and status bars.
-     * @param frameworkResources The framework resources
-     * @param currentTheme The current theme
-     * @param context The context
-     * @return the pixel height offset
-     */
-    private int getScreenOffset(Map<String, Map<String, ResourceValue>> frameworkResources,
-            StyleResourceValue currentTheme, BridgeContext context) {
-        int offset = 0;
-
-        // get the title bar flag from the current theme.
-        ResourceValue value = context.findItemInStyle(currentTheme, "windowNoTitle");
-
-        // because it may reference something else, we resolve it.
-        value = context.resolveResValue(value);
-
-        // if there's a value and it's true (default is false)
-        if (value == null || value.getValue() == null ||
-                XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
-            // default size of the window title bar
-            int defaultOffset = DEFAULT_TITLE_BAR_HEIGHT;
-
-            // get value from the theme.
-            value = context.findItemInStyle(currentTheme, "windowTitleSize");
-
-            // resolve it
-            value = context.resolveResValue(value);
-
-            if (value != null) {
-                // get the numerical value, if available
-                TypedValue typedValue = ResourceHelper.getValue(value.getValue());
-                if (typedValue != null) {
-                    // compute the pixel value based on the display metrics
-                    defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
-                }
-            }
-
-            offset += defaultOffset;
-        }
-
-        // get the fullscreen flag from the current theme.
-        value = context.findItemInStyle(currentTheme, "windowFullscreen");
-
-        // because it may reference something else, we resolve it.
-        value = context.resolveResValue(value);
-
-        if (value == null || value.getValue() == null ||
-                XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
-
-            // default value
-            int defaultOffset = DEFAULT_STATUS_BAR_HEIGHT;
-
-            // get the real value, first the list of Dimensions from the framework map
-            Map<String, ResourceValue> dimens = frameworkResources.get(BridgeConstants.RES_DIMEN);
-
-            // now get the value
-            value = dimens.get("status_bar_height");
-            if (value != null) {
-                TypedValue typedValue = ResourceHelper.getValue(value.getValue());
-                if (typedValue != null) {
-                    // compute the pixel value based on the display metrics
-                    defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
-                }
-            }
-
-            // add the computed offset.
-            offset += defaultOffset;
-        }
-
-        return offset;
-
-    }
-
-    /**
-     * Post process on a view hierachy that was just inflated.
-     * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the
-     * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
-     * based on the content of the {@link FrameLayout}.
-     * @param view the root view to process.
-     * @param projectCallback callback to the project.
-     */
-    private void postInflateProcess(View view, IProjectCallback projectCallback)
-            throws PostInflateException {
-        if (view instanceof TabHost) {
-            setupTabHost((TabHost)view, projectCallback);
-        } else if (view instanceof ViewGroup) {
-            ViewGroup group = (ViewGroup)view;
-            final int count = group.getChildCount();
-            for (int c = 0 ; c < count ; c++) {
-                View child = group.getChildAt(c);
-                postInflateProcess(child, projectCallback);
-            }
-        }
-    }
-
-    /**
-     * Sets up a {@link TabHost} object.
-     * @param tabHost the TabHost to setup.
-     * @param projectCallback The project callback object to access the project R class.
-     * @throws PostInflateException
-     */
-    private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback)
-            throws PostInflateException {
-        // look for the TabWidget, and the FrameLayout. They have their own specific names
-        View v = tabHost.findViewById(android.R.id.tabs);
-
-        if (v == null) {
-            throw new PostInflateException(
-                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
-        }
-
-        if ((v instanceof TabWidget) == false) {
-            throw new PostInflateException(String.format(
-                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
-                    "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
-        }
-
-        v = tabHost.findViewById(android.R.id.tabcontent);
-
-        if (v == null) {
-            // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty)
-            throw new PostInflateException(
-                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
-        }
-
-        if ((v instanceof FrameLayout) == false) {
-            throw new PostInflateException(String.format(
-                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
-                    "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
-        }
-
-        FrameLayout content = (FrameLayout)v;
-
-        // now process the content of the framelayout and dynamically create tabs for it.
-        final int count = content.getChildCount();
-
-        if (count == 0) {
-            throw new PostInflateException(
-                    "The FrameLayout for the TabHost has no content. Rendering failed.\n");
-        }
-
-        // this must be called before addTab() so that the TabHost searches its TabWidget
-        // and FrameLayout.
-        tabHost.setup();
-
-        // for each child of the framelayout, add a new TabSpec
-        for (int i = 0 ; i < count ; i++) {
-            View child = content.getChildAt(i);
-            String tabSpec = String.format("tab_spec%d", i+1);
-            int id = child.getId();
-            String[] resource = projectCallback.resolveResourceValue(id);
-            String name;
-            if (resource != null) {
-                name = resource[0]; // 0 is resource name, 1 is resource type.
-            } else {
-                name = String.format("Tab %d", i+1); // default name if id is unresolved.
-            }
-            tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
-        }
-    }
-
-
-    /**
-     * Visits a View and its children and generate a {@link ViewInfo} containing the
-     * bounds of all the views.
-     * @param view the root View
-     * @param context the context.
-     */
-    private ViewInfo visit(View view, BridgeContext context) {
-        if (view == null) {
-            return null;
-        }
-
-        ViewInfo result = new ViewInfo(view.getClass().getName(),
-                context.getViewKey(view),
-                view.getLeft(), view.getTop(), view.getRight(), view.getBottom(),
-                view, view.getLayoutParams());
-
-        if (view instanceof ViewGroup) {
-            ViewGroup group = ((ViewGroup) view);
-            List<ViewInfo> children = new ArrayList<ViewInfo>();
-            for (int i = 0; i < group.getChildCount(); i++) {
-                children.add(visit(group.getChildAt(i), context));
-            }
-            result.setChildren(children);
-        }
-
-        return result;
-    }
-
-    private void invalidateRenderingSize() {
-        mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
-    }
-
-    public BufferedImage getImage() {
-        return mImage;
-    }
-
-    public ViewInfo getViewInfo() {
-        return mViewInfo;
-    }
-
-    public Map<String, String> getDefaultViewPropertyValues(Object viewObject) {
-        return mContext.getDefaultPropMap(viewObject);
-    }
-
-    public void setScene(LayoutScene scene) {
-        mScene = scene;
-    }
-
-    public LayoutScene getScene() {
-        return mScene;
-    }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java
index 2e2c5f4..35e5987 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java
@@ -16,9 +16,9 @@
 
 package com.android.layoutlib.bridge.impl;
 
-import com.android.layoutlib.api.SceneResult;
-import com.android.layoutlib.api.LayoutScene.IAnimationListener;
-import com.android.layoutlib.api.SceneResult.SceneStatus;
+import com.android.ide.common.rendering.api.IAnimationListener;
+import com.android.ide.common.rendering.api.Result;
+import com.android.ide.common.rendering.api.Result.Status;
 
 import android.animation.Animator;
 
@@ -26,19 +26,19 @@
 
     private final Animator mAnimator;
 
-    public PlayAnimationThread(Animator animator, LayoutSceneImpl scene, String animName,
+    public PlayAnimationThread(Animator animator, RenderSessionImpl scene, String animName,
             IAnimationListener listener) {
         super(scene, animName, listener);
         mAnimator = animator;
     }
 
     @Override
-    public SceneResult preAnimation() {
+    public Result preAnimation() {
         // start the animation. This will send a message to the handler right away, so
         // the queue is filled when this method returns.
         mAnimator.start();
 
-        return SceneStatus.SUCCESS.createResult();
+        return Status.SUCCESS.createResult();
     }
 
     @Override
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
new file mode 100644
index 0000000..2439791
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -0,0 +1,1282 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.impl;
+
+import static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND;
+import static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION;
+import static com.android.ide.common.rendering.api.Result.Status.ERROR_LOCK_INTERRUPTED;
+import static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED;
+import static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT;
+import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
+import static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN;
+import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
+
+import com.android.ide.common.rendering.api.IAnimationListener;
+import com.android.ide.common.rendering.api.ILayoutPullParser;
+import com.android.ide.common.rendering.api.IProjectCallback;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.Params;
+import com.android.ide.common.rendering.api.RenderSession;
+import com.android.ide.common.rendering.api.ResourceDensity;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.Result;
+import com.android.ide.common.rendering.api.StyleResourceValue;
+import com.android.ide.common.rendering.api.ViewInfo;
+import com.android.ide.common.rendering.api.Params.RenderingMode;
+import com.android.ide.common.rendering.api.Result.Status;
+import com.android.internal.util.XmlUtils;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.BridgeInflater;
+import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
+import com.android.layoutlib.bridge.android.BridgeWindow;
+import com.android.layoutlib.bridge.android.BridgeWindowSession;
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.LayoutTransition;
+import android.animation.LayoutTransition.TransitionListener;
+import android.app.Fragment_Delegate;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap_Delegate;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.AttachInfo;
+import android.view.View.MeasureSpec;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.FrameLayout;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Class implementing the render session.
+ *
+ * A session is a stateful representation of a layout file. It is initialized with data coming
+ * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then
+ * be done on the layout.
+ *
+ */
+public class RenderSessionImpl {
+
+    private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
+    private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
+
+    /**
+     * The current context being rendered. This is set through {@link #acquire(long)} and
+     * {@link #init(long)}, and unset in {@link #release()}.
+     */
+    private static BridgeContext sCurrentContext = null;
+
+    private final Params mParams;
+
+    // scene state
+    private RenderSession mScene;
+    private BridgeContext mContext;
+    private BridgeXmlBlockParser mBlockParser;
+    private BridgeInflater mInflater;
+    private StyleResourceValue mCurrentTheme;
+    private int mScreenOffset;
+    private ResourceValue mWindowBackground;
+    private FrameLayout mViewRoot;
+    private Canvas mCanvas;
+    private int mMeasuredScreenWidth = -1;
+    private int mMeasuredScreenHeight = -1;
+
+    // information being returned through the API
+    private BufferedImage mImage;
+    private ViewInfo mViewInfo;
+
+    private static final class PostInflateException extends Exception {
+        private static final long serialVersionUID = 1L;
+
+        public PostInflateException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * Creates a layout scene with all the information coming from the layout bridge API.
+     * <p>
+     * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init()}, which act as a
+     * call to {@link RenderSessionImpl#acquire(long)}
+     *
+     * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams)
+     */
+    public RenderSessionImpl(Params params) {
+        // copy the params.
+        mParams = new Params(params);
+    }
+
+    /**
+     * Initializes and acquires the scene, creating various Android objects such as context,
+     * inflater, and parser.
+     *
+     * @param timeout the time to wait if another rendering is happening.
+     *
+     * @return whether the scene was prepared
+     *
+     * @see #acquire(long)
+     * @see #release()
+     */
+    public Result init(long timeout) {
+        // acquire the lock. if the result is null, lock was just acquired, otherwise, return
+        // the result.
+        Result result = acquireLock(timeout);
+        if (result != null) {
+            return result;
+        }
+
+        Bridge.setLog(mParams.getLog());
+
+        // setup the display Metrics.
+        DisplayMetrics metrics = new DisplayMetrics();
+        metrics.densityDpi = mParams.getDensity();
+        metrics.density = mParams.getDensity() / (float) DisplayMetrics.DENSITY_DEFAULT;
+        metrics.scaledDensity = metrics.density;
+        metrics.widthPixels = mParams.getScreenWidth();
+        metrics.heightPixels = mParams.getScreenHeight();
+        metrics.xdpi = mParams.getXdpi();
+        metrics.ydpi = mParams.getYdpi();
+
+        // find the current theme and compute the style inheritance map
+        Map<StyleResourceValue, StyleResourceValue> styleParentMap =
+            new HashMap<StyleResourceValue, StyleResourceValue>();
+
+        mCurrentTheme = computeStyleMaps(mParams.getThemeName(), mParams.isProjectTheme(),
+                mParams.getProjectResources().get(BridgeConstants.RES_STYLE),
+                mParams.getFrameworkResources().get(BridgeConstants.RES_STYLE), styleParentMap);
+
+        // build the context
+        mContext = new BridgeContext(mParams.getProjectKey(), metrics, mCurrentTheme,
+                mParams.getProjectResources(), mParams.getFrameworkResources(),
+                styleParentMap, mParams.getProjectCallback());
+
+        // set the current rendering context
+        sCurrentContext = mContext;
+
+        // make sure the Resources object references the context (and other objects) for this
+        // scene
+        mContext.initResources();
+
+        // get the screen offset and window-background resource
+        mWindowBackground = null;
+        mScreenOffset = 0;
+        if (mCurrentTheme != null && mParams.isBgColorOverridden() == false) {
+            mWindowBackground = mContext.findItemInStyle(mCurrentTheme, "windowBackground");
+            mWindowBackground = mContext.resolveResValue(mWindowBackground);
+
+            mScreenOffset = getScreenOffset(mParams.getFrameworkResources(), mCurrentTheme,
+                    mContext);
+        }
+
+        // build the inflater and parser.
+        mInflater = new BridgeInflater(mContext, mParams.getProjectCallback());
+        mContext.setBridgeInflater(mInflater);
+        mInflater.setFactory2(mContext);
+
+        mBlockParser = new BridgeXmlBlockParser(mParams.getLayoutDescription(),
+                mContext, false /* platformResourceFlag */);
+
+        return SUCCESS.createResult();
+    }
+
+    /**
+     * Prepares the scene for action.
+     * <p>
+     * This call is blocking if another rendering/inflating is currently happening, and will return
+     * whether the preparation worked.
+     *
+     * The preparation can fail if another rendering took too long and the timeout was elapsed.
+     *
+     * More than one call to this from the same thread will have no effect and will return
+     * {@link Result#SUCCESS}.
+     *
+     * After scene actions have taken place, only one call to {@link #release()} must be
+     * done.
+     *
+     * @param timeout the time to wait if another rendering is happening.
+     *
+     * @return whether the scene was prepared
+     *
+     * @see #release()
+     *
+     * @throws IllegalStateException if {@link #init(long)} was never called.
+     */
+    public Result acquire(long timeout) {
+        if (mContext == null) {
+            throw new IllegalStateException("After scene creation, #init() must be called");
+        }
+
+        // acquire the lock. if the result is null, lock was just acquired, otherwise, return
+        // the result.
+        Result result = acquireLock(timeout);
+        if (result != null) {
+            return result;
+        }
+
+        // make sure the Resources object references the context (and other objects) for this
+        // scene
+        mContext.initResources();
+        sCurrentContext = mContext;
+        Bridge.setLog(mParams.getLog());
+
+        return SUCCESS.createResult();
+    }
+
+    /**
+     * Acquire the lock so that the scene can be acted upon.
+     * <p>
+     * This returns null if the lock was just acquired, otherwise it returns
+     * {@link Result#SUCCESS} if the lock already belonged to that thread, or another
+     * instance (see {@link Result#getStatus()}) if an error occurred.
+     *
+     * @param timeout the time to wait if another rendering is happening.
+     * @return null if the lock was just acquire or another result depending on the state.
+     *
+     * @throws IllegalStateException if the current context is different than the one owned by
+     *      the scene.
+     */
+    private Result acquireLock(long timeout) {
+        ReentrantLock lock = Bridge.getLock();
+        if (lock.isHeldByCurrentThread() == false) {
+            try {
+                boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS);
+
+                if (acquired == false) {
+                    return ERROR_TIMEOUT.createResult();
+                }
+            } catch (InterruptedException e) {
+                return ERROR_LOCK_INTERRUPTED.createResult();
+            }
+        } else {
+            // This thread holds the lock already. Checks that this wasn't for a different context.
+            // If this is called by init, mContext will be null and so should sCurrentContext
+            // anyway
+            if (mContext != sCurrentContext) {
+                throw new IllegalStateException("Acquiring different scenes from same thread without releases");
+            }
+            return SUCCESS.createResult();
+        }
+
+        return null;
+    }
+
+    /**
+     * Cleans up the scene after an action.
+     */
+    public void release() {
+        ReentrantLock lock = Bridge.getLock();
+
+        // with the use of finally blocks, it is possible to find ourself calling this
+        // without a successful call to prepareScene. This test makes sure that unlock() will
+        // not throw IllegalMonitorStateException.
+        if (lock.isHeldByCurrentThread()) {
+            // Make sure to remove static references, otherwise we could not unload the lib
+            mContext.disposeResources();
+            Bridge.setLog(null);
+            sCurrentContext = null;
+
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Inflates the layout.
+     * <p>
+     * {@link #acquire(long)} must have been called before this.
+     *
+     * @throws IllegalStateException if the current context is different than the one owned by
+     *      the scene, or if {@link #init(long)} was not called.
+     */
+    public Result inflate() {
+        checkLock();
+
+        try {
+
+            mViewRoot = new FrameLayout(mContext);
+
+            // Sets the project callback (custom view loader) to the fragment delegate so that
+            // it can instantiate the custom Fragment.
+            Fragment_Delegate.setProjectCallback(mParams.getProjectCallback());
+
+            View view = mInflater.inflate(mBlockParser, mViewRoot);
+
+            // post-inflate process. For now this supports TabHost/TabWidget
+            postInflateProcess(view, mParams.getProjectCallback());
+
+            Fragment_Delegate.setProjectCallback(null);
+
+            // set the AttachInfo on the root view.
+            AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
+                    new Handler(), null);
+            info.mHasWindowFocus = true;
+            info.mWindowVisibility = View.VISIBLE;
+            info.mInTouchMode = false; // this is so that we can display selections.
+            info.mHardwareAccelerated = false;
+            mViewRoot.dispatchAttachedToWindow(info, 0);
+
+            // get the background drawable
+            if (mWindowBackground != null) {
+                Drawable d = ResourceHelper.getDrawable(mWindowBackground,
+                        mContext, true /* isFramework */);
+                mViewRoot.setBackgroundDrawable(d);
+            }
+
+            return SUCCESS.createResult();
+        } catch (PostInflateException e) {
+            return ERROR_INFLATION.createResult(e.getMessage(), e);
+        } catch (Throwable e) {
+            // get the real cause of the exception.
+            Throwable t = e;
+            while (t.getCause() != null) {
+                t = t.getCause();
+            }
+
+            return ERROR_INFLATION.createResult(t.getMessage(), t);
+        }
+    }
+
+    /**
+     * Renders the scene.
+     * <p>
+     * {@link #acquire(long)} must have been called before this.
+     *
+     * @throws IllegalStateException if the current context is different than the one owned by
+     *      the scene, or if {@link #acquire(long)} was not called.
+     *
+     * @see SceneParams#getRenderingMode()
+     * @see LayoutScene#render(long)
+     */
+    public Result render() {
+        checkLock();
+
+        try {
+            if (mViewRoot == null) {
+                return ERROR_NOT_INFLATED.createResult();
+            }
+            // measure the views
+            int w_spec, h_spec;
+
+            RenderingMode renderingMode = mParams.getRenderingMode();
+
+            // only do the screen measure when needed.
+            boolean newRenderSize = false;
+            if (mMeasuredScreenWidth == -1) {
+                newRenderSize = true;
+                mMeasuredScreenWidth = mParams.getScreenWidth();
+                mMeasuredScreenHeight = mParams.getScreenHeight();
+
+                if (renderingMode != RenderingMode.NORMAL) {
+                    // measure the full size needed by the layout.
+                    w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth,
+                            renderingMode.isHorizExpand() ?
+                                    MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
+                                    : MeasureSpec.EXACTLY);
+                    h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight - mScreenOffset,
+                            renderingMode.isVertExpand() ?
+                                    MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
+                                    : MeasureSpec.EXACTLY);
+                    mViewRoot.measure(w_spec, h_spec);
+
+                    if (renderingMode.isHorizExpand()) {
+                        int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth();
+                        if (neededWidth > mMeasuredScreenWidth) {
+                            mMeasuredScreenWidth = neededWidth;
+                        }
+                    }
+
+                    if (renderingMode.isVertExpand()) {
+                        int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight();
+                        if (neededHeight > mMeasuredScreenHeight - mScreenOffset) {
+                            mMeasuredScreenHeight = neededHeight + mScreenOffset;
+                        }
+                    }
+                }
+            }
+
+            // remeasure with the size we need
+            // This must always be done before the call to layout
+            w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, MeasureSpec.EXACTLY);
+            h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight - mScreenOffset,
+                    MeasureSpec.EXACTLY);
+            mViewRoot.measure(w_spec, h_spec);
+
+            // now do the layout.
+            mViewRoot.layout(0, mScreenOffset, mMeasuredScreenWidth, mMeasuredScreenHeight);
+
+            // draw the views
+            // create the BufferedImage into which the layout will be rendered.
+            if (newRenderSize || mCanvas == null) {
+                if (mParams.getImageFactory() != null) {
+                    mImage = mParams.getImageFactory().getImage(mMeasuredScreenWidth,
+                            mMeasuredScreenHeight - mScreenOffset);
+                } else {
+                    mImage = new BufferedImage(mMeasuredScreenWidth,
+                            mMeasuredScreenHeight - mScreenOffset, BufferedImage.TYPE_INT_ARGB);
+                }
+
+                if (mParams.isBgColorOverridden()) {
+                    Graphics2D gc = mImage.createGraphics();
+                    gc.setColor(new Color(mParams.getOverrideBgColor(), true));
+                    gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight - mScreenOffset);
+                    gc.dispose();
+                }
+
+                // create an Android bitmap around the BufferedImage
+                Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
+                        true /*isMutable*/,
+                        ResourceDensity.getEnum(mParams.getDensity()));
+
+                // create a Canvas around the Android bitmap
+                mCanvas = new Canvas(bitmap);
+                mCanvas.setDensity(mParams.getDensity());
+            }
+
+            mViewRoot.draw(mCanvas);
+
+            mViewInfo = visit(((ViewGroup)mViewRoot).getChildAt(0), mContext);
+
+            // success!
+            return SUCCESS.createResult();
+        } catch (Throwable e) {
+            // get the real cause of the exception.
+            Throwable t = e;
+            while (t.getCause() != null) {
+                t = t.getCause();
+            }
+
+            return ERROR_UNKNOWN.createResult(t.getMessage(), t);
+        }
+    }
+
+    /**
+     * Animate an object
+     * <p>
+     * {@link #acquire(long)} must have been called before this.
+     *
+     * @throws IllegalStateException if the current context is different than the one owned by
+     *      the scene, or if {@link #acquire(long)} was not called.
+     *
+     * @see LayoutScene#animate(Object, String, boolean, IAnimationListener)
+     */
+    public Result animate(Object targetObject, String animationName,
+            boolean isFrameworkAnimation, IAnimationListener listener) {
+        checkLock();
+
+        // find the animation file.
+        ResourceValue animationResource = null;
+        int animationId = 0;
+        if (isFrameworkAnimation) {
+            animationResource = mContext.getFrameworkResource(BridgeConstants.RES_ANIMATOR,
+                    animationName);
+            if (animationResource != null) {
+                animationId = Bridge.getResourceValue(BridgeConstants.RES_ANIMATOR,
+                        animationName);
+            }
+        } else {
+            animationResource = mContext.getProjectResource(BridgeConstants.RES_ANIMATOR,
+                    animationName);
+            if (animationResource != null) {
+                animationId = mContext.getProjectCallback().getResourceValue(
+                        BridgeConstants.RES_ANIMATOR, animationName);
+            }
+        }
+
+        if (animationResource != null) {
+            try {
+                Animator anim = AnimatorInflater.loadAnimator(mContext, animationId);
+                if (anim != null) {
+                    anim.setTarget(targetObject);
+
+                    new PlayAnimationThread(anim, this, animationName, listener).start();
+
+                    return SUCCESS.createResult();
+                }
+            } catch (Exception e) {
+                // get the real cause of the exception.
+                Throwable t = e;
+                while (t.getCause() != null) {
+                    t = t.getCause();
+                }
+
+                return ERROR_UNKNOWN.createResult(t.getMessage(), t);
+            }
+        }
+
+        return ERROR_ANIM_NOT_FOUND.createResult();
+    }
+
+    /**
+     * Insert a new child into an existing parent.
+     * <p>
+     * {@link #acquire(long)} must have been called before this.
+     *
+     * @throws IllegalStateException if the current context is different than the one owned by
+     *      the scene, or if {@link #acquire(long)} was not called.
+     *
+     * @see LayoutScene#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
+     */
+    public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
+            final int index, IAnimationListener listener) {
+        checkLock();
+
+        // create a block parser for the XML
+        BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(childXml, mContext,
+                false /* platformResourceFlag */);
+
+        // inflate the child without adding it to the root since we want to control where it'll
+        // get added. We do pass the parentView however to ensure that the layoutParams will
+        // be created correctly.
+        final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/);
+
+        invalidateRenderingSize();
+
+        if (listener != null) {
+            new AnimationThread(this, "insertChild", listener) {
+
+                @Override
+                public Result preAnimation() {
+                    parentView.setLayoutTransition(new LayoutTransition());
+                    return addView(parentView, child, index);
+                }
+
+                @Override
+                public void postAnimation() {
+                    parentView.setLayoutTransition(null);
+                }
+            }.start();
+
+            // always return success since the real status will come through the listener.
+            return SUCCESS.createResult(child);
+        }
+
+        // add it to the parentView in the correct location
+        Result result = addView(parentView, child, index);
+        if (result.isSuccess() == false) {
+            return result;
+        }
+
+        result = render();
+        if (result.isSuccess()) {
+            result = result.getCopyWithData(child);
+        }
+
+        return result;
+    }
+
+    /**
+     * Adds a given view to a given parent at a given index.
+     *
+     * @param parent the parent to receive the view
+     * @param view the view to add to the parent
+     * @param index the index where to do the add.
+     *
+     * @return a Result with {@link Status#SUCCESS} or
+     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
+     *     adding views.
+     */
+    private Result addView(ViewGroup parent, View view, int index) {
+        try {
+            parent.addView(view, index);
+            return SUCCESS.createResult();
+        } catch (UnsupportedOperationException e) {
+            // looks like this is a view class that doesn't support children manipulation!
+            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
+        }
+    }
+
+    /**
+     * Moves a view to a new parent at a given location
+     * <p>
+     * {@link #acquire(long)} must have been called before this.
+     *
+     * @throws IllegalStateException if the current context is different than the one owned by
+     *      the scene, or if {@link #acquire(long)} was not called.
+     *
+     * @see LayoutScene#moveChild(Object, Object, int, Map, IAnimationListener)
+     */
+    public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
+            Map<String, String> layoutParamsMap, final IAnimationListener listener) {
+        checkLock();
+
+        invalidateRenderingSize();
+
+        LayoutParams layoutParams = null;
+        if (layoutParamsMap != null) {
+            // need to create a new LayoutParams object for the new parent.
+            layoutParams = newParentView.generateLayoutParams(
+                    new BridgeLayoutParamsMapAttributes(layoutParamsMap));
+        }
+
+        // get the current parent of the view that needs to be moved.
+        final ViewGroup previousParent = (ViewGroup) childView.getParent();
+
+        if (listener != null) {
+            final LayoutParams params = layoutParams;
+
+            // there is no support for animating views across layouts, so in case the new and old
+            // parent views are different we fake the animation through a no animation thread.
+            if (previousParent != newParentView) {
+                new Thread("not animated moveChild") {
+                    @Override
+                    public void run() {
+                        Result result = moveView(previousParent, newParentView, childView, index,
+                                params);
+                        if (result.isSuccess() == false) {
+                            listener.done(result);
+                        }
+
+                        // ready to do the work, acquire the scene.
+                        result = acquire(250);
+                        if (result.isSuccess() == false) {
+                            listener.done(result);
+                            return;
+                        }
+
+                        try {
+                            result = render();
+                            if (result.isSuccess()) {
+                                listener.onNewFrame(RenderSessionImpl.this.getSession());
+                            }
+                        } finally {
+                            release();
+                        }
+
+                        listener.done(result);
+                    }
+                }.start();
+            } else {
+                new AnimationThread(this, "moveChild", listener) {
+
+                    @Override
+                    public Result preAnimation() {
+                        // set up the transition for the parent.
+                        LayoutTransition transition = new LayoutTransition();
+                        previousParent.setLayoutTransition(transition);
+
+                        // tweak the animation durations and start delays (to match the duration of
+                        // animation playing just before).
+                        // Note: Cannot user Animation.setDuration() directly. Have to set it
+                        // on the LayoutTransition.
+                        transition.setDuration(LayoutTransition.DISAPPEARING, 100);
+                        // CHANGE_DISAPPEARING plays after DISAPPEARING
+                        transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100);
+
+                        transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100);
+
+                        transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100);
+                        // CHANGE_APPEARING plays after CHANGE_APPEARING
+                        transition.setStartDelay(LayoutTransition.APPEARING, 100);
+
+                        transition.setDuration(LayoutTransition.APPEARING, 100);
+
+                        return moveView(previousParent, newParentView, childView, index, params);
+                    }
+
+                    @Override
+                    public void postAnimation() {
+                        previousParent.setLayoutTransition(null);
+                        newParentView.setLayoutTransition(null);
+                    }
+                }.start();
+            }
+
+            // always return success since the real status will come through the listener.
+            return SUCCESS.createResult(layoutParams);
+        }
+
+        Result result = moveView(previousParent, newParentView, childView, index, layoutParams);
+        if (result.isSuccess() == false) {
+            return result;
+        }
+
+        result = render();
+        if (layoutParams != null && result.isSuccess()) {
+            result = result.getCopyWithData(layoutParams);
+        }
+
+        return result;
+    }
+
+    /**
+     * Moves a View from its current parent to a new given parent at a new given location, with
+     * an optional new {@link LayoutParams} instance
+     *
+     * @param previousParent the previous parent, still owning the child at the time of the call.
+     * @param newParent the new parent
+     * @param movedView the view to move
+     * @param index the new location in the new parent
+     * @param params an option (can be null) {@link LayoutParams} instance.
+     *
+     * @return a Result with {@link Status#SUCCESS} or
+     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
+     *     adding views.
+     */
+    private Result moveView(ViewGroup previousParent, final ViewGroup newParent,
+            final View movedView, final int index, final LayoutParams params) {
+        try {
+            // check if there is a transition on the previousParent.
+            LayoutTransition previousTransition = previousParent.getLayoutTransition();
+            if (previousTransition != null) {
+                // in this case there is an animation. This means we have to wait for the child's
+                // parent reference to be null'ed out so that we can add it to the new parent.
+                // It is technically removed right before the DISAPPEARING animation is done (if
+                // the animation of this type is not null, otherwise it's after which is impossible
+                // to handle).
+                // Because there is no move animation, if the new parent is the same as the old
+                // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
+                // adding the child or the child will appear in its new location before the
+                // other children have made room for it.
+
+                // add a listener to the transition to be notified of the actual removal.
+                previousTransition.addTransitionListener(new TransitionListener() {
+                    private int mChangeDisappearingCount = 0;
+
+                    public void startTransition(LayoutTransition transition, ViewGroup container,
+                            View view, int transitionType) {
+                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
+                            mChangeDisappearingCount++;
+                        }
+                    }
+
+                    public void endTransition(LayoutTransition transition, ViewGroup container,
+                            View view, int transitionType) {
+                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
+                            mChangeDisappearingCount--;
+                        }
+
+                        if (transitionType == LayoutTransition.CHANGE_DISAPPEARING &&
+                                mChangeDisappearingCount == 0) {
+                            // add it to the parentView in the correct location
+                            if (params != null) {
+                                newParent.addView(movedView, index, params);
+                            } else {
+                                newParent.addView(movedView, index);
+                            }
+                        }
+                    }
+                });
+
+                // remove the view from the current parent.
+                previousParent.removeView(movedView);
+
+                // and return since adding the view to the new parent is done in the listener.
+                return SUCCESS.createResult();
+            } else {
+                // standard code with no animation. pretty simple.
+                previousParent.removeView(movedView);
+
+                // add it to the parentView in the correct location
+                if (params != null) {
+                    newParent.addView(movedView, index, params);
+                } else {
+                    newParent.addView(movedView, index);
+                }
+
+                return SUCCESS.createResult();
+            }
+        } catch (UnsupportedOperationException e) {
+            // looks like this is a view class that doesn't support children manipulation!
+            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
+        }
+    }
+
+    /**
+     * Removes a child from its current parent.
+     * <p>
+     * {@link #acquire(long)} must have been called before this.
+     *
+     * @throws IllegalStateException if the current context is different than the one owned by
+     *      the scene, or if {@link #acquire(long)} was not called.
+     *
+     * @see LayoutScene#removeChild(Object, IAnimationListener)
+     */
+    public Result removeChild(final View childView, IAnimationListener listener) {
+        checkLock();
+
+        invalidateRenderingSize();
+
+        final ViewGroup parent = (ViewGroup) childView.getParent();
+
+        if (listener != null) {
+            new AnimationThread(this, "moveChild", listener) {
+
+                @Override
+                public Result preAnimation() {
+                    parent.setLayoutTransition(new LayoutTransition());
+                    return removeView(parent, childView);
+                }
+
+                @Override
+                public void postAnimation() {
+                    parent.setLayoutTransition(null);
+                }
+            }.start();
+
+            // always return success since the real status will come through the listener.
+            return SUCCESS.createResult();
+        }
+
+        Result result = removeView(parent, childView);
+        if (result.isSuccess() == false) {
+            return result;
+        }
+
+        return render();
+    }
+
+    /**
+     * Removes a given view from its current parent.
+     *
+     * @param view the view to remove from its parent
+     *
+     * @return a Result with {@link Status#SUCCESS} or
+     *     {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
+     *     adding views.
+     */
+    private Result removeView(ViewGroup parent, View view) {
+        try {
+            parent.removeView(view);
+            return SUCCESS.createResult();
+        } catch (UnsupportedOperationException e) {
+            // looks like this is a view class that doesn't support children manipulation!
+            return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
+        }
+    }
+
+    /**
+     * Returns the log associated with the session.
+     * @return the log or null if there are none.
+     */
+    public LayoutLog getLog() {
+        if (mParams != null) {
+            return mParams.getLog();
+        }
+
+        return null;
+    }
+
+    /**
+     * Checks that the lock is owned by the current thread and that the current context is the one
+     * from this scene.
+     *
+     * @throws IllegalStateException if the current context is different than the one owned by
+     *      the scene, or if {@link #acquire(long)} was not called.
+     */
+    private void checkLock() {
+        ReentrantLock lock = Bridge.getLock();
+        if (lock.isHeldByCurrentThread() == false) {
+            throw new IllegalStateException("scene must be acquired first. see #acquire(long)");
+        }
+        if (sCurrentContext != mContext) {
+            throw new IllegalStateException("Thread acquired a scene but is rendering a different one");
+        }
+    }
+
+
+    /**
+     * Compute style information from the given list of style for the project and framework.
+     * @param themeName the name of the current theme.  In order to differentiate project and
+     * platform themes sharing the same name, all project themes must be prepended with
+     * a '*' character.
+     * @param isProjectTheme Is this a project theme
+     * @param inProjectStyleMap the project style map
+     * @param inFrameworkStyleMap the framework style map
+     * @param outInheritanceMap the map of style inheritance. This is filled by the method
+     * @return the {@link StyleResourceValue} matching <var>themeName</var>
+     */
+    private StyleResourceValue computeStyleMaps(
+            String themeName, boolean isProjectTheme, Map<String,
+            ResourceValue> inProjectStyleMap, Map<String, ResourceValue> inFrameworkStyleMap,
+            Map<StyleResourceValue, StyleResourceValue> outInheritanceMap) {
+
+        if (inProjectStyleMap != null && inFrameworkStyleMap != null) {
+            // first, get the theme
+            ResourceValue theme = null;
+
+            // project theme names have been prepended with a *
+            if (isProjectTheme) {
+                theme = inProjectStyleMap.get(themeName);
+            } else {
+                theme = inFrameworkStyleMap.get(themeName);
+            }
+
+            if (theme instanceof StyleResourceValue) {
+                // compute the inheritance map for both the project and framework styles
+                computeStyleInheritance(inProjectStyleMap.values(), inProjectStyleMap,
+                        inFrameworkStyleMap, outInheritanceMap);
+
+                // Compute the style inheritance for the framework styles/themes.
+                // Since, for those, the style parent values do not contain 'android:'
+                // we want to force looking in the framework style only to avoid using
+                // similarly named styles from the project.
+                // To do this, we pass null in lieu of the project style map.
+                computeStyleInheritance(inFrameworkStyleMap.values(), null /*inProjectStyleMap */,
+                        inFrameworkStyleMap, outInheritanceMap);
+
+                return (StyleResourceValue)theme;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Compute the parent style for all the styles in a given list.
+     * @param styles the styles for which we compute the parent.
+     * @param inProjectStyleMap the map of project styles.
+     * @param inFrameworkStyleMap the map of framework styles.
+     * @param outInheritanceMap the map of style inheritance. This is filled by the method.
+     */
+    private void computeStyleInheritance(Collection<ResourceValue> styles,
+            Map<String, ResourceValue> inProjectStyleMap,
+            Map<String, ResourceValue> inFrameworkStyleMap,
+            Map<StyleResourceValue, StyleResourceValue> outInheritanceMap) {
+        for (ResourceValue value : styles) {
+            if (value instanceof StyleResourceValue) {
+                StyleResourceValue style = (StyleResourceValue)value;
+                StyleResourceValue parentStyle = null;
+
+                // first look for a specified parent.
+                String parentName = style.getParentStyle();
+
+                // no specified parent? try to infer it from the name of the style.
+                if (parentName == null) {
+                    parentName = getParentName(value.getName());
+                }
+
+                if (parentName != null) {
+                    parentStyle = getStyle(parentName, inProjectStyleMap, inFrameworkStyleMap);
+
+                    if (parentStyle != null) {
+                        outInheritanceMap.put(style, parentStyle);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Searches for and returns the {@link StyleResourceValue} from a given name.
+     * <p/>The format of the name can be:
+     * <ul>
+     * <li>[android:]&lt;name&gt;</li>
+     * <li>[android:]style/&lt;name&gt;</li>
+     * <li>@[android:]style/&lt;name&gt;</li>
+     * </ul>
+     * @param parentName the name of the style.
+     * @param inProjectStyleMap the project style map. Can be <code>null</code>
+     * @param inFrameworkStyleMap the framework style map.
+     * @return The matching {@link StyleResourceValue} object or <code>null</code> if not found.
+     */
+    private StyleResourceValue getStyle(String parentName,
+            Map<String, ResourceValue> inProjectStyleMap,
+            Map<String, ResourceValue> inFrameworkStyleMap) {
+        boolean frameworkOnly = false;
+
+        String name = parentName;
+
+        // remove the useless @ if it's there
+        if (name.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) {
+            name = name.substring(BridgeConstants.PREFIX_RESOURCE_REF.length());
+        }
+
+        // check for framework identifier.
+        if (name.startsWith(BridgeConstants.PREFIX_ANDROID)) {
+            frameworkOnly = true;
+            name = name.substring(BridgeConstants.PREFIX_ANDROID.length());
+        }
+
+        // at this point we could have the format <type>/<name>. we want only the name as long as
+        // the type is style.
+        if (name.startsWith(BridgeConstants.REFERENCE_STYLE)) {
+            name = name.substring(BridgeConstants.REFERENCE_STYLE.length());
+        } else if (name.indexOf('/') != -1) {
+            return null;
+        }
+
+        ResourceValue parent = null;
+
+        // if allowed, search in the project resources.
+        if (frameworkOnly == false && inProjectStyleMap != null) {
+            parent = inProjectStyleMap.get(name);
+        }
+
+        // if not found, then look in the framework resources.
+        if (parent == null) {
+            parent = inFrameworkStyleMap.get(name);
+        }
+
+        // make sure the result is the proper class type and return it.
+        if (parent instanceof StyleResourceValue) {
+            return (StyleResourceValue)parent;
+        }
+
+        assert false;
+        mParams.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
+                String.format("Unable to resolve parent style name: %s", parentName),
+                null /*data*/);
+
+        return null;
+    }
+
+    /**
+     * Computes the name of the parent style, or <code>null</code> if the style is a root style.
+     */
+    private String getParentName(String styleName) {
+        int index = styleName.lastIndexOf('.');
+        if (index != -1) {
+            return styleName.substring(0, index);
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the top screen offset. This depends on whether the current theme defines the user
+     * of the title and status bars.
+     * @param frameworkResources The framework resources
+     * @param currentTheme The current theme
+     * @param context The context
+     * @return the pixel height offset
+     */
+    private int getScreenOffset(Map<String, Map<String, ResourceValue>> frameworkResources,
+            StyleResourceValue currentTheme, BridgeContext context) {
+        int offset = 0;
+
+        // get the title bar flag from the current theme.
+        ResourceValue value = context.findItemInStyle(currentTheme, "windowNoTitle");
+
+        // because it may reference something else, we resolve it.
+        value = context.resolveResValue(value);
+
+        // if there's a value and it's true (default is false)
+        if (value == null || value.getValue() == null ||
+                XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
+            // default size of the window title bar
+            int defaultOffset = DEFAULT_TITLE_BAR_HEIGHT;
+
+            // get value from the theme.
+            value = context.findItemInStyle(currentTheme, "windowTitleSize");
+
+            // resolve it
+            value = context.resolveResValue(value);
+
+            if (value != null) {
+                // get the numerical value, if available
+                TypedValue typedValue = ResourceHelper.getValue(value.getValue());
+                if (typedValue != null) {
+                    // compute the pixel value based on the display metrics
+                    defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
+                }
+            }
+
+            offset += defaultOffset;
+        }
+
+        // get the fullscreen flag from the current theme.
+        value = context.findItemInStyle(currentTheme, "windowFullscreen");
+
+        // because it may reference something else, we resolve it.
+        value = context.resolveResValue(value);
+
+        if (value == null || value.getValue() == null ||
+                XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
+
+            // default value
+            int defaultOffset = DEFAULT_STATUS_BAR_HEIGHT;
+
+            // get the real value, first the list of Dimensions from the framework map
+            Map<String, ResourceValue> dimens = frameworkResources.get(BridgeConstants.RES_DIMEN);
+
+            // now get the value
+            value = dimens.get("status_bar_height");
+            if (value != null) {
+                TypedValue typedValue = ResourceHelper.getValue(value.getValue());
+                if (typedValue != null) {
+                    // compute the pixel value based on the display metrics
+                    defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
+                }
+            }
+
+            // add the computed offset.
+            offset += defaultOffset;
+        }
+
+        return offset;
+
+    }
+
+    /**
+     * Post process on a view hierachy that was just inflated.
+     * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the
+     * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
+     * based on the content of the {@link FrameLayout}.
+     * @param view the root view to process.
+     * @param projectCallback callback to the project.
+     */
+    private void postInflateProcess(View view, IProjectCallback projectCallback)
+            throws PostInflateException {
+        if (view instanceof TabHost) {
+            setupTabHost((TabHost)view, projectCallback);
+        } else if (view instanceof ViewGroup) {
+            ViewGroup group = (ViewGroup)view;
+            final int count = group.getChildCount();
+            for (int c = 0 ; c < count ; c++) {
+                View child = group.getChildAt(c);
+                postInflateProcess(child, projectCallback);
+            }
+        }
+    }
+
+    /**
+     * Sets up a {@link TabHost} object.
+     * @param tabHost the TabHost to setup.
+     * @param projectCallback The project callback object to access the project R class.
+     * @throws PostInflateException
+     */
+    private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback)
+            throws PostInflateException {
+        // look for the TabWidget, and the FrameLayout. They have their own specific names
+        View v = tabHost.findViewById(android.R.id.tabs);
+
+        if (v == null) {
+            throw new PostInflateException(
+                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
+        }
+
+        if ((v instanceof TabWidget) == false) {
+            throw new PostInflateException(String.format(
+                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
+                    "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
+        }
+
+        v = tabHost.findViewById(android.R.id.tabcontent);
+
+        if (v == null) {
+            // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty)
+            throw new PostInflateException(
+                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
+        }
+
+        if ((v instanceof FrameLayout) == false) {
+            throw new PostInflateException(String.format(
+                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
+                    "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
+        }
+
+        FrameLayout content = (FrameLayout)v;
+
+        // now process the content of the framelayout and dynamically create tabs for it.
+        final int count = content.getChildCount();
+
+        if (count == 0) {
+            throw new PostInflateException(
+                    "The FrameLayout for the TabHost has no content. Rendering failed.\n");
+        }
+
+        // this must be called before addTab() so that the TabHost searches its TabWidget
+        // and FrameLayout.
+        tabHost.setup();
+
+        // for each child of the framelayout, add a new TabSpec
+        for (int i = 0 ; i < count ; i++) {
+            View child = content.getChildAt(i);
+            String tabSpec = String.format("tab_spec%d", i+1);
+            int id = child.getId();
+            String[] resource = projectCallback.resolveResourceValue(id);
+            String name;
+            if (resource != null) {
+                name = resource[0]; // 0 is resource name, 1 is resource type.
+            } else {
+                name = String.format("Tab %d", i+1); // default name if id is unresolved.
+            }
+            tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
+        }
+    }
+
+
+    /**
+     * Visits a View and its children and generate a {@link ViewInfo} containing the
+     * bounds of all the views.
+     * @param view the root View
+     * @param context the context.
+     */
+    private ViewInfo visit(View view, BridgeContext context) {
+        if (view == null) {
+            return null;
+        }
+
+        ViewInfo result = new ViewInfo(view.getClass().getName(),
+                context.getViewKey(view),
+                view.getLeft(), view.getTop(), view.getRight(), view.getBottom(),
+                view, view.getLayoutParams());
+
+        if (view instanceof ViewGroup) {
+            ViewGroup group = ((ViewGroup) view);
+            List<ViewInfo> children = new ArrayList<ViewInfo>();
+            for (int i = 0; i < group.getChildCount(); i++) {
+                children.add(visit(group.getChildAt(i), context));
+            }
+            result.setChildren(children);
+        }
+
+        return result;
+    }
+
+    private void invalidateRenderingSize() {
+        mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
+    }
+
+    public BufferedImage getImage() {
+        return mImage;
+    }
+
+    public ViewInfo getViewInfo() {
+        return mViewInfo;
+    }
+
+    public Map<String, String> getDefaultProperties(Object viewObject) {
+        return mContext.getDefaultPropMap(viewObject);
+    }
+
+    public void setScene(RenderSession session) {
+        mScene = session;
+    }
+
+    public RenderSession getSession() {
+        return mScene;
+    }
+}
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 f03931f..475b4be2 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
@@ -16,9 +16,10 @@
 
 package com.android.layoutlib.bridge.impl;
 
-import com.android.layoutlib.api.DensityBasedResourceValue;
-import com.android.layoutlib.api.ResourceDensity;
-import com.android.layoutlib.api.ResourceValue;
+import com.android.ide.common.rendering.api.DensityBasedResourceValue;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.ResourceDensity;
+import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
@@ -27,7 +28,6 @@
 
 import org.kxml2.io.KXmlParser;
 import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
 
 import android.graphics.Bitmap;
 import android.graphics.Bitmap_Delegate;
@@ -40,7 +40,6 @@
 import android.util.TypedValue;
 
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 import java.net.MalformedURLException;
@@ -66,14 +65,18 @@
     public static int getColor(String value) {
         if (value != null) {
             if (value.startsWith("#") == false) {
-                throw new NumberFormatException();
+                throw new NumberFormatException(
+                        String.format("Color value '%s' must start with #", value));
             }
 
             value = value.substring(1);
 
             // make sure it's not longer than 32bit
             if (value.length() > 8) {
-                throw new NumberFormatException();
+                throw new NumberFormatException(String.format(
+                        "Color value '%s' is too long. Format is either" +
+                        "#AARRGGBB, #RRGGBB, #RGB, or #ARGB",
+                        value));
             }
 
             if (value.length() == 3) { // RGB format
@@ -162,7 +165,8 @@
                         // URL is wrong, we'll return null below
                     } catch (IOException e) {
                         // failed to read the file, we'll return null below.
-                        Bridge.getLog().error(null, e);
+                        Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
+                                "Failed lot load " + file.getAbsolutePath(), e, null /*data*/);
                     }
                 }
 
@@ -190,13 +194,15 @@
                     d = Drawable.createFromXml(context.getResources(),
                             new BridgeXmlBlockParser(parser, context, isFramework));
                     return d;
-                } catch (XmlPullParserException e) {
-                    Bridge.getLog().error(null, e);
-                } catch (FileNotFoundException e) {
-                    // will not happen, since we pre-check
-                } catch (IOException e) {
-                    Bridge.getLog().error(null, e);
+                } 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, null /*data*/);
                 }
+            } else {
+                Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                        String.format("File %s does not exist (or is not a file)", stringValue),
+                        null /*data*/);
             }
 
             return null;
@@ -222,7 +228,8 @@
                     return new BitmapDrawable(context.getResources(), bitmap);
                 } catch (IOException e) {
                     // we'll return null below
-                    Bridge.getLog().error(null, e);
+                    Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
+                            "Failed lot load " + bmpFile.getAbsolutePath(), e, null /*data*/);
                 }
             } else {
                 // attempt to get a color from the value
@@ -231,8 +238,9 @@
                     return new ColorDrawable(color);
                 } catch (NumberFormatException e) {
                     // we'll return null below.
-                    Bridge.getLog().error(null,
-                            "failed to convert " + stringValue + " into a drawable");
+                    Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
+                            "Failed to convert " + stringValue + " into a drawable", e,
+                            null /*data*/);
                 }
             }
         }
diff --git a/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java b/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java
index 1ec6262..6d013bb 100644
--- a/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java
+++ b/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java
@@ -16,7 +16,7 @@
 
 package com.google.android.maps;
 
-import com.android.layoutlib.bridge.android.MockView;
+import com.android.layoutlib.bridge.MockView;
 
 import android.content.Context;
 import android.os.Bundle;
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 1d40d33..4198006 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -97,6 +97,7 @@
         "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
         "android.os.Handler#sendMessageAtTime",
         "android.view.View#isInEditMode",
+        "com.android.internal.util.XmlUtils#convertValueToInt"
         // TODO: comment out once DelegateClass is working
         // "android.content.res.Resources$Theme#obtainStyledAttributes",
     };
@@ -106,17 +107,39 @@
      */
     private final static String[] DELEGATE_CLASS_NATIVES = new String[] {
         "android.animation.PropertyValuesHolder",
+        "android.graphics.AvoidXfermode",
         "android.graphics.Bitmap",
+        "android.graphics.BitmapShader",
+        "android.graphics.BlurMaskFilter",
         "android.graphics.Canvas",
+        "android.graphics.ColorFilter",
+        "android.graphics.ColorMatrixColorFilter",
+        "android.graphics.ComposePathEffect",
+        "android.graphics.ComposeShader",
+        "android.graphics.CornerPathEffect",
         "android.graphics.DashPathEffect",
+        "android.graphics.DiscretePathEffect",
+        "android.graphics.DrawFilter",
+        "android.graphics.EmbossMaskFilter",
+        "android.graphics.LayerRasterizer",
+        "android.graphics.LightingColorFilter",
         "android.graphics.LinearGradient",
+        "android.graphics.MaskFilter",
         "android.graphics.Matrix",
         "android.graphics.NinePatch",
         "android.graphics.Paint",
+        "android.graphics.PaintFlagsDrawFilter",
+        "android.graphics.Path",
+        "android.graphics.PathDashPathEffect",
         "android.graphics.PathEffect",
+        "android.graphics.PixelXorXfermode",
+        "android.graphics.PorterDuffColorFilter",
         "android.graphics.PorterDuffXfermode",
         "android.graphics.RadialGradient",
+        "android.graphics.Rasterizer",
+        "android.graphics.Region",
         "android.graphics.Shader",
+        "android.graphics.SumPathEffect",
         "android.graphics.SweepGradient",
         "android.graphics.Typeface",
         "android.graphics.Xfermode",
@@ -140,7 +163,6 @@
     private final static String[] RENAMED_CLASSES =
         new String[] {
             "android.graphics.BitmapFactory",       "android.graphics._Original_BitmapFactory",
-            "android.graphics.Path",                "android.graphics._Original_Path",
             "android.os.ServiceManager",            "android.os._Original_ServiceManager",
             "android.view.SurfaceView",             "android.view._Original_SurfaceView",
             "android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index 51236fe..90d286d 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -519,10 +519,15 @@
      * @param session the session that receives the incoming call
      * @param sessionDescription the session description of the incoming call
      * @throws SipException if the SIP service fails to attach this object to
-     *        the session
+     *        the session or VOIP API is not supported by the device
+     * @see SipManager#isVoipSupported
      */
     public void attachCall(SipSession session, String sessionDescription)
             throws SipException {
+        if (!SipManager.isVoipSupported(mContext)) {
+            throw new SipException("VOIP API is not supported");
+        }
+
         synchronized (this) {
             mSipSession = session;
             mPeerSd = sessionDescription;
@@ -548,10 +553,15 @@
      *        SIP protocol) is used if {@code timeout} is zero or negative.
      * @see Listener#onError
      * @throws SipException if the SIP service fails to create a session for the
-     *        call
+     *        call or VOIP API is not supported by the device
+     * @see SipManager#isVoipSupported
      */
     public void makeCall(SipProfile peerProfile, SipSession sipSession,
             int timeout) throws SipException {
+        if (!SipManager.isVoipSupported(mContext)) {
+            throw new SipException("VOIP API is not supported");
+        }
+
         synchronized (this) {
             mSipSession = sipSession;
             try {
@@ -595,6 +605,9 @@
     public void holdCall(int timeout) throws SipException {
         synchronized (this) {
             if (mHold) return;
+            if (mSipSession == null) {
+                throw new SipException("Not in a call to hold call");
+            }
             mSipSession.changeCall(createHoldOffer().encode(), timeout);
             mHold = true;
             setAudioGroupMode();
@@ -614,6 +627,9 @@
      */
     public void answerCall(int timeout) throws SipException {
         synchronized (this) {
+            if (mSipSession == null) {
+                throw new SipException("No call to answer");
+            }
             try {
                 mAudioStream = new AudioStream(InetAddress.getByName(
                         getLocalIp()));
@@ -983,16 +999,6 @@
 
         if (isWifiOn()) grabWifiHighPerfLock();
 
-        if (!mHold) {
-            /* The recorder volume will be very low if the device is in
-             * IN_CALL mode. Therefore, we have to set the mode to NORMAL
-             * in order to have the normal microphone level.
-             */
-            ((AudioManager) mContext.getSystemService
-                    (Context.AUDIO_SERVICE))
-                    .setMode(AudioManager.MODE_NORMAL);
-        }
-
         // AudioGroup logic:
         AudioGroup audioGroup = getAudioGroup();
         if (mHold) {
diff --git a/voip/java/android/net/sip/SipManager.java b/voip/java/android/net/sip/SipManager.java
index 2e386620..dce46fe 100644
--- a/voip/java/android/net/sip/SipManager.java
+++ b/voip/java/android/net/sip/SipManager.java
@@ -133,7 +133,7 @@
     }
 
     /**
-     * Returns true if the system supports SIP-based VoIP.
+     * Returns true if the system supports SIP-based VOIP API.
      */
     public static boolean isVoipSupported(Context context) {
         return context.getPackageManager().hasSystemFeature(
@@ -305,12 +305,17 @@
      * @param timeout the timeout value in seconds. Default value (defined by
      *        SIP protocol) is used if {@code timeout} is zero or negative.
      * @return a {@link SipAudioCall} object
-     * @throws SipException if calling the SIP service results in an error
+     * @throws SipException if calling the SIP service results in an error or
+     *      VOIP API is not supported by the device
      * @see SipAudioCall.Listener#onError
+     * @see #isVoipSupported
      */
     public SipAudioCall makeAudioCall(SipProfile localProfile,
             SipProfile peerProfile, SipAudioCall.Listener listener, int timeout)
             throws SipException {
+        if (!isVoipSupported(mContext)) {
+            throw new SipException("VOIP API is not supported");
+        }
         SipAudioCall call = new SipAudioCall(mContext, localProfile);
         call.setListener(listener);
         SipSession s = createSipSession(localProfile, null);
@@ -332,12 +337,17 @@
      * @param timeout the timeout value in seconds. Default value (defined by
      *        SIP protocol) is used if {@code timeout} is zero or negative.
      * @return a {@link SipAudioCall} object
-     * @throws SipException if calling the SIP service results in an error
+     * @throws SipException if calling the SIP service results in an error or
+     *      VOIP API is not supported by the device
      * @see SipAudioCall.Listener#onError
+     * @see #isVoipSupported
      */
     public SipAudioCall makeAudioCall(String localProfileUri,
             String peerProfileUri, SipAudioCall.Listener listener, int timeout)
             throws SipException {
+        if (!isVoipSupported(mContext)) {
+            throw new SipException("VOIP API is not supported");
+        }
         try {
             return makeAudioCall(
                     new SipProfile.Builder(localProfileUri).build(),
diff --git a/voip/java/android/net/sip/SipProfile.java b/voip/java/android/net/sip/SipProfile.java
index 4029ed0..c7e18df 100644
--- a/voip/java/android/net/sip/SipProfile.java
+++ b/voip/java/android/net/sip/SipProfile.java
@@ -49,6 +49,7 @@
     private String mDomain;
     private String mProtocol = UDP;
     private String mProfileName;
+    private String mAuthUserName;
     private int mPort = DEFAULT_PORT;
     private boolean mSendKeepAlive = false;
     private boolean mAutoRegistration = true;
@@ -147,6 +148,18 @@
         }
 
         /**
+         * Sets the username used for authentication.
+         *
+         * @param name auth. name of the profile
+         * @return this builder object
+         * @hide // TODO: remove when we make it public
+         */
+        public Builder setAuthUserName(String name) {
+            mProfile.mAuthUserName = name;
+            return this;
+        }
+
+        /**
          * Sets the name of the profile. This name is given by user.
          *
          * @param name name of the profile
@@ -177,7 +190,7 @@
          */
         public Builder setPort(int port) throws IllegalArgumentException {
             if ((port > 65535) || (port < 1000)) {
-                throw new IllegalArgumentException("incorrect port arugment");
+                throw new IllegalArgumentException("incorrect port arugment: " + port);
             }
             mProfile.mPort = port;
             return this;
@@ -300,6 +313,7 @@
         mAutoRegistration = (in.readInt() == 0) ? false : true;
         mCallingUid = in.readInt();
         mPort = in.readInt();
+        mAuthUserName = in.readString();
     }
 
     @Override
@@ -314,6 +328,7 @@
         out.writeInt(mAutoRegistration ? 1 : 0);
         out.writeInt(mCallingUid);
         out.writeInt(mPort);
+        out.writeString(mAuthUserName);
     }
 
     @Override
@@ -375,6 +390,17 @@
     }
 
     /**
+     * Gets the username for authentication. If it is null, then the username
+     * should be used in authentication instead.
+     *
+     * @return the auth. username
+     * @hide // TODO: remove when we make it public
+     */
+    public String getAuthUserName() {
+        return mAuthUserName;
+    }
+
+    /**
      * Gets the password.
      *
      * @return the password
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 30ddfb5..aa616a9 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -872,8 +872,13 @@
                 }
                 return true;
             } else {
-                onError(SipErrorCode.INVALID_CREDENTIALS,
-                        "incorrect username or password");
+                if (crossDomainAuthenticationRequired(response)) {
+                    onError(SipErrorCode.CROSS_DOMAIN_AUTHENTICATION,
+                            getRealmFromResponse(response));
+                } else {
+                    onError(SipErrorCode.INVALID_CREDENTIALS,
+                            "incorrect username or password");
+                }
                 return false;
             }
         }
@@ -890,7 +895,9 @@
                         challengedTransaction, String realm) {
                     return new UserCredentials() {
                         public String getUserName() {
-                            return mLocalProfile.getUserName();
+                            String username = mLocalProfile.getAuthUserName();
+                            return (!TextUtils.isEmpty(username) ? username :
+                                    mLocalProfile.getUserName());
                         }
 
                         public String getPassword() {
@@ -1025,10 +1032,7 @@
                     return true;
                 case Response.UNAUTHORIZED:
                 case Response.PROXY_AUTHENTICATION_REQUIRED:
-                    if (crossDomainAuthenticationRequired(response)) {
-                        onError(SipErrorCode.CROSS_DOMAIN_AUTHENTICATION,
-                                getRealmFromResponse(response));
-                    } else if (handleAuthentication(event)) {
+                    if (handleAuthentication(event)) {
                         addSipSession(this);
                     }
                     return true;
@@ -1333,10 +1337,12 @@
             SipURI uri = (SipURI) address.getURI();
             String username = uri.getUser();
             if (username == null) username = ANONYMOUS;
-            return new SipProfile.Builder(username, uri.getHost())
-                    .setPort(uri.getPort())
-                    .setDisplayName(address.getDisplayName())
-                    .build();
+            int port = uri.getPort();
+            SipProfile.Builder builder =
+                    new SipProfile.Builder(username, uri.getHost())
+                    .setDisplayName(address.getDisplayName());
+            if (port > 0) builder.setPort(port);
+            return builder.build();
         } catch (IllegalArgumentException e) {
             throw new SipException("createPeerProfile()", e);
         } catch (ParseException e) {
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index cba1123..c031eee 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -63,6 +63,14 @@
 // real jitter buffer. For a stream at 8000Hz it takes 8192 bytes. These numbers
 // are chosen by experiments and each of them can be adjusted as needed.
 
+// Originally a stream does not send packets when it is receive-only or there is
+// nothing to mix. However, this causes some problems with certain firewalls and
+// proxies. A firewall might remove a port mapping when there is no outgoing
+// packet for a preiod of time, and a proxy might wait for incoming packets from
+// both sides before start forwarding. To solve these problems, we send out a
+// silence packet on the stream for every second. It should be good enough to
+// keep the stream alive with relatively low resources.
+
 // Other notes:
 // + We use elapsedRealtime() to get the time. Since we use 32bit variables
 //   instead of 64bit ones, comparison must be done by subtraction.
@@ -110,7 +118,7 @@
     int mSampleRate;
     int mSampleCount;
     int mInterval;
-    int mLogThrottle;
+    int mKeepAlive;
 
     int16_t *mBuffer;
     int mBufferMask;
@@ -262,12 +270,8 @@
     ++mSequence;
     mTimestamp += mSampleCount;
 
-    if (mMode == RECEIVE_ONLY) {
-        return;
-    }
-
     // If there is an ongoing DTMF event, send it now.
-    if (mDtmfEvent != -1) {
+    if (mMode != RECEIVE_ONLY && mDtmfEvent != -1) {
         int duration = mTimestamp - mDtmfStart;
         // Make sure duration is reasonable.
         if (duration >= 0 && duration < mSampleRate * 100) {
@@ -289,43 +293,55 @@
         mDtmfEvent = -1;
     }
 
-    // It is time to mix streams.
-    bool mixed = false;
     int32_t buffer[mSampleCount + 3];
-    memset(buffer, 0, sizeof(buffer));
-    while (chain) {
-        if (chain != this &&
-            chain->mix(buffer, tick - mInterval, tick, mSampleRate)) {
-            mixed = true;
+    int16_t samples[mSampleCount];
+    if (mMode == RECEIVE_ONLY) {
+        if ((mTick ^ mKeepAlive) >> 10 == 0) {
+            return;
         }
-        chain = chain->mNext;
-    }
-    if (!mixed) {
-        if ((mTick ^ mLogThrottle) >> 10) {
-            mLogThrottle = mTick;
+        mKeepAlive = mTick;
+        memset(samples, 0, sizeof(samples));
+    } else {
+        // Mix all other streams.
+        bool mixed = false;
+        memset(buffer, 0, sizeof(buffer));
+        while (chain) {
+            if (chain != this &&
+                chain->mix(buffer, tick - mInterval, tick, mSampleRate)) {
+                mixed = true;
+            }
+            chain = chain->mNext;
+        }
+
+        if (mixed) {
+            // Saturate into 16 bits.
+            for (int i = 0; i < mSampleCount; ++i) {
+                int32_t sample = buffer[i];
+                if (sample < -32768) {
+                    sample = -32768;
+                }
+                if (sample > 32767) {
+                    sample = 32767;
+                }
+                samples[i] = sample;
+            }
+        } else {
+            if ((mTick ^ mKeepAlive) >> 10 == 0) {
+                return;
+            }
+            mKeepAlive = mTick;
+            memset(samples, 0, sizeof(samples));
             LOGV("stream[%d] no data", mSocket);
         }
-        return;
     }
 
-    // Cook the packet and send it out.
-    int16_t samples[mSampleCount];
-    for (int i = 0; i < mSampleCount; ++i) {
-        int32_t sample = buffer[i];
-        if (sample < -32768) {
-            sample = -32768;
-        }
-        if (sample > 32767) {
-            sample = 32767;
-        }
-        samples[i] = sample;
-    }
     if (!mCodec) {
         // Special case for device stream.
         send(mSocket, samples, sizeof(samples), MSG_DONTWAIT);
         return;
     }
 
+    // Cook the packet and send it out.
     buffer[0] = htonl(mCodecMagic | mSequence);
     buffer[1] = htonl(mTimestamp);
     buffer[2] = mSsrc;
@@ -468,7 +484,7 @@
         ON_HOLD = 0,
         MUTED = 1,
         NORMAL = 2,
-        EC_ENABLED = 3,
+        ECHO_SUPPRESSION = 3,
         LAST_MODE = 3,
     };
 
@@ -603,6 +619,10 @@
     if (mode < 0 || mode > LAST_MODE) {
         return false;
     }
+    if (mode == ECHO_SUPPRESSION && AudioSystem::getParameters(
+        0, String8("ec_supported")) == "ec_supported=yes") {
+        mode = NORMAL;
+    }
     if (mMode == mode) {
         return true;
     }
@@ -759,8 +779,8 @@
     AudioTrack track;
     AudioRecord record;
     if (track.set(AudioSystem::VOICE_CALL, sampleRate, AudioSystem::PCM_16_BIT,
-        AudioSystem::CHANNEL_OUT_MONO, output) != NO_ERROR ||
-        record.set(AUDIO_SOURCE_MIC, sampleRate, AudioSystem::PCM_16_BIT,
+        AudioSystem::CHANNEL_OUT_MONO, output) != NO_ERROR || record.set(
+        AUDIO_SOURCE_VOICE_COMMUNICATION, sampleRate, AudioSystem::PCM_16_BIT,
         AudioSystem::CHANNEL_IN_MONO, input) != NO_ERROR) {
         LOGE("cannot initialize audio device");
         return false;
@@ -883,7 +903,7 @@
     int codecType = -1;
     char codecName[16];
     int sampleRate = -1;
-    sscanf(codecSpec, "%d %[^/]%*c%d", &codecType, codecName, &sampleRate);
+    sscanf(codecSpec, "%d %15[^/]%*c%d", &codecType, codecName, &sampleRate);
     codec = newAudioCodec(codecName);
     int sampleCount = (codec ? codec->set(sampleRate, codecSpec) : -1);
     env->ReleaseStringUTFChars(jCodecSpec, codecSpec);
diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java
index f823314..f96a5ae 100644
--- a/wifi/java/android/net/wifi/SupplicantStateTracker.java
+++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java
@@ -48,6 +48,9 @@
     /* Maximum retries on a password failure notification */
     private static final int MAX_RETRIES_ON_PASSWORD_FAILURE = 2;
 
+    /* Tracks if networks have been disabled during a connection */
+    private boolean mNetworksDisabledDuringConnect = false;
+
     private Context mContext;
 
     private HierarchicalState mUninitializedState = new UninitializedState();
@@ -79,11 +82,16 @@
         start();
     }
 
-    public void resetSupplicantState() {
-        transitionTo(mUninitializedState);
+    private void handleNetworkConnectionFailure(int netId) {
+        /* If other networks disabled during connection, enable them */
+        if (mNetworksDisabledDuringConnect) {
+            WifiConfigStore.enableAllNetworks();
+            mNetworksDisabledDuringConnect = false;
+        }
+        /* Disable failed network */
+        WifiConfigStore.disableNetwork(netId);
     }
 
-
     private void transitionOnSupplicantStateChange(StateChangeResult stateChangeResult) {
         SupplicantState supState = (SupplicantState) stateChangeResult.state;
 
@@ -121,11 +129,11 @@
         }
     }
 
-    private void sendSupplicantStateChangedBroadcast(StateChangeResult sc, boolean failedAuth) {
+    private void sendSupplicantStateChangedBroadcast(SupplicantState state, boolean failedAuth) {
         Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
-        intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable)sc.state);
+        intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable) state);
         if (failedAuth) {
             intent.putExtra(
                 WifiManager.EXTRA_SUPPLICANT_ERROR,
@@ -153,11 +161,17 @@
                     break;
                 case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-                    sendSupplicantStateChangedBroadcast(stateChangeResult,
-                            mAuthFailureInSupplicantBroadcast);
+                    SupplicantState state = stateChangeResult.state;
+                    sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
                     mAuthFailureInSupplicantBroadcast = false;
                     transitionOnSupplicantStateChange(stateChangeResult);
                     break;
+                case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE:
+                    transitionTo(mUninitializedState);
+                    break;
+                case WifiStateMachine.CMD_CONNECT_NETWORK:
+                    mNetworksDisabledDuringConnect = true;
+                    break;
                 default:
                     Log.e(TAG, "Ignoring " + message);
                     break;
@@ -166,31 +180,28 @@
         }
     }
 
+    /*
+     * This indicates that the supplicant state as seen
+     * by the framework is not initialized yet. We are
+     * in this state right after establishing a control
+     * channel connection before any supplicant events
+     * or after we have lost the control channel
+     * connection to the supplicant
+     */
     class UninitializedState extends HierarchicalState {
         @Override
          public void enter() {
              if (DBG) Log.d(TAG, getName() + "\n");
-             mWifiStateMachine.setNetworkAvailable(false);
          }
-        @Override
-        public void exit() {
-            mWifiStateMachine.setNetworkAvailable(true);
-        }
     }
 
     class InactiveState extends HierarchicalState {
         @Override
          public void enter() {
              if (DBG) Log.d(TAG, getName() + "\n");
-             mWifiStateMachine.setNetworkAvailable(false);
          }
-        @Override
-        public void exit() {
-            mWifiStateMachine.setNetworkAvailable(true);
-        }
     }
 
-
     class DisconnectedState extends HierarchicalState {
         @Override
          public void enter() {
@@ -205,7 +216,7 @@
              if (mPasswordFailuresCount >= MAX_RETRIES_ON_PASSWORD_FAILURE) {
                  Log.d(TAG, "Failed to authenticate, disabling network " +
                          stateChangeResult.networkId);
-                 WifiConfigStore.disableNetwork(stateChangeResult.networkId);
+                 handleNetworkConnectionFailure(stateChangeResult.networkId);
                  mPasswordFailuresCount = 0;
              }
          }
@@ -239,7 +250,7 @@
             switch (message.what) {
                 case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-                    SupplicantState state = (SupplicantState) stateChangeResult.state;
+                    SupplicantState state = stateChangeResult.state;
                     if (state == SupplicantState.ASSOCIATING ||
                             state == SupplicantState.ASSOCIATED ||
                             state == SupplicantState.FOUR_WAY_HANDSHAKE ||
@@ -250,10 +261,10 @@
                         if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) {
                             Log.d(TAG, "Supplicant loop detected, disabling network " +
                                     stateChangeResult.networkId);
-                            WifiConfigStore.disableNetwork(stateChangeResult.networkId);
+                            handleNetworkConnectionFailure(stateChangeResult.networkId);
                         }
                         mLoopDetectIndex = state.ordinal();
-                        sendSupplicantStateChangedBroadcast(stateChangeResult,
+                        sendSupplicantStateChangedBroadcast(state,
                                 mAuthFailureInSupplicantBroadcast);
                     } else {
                         //Have the DefaultState handle the transition
@@ -273,16 +284,19 @@
              if (DBG) Log.d(TAG, getName() + "\n");
              /* Reset password failure count */
              mPasswordFailuresCount = 0;
-         }
+             if (mNetworksDisabledDuringConnect) {
+                 WifiConfigStore.enableAllNetworks();
+                 mNetworksDisabledDuringConnect = false;
+             }
+        }
         @Override
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch(message.what) {
                 case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-                    SupplicantState state = (SupplicantState) stateChangeResult.state;
-                    sendSupplicantStateChangedBroadcast(stateChangeResult,
-                            mAuthFailureInSupplicantBroadcast);
+                    SupplicantState state = stateChangeResult.state;
+                    sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
                     /* Ignore a re-auth in completed state */
                     if (state == SupplicantState.ASSOCIATING ||
                             state == SupplicantState.ASSOCIATED ||
@@ -293,6 +307,10 @@
                     }
                     transitionOnSupplicantStateChange(stateChangeResult);
                     break;
+                case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE:
+                    sendSupplicantStateChangedBroadcast(SupplicantState.DISCONNECTED, false);
+                    transitionTo(mUninitializedState);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -307,4 +325,4 @@
             if (DBG) Log.d(TAG, getName() + "\n");
         }
     }
-}
\ No newline at end of file
+}
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index f597934..56bc5d7 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -164,10 +164,12 @@
      * of configured networks indicates all networks as being enabled
      */
     static void enableAllNetworks() {
+        boolean networkEnabledStateChanged = false;
         synchronized (sConfiguredNetworks) {
             for(WifiConfiguration config : sConfiguredNetworks.values()) {
                 if(config != null && config.status == Status.DISABLED) {
                     if(WifiNative.enableNetworkCommand(config.networkId, false)) {
+                        networkEnabledStateChanged = true;
                         config.status = Status.ENABLED;
                     } else {
                         Log.e(TAG, "Enable network failed on " + config.networkId);
@@ -176,8 +178,10 @@
             }
         }
 
-        WifiNative.saveConfigCommand();
-        sendConfiguredNetworksChangedBroadcast();
+        if (networkEnabledStateChanged) {
+            WifiNative.saveConfigCommand();
+            sendConfiguredNetworksChangedBroadcast();
+        }
     }
 
     /**
@@ -1112,7 +1116,7 @@
 
         value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.ssidVarName);
         if (!TextUtils.isEmpty(value)) {
-            config.SSID = removeDoubleQuotes(value);
+            config.SSID = value;
         } else {
             config.SSID = null;
         }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 17a35c4..8718117 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -62,11 +62,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.app.backup.IBackupManager;
-import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothProfile;
 import android.content.BroadcastReceiver;
 import android.content.Intent;
 import android.content.Context;
@@ -120,6 +116,8 @@
     private int mReconnectCount = 0;
     private boolean mIsScanMode = false;
 
+    private boolean mBluetoothConnectionActive = false;
+
     /**
      * Interval in milliseconds between polling for RSSI
      * and linkspeed information
@@ -138,16 +136,6 @@
 
     private int mSupplicantRestartCount = 0;
 
-    /**
-     * Instance of the bluetooth headset helper. This needs to be created
-     * early because there is a delay before it actually 'connects', as
-     * noted by its javadoc. If we check before it is connected, it will be
-     * in an error state and we will not disable coexistence.
-     */
-    private BluetoothHeadset mBluetoothHeadset;
-
-    private BluetoothA2dp mBluetoothA2dp;
-
     private LinkProperties mLinkProperties;
 
     // Wakelock held during wifi start/stop and driver load/unload
@@ -161,10 +149,6 @@
     private SupplicantStateTracker mSupplicantStateTracker;
     private WpsStateMachine mWpsStateMachine;
 
-    /* Connection to a specific network involves disabling all networks,
-     * this flag tracks if networks need to be re-enabled */
-    private boolean mEnableAllNetworks = false;
-
     private AlarmManager mAlarmManager;
     private PendingIntent mScanIntent;
     /* Tracks current frequency mode */
@@ -190,10 +174,6 @@
     static final int CMD_UNLOAD_DRIVER_SUCCESS            = 5;
     /* Indicates driver unload failed */
     static final int CMD_UNLOAD_DRIVER_FAILURE            = 6;
-    /* Set bluetooth headset proxy */
-    static final int CMD_SET_BLUETOOTH_HEADSET_PROXY      = 7;
-    /* Set bluetooth A2dp proxy */
-    static final int CMD_SET_BLUETOOTH_A2DP_PROXY         = 8;
 
     /* Start the supplicant */
     static final int CMD_START_SUPPLICANT                 = 11;
@@ -213,6 +193,7 @@
     /* Stop the soft access point */
     static final int CMD_STOP_AP                          = 22;
 
+    static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE   = 23;
 
     /* Supplicant events */
     /* Connection to supplicant established */
@@ -243,14 +224,16 @@
     static final int CMD_REMOVE_NETWORK                   = 53;
     /* Enable a network. The device will attempt a connection to the given network. */
     static final int CMD_ENABLE_NETWORK                   = 54;
+    /* Enable all networks */
+    static final int CMD_ENABLE_ALL_NETWORKS              = 55;
     /* Disable a network. The device does not attempt a connection to the given network. */
-    static final int CMD_DISABLE_NETWORK                  = 55;
+    static final int CMD_DISABLE_NETWORK                  = 56;
     /* Blacklist network. De-prioritizes the given BSSID for connection. */
-    static final int CMD_BLACKLIST_NETWORK                = 56;
+    static final int CMD_BLACKLIST_NETWORK                = 57;
     /* Clear the blacklist network list */
-    static final int CMD_CLEAR_BLACKLIST                  = 57;
+    static final int CMD_CLEAR_BLACKLIST                  = 58;
     /* Save configuration */
-    static final int CMD_SAVE_CONFIG                      = 58;
+    static final int CMD_SAVE_CONFIG                      = 59;
 
     /* Supplicant commands after driver start*/
     /* Initiate a scan */
@@ -279,17 +262,6 @@
      * - DTIM wake up settings
      */
     static final int CMD_SET_HIGH_PERF_MODE               = 77;
-    /* Set bluetooth co-existence
-     * BLUETOOTH_COEXISTENCE_MODE_ENABLED
-     * BLUETOOTH_COEXISTENCE_MODE_DISABLED
-     * BLUETOOTH_COEXISTENCE_MODE_SENSE
-     */
-    static final int CMD_SET_BLUETOOTH_COEXISTENCE        = 78;
-    /* Enable/disable bluetooth scan mode
-     * true(1)
-     * false(0)
-     */
-    static final int CMD_SET_BLUETOOTH_SCAN_MODE          = 79;
     /* Set the country code */
     static final int CMD_SET_COUNTRY_CODE                 = 80;
     /* Request connectivity manager wake lock before driver stop */
@@ -326,13 +298,14 @@
     /* Set the frequency band */
     static final int CMD_SET_FREQUENCY_BAND               = 90;
 
-    /* Commands from the SupplicantStateTracker */
-    /* Indicates whether a wifi network is available for connection */
-    static final int CMD_SET_NETWORK_AVAILABLE             = 111;
+    /* Commands from/to the SupplicantStateTracker */
+    /* Reset the supplicant state tracker */
+    static final int CMD_RESET_SUPPLICANT_STATE           = 111;
+
 
     /* Commands/events reported by WpsStateMachine */
     /* Indicates the completion of WPS activity */
-    static final int WPS_COMPLETED_EVENT                   = 121;
+    static final int WPS_COMPLETED_EVENT                  = 121;
 
     private static final int CONNECT_MODE   = 1;
     private static final int SCAN_ONLY_MODE = 2;
@@ -475,15 +448,7 @@
         mInterfaceName = SystemProperties.get("wifi.interface", "tiwlan0");
         mSupplicantStateTracker = new SupplicantStateTracker(context, this, getHandler());
         mWpsStateMachine = new WpsStateMachine(context, this, getHandler());
-
         mLinkProperties = new LinkProperties();
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        if (adapter != null) {
-            adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
-                                    BluetoothProfile.A2DP);
-            adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
-                                    BluetoothProfile.HEADSET);
-        }
 
         mNetworkInfo.setIsAvailable(false);
         mLinkProperties.clear();
@@ -849,6 +814,10 @@
        sendMessage(obtainMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0));
     }
 
+    public void enableAllNetworks() {
+        sendMessage(CMD_ENABLE_ALL_NETWORKS);
+    }
+
     /**
      * Start packet filtering
      */
@@ -909,26 +878,10 @@
     }
 
     /**
-     * Set bluetooth coex mode:
-     *
-     * @param mode
-     *  BLUETOOTH_COEXISTENCE_MODE_ENABLED
-     *  BLUETOOTH_COEXISTENCE_MODE_DISABLED
-     *  BLUETOOTH_COEXISTENCE_MODE_SENSE
+     * Send a message indicating bluetooth adapter connection state changed
      */
-    public void setBluetoothCoexistenceMode(int mode) {
-        sendMessage(obtainMessage(CMD_SET_BLUETOOTH_COEXISTENCE, mode, 0));
-    }
-
-    /**
-     * Enable or disable Bluetooth coexistence scan mode. When this mode is on,
-     * some of the low-level scan parameters used by the driver are changed to
-     * reduce interference with A2DP streaming.
-     *
-     * @param isBluetoothPlaying whether to enable or disable this mode
-     */
-    public void setBluetoothScanMode(boolean isBluetoothPlaying) {
-        sendMessage(obtainMessage(CMD_SET_BLUETOOTH_SCAN_MODE, isBluetoothPlaying ? 1 : 0, 0));
+    public void sendBluetoothAdapterStateChange(int state) {
+        sendMessage(obtainMessage(CMD_BLUETOOTH_ADAPTER_STATE_CHANGE, state, 0));
     }
 
     /**
@@ -1001,7 +954,6 @@
         sb.append("mLastSignalLevel ").append(mLastSignalLevel).append(LS);
         sb.append("mLastBssid ").append(mLastBssid).append(LS);
         sb.append("mLastNetworkId ").append(mLastNetworkId).append(LS);
-        sb.append("mEnableAllNetworks ").append(mEnableAllNetworks).append(LS);
         sb.append("mReconnectCount ").append(mReconnectCount).append(LS);
         sb.append("mIsScanMode ").append(mIsScanMode).append(LS);
         sb.append("Supplicant status").append(LS)
@@ -1308,54 +1260,6 @@
                                       DEFAULT_MAX_DHCP_RETRIES);
     }
 
-    /**
-     * Whether to disable coexistence mode while obtaining IP address. We
-     * disable coexistence if the headset indicates that there are no
-     * connected devices. If we have not got an indication of the service
-     * connection yet, we go ahead with disabling coexistence mode.
-     *
-     * @return Whether to disable coexistence mode.
-     */
-    private boolean shouldDisableCoexistenceMode() {
-        if (mBluetoothHeadset == null) return true;
-        List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
-        return (devices.size() != 0 ? false : true);
-    }
-
-    private void checkIsBluetoothPlaying() {
-        boolean isBluetoothPlaying = false;
-        if (mBluetoothA2dp != null) {
-            List<BluetoothDevice> connected = mBluetoothA2dp.getConnectedDevices();
-
-            for (BluetoothDevice device : connected) {
-                if (mBluetoothA2dp.isA2dpPlaying(device)) {
-                    isBluetoothPlaying = true;
-                    break;
-                }
-            }
-        }
-        setBluetoothScanMode(isBluetoothPlaying);
-    }
-
-    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
-        new BluetoothProfile.ServiceListener() {
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-                if (profile == BluetoothProfile.HEADSET) {
-                    sendMessage(CMD_SET_BLUETOOTH_HEADSET_PROXY, proxy);
-                } else if (profile == BluetoothProfile.A2DP) {
-                    sendMessage(CMD_SET_BLUETOOTH_A2DP_PROXY, proxy);
-                }
-        }
-
-        public void onServiceDisconnected(int profile) {
-                if (profile == BluetoothProfile.HEADSET) {
-                    sendMessage(CMD_SET_BLUETOOTH_HEADSET_PROXY, null);
-                } else if (profile == BluetoothProfile.A2DP) {
-                    sendMessage(CMD_SET_BLUETOOTH_A2DP_PROXY, null);
-                }
-        }
-    };
-
     private void sendScanResultsAvailableBroadcast() {
         Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -1453,20 +1357,17 @@
      ********************************************************/
 
     /**
-     * A structure for supplying information about a supplicant state
-     * change in the STATE_CHANGE event message that comes from the
-     * WifiMonitor
-     * thread.
+     * Stores supplicant state change information passed from WifiMonitor
      */
     static class StateChangeResult {
-        StateChangeResult(int networkId, String BSSID, Object state) {
+        StateChangeResult(int networkId, String BSSID, SupplicantState state) {
             this.state = state;
             this.BSSID = BSSID;
             this.networkId = networkId;
         }
         int networkId;
         String BSSID;
-        Object state;
+        SupplicantState state;
     }
 
     /**
@@ -1505,11 +1406,9 @@
      */
     void notifyNetworkStateChange(DetailedState newState, String BSSID, int networkId) {
         if (newState == NetworkInfo.DetailedState.CONNECTED) {
-            sendMessage(obtainMessage(NETWORK_CONNECTION_EVENT,
-                    new StateChangeResult(networkId, BSSID, newState)));
+            sendMessage(obtainMessage(NETWORK_CONNECTION_EVENT, networkId, 0, BSSID));
         } else {
-            sendMessage(obtainMessage(NETWORK_DISCONNECTION_EVENT,
-                    new StateChangeResult(networkId, BSSID, newState)));
+            sendMessage(obtainMessage(NETWORK_DISCONNECTION_EVENT, networkId, 0, BSSID));
         }
     }
 
@@ -1550,10 +1449,6 @@
         setWifiEnabled(true);
     }
 
-    void setNetworkAvailable(boolean available) {
-        sendMessage(obtainMessage(CMD_SET_NETWORK_AVAILABLE, available ? 1 : 0, 0));
-    }
-
     /********************************************************
      * HSM states
      *******************************************************/
@@ -1563,11 +1458,9 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch (message.what) {
-                case CMD_SET_BLUETOOTH_HEADSET_PROXY:
-                    mBluetoothHeadset = (BluetoothHeadset) message.obj;
-                    break;
-                case CMD_SET_BLUETOOTH_A2DP_PROXY:
-                    mBluetoothA2dp = (BluetoothA2dp) message.obj;
+                case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE:
+                    mBluetoothConnectionActive = (message.arg1 !=
+                            BluetoothAdapter.STATE_DISCONNECTED);
                     break;
                     /* Synchronous call returns */
                 case CMD_PING_SUPPLICANT:
@@ -1581,9 +1474,6 @@
                 case CMD_ENABLE_RSSI_POLL:
                     mEnableRssiPolling = (message.arg1 == 1);
                     break;
-                case CMD_SET_NETWORK_AVAILABLE:
-                    mNetworkInfo.setIsAvailable(message.arg1 == 1);
-                    break;
                     /* Discard */
                 case CMD_LOAD_DRIVER:
                 case CMD_UNLOAD_DRIVER:
@@ -1611,8 +1501,6 @@
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
                 case CMD_SET_HIGH_PERF_MODE:
-                case CMD_SET_BLUETOOTH_COEXISTENCE:
-                case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_COUNTRY_CODE:
                 case CMD_SET_FREQUENCY_BAND:
                 case CMD_REQUEST_CM_WAKELOCK:
@@ -1620,6 +1508,7 @@
                 case CMD_SAVE_NETWORK:
                 case CMD_FORGET_NETWORK:
                 case CMD_RSSI_POLL:
+                case CMD_ENABLE_ALL_NETWORKS:
                     break;
                 case CMD_START_WPS:
                     WpsConfiguration config = (WpsConfiguration) message.obj;
@@ -1722,8 +1611,6 @@
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
                 case CMD_SET_HIGH_PERF_MODE:
-                case CMD_SET_BLUETOOTH_COEXISTENCE:
-                case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_COUNTRY_CODE:
                 case CMD_SET_FREQUENCY_BAND:
                 case CMD_START_PACKET_FILTERING:
@@ -1755,7 +1642,6 @@
                     if(WifiNative.startSupplicant()) {
                         Log.d(TAG, "Supplicant start successful");
                         mWifiMonitor.startMonitoring();
-                        setWifiState(WIFI_STATE_ENABLED);
                         transitionTo(mSupplicantStartingState);
                     } else {
                         Log.e(TAG, "Failed to start supplicant!");
@@ -1851,8 +1737,6 @@
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
                 case CMD_SET_HIGH_PERF_MODE:
-                case CMD_SET_BLUETOOTH_COEXISTENCE:
-                case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_COUNTRY_CODE:
                 case CMD_SET_FREQUENCY_BAND:
                 case CMD_START_PACKET_FILTERING:
@@ -1914,8 +1798,11 @@
             switch(message.what) {
                 case SUP_CONNECTION_EVENT:
                     Log.d(TAG, "Supplicant connection established");
+                    setWifiState(WIFI_STATE_ENABLED);
                     mSupplicantRestartCount = 0;
-                    mSupplicantStateTracker.resetSupplicantState();
+                    /* Reset the supplicant state to indicate the supplicant
+                     * state is not known at this time */
+                    mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
                     /* Initialize data structures */
                     mLastBssid = null;
                     mLastNetworkId = -1;
@@ -1928,8 +1815,6 @@
                     //TODO: initialize and fix multicast filtering
                     //mWM.initializeMulticastFiltering();
 
-                    checkIsBluetoothPlaying();
-
                     sendSupplicantConnectionChangedBroadcast(true);
                     transitionTo(mDriverStartedState);
                     break;
@@ -1944,7 +1829,7 @@
                         Log.e(TAG, "Failed " + mSupplicantRestartCount +
                                 " times to start supplicant, unload driver");
                         transitionTo(mDriverLoadedState);
-                        sendMessage(CMD_UNLOAD_DRIVER);
+                        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
                     }
                     break;
                 case CMD_LOAD_DRIVER:
@@ -1958,8 +1843,6 @@
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
                 case CMD_SET_HIGH_PERF_MODE:
-                case CMD_SET_BLUETOOTH_COEXISTENCE:
-                case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_COUNTRY_CODE:
                 case CMD_SET_FREQUENCY_BAND:
                 case CMD_START_PACKET_FILTERING:
@@ -1981,36 +1864,41 @@
             EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
             /* Initialize for connect mode operation at start */
             mIsScanMode = false;
+            /* Wifi is available as long as we have a connection to supplicant */
+            mNetworkInfo.setIsAvailable(true);
         }
         @Override
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             WifiConfiguration config;
+            boolean eventLoggingEnabled = true;
             switch(message.what) {
                 case CMD_STOP_SUPPLICANT:   /* Supplicant stopped by user */
-                    EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
                     Log.d(TAG, "stopping supplicant");
                     if (!WifiNative.stopSupplicant()) {
                         Log.e(TAG, "Failed to stop supplicant, issue kill");
                         WifiNative.killSupplicant();
                     }
+                    mNetworkInfo.setIsAvailable(false);
                     handleNetworkDisconnect();
+                    setWifiState(WIFI_STATE_DISABLING);
                     sendSupplicantConnectionChangedBroadcast(false);
-                    mSupplicantStateTracker.resetSupplicantState();
+                    mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
                     transitionTo(mSupplicantStoppingState);
                     break;
                 case SUP_DISCONNECTION_EVENT:  /* Supplicant connection lost */
-                    EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
                     Log.e(TAG, "Connection lost, restart supplicant");
                     WifiNative.killSupplicant();
                     WifiNative.closeSupplicantConnection();
+                    mNetworkInfo.setIsAvailable(false);
                     handleNetworkDisconnect();
                     sendSupplicantConnectionChangedBroadcast(false);
-                    mSupplicantStateTracker.resetSupplicantState();
+                    mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
                     transitionTo(mDriverLoadedState);
                     sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
                     break;
                 case SCAN_RESULTS_EVENT:
+                    eventLoggingEnabled = false;
                     setScanResults(WifiNative.scanResultsCommand());
                     sendScanResultsAvailableBroadcast();
                     break;
@@ -2019,28 +1907,26 @@
                     mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
                     break;
                 case CMD_ADD_OR_UPDATE_NETWORK:
-                    EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
                     config = (WifiConfiguration) message.obj;
                     mReplyChannel.replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK,
                             WifiConfigStore.addOrUpdateNetwork(config));
                     break;
                 case CMD_REMOVE_NETWORK:
-                    EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
                     ok = WifiConfigStore.removeNetwork(message.arg1);
                     mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
                     break;
                 case CMD_ENABLE_NETWORK:
-                    EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
                     ok = WifiConfigStore.enableNetwork(message.arg1, message.arg2 == 1);
                     mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
                     break;
+                case CMD_ENABLE_ALL_NETWORKS:
+                    WifiConfigStore.enableAllNetworks();
+                    break;
                 case CMD_DISABLE_NETWORK:
-                    EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
                     ok = WifiConfigStore.disableNetwork(message.arg1);
                     mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
                     break;
                 case CMD_BLACKLIST_NETWORK:
-                    EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
                     WifiNative.addToBlacklistCommand((String)message.obj);
                     break;
                 case CMD_CLEAR_BLACKLIST:
@@ -2064,7 +1950,6 @@
                     /* Cannot start soft AP while in client mode */
                 case CMD_START_AP:
                     Log.d(TAG, "Failed to start soft AP with a running supplicant");
-                    EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
                     setWifiApState(WIFI_AP_STATE_FAILED);
                     break;
                 case CMD_SET_SCAN_MODE:
@@ -2080,8 +1965,16 @@
                 default:
                     return NOT_HANDLED;
             }
+            if (eventLoggingEnabled) {
+                EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+            }
             return HANDLED;
         }
+
+        @Override
+        public void exit() {
+            mNetworkInfo.setIsAvailable(false);
+        }
     }
 
     class SupplicantStoppingState extends HierarchicalState {
@@ -2113,8 +2006,6 @@
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
                 case CMD_SET_HIGH_PERF_MODE:
-                case CMD_SET_BLUETOOTH_COEXISTENCE:
-                case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_COUNTRY_CODE:
                 case CMD_SET_FREQUENCY_BAND:
                 case CMD_START_PACKET_FILTERING:
@@ -2151,8 +2042,6 @@
                 case PASSWORD_MAY_BE_INCORRECT_EVENT:
                 case CMD_SET_SCAN_TYPE:
                 case CMD_SET_HIGH_PERF_MODE:
-                case CMD_SET_BLUETOOTH_COEXISTENCE:
-                case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_COUNTRY_CODE:
                 case CMD_SET_FREQUENCY_BAND:
                 case CMD_START_PACKET_FILTERING:
@@ -2180,6 +2069,12 @@
             mIsRunning = true;
             updateBatteryWorkSource(null);
 
+            /**
+             * Enable bluetooth coexistence scan mode when bluetooth connection is active.
+             * When this mode is on, some of the low-level scan parameters used by the
+             * driver are changed to reduce interference with bluetooth
+             */
+            WifiNative.setBluetoothCoexistenceScanModeCommand(mBluetoothConnectionActive);
             /* set country code */
             setCountryCode();
             /* set frequency band of operation */
@@ -2200,6 +2095,7 @@
         @Override
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+            boolean eventLoggingEnabled = true;
             switch(message.what) {
                 case CMD_SET_SCAN_TYPE:
                     if (message.arg1 == SCAN_ACTIVE) {
@@ -2209,17 +2105,12 @@
                     }
                     break;
                 case CMD_START_SCAN:
+                    eventLoggingEnabled = false;
                     WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE);
                     break;
                 case CMD_SET_HIGH_PERF_MODE:
                     setHighPerfModeEnabledNative(message.arg1 == 1);
                     break;
-                case CMD_SET_BLUETOOTH_COEXISTENCE:
-                    WifiNative.setBluetoothCoexistenceModeCommand(message.arg1);
-                    break;
-                case CMD_SET_BLUETOOTH_SCAN_MODE:
-                    WifiNative.setBluetoothCoexistenceScanModeCommand(message.arg1 == 1);
-                    break;
                 case CMD_SET_COUNTRY_CODE:
                     String country = (String) message.obj;
                     Log.d(TAG, "set country code " + country);
@@ -2238,6 +2129,11 @@
                         Log.e(TAG, "Failed to set frequency band " + band);
                     }
                     break;
+                case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE:
+                    mBluetoothConnectionActive = (message.arg1 !=
+                            BluetoothAdapter.STATE_DISCONNECTED);
+                    WifiNative.setBluetoothCoexistenceScanModeCommand(mBluetoothConnectionActive);
+                    break;
                 case CMD_STOP_DRIVER:
                     mWakeLock.acquire();
                     WifiNative.stopDriverCommand();
@@ -2253,7 +2149,9 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+            if (eventLoggingEnabled) {
+                EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+            }
             return HANDLED;
         }
         @Override
@@ -2283,8 +2181,6 @@
                 case CMD_STOP_DRIVER:
                 case CMD_SET_SCAN_TYPE:
                 case CMD_SET_HIGH_PERF_MODE:
-                case CMD_SET_BLUETOOTH_COEXISTENCE:
-                case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_COUNTRY_CODE:
                 case CMD_SET_FREQUENCY_BAND:
                 case CMD_START_PACKET_FILTERING:
@@ -2380,7 +2276,7 @@
                     break;
                 case SUPPLICANT_STATE_CHANGE_EVENT:
                     stateChangeResult = (StateChangeResult) message.obj;
-                    SupplicantState state = (SupplicantState) stateChangeResult.state;
+                    SupplicantState state = stateChangeResult.state;
                     // Supplicant state change
                     // [31-13] Reserved for future use
                     // [8 - 0] Supplicant state (as defined in SupplicantState.java)
@@ -2423,11 +2319,8 @@
                         WifiConfigStore.selectNetwork(netId);
                     }
 
-                    /* Save a flag to indicate that we need to enable all
-                     * networks after supplicant indicates a network
-                     * state change event
-                     */
-                    mEnableAllNetworks = true;
+                    /* The state tracker handles enabling networks upon completion/failure */
+                    mSupplicantStateTracker.sendMessage(CMD_CONNECT_NETWORK);
 
                     WifiNative.reconnectCommand();
 
@@ -2445,13 +2338,13 @@
                     return NOT_HANDLED;
                 case NETWORK_CONNECTION_EVENT:
                     Log.d(TAG,"Network connection established");
-                    stateChangeResult = (StateChangeResult) message.obj;
+                    mLastNetworkId = message.arg1;
+                    mLastBssid = (String) message.obj;
 
                     //TODO: make supplicant modification to push this in events
                     mWifiInfo.setSSID(fetchSSID());
-                    mWifiInfo.setBSSID(mLastBssid = stateChangeResult.BSSID);
-                    mWifiInfo.setNetworkId(stateChangeResult.networkId);
-                    mLastNetworkId = stateChangeResult.networkId;
+                    mWifiInfo.setBSSID(mLastBssid);
+                    mWifiInfo.setNetworkId(mLastNetworkId);
                     /* send event to CM & network change broadcast */
                     setNetworkDetailedState(DetailedState.OBTAINING_IPADDR);
                     sendNetworkStateChangeBroadcast(mLastBssid);
@@ -2486,7 +2379,7 @@
                 mModifiedBluetoothCoexistenceMode = false;
                 mPowerMode = POWER_MODE_AUTO;
 
-                if (shouldDisableCoexistenceMode()) {
+                if (!mBluetoothConnectionActive) {
                     /*
                      * There are problems setting the Wi-Fi driver's power
                      * mode to active when bluetooth coexistence mode is
@@ -2668,6 +2561,7 @@
         @Override
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
+            boolean eventLoggingEnabled = true;
             switch (message.what) {
                 case CMD_DISCONNECT:
                     WifiNative.disconnectCommand();
@@ -2691,6 +2585,7 @@
                     }
                     break;
                 case CMD_START_SCAN:
+                    eventLoggingEnabled = false;
                     /* When the network is connected, re-scanning can trigger
                      * a reconnection. Put it in scan-only mode during scan.
                      * When scan results are received, the mode is switched
@@ -2726,6 +2621,7 @@
                 case NETWORK_CONNECTION_EVENT:
                     break;
                 case CMD_RSSI_POLL:
+                    eventLoggingEnabled = false;
                     if (message.arg1 == mRssiPollToken) {
                         // Get Info and continue polling
                         fetchRssiAndLinkSpeedNative();
@@ -2748,7 +2644,9 @@
                 default:
                     return NOT_HANDLED;
             }
-            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+            if (eventLoggingEnabled) {
+                EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
+            }
             return HANDLED;
         }
     }
@@ -2781,13 +2679,6 @@
             EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
             return HANDLED;
         }
-        @Override
-        public void exit() {
-            if (mEnableAllNetworks) {
-                mEnableAllNetworks = false;
-                WifiConfigStore.enableAllNetworks();
-            }
-        }
     }
 
     class DisconnectedState extends HierarchicalState {
@@ -2825,8 +2716,7 @@
                     break;
                 case SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-                    SupplicantState state = (SupplicantState) stateChangeResult.state;
-                    setNetworkDetailedState(WifiInfo.getDetailedStateOf(state));
+                    setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state));
                     /* DriverStartedState does the rest of the handling */
                     return NOT_HANDLED;
                 default: